http://p9c.cc.titech.ac.jp/inferno/module.html
2003/10/17にamazonで買っちゃいました。届くのが楽しみです。 2003/10/27に届きました。でも、暇がなくてまだ読んでません… 2chでのつっこみによると、この本は4thでは半分ぐらい意味がなくなってい るらしい…が〜ん。
Inferno Programming Book : An Introduction to Programming for the Inferno Distributed System ISBN:0470849711 (Hard cover book) Atkins, Martin /Pike, Rob /Trickey, Howard / Publisher:John Wiley & Sons Inc (Sd) Published 2003/10
こっちが最新らしいが、まだ出ていないらしいです。(2003/10/30現在)
implement Myprog; include "sys.m"; sys: Sys; include "draw.m"; Myprog: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; init(ctxt: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; sys->print("Hello, world\n"); for (; argv!=nil; argv = tl argv) sys->print("%s ", hd argv); sys->print("\n"); }
"Hello, world"のところに日本語を書いても平気。(ただし、フォントがあれば)
上記のソースコードを適当なファイル名(ここではMyprog.b)で保存して、
> limbo Myprog.b
すると、Myprog.disっていうファイルができる。
>./Myprog.disとかやると実行される。
01: implement Myprog; # Myprogというmoduleを実装するぜ、ということを宣言。 02: include "sys.m"; # /moduleにある"sys.m"というファイルをinclude 03: sys: Sys; # sysという変数はSysを表すことを宣言 04: include "draw.m"; # /moduleにある"draw.m"というファイルをinclude
05: Myprog: module { 06: init: fn(nil: ref Draw->Context, argv: list of string); 07: };
08: init(nil: ref Draw->Context, argv: list of string) 09: { 10: sys = load Sys Sys->PATH; 11: sys->print("Hello, world\n"); 12: for (; argv!=nil; argv = tl argv) 13: sys->print("%s ", hd argv); 14: sys->print("\n"); 15: }
3行目の宣言は、Sys moduleのinstanceを利用するときに重要となる。
5-7行目はこのmoduleで実装されるcommandの宣言。このmoduleではinitという 関数がref Draw->Contextとlist of stringsという二つの引数をとって実装さ れるって宣言している。
"nil : "は返り値がないことを示す。 "ref Draw->Context"はdraw.m moduleを呼び出して、グラフィックに 書くときにreferされるっていうことを示す。 このmoduleでは単にprintするだけなので、結局これは使われない。
limboでは、Cのmainみたいに必ずinitで始めなければならない、ということはない。 でも、習慣的にinitを使う。
10行目はSys moduleと接続する。Sysをsysって宣言してるのかな?
11行目で表示。Sysではなくsysで使用している。
12行目と13行目のforは、iterater。hdはHeadをtlはTailをさしている。14行目 は改行を出しているだけ。
以下の文字は予約語。
adt alt array big break byte case chan con continue cyclic do else exit fn for hd if implement import include int len list load module nil of or pick real ref return self spawn string tagof tl to type while
\' single quote \" double quote \\ backslash \t tab \n newline \r carriage return \b backspace \a alert character (bell) \v vertical tab \udddd Unicode character named by 4 hexadecimal digits \0 NUL
limboにはObjectは三つある。
文法は以下の通り。
type: data-type function-type
以下の種類がdata-typeの中にある。
data-type: byte int big real string tuple-type array of data-type list of data-type chan of data-type adt-type ref adt-type module-type module-qualified-type type-name data-type-list: data-type data-type-list , data-type
chan of data-type
system中の他のAgentとの通信を確立する。 channelは、ローカル上のプロセス 間通信に使われる。
chan of (int, string)
はintegerとstringのtupleを送信するchannel typeである。
c <-= (123, "Hello");
は、このようなchannel(ここではC)の宣言と初期化を示している。
Function typeは返値を持つ。その文法を下記に示す。
function-type: fn function-arg-ret function-arg-ret: ( formal-arg-listopt ) ( formal-arg-listopt ) : data-type formal-arg-list: formal-arg formal-arg-list , formal-arg formal-arg: nil-or-D-list : type nil-or-D : self refopt identifier nil-or-D : self identifier * nil-or-D-list: nil-or-D nil-or-D-list , nil-or-D nil-or-D: identifier nil
例を下記に示す。
fn (nil: int, nil: int): int fn (radius: int, angle: int): int fn (radius, angle: int): int
i, j: int = 1; r, s: real = 1.0;
このとき、iとjはintとして宣言され、両方に1が入る。rとsはrealとして宣言さ れ、両方に1.0が入る
identifier := expression ; ( identifier-list ) := expression ;も同じ意味。
つまり、以下の二つは同じ意味。
下のも可能。
Seven: con 3+4;Sevenは、constant 7とまったく同じ意味になる。
con typeの宣言中では、iotaという識別子は特別な意味が生じる。
It is equivalent to the integer constant 0 when evaluating the expression for the first (leftmost) identifier declared, 1 for the second, and so on numerically. For example, the declaration
M0, M1, M2, M3, M4: con (1<<iota);
declares several constants M0 through M4 with the values 1, 2, 4, 8, 16 respectively.
adtはabstract data typeという意味である。
After an adt-declaration, the identifier becomes the name of the type of that adt. For example, after
Point: adt { x, y: int; add: fn (p: Point, q: Point): Point; eq: fn (p: Point, q: Point): int; };
the name Point is a type name for an adt of two integers and two functions; the fragment
r, s: Point; xcoord: int; ... xcoord = s.x; r = r.add(r, s);
makes sense. The first assignment selects one of the data members of s; the second calls one of the function members of r.
expression ;
{}で記述を囲むと、scopeがその中だけに制限される。Cと同じ。
The conditional statement takes two forms:
if ( expression ) statement if ( expression ) statement else statement
The simple looping statements are
labelopt while ( expressionopt ) statement labelopt do statement while ( expressionopt ) ;
labelopt for ( expression-1opt ; expression-2opt ; expression-3opt ) statement
これは下記と同じ。
expression-1 ; while ( expression-2 ) { statement expression-3 ; }
The case statement transfers control to one of several places depending on the value of an expression:
labelopt case expression { qual-statement-sequence }
実際の使用例。
case i { 1 or 8 => sys->print("Begins with a vowel\n)"; 0 or 2 to 7 or 9 => sys->print("Begins with a consonant\n"); * => sys->print("Sorry, didn't understand\n"); }
The alt statement transfers control to one of several groups of statements depending on the readiness of communication channels. Its syntax resembles that of case:
labelopt alt { qual-statement-sequence }
outchan := chan of string;
inchan := chan of int;
alt {
i := <-inchan =>
sys->print("Received %d\n", i);
outchan <- = "message" =>
sys->print("Sent the message\n");
}
i := <-inchan => sys->print("Received %d\n", i);
The pick statement transfers control to one of several groups of statements depending upon the resulting variant type of a pick adt expression. The syntax resembles that of case:
labelopt pick identifier := expression { pqual-statement-sequence }
The break statement
break identifieropt ;
The continue statement
continue identifieropt ;
return expressionopt ;
f, g: fn(a: int);
f(a: int) {
. . .
return g(a+1);
}
これは下記と同じ。
f(a: int) {
. . .
g(a+1);
return;
}
spwanは、新しいthreadを作り出す。
spawn term ( expression-listopt ) ;
exit ;
For example, after the module and variable declarations
M: module { One: con 1; Thing: adt { t: int; f: fn(); }; g: fn(); }; m: M;
th1: M->Thing; th2: m->Thing;
モジュールを呼び出すには、以下のようにする。
m->g(); m->th1.f();