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"という文字列は…どこから来て…どこへ行くんだろう…

  1. 実はガベコレが動いている
  2. 実はリークしてる
  3. なんかマジック


こういうときはgcc -Sだぜー。
ふっふっふ…PPCを勉強してきたのはこの時のための伏線であったのだっ!

$ gcc -S append.adb
$ cat append.s
	.file	"append.adb"
	.section	".data"
	.align 2
(…なんだかすごい色々な…)
	.section	.note.GNU-stack,"",@progbits
$ 

読めぬー。


しかし、いくつか気付いた点がっ

  • r12まで使ってすごいスーパースカラーしそうなストールしなさそうなコードが出てる!x86という鎖から解かれたGCCはこうも美しく輝くものなのか!!

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ってやつを追いかければ、なんとかなりかけですねっ!
こいつの実体は、//adainclude/s-secsta.ad[bs]にあります!

   --------------
   -- 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は色々夢が詰まってそう。