スタック型指向プログラミング言語「Temaki」

【概要】

Temaki言語は、WebブラウザやRhino(JavaScript)で動作する、とても小さなプログラミング言語です。

【サンプル】

【ソースコード】



言語仕様

高機能な逆ポーランド電卓という趣。FORTH/PostScript言語に影響を受けています。

基本的な書き方

値を書くと、スタックに乗せられ、+や*などの演算子や関数を記述すると、スタックから値を下ろし、計算結果をスタックに乗せます。

以下のように書くと、3と5がスタックに乗せられ、+によりスタックから2つ値が下ろされ、計算結果である8がスタックに乗せられます。その後、printでスタックから1つ値が下ろされ、値が(つまり8が)出力されます。

3 5 + print
# 表示結果 8

FORTH系言語に倣って、"print"は"."(ドット)で代用できます。(ちなみに、#から始まる行がコメントです。)

1 2 3 * + .
# 表示結果 7

変数を使うには、setとgetを使います。

100 v set
v get print
# 表示結果 100

ただ、毎回、getを使うのは野暮ったいので、変数名の前に%をつけると、getを書いたのと同じ意味になります。

200 v set
%v print
# 表示結果 200

条件分岐も書くことができます。以下は、変数vの値が偶数か奇数かを判定して表示します。
条件のコードを波括弧 { ... } で括ります。

# 100を変数vにセット
100 v set
# if文で条件分岐
{ "偶数" print } # TRUEのとき
{ "奇数" print } # FALSEのとき
%v 2 % 0 ==   # 条件(変数vを2で割った余りが0かどうか)
ifelse

繰り返しも書くことができます。1から10までの足し算です。

0 kei set
1 i set
{
  %kei %i + kei set
  i inc
}
%i 10 <= # 条件(iが10以下の間)
while
"1から10を合計すると..." print
%kei print

とにかく、波カッコ内がブロックを表しますが、ブロックを変数に代入することが可能です。代入したブロックは、条件分岐や繰り返しに使うことができます。

2 v set
# ブロックを定義
{ "hoge" print } hoge_print set
{ "fuga" print } fuga_print set
# 条件分岐
%hoge_print
%fuga_print
%v 2 ==
ifelse

さらに、ブロックをcallすると、ブロックを関数として利用することができます。

{ "hoge" print } test_func set
test_func call

毎回、callを書くのは面倒なので、callをエクスクラメーションマーク「!」で代用できます。

{ "fuga" print } test_func set
test_func!

関数内では、ローカル変数が有効です。ローカル変数を使うには、lsetを利用します。

{
  100 v lset
  %v print
} call

要素

  • " ... " あるいは '...' ... 文字列
  • 数値 (34 12.3 12345 -50)
  • 演算子 ( + - * / % >= > <= < = != || &&)
  • # で行コメント
  • { ... } ブロック
  • ( ... ) は無意味。式を見やすく装飾できる

変数操作

set

(value) (name) set

値(value)をグローバル変数(name)に代入します。
値(value)は値だけでなく、ブロック(block)も可能です。

3 v set
v get print
# result: 3

get

get

変数(グローバル・ローカル)の値を参照する

%(name)

%(name)

getと同じ。変数の値を参照します。

inc

(var) inc

変数(var)の値を1加算します。

dec

 (var) dec

変数(var)の値を1減らします。

配列操作

array_new

array_new

配列を作成してスタックに乗せます。

array_set

(array) (index) (value) array_set

配列(array)の(index)に値(value)を代入します。

array_get

(array) (index) array_get

配列(array)の(index)から値を得てスタックに乗せる

制御構文

if

{ ... } (value) if

(value)が真ならば {...}を実行します。

ifelse

{ (true block) } { (false block) } (value) ifelse
(value)が真ならば(true block)を偽ならば(false block)を実行します。

for

 { ... } (from) (to) (var) for

ループ変数(var)の値を(from)から(to)まで、順にブロック {...}を実行します。

while

 { ... } (expr) while

式(expr)が真であればブロック{...}を繰り返し実行します。

call

{ ... } call

ローカルスコープを作成し、ブロック { ... } を実行します。

!

{ ... } !

callと同じ。ローカルスコープを作成し、ブロック { ... } を実行します。

exit

exit

callで呼び出したローカルブロックを抜けます。

continue

continue

for / while ループで、ブロックの途中で、次のループに移ります。

break

break

for / while ループで、ブロックの途中で、ループを抜けます。

quit

quit

プログラムの実行を停止します。

スタック操作

dup

dup

スタックトップの値を複製します。

drop

drop

スタックトップの値を削除します。

その他

jseval

(str) jseval

文字列(str)をJavaScriptの式として実行します。