この文書では、Umuインタプリタの使い方を解説します。
最初の一歩
インタプリタを REPL(Read-Evaluate-Print Loop) と呼ばれる対話環境で
起動するには、オプション -i
を付けてコマンド umu
を実行してください。
$ umu/exe/umu -i
umu:1> print "Hello world"
Hello world
val it : Unit = ()
umu:2> # [Ctrl]+[d]を入力
$
オプション -i
に続いてスクリプトが書かれたファイルを指定すると、
そのファイルを読み込んでからREPLを起動します。
$ umu/exe/umu -i umu/example/factorial.umu
umu:1> factorial 3
val it : Int = 6
umu:2>
REPLのサブコマンド
REPLでは以下のサブコマンドが使えます。
- :class
-
クラスに関する情報を表示します。
- :env と :envall
-
環境に関する情報を表示します。
- :dump と :nodump
-
実行時のダンプ表示を制御します。
- :trace と :notrace
-
実行時のトレース表示を制御します。
:class
概要
サブコマンド :class
だけを指定すると、
クラス間の継承(インヘリタンス)関係を階層的に表示します。
umu:1> :class
Top/
Class
Object/
Atom/
Bool
Number/
Float
Int
String
Symbol
:
:
:
umu:2>
詳細
サブコマンド :class
の後にクラス名を指定すると、
指定されたクラスの情報とそのクラスが応答できるメッセージの一覧を表示します。
umu:1> :class Bool
ABSTRACT CLASS?: No, this is a concrete class
SUPERCLASS: Atom
ANCESTORS: Atom, Object, Top
CLASS MESSAGES:
&Bool.true : Bool
&Bool.false : Bool
INHERITED INSTANCE MESSAGES:
INHERIT FROM: Object
Object#show : String
Object#to-s : String
Object#contents : Top
Object#== : Object -> Bool
Object#force : Top
INSTANCE MESSAGES:
Bool#< : Bool -> Bool
Bool#not : Bool
umu:2>
:env と :envall
変数名、定数名、関数名、モジュール名といった名前は、 環境(environment)と呼ばれる辞書に登録されています。
サブコマンド :env
は、環境から利用者が宣言した名前を抽出して表示します。
$ umu/exe/umu -i
umu:1> val x = 3 # 変数 x を宣言
val x : Int = 3
umu:2> :env # 環境を確認 ==> x
structure Umu
val x : Int
umu:3> val y = 4 # 変数 y を宣言
val y : Int = 4
umu:4> :env # 環境を確認 ==> x, y
structure Umu
val x : Int
val y : Int
umu:5> x + y # 式を評価
val it : Int = 7
umu:6> :env # 環境を確認 ==> x, y, it
structure Umu
val x : Int
val y : Int
val it : Int
umu:7>
もしコマンド引数でスクリプトを指定していれば、 そのスクリプト内で宣言された名前も表示します。
$ umu/exe/umu -i umu/example/factorial.umu
umu:1> :env
structure Umu
fun factorial
umu:2>
サブコマンド :envall
は、
現在の環境に登録されているすべての名前を表示します。
umu:1> :envall
fun !!
fun *
fun +
fun :=
:
:
:
fun zero
fun zero?
fun zip
fun |
umu:2>
:dump と :nodump
インタプリタは入力されたスクリプトを以下の流れで処理します。
/ソース(スクリプト)/ ->
<字句解析> -> [トークンの並び] ->
<構文解析> -> [具象構文木] ->
<脱糖化> -> [抽象構文木] ->
<評価> ->
/結果(環境と値)/
ダンプ機能は、この処理の過程で生成される以下の中間オブジェクトを表示します。
-
トークンの並び(tokens)
-
具象構文木(concrete syntax tree)
-
抽象構文木(abstract syntax tree)
ダンプ機能を有効とするにはサブコマンド :dump
を使用し、
無効とするには :nodump
を使用してください。
umu:1> :dump
umu:2> 3 + 4
________ Source: '<stdin>' ________
0002: 3 + 4
________ Tokens: '<stdin>' ________
0002: INT(3) SP '+' SP INT(4) NL("\n")
________ Concrete Syntax: #2 in "<stdin>" ________
(3 + 4)
________ Abstract Syntax: #2 in "<stdin>" ________
(+ 3 4)
val it : Int = 7
umu:3> :nodump
umu:4>
:trace と :notrace
トレース機能は、 インタプリタ内部の脱糖化(desugaring)処理と評価(evaluation)処理について、 その過程を階層的な軌跡(trace)で表示します。
トレース機能を有効とするにはサブコマンド :trace
を使用し、
無効とするには :notrace
を使用してください。
umu:1> :trace
umu:2> 3 + 4
________ Source: '<stdin>' ________
0002: 3 + 4
________ Desugar Trace ________
[Desu] Redefinable (CSCEB::Infix): (3 + 4)
| [Desu] Int (CSCEUA::Number): 3 --> Int (ASCEUA::Number): 3
| [Desu] Int (CSCEUA::Number): 4 --> Int (ASCEUA::Number): 4
--> Apply (ASCEB): (+ 3 4)
________ Evaluator Trace ________
[Eval(Expr)] Apply (ASCEB): (+ 3 4)
| [Eval(Expr)] Short (ASCEU::Identifier): +
| --> Fun (VC): #<+: {x : Number y : Number -> (x).(+ y)}>
| [Eval(Expr)] Int (ASCEUA::Number): 3 --> Int (VCAN): 3
| [Eval(Expr)] Int (ASCEUA::Number): 4 --> Int (VCAN): 4
| [Apply] Fun (VC): (#<+: {x : Number y : Number -> (x).(+ y)}> 3 4)
| | [Eval(Expr)] Entry (ASCEB::Send): (x).(+ y)
| | | [Eval(Expr)] Short (ASCEU::Identifier): x
| | | --> Int (VCAN): 3
| | | [Eval(Expr)] Short (ASCEU::Identifier): y
| | | --> Int (VCAN): 4
| | | [Invoke] Int (VCAN): (3).meth_add(4 : Int) -> Int
| | | --> Int (VCAN): 7
| | --> Int (VCAN): 7
| --> Int (VCAN): 7
--> Int (VCAN): 7
val it : Int = 7
umu:3> :notrace
umu:4>