TypeScript と Node.js で構築された、シンプルで軽量なプログラミング言語インタープリターです。
- 演算子の多重定義: 多くの演算子が数値以外(文字列、配列、オブジェクト)に対しても直感的な動作をします。
+(加算):- 配列 + 配列: 配列の結合。
- オブジェクト + オブジェクト: プロパティの結合(右辺で上書き)。
-(減算):- 文字列 - 文字列: 一致した部分文字列の削除。
- 配列 - 配列: 右辺の配列に含まれる要素を左辺から削除。
- オブジェクト - オブジェクト: 右辺のオブジェクトとキー・値の両方が一致するプロパティを削除。
*(乗算):- 文字列 * 数値: 文字列の繰り返し。
- 配列 * 数値: 配列の要素を繰り返した新しい配列。
- 比較演算 (
<,>,<=,>=):- 文字列: 包含関係 (
"a" < "abc"は true)。 - 配列: 部分集合・包含関係。
- オブジェクト: プロパティの包含関係(部分集合判定)。
- 文字列: 包含関係 (
- 論理演算: AND (
&), OR (|), NOT (!) 。 - 比較演算:
==(値の等価),!=,<,<=,>,>=。 - 変数: 自由な変数名への代入と更新。レキシカルスコープをサポート。
- 関数:
functionキーワードによる第一級関数の定義。returnによる値の返却(値なしも可)。 - 基本型: 数値 (Number)、文字列 (String)、ブール値 (Boolean:
true/false)、およびundefined。 - 配列 (List):
[...]による配列の作成。インデックスによる要素の取得と更新(1始まり)。 - ブロック:
( ... )による処理のグループ化。最後に評価された値を返し、新しいスコープを作成します。 - 制御構文(式): すべての制御構文は値を返す「式」として扱われます。
- 条件分岐:
if (条件) 式 else 式。 - 繰り返し:
while (条件) 式。各ループの結果を配列として返します。 - 反復:
for (変数 in 配列) 式。配列の各要素を順に処理し、各ループの結果を配列として返します。 - 関数脱出:
return 式。関数から値を返して即座に終了します。
- 条件分岐:
- ジャンプ文:
break,continueによる制御。break,continueはオプションで値を返すことができ、ループの結果リストに含まれます。- 値を指定しない
continueは、そのイテレーションの結果をスキップ(フィルタリング)するために使用できます。
- オブジェクト (Object):
{ key: value, ... }によるオブジェクトの作成。ドット記法 (obj.key) やブラケット記法 (obj["key"]) によるプロパティの取得と更新。 - this キーワード: オブジェクトのメソッド内で、そのオブジェクト自身を参照します。
- 組み込み関数:
print(値): 値を標準出力に表示します。range(開始, 終了): 開始から終了までの数値を含む配列(例:range(1, 3)は[1, 2, 3])を生成します。parseNumber: 文字列を数値に変換します。parseString: 数値を文字列に変換します。
- コメント:
#で囲まれたテキストはコメントとして無視されます。
bs コマンドをグローバルに使用できるようにするには、リポジトリをクローンして以下を実行します:
npm install
npm link.bs 拡張子のファイルを bs コマンドで実行します:
bs ファイルのパス実行すると以下のファイルが生成されます:
- tokens.json: 字句解析されたコードが記述されます。
- ast.json: 構文解析されたコードが記述されます。
ターミナルに結果が出力されます。
#出力#
print("Hello World!")
#多重定義された演算子#
# 文字列 #
print("HelloWorld" - "World") #Hello#
print("Go" * 3) #GoGoGo#
print("bc" < "abc") #true (包含)#
# 配列 #
print([1, 2] + [3, 4]) #[1, 2, 3, 4]#
print([1, 2, 3] - [2]) #[1, 3]#
print([1, 2] * 2) #[1, 2, 1, 2]#
print([1] < [1, 2]) #true (部分集合)#
# オブジェクト #
print({a: 1} + {b: 2}) #{a: 1, b: 2}#
print({a: 1, b: 2} - {a: 1}) #{b: 2}#
print({a: 1} < {a: 1, b: 2}) #true (部分集合)#
#変数#
mysteriousNumber = 0
mysteriousNumber = 2
print(mysteriousNumber) #2#
#ブール値と論理演算#
print(true)
print(!false) #true#
print(true & false) #false#
print(true | false) #true#
#比較演算子#
age = 14
print(age == 15) #false#
print(age == 14) #true#
print([1, 2] == [1, 2]) #true#
#ブロック#
v = (
a = 1
b = 2
a + b
)
print(v) #3#
#関数#
add = function (a, b) (
sum = a + b
return sum
)
print(add(3, 4)) #7#
divide = function (a, b) (
if (b == 0) return;
return a / b
)
print(divide(10, 2)) #5#
print(divide(10, 0)); #undefined#
#即時関数#
(function () (
print("Hello!")
))()
#条件分岐#
age = 16
if (age >= 18) (
print("大人です")
) else (
print("子供です")
) #子供です#
beverage = if (age >= 20) "ビール" else "ジュース"
print(beverage) #ジュース#
#再帰#
fact = function (n) (
if (n == 0) (
return 1
)
return n * fact(n - 1)
)
print(fact(5)) #120#
#while文#
i = 0
while (i < 5) (
print(i)
i = i + 1
) #0 1 2 3 4#
i = 0
print(while (i < 6) (
if (i == 3) break;
i = i + 1
)) #[1, 2, 3]#
#配列#
studentNames = ["田中", "佐藤", "鈴木"]
print(studentNames[1]) #田中#
studentNames[2] = "内藤"
print(studentNames[2]) #内藤#
#for文#
text = ""
for (i in range(0, 9)) (
if (i == 3) continue;
text = text + i
)
print(text) #012456789#
evens = for (i in range(1, 10)) if (i % 2 == 0) i
print(evens) #[2, 4, 6, 8, 10]#
#オブジェクト#
student = {
name: "山田太郎",
age: 15,
scores: {japanese: 90, math: 70, english: 80}
}
subject = "math"
student.scores[subject] = 100
print(student.scores) #{japanese: 90, math: 100, english: 80}#
#クラスもどき#
Student = function (name, age) {
name: name
age: age
introduceSelf: function () (
print("私の名前は" + this.name + "です。" + this.age + "歳です。")
)
}
tanaka = Student("田中", 18)
tanaka.introduceSelf() #私の名前は田中です。18歳です。#
#継承もどき#
FreshmanStudent = function (name, age, selectedLanguage) (
super = Student(name, age)
return super + {
selectedLanguage: selectedLanguage
introduceSelf: function () (
super.introduceSelf()
print(this.selectedLanguage + "選択です。")
)
}
)
tanaka = FreshmanStudent("田中", 18, "ドイツ語")
tanaka.introduceSelf() #私の名前は田中です。18歳です。ドイツ語選択です。#
#応用例: 3の倍数と3がつく数字の時だけアホになる関数#
nabeatsu = function (start, end) (
for (i in range(start, end)) (
iStr = parseString(i)
if (i % 3 == 0 | iStr >= "3") (
print(iStr + "~~~!!!")
) else (
print(i)
)
)
)
nabeatsu(1, 100) #1 2 3~~~!!! ...#
#応用例: 素数フィルタ#
getPrimes = function (max) (
for (n in range(2, max)) (
is_prime = true
for (i in range(2, n - 1)) (
if (n % i == 0) (
is_prime = false
break
)
)
if (is_prime) n else continue
)
)
print(getPrimes(30)) #[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]#
- Tokenizer (
tokenizer.ts): ソースコードをトークンのストリームに変換します。 - Parser (
parser.ts): トークンを抽象構文木 (AST) に変換します。 - Evaluator (
evaluator.ts): AST を再帰的に走査し、プログラムを実行します。 - Interpreter (
interpreter.mts): 各コンポーネントを統合するエントリポイントです。