このページは malbolge20_creator
リポジトリの compiler/ternary(制御付き疑似命令列 .mg から
低級アセンブリ言語 .mc へのコンパイラ)の入力言語であり,
そのソース(parser.yy / scanner.ll / define.h / CodeBlock.cc)
を一次情報として記述している.C風高級言語のコンパイラ
(compiler/highlevel)が出力する言語でもある.
| program | ::= | global_decl* prototype* routine* |
| global_decl | ::= | var_decl | FLAG flag_name = ( TRUE | FALSE ) |
| prototype | ::= | PROTO routine_name |
| routine | ::= | DEF routine_name (改行) var_decl* statement* END |
| var_decl | ::= | VAR var_name = num |
| statement | ::= |
OPR variable |
ROT variable |
IND_OPR variable | OUTPUT | INPUT | SET flag_name | RESET flag_name | FLIP flag_name | IF flag_name statement* ELSE statement* END | REPEAT ( num | INF ) statement* END | BREAK num? | SWITCH variable ( CASE0 statement* )? ( CASE1 statement* )? ( CASE2 statement* )? END | CALL routine_name | RETURN |
| variable | ::= | var_name | var_name @ routine_name | CON0 | CON1 | CON2 | BASE | RETURN_ADDR |
※num は10進の非負整数,または3進数(t を末尾に付ける.例:
01201201200120120120t)のいずれか.var_name/routine_name/flag_name
は英字から始まり英数字とアンダースコアが続く任意の文字列.CON0 CON1 CON2
BASE RETURN_ADDR は変数名として使える予約語(下記参照).
hello.mg — compiler/highlevel/sample/hello.c を
compiler/highlevel/parser でコンパイルして得られた実例(VAR/PROTO/
DEF/ROT/OPR/OUTPUT/END を含む)
入力プログラムの全体像は以下の通り.
------------------------------VAR / FLAG)PROTO)コメントは # から改行までとなり無視される.キーワード(VAR FLAG
DEF END ROT OPR 等)は大文字小文字を区別しない.
VAR はメモリ上に1ワードを確保し初期値を与える.グローバル宣言はすべてのルーチンから,
ルーチン内のローカル宣言はそのルーチン内(および @ routine_name を付けた他ルーチンから)参照できる.
FLAG は低級アセンブリの周期フラグに対応する2値(TRUE/FALSE)の
状態を持つ名前を宣言する.SET/RESET で明示的にON/OFFにでき,
IF/SWITCH の分岐条件として使う.
CON0(0)・CON1(1)・CON2(Malbolgeのアキュムレータ相当)・
BASE・RETURN_ADDR は各ルーチンに自動的に用意される予約変数で,
宣言なしに参照できる.
以下の命令は 低級アセンブリ言語(LAL) の同名命令へほぼ1対1で
展開される.A はMalbolgeのアキュムレータ,rotr/op はLALの定義に従う.
| 命令 | 動作 |
| ROT variable | A, variable := rotr( variable ) |
| OPR variable | A, variable := op( A, variable ) |
| IND_OPR variable | variable の値をアドレスとみなし,その参照先に対して OPR と同じ動作を行う(配列要素へのアクセスに使う) |
| OUTPUT | A の値を1文字出力する |
| INPUT | 1文字入力し A に格納する |
| SET / RESET flag_name | フラグをON/OFFにする |
| FLIP flag_name | フラグの周期状態を1つ進める |
制御構造は低級アセンブリの IF/BRANCH と各種フラグを組み合わせて実現される.
| 命令 | 動作 |
| IF flag_name ... ELSE ... END | フラグがONなら前半,OFFなら後半(ELSE以降)を実行する |
| REPEAT num ... END | num 回(INF のときは無限に)本体を繰り返す |
| BREAK num? | 内側から数えて num 重目(省略時は1重目)の REPEAT を抜ける |
| SWITCH variable CASE0 ... CASE1 ... CASE2 ... END | variable の値(0,1,2のいずれか)に応じて CASE0/CASE1/CASE2 のいずれかへ分岐する(省略した CASEn は空扱い) |
| CALL routine_name | 戻り先アドレスを保存した上で対象ルーチンの先頭へジャンプする(関数呼び出し) |
| RETURN | CALL で保存された戻り先アドレスへジャンプする.MAIN ルーチンでは代わりにプログラムを終了する |
C風高級言語のコンパイラは,1つの int/bool
変数を1つの VAR に,配列を連続領域+IND_OPR による間接アクセスに,関数を
DEF/CALL/RETURN(と引数・戻り値受け渡し用のソフトウェアスタック)に,
if/while を SWITCH/REPEAT/BREAK の組み合わせに
変換する.