Lunar言語の中間表現であり、ここからLLVM IRへ変換。
- IR := TOP*
- TOP := GLOBAL | THREADLOCAL | IMPORT | TOPSTATEMENT | DEFUN | EXPR
- TOPSTATEMENT := LET | COND | WHILE | SELECT | BLOCK | STRUCT | CUNION | UNION
- STATEMENT := LET | COND | WHILE | BREAK | SELECT | RETURN | STRUCT | CUNION | UNION | BLOCK | LEAP
- STEXPR := STATMENT | EXPR
- LITERAL := STR32 | STR8 | CHAR32 | CHAR8 | INT | FLOAT | HEX | OCT | BIN | ATOM
- EXPRIDENT := EXPR | IDENTIFIER
- EXPRIDENTLIT := EXPR | IDENTIFIER | LITERAL
- EXPR := LAMBDA | NEW | MKSTREAM | TYPEOF | THREAD | CALLFUNC
- GLOBAL := ( global ( ( ( ( TYPE IDENTIFIER )+ ) EXPRIDENTLIT? )+ ) )
- THREADLOCAL := ( threadlocal ( ( ( ( TYPE IDENTIFIER )+ ) EXPRIDENTLIT? )+ ) )
- IMPORT := ( import STR32+ )
Lunar IRにはオーナーという概念があり、変数を利用する際には、その変数がどのような所有権で扱われるかを指定する。
構文:
- OWNERSHIP := unique | shared | ref
セマンティクス:
- unique
- ただ唯一のオーナーのみから保持される変数である。所有権の移動はmoveにて行われる。
- shared
- 複数のオーナーから保持される変数である。内部的には参照カウントを保持している。
- reference
- unique、shared、immovalbe変数の所有権に影響を及ばさずに参照するための変数である。
- immovable
- 所有権の変更が許されない変数である。
型指定は、所有権と実際の型を指定して行う。 所有権の指定が省略された場合はimmovable変数となる。
構文:
- TYPE := TYPE0 | ( OWNERSHIP TYPE0 )
- TYPE0 := SCALAR | ARRAY | STRING | BINARY | LIST | STRUCT | DICT | SET | UNION | FUNCTYPE | RSTREAM | WSTREAM | RFILESTREAM | WFILESTREAM | RSOCKSTREAM | WSOCKSTREAM | RSIGSTREAM | RTHREADSTREAM | WTHREADSTREAM | PTR | CUNION | PARSEC | IDENTIFIER
ここで、IDENTIFIERとは空白文字以外からなる、1文字以上の文字かつ、先頭が数字ではない文字列かつ、 予約文字(列)以外の文字列である。
以下の型がプリミティブなスカラオブジェクトとして利用可能。
- bool
- u64
- s64
- u32
- s32
- u16
- s16
- u8
- s8
- double
- float
- char (u32の別名、UTF-32)
- atom
構文:
- SCALAR := SCALARTYPE LITERAL | SCALARTYPE
- SCALARTYPE := bool | u64 | s64 | u32 | s32 | u16 | s16 | u8 | s8 | double | float | char | atom
構文:
- FUNCTYPE := ( func ( TYPE* ) ( TYPE* ) )
セマンティクス:
- ( func ( 戻り値の型* ) ( 引数の型* ) )
関数には所有権という概念はない。
構文:
- STRUCT := ( struct IDENTIFIER? ( TYPE IDENTIFIER )* )
セマンティクス:
- ( struct 構造体の名前 ( 構造体メンバの型 構造体メンバの名前 )* )
構文:
- UNION := ( union IDENTIFIER? ( TYPE IDENTIFIER )* )
セマンティクス:
- ( union 多相型の名前 ( 多相型となる型 型の名前 )* )
構文:
- CUNION := ( cunion IDENTIFIER? ( TYPE IDENTIFIER )* )
セマンティクス:
- ( cunion 構造体の名前 ( 構造体メンバの型 構造体メンバの名前 )* )
C関数と互換性を保つために利用され、それ以外での利用は非推奨である。
C関数と互換性を保つために利用され、それ以外での利用は非推奨である。
構文:
- PTR := ( ptr TYPE )
セマンティクス:
- ( ptr ポインタの型 )
(ptr u64)
(ptr (shared mystruct))
(ptr (ptr (unique u32)))
構文:
- ARRAY := ( array TYPE SIZE ) | ( array TYPE )
- SIZE := DIGIT | HEX | OCT | BIN
SIZEを指定した場合は、固定長となる。
例:
(array u64 10)
(array (shared u32) 5)
(array (unique u32) 5)
(array (ref u32) 5)
構文:
- STRING := string
内部的にはUTF-32。
構文:
- BINARY := binary
構文:
- LIST := ( list TYPE )
例:
(list u64)
(list (shared u16))
(list (unique u16))
(list (ref u16))
例:
(struct my_data
(u32 foo)
((shared u32) bar)
((unique u32) baz)
((ref u32) qux))
構文
- DICT := ( dict TYPE TYPE )
セマンティクス
- ( dict Keyの型 Valueの型 )
例:
(dict u32 (unique string))
構文
- SET := ( set TYPE )
セマンティクス
- ( set 値の型 )
(set (unique u32))
データストリームは読み込み用の端点と、書き込み用の端点から構成される。
構文:
- RSTREAM := ( rstrm TYPE )
- WSTREAM := ( wstrm TYPE )
セマンティクス:
- ( rstrm ストリームに渡すデータの型 )
- ( wstrm ストリームに渡すデータの型 )
データストリームには以下の制約がある。
- 読み込み用の端点は所有権がuniqueであり、書き込み用の端点は所有権がsharedでなければならない。
- RFILESTREAM := rfilestrm
- WFILESTREAM := wfilestrm
- RSOCKSTREAM := rsockstrm
- WSOCKSTREAM := wsockstrm
- RSIGSTREAM := rsigstrm
- RTHREADTREAM := ( rthreadstrm TYPE )
- WTHREADTREAM := ( wthreadstrm TYPE )
構文:
- PARSEC := ( parsec string ) | ( parsec binary)
構文:
- DEFUN := ( defun IDENTIFIER ( TYPE* ) ( ( TYPE IDENTIFIER )* ) STEXPR* )
構文:
- CALLFUNC := ( EXPRIDENT EXPRIDENTLIT* )
関数定義に応じた値を返す。
構文:
- LAMBDA := ( lambda ( TYPE* ) ( ( TYPE IDENTIFIER )* ) STEXPR* )
関数型の値を返す。
構文:
- LET := ( let ( ( ( ( TYPE IDENTIFIER )+ ) EXPRIDENTLIT? )+ ) STEXPR* )
セマンティクス:
- ( let ( ( ( ( 型 変数名 )+ ) 束縛する値 )+ ) 式* )
関数は複数の値を返すこともあるため、複数の変数名を記述できるように。
構文:
- IF := ( if EXPRIDENTLIT EXPRIDENTLIT EXPRIDENTLIT )
セマンティクス:
- ( if 条件 条件が真の時の値 条件が偽の時の値 )
if は式であり値を返す。C言語の?構文みたいなもの。
構文:
- COND := ( cond ( EXPRIDENTLIT STEXPR* )+ ( else STEXPR* )? )
セマンティクス:
- ( cond ( 条件 条件が真の時に実行する式* )+ ( else どの条件にも当てはまらない場合に実行する式* )? )
cond は制御構文であり、値は返さない。
構文:
- WHILE := ( while EXPRIDENTLIT STEXPR* )
セマンティクス:
- ( while 条件 条件が真の間実行する式* )
構文:
- BREAK := ( break )
while ループの制御から脱出するときに使う。
構文:
- BLOCK := ( block ( STEXPR* ) ( STEXPR* ) )
セマンティクス:
- ( block ( 式* ) ( leap後に実行される式* ) )
構文:
- LEAP := ( leap )
block 脱出するときに使う。
構文:
- RETURN := ( return ( EXPRIDENTLIT* ) )
セマンティクス:
- ( return ( 返り値* ) )
構文:
- SELECT := ( select ( EXPRIDENT STEXPR* )* ( timeout EXPRIDENTLIT STEXPR* )? )
セマンティクス:
- ( select (ストリーム ストリームに入力があった時に実行する式) (timeout タイムアウトするまでの時間[ms] )? )
ストリームの入力待ちを行う。 入力待ちの際、他に実行可能なグリーンスレッドがある場合はそちらに処理が移行。
- ATOM := `IDENTIFIER
- STR32 := " CHARS* "
- STR8 := b " CHARS* "
- ESCAPE := \a | \b | \f | \r | \n | \t | \v | \\ | ? | ' | " | \0 | \UXXXXXXXX | \uXXXX
- CHARS := ESCAPE | ESCAPE以外の文字
- CHAR32 := ' CHARS '
- CHAR8 := b ' CHARS '
- INT := -? DIGIT
- DIGIT := NUM1to9 NUM0to9* | 0
- NUM1to9 := 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
- NUM0to9 := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
- FLOAT := INT . NUM0to9+ EXP? f?
- EXP := EE SIGN NUM+
- EE := e | E
- SIGN := - | +
最後にfがついた場合は単精度で、つかない場合は倍精度となる。
- HEX := 0x HEXNUM2* | 0X HEXNUM2*
- HEXNUM2 := HEXNUM HEXNUM
- HEXNUM := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | A | b | B | c | C | d | D | f | F
- OCT := 0 OCTNUM*
- OCTNUM := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
- BIN := 0b BINNUM* | 0B BINNUM*
- BINNUM := 0 | 1
- TRUE := ture
- FALSE := false
構文:
- NEW := ( new TYPE EXPRIDENTLIT? )
セマンティクス:
- ( new 型 初期化引数 )
TYPE型の値を返す。
構文:
- COPY := ( copy EXPRIDENT EXPRIDENTLIT )
セマンティクス:
- ( copy 書き換える変数 書き換える値 )
構文:
- ASSOC := ( assoc EXPRIDENT EXPRIDENT )
セマンティクス:
- ( assoc 変数 束縛先 )
ただし、束縛先を変更できるのはuniqueかshared変数のみである。
構文:
- TYPEOF := ( type TYPE EXPRIDENTLIT )
セマンティクス:
- ( type 検査する形名 識別子など )
type 式は真偽値を返す式であり、多相型変数の型を動的に検査するために利用される。
例:
(type u32 var)
構文:
- MKSTREAM := ( mkstream TYPE EXPRIDENTLIT )
セマンティクス:
- ( mkstream ストリームの型 サイズ )
(unique (rstrm TYPE))と(shared (wstrm TYPE))の2つの値を返す。
構文:
- MKFILESTREAM := ( mkfilestream EXPRIDENTLIT )
セマンティクス:
- ( mkfilestream ファイルディスクリプタ )
構文:
- MKSOCKSTREAM := ( mksockstream EXPRIDENTLIT )
セマンティクス:
- ( mksockstream ソケットファイルディスクリプタ )
構文:
- MKSIGNALSTREAM := ( mksognalstream EXPRIDENTLIT )
セマンティクス:
- ( mksignalstream シグナル番号 )
構文:
- GETTHREADQ := ( getthreadq EXPRIDENTLIT )
セマンティクス:
- ( getthreadq スレッドID )
構文:
- PUSH := ( push EXPRIDENTLIT EXPRIDENTLIT )
セマンティクス:
- ( push ストリーム型 挿入するデータ )
ストリームの最後尾にデータを挿入する。 STRM_SUCCESS, STRM_CLOSED, STRM_NO_VACANCYのいずれかの値を返す。
構文:
- POP := ( pop EXPRIDENT )
セマンティクス:
- ( pop ストリーム )
ストリームから先頭のデータを取り出す。 返り値は、(取り出した値 エラー)となり、エラーはSTRM_SUCCESS, STRM_CLOSED, STRM_NO_VACANCYのいずれかとなる。
構文:
- SPAWN := ( spawn EXPRIDENTLIT EXPRIDENT EXPRIDENTLIT)
セマンティクス:
- ( spawn スタックサイズ 呼び出す関数 関数へ渡す引数)
返り値はスレッド内で一意に識別されるs64型の整数値。
構文:
- SCHEDULE := ( schedule )
他のグリーンスレッドに制御を渡す。
OSネイティブなデタッチスレッドを生成。
構文:
- THREAD := ( thread EXPRIDENTLIT TYPE EXPRIDENTLIT EXPRIDENT EXPRIDENTLIT )
セマンティクス:
- ( thread スレッドの名前 スレッドキューの型 キューのサイズ 呼び出す関数 関数へ渡す引数 )
- SPIN_LOCK := ( spin_lock EXPRIDENT )
- SPIN_LOCK_INIT := ( spin_lock_init EXPRIDENT )
- SPIN_TRY_LOCK := ( spin_try_lock EXPRIDENT )
- SPIN_UNLOCK := ( spin_unlock EXPRIDENT )
- PARSE := (parse EXPRIDENT PARSECOPS EXPRIDENTLIT*)
- PARSECOPS := PARSECCHAR | PARSECMANY | PARSECMANY1 | PARSECTRY | PARSECTRYEND | PARSECLA | PARSECLAEND | PARSECDIGIT | PARSECHEX | PARSECOCT | PARSECSPACE | PARSECSATIS | PARSECSTR
- PARSECCHAR := character
- PARSECTRY := try
- PARSERTRYEND := try_end
- PARSECLA := look_ahead
- PARSECLAEND := look_ahead_end
- PARSECDIGT := digit
- PARSECHEX := hex
- PARSECOCT := oct
- PARSECSPACE := space
- PARSECSATIS := satisfy
- PARSECSTR := string
- PARSECRESULT := result
(let (parsec (p) (new parsec string rstream))
(parse p character 'a'))
構文:
- CCALL := ( ccall EXPRIDENT EXPRIDENTLIT* )
セマンティクス:
- ( ccall C関数 引数* )
shared、unique変数はポインタ渡し。immovableは値渡しとなる。 pointerのpointerはptr型を利用して実現する。
モジュール読み込み
構文:
- DLOPEN := ( dlopen EXPRIDENTLIT )
セマンティクス:
- ( dlopen モジュールへのパス )
動的ライブラリ、.soファイルを読み込む。
返り値はハンドラ。
- DLCLOSE := ( dlclose EXPRIDENT )
構文:
- DLSYM := ( dlsym EXPRIDENT EXPRIDENTLIT )
セマンティクス:
- ( dlsym モジュール シンボル名 )
PTR型へ変換
構文:
- TOPTR := ( toptr EXPRIDENT )
PTR型の参照外し
構文:
- DEREF := ( deref EXPRIDENT )
セマンティクス:
- ( deref PTR型変数 )
返り値は、参照外しを行った値。
- INCCNT := ( inccnt EXPRIDENT )
- DECCNT := ( deccnt EXPRIDENT )
- ADD := ( add EXPRIDENTLIT EXPRIDENTLIT+ )
- MINUS := ( minus EXPRIDENTLIT EXPRIDENTLIT+ )
- MULTI := ( mul EXPRIDENTLIT EXPRIDENTLIT+ )
- DIV := ( div EXPRIDENTLIT EXPRIDENTLIT+ )
- MOD := ( mod EXPRIDENTLIT EXPRIDENTLIT+ )
- BAND := ( band EXPRIDENTLIT EXPRIDENTLIT+ )
- BOR := ( bor EXPRIDENTLIT EXPRIDENTLIT+ )
- BXOR := ( bxor EXPRIDENTLIT EXPRIDENTLIT+ )
- BNOT := ( bnot EXPRIDENTLIT )
- BSL := ( bsl EXPRIDENT EXPRIDENT ) // 論理左シフト
- BSR := ( bsr EXPRIDENT EXPRIDENT ) // 論理右シフト
- BASL := ( basl EXPRIDENT EXPRIDENT ) // 算術左シフト
- BASR := ( basr EXPRIDENT EXPRIDENT ) // 算術右シフト
- BPOPCNT := ( bpopcnt EXPRIDENT )
- BLZCNT := ( blzcnt EXPRIDENT )
- AND := ( and EXPRIDENTLIT EXPRIDENTLIT+ )
- OR := ( or EXPRIDENTLIT EXPRIDENTLIT+ )
- EQ := ( eq EXPRIDENTLIT EXPRIDENTLIT+ )
- NOT := ( not EXPRIDENTLIT )
- SOCKET := ( socket SOCKDOMAIN SOCKTYPE )
- SOCKDOMAIN := PF_UNIX | PF_INET | PF_INET6
- SOCKTYPE := SOCK_STREAM | SOCK_DGRAM | SOCK_RAW
返り値のディスクリプタはmksockstreamと結び付けられなければならない。
構文:
- OPEN := ( open EXPRIDENTLIT (OFLAGS*) )
- OFLAGS := O_RDONLY | O_WONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_SHLOCK | O_EXLOCK | O_NOFOLLOW | O_SYMLINK | O_EVTONLY | O_CLOEXEC
セマンティクス:
- ( open フィアル名 フラグ )
返り値のディスクリプタはmkfilestreamと結び付けられなければならない。
- PRINT := ( print EXPRIDENTLIT+ )
文字列を標準出力へ出力。引数はstring型のみ。
- TOSTR := ( tostr EXPRIDENTLIT )
引数を文字列へ変換。immovalなstring型を返す。