Ada文字列
ふる・あだーーー(全加算器)。えいだです!!ネタ切れ感漂ってます!そんなことないです。
というわけでネタ切れっぽなので(やっぱそうなのかー)ふとぅーにAdaでもやろうと思ったのであるのだった。
今日はこのへん参照してる気がー
http://adahome.com/Tutorials/Lovelace/lesson8.htm
さて、Adaの特徴として、文字列がよりどりみどりというのがあるんですなー(よりどりみどりというほどではないですなー)
- String
- Bounded_String
- Unbounded_String
- etc...
これは、若干面白いところでないかという説な部分であるかなしかー。
まず、GCの無い言語で、一番困るのは、文字列だと思わるるー。文字列を長くしたり短くしたりするたびに、'\0'が潰れないかとか、freeし忘れてないかとか心臓によろしくぬー。
それで、その文字列問題を完全に放棄したのがC言語なー。(それはそれで仕方ないところだがー)
そんで、文字列ライブラリを実装するために、ぐちょぐちょと楽しいルールを言語仕様にしていったのがC++なー(と、Joel氏がどっかで書いてたような)
さて、この問題に、Adaはどう立ち向かうのかっ!というのが、今回のテーマなのであっる。
まずー、C言語使いには考えられないことどすが、なんと、Adaでは、文字列の連結ができるー!!
with Ada.Text_Io; procedure Append is A:String := "hello"; B:String := "world"; begin declare C : String := A&" "&B; begin Ada.Text_Io.Put_Line( A & " " & B ); end ; end Append;
これで、"hello world"だー。いったいどういう仕組みなんだー。
"hello world"という文字列は…どこから来て…どこへ行くんだろう…
- 実はガベコレが動いている
- 実はリークしてる
- なんかマジック
こういうときはgcc -Sだぜー。
ふっふっふ…PPCを勉強してきたのはこの時のための伏線であったのだっ!
$ gcc -S append.adb $ cat append.s .file "append.adb" .section ".data" .align 2 (…なんだかすごい色々な…) .section .note.GNU-stack,"",@progbits $
読めぬー。
しかし、いくつか気付いた点がっ
Ada関係ぬ。
さて、てと、これではいかんので、一歩ずつ詰めますよーやる気続く限り。(そして、そのやる気は既に失われつつあるのだった!)
まず、Adaの文字列型はどういう構造になってるですだろうかっ!
function Str return String is begin return "a"; end Str;
こーんなコードを用意しまして、
(略) C.0.411: .long 1 .long 1 .ascii "a" .zero 3 .section ".text" .align 2 .globl _ada_str .type _ada_str, @function _ada_str: .LFB3: mflr 0 .LCFI0: stwu 1,-32(1) .LCFI1: stmw 29,20(1) .LCFI2: mr 29,3 stw 0,36(1) .LCFI3: li 3,12 bl system__secondary_stack__ss_allocate lis 9,C.0.411@ha addi 0,3,8 stw 3,4(29) la 9,C.0.411@l(9) stw 0,0(29) lswi 5,9,12 stswi 5,3,12 lwz 0,36(1) mr 3,29 lmw 29,20(1) addi 1,1,32 mtlr 0 blr (略)
大体こんな感じになりますよーと。
相変わらずPPCが読めないのは内緒だぞっ!(お前は前回まで何をやっていたんだーーー!)
と、いうわけで、反則技を使いませう。
$ gcc -S -Os str.adb -fdump-tree-all
なんと、こうすることでC言語みたいなTREE表現を読めるようになるので、PPCもAdaも見なくてよいというものだあァァァーーもはやどれが手段でどれが目的なんだかわかんねぇーーー!
↓出力されたstr.adb.t69.final_cleanup
Str () { typedef character str__T1b[1:1]; typedef <unnamed type> struct <unnamed type>; static struct ALLOC C.0 = {.BOUNDS={.LB0=1, .UB0=1}, .ARRAY="a"}; struct ALLOC * D.410; system__address D.408; <bb 0>: D.408 = system__secondary_stack__ss_allocate (12); D.410 = (struct ALLOC *) D.408; *D.410 = C.0; <retval>.P_ARRAY = (character[(long int) <PLACEHOLDER_EXPR struct string___XUP>.P_BOUNDS->LB0:(long int) <PLACEHOLDER_EXPR struct string___XUP>.P_BOUNDS->UB0] *) &D.410->ARRAY; <retval>.P_BOUNDS = &D.410->BOUNDS; return <retval>; }
これなら読めるよっ!
ここで、重要そうなのは、
- ALLOC型。配列下限、上限+中身?
- system__secondary_stack__ss_allocate いかにも割り当てな。12byteってALLOC型だろなー。
ってとこですかねー
さて、ここで、system__secondary_stack__ss_allocateってやつを追いかければ、なんとかなりかけですねっ!
こいつの実体は、/
-------------- -- Allocate -- -------------- procedure SS_Allocate (Addr : out Address; Storage_Size : SSE.Storage_Count) is Max_Align : constant SS_Ptr := SS_Ptr (Standard'Maximum_Alignment); Max_Size : constant SS_Ptr := ((SS_Ptr (Storage_Size) + Max_Align - 1) / Max_Align) * Max_Align; (...略...)
やべー。もっとあっさり終わるはずが、こいつは、奥が深いぜっ!
というわけで、やる気ある限り続く。(そして、そのやる気は既に略)
今日のまとめ:
- Adaの文字列は奥が深い。
- s-xxx.adbは色々夢が詰まってそう。