Skip to content

murakami/LISP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LISP Interpreter

SwiftによるミニマルなLisp処理系の実装です。コマンドラインで動作するREPL(Read-Eval-Print Loop)を提供します。

特徴

  • 純粋なSwiftで実装された軽量なLisp処理系
  • 対話的なREPLインターフェース
  • 基本的なLisp機能をサポート
  • 外部依存なし(標準ライブラリのみ使用)

セットアップ

必要要件

  • Swift 5.0以降
  • macOS、Linux、またはSwiftが動作する環境

インストール

# ファイルに実行権限を付与
chmod +x main.swift

実行方法

# shebang経由で直接実行
./main.swift

# または、swiftコマンドで実行
swift main.swift

使い方

REPL の起動

プログラムを実行すると、対話型REPLが起動します:

Bitz Lisp Interpreter
Type 'exit' or 'quit' to exit

> 

プロンプト > に続けてLisp式を入力すると、評価結果が表示されます。

終了方法

REPLを終了するには、exit または quit と入力します。

サポートされる機能

データ型

数値(Number)

整数および浮動小数点数をサポートします。

> 42
42

> 3.14
3.14

> -10
-10

シンボル(Symbol)

変数名や関数名として使用されます。

> x
Error: Undefined symbol: x

> (define x 10)
10

> x
10

リスト(List)

括弧で囲まれた要素の並びです。

> (list 1 2 3)
(1 2 3)

> (quote (a b c))
(a b c)

真偽値(Boolean)

  • t : 真(true)
  • nil : 偽(false)および空リスト
> t
t

> nil
nil

> (if t 1 2)
1

> (if nil 1 2)
2

関数(Function)

第一級オブジェクトとして扱われます。

> (lambda (x) (* x x))
<function>

特殊形式

quote

式を評価せずにそのまま返します。

構文: (quote expr)

> (quote (1 2 3))
(1 2 3)

> (quote x)
x

define

変数を定義します。

構文: (define symbol value)

> (define x 10)
10

> x
10

> (define y (* x 2))
20

> y
20

if

条件分岐を行います。

構文: (if condition then-expr else-expr)

条件が真(nilfalse以外)の場合はthen-exprを、偽の場合はelse-exprを評価します。

> (if (> 5 3) 100 200)
100

> (if (< 5 3) 100 200)
200

> (if nil "yes" "no")
"no"

> (if 0 "yes" "no")
"yes"

lambda

無名関数を定義します。

構文: (lambda (param1 param2 ...) body)

> (lambda (x) (* x x))
<function>

> ((lambda (x) (* x x)) 5)
25

> (define square (lambda (x) (* x x)))
<function>

> (square 7)
49

> (define add (lambda (a b) (+ a b)))
<function>

> (add 3 4)
7

組み込み関数

算術演算

+ (加算)

構文: (+ num1 num2 ...)

複数の数値を加算します。引数がない場合は0を返します。

> (+ 1 2 3)
6

> (+ 10 20)
30

> (+)
0
- (減算)

構文: (- num1 num2 ...) または (- num)

複数の数値の減算を行います。引数が1つの場合は符号反転します。

> (- 10 3)
7

> (- 100 30 20)
50

> (- 5)
-5
* (乗算)

構文: (* num1 num2 ...)

複数の数値を乗算します。引数がない場合は1を返します。

> (* 2 3 4)
24

> (* 5 5)
25

> (*)
1
/ (除算)

構文: (/ num1 num2 ...) または (/ num)

除算を行います。引数が1つの場合は逆数を返します。

> (/ 10 2)
5

> (/ 100 2 5)
10

> (/ 4)
0.25

比較演算

= (等価)

構文: (= num1 num2)

2つの数値が等しいかを判定します。

> (= 5 5)
t

> (= 3 4)
nil
< (小なり)

構文: (< num1 num2)

第一引数が第二引数より小さいかを判定します。

> (< 3 5)
t

> (< 5 3)
nil

> (< 5 5)
nil
> (大なり)

構文: (> num1 num2)

第一引数が第二引数より大きいかを判定します。

> (> 5 3)
t

> (> 3 5)
nil

> (> 5 5)
nil

リスト操作

list

構文: (list elem1 elem2 ...)

引数からリストを作成します。

> (list 1 2 3)
(1 2 3)

> (list)
()

> (list 1 (+ 2 3) 4)
(1 5 4)
car

構文: (car list)

リストの最初の要素を返します。

> (car (list 1 2 3))
1

> (car (quote (a b c)))
a
cdr

構文: (cdr list)

リストの最初の要素を除いた残りのリストを返します。

> (cdr (list 1 2 3))
(2 3)

> (cdr (quote (a b c)))
(b c)

> (cdr (list 1))
()
cons

構文: (cons elem list)

要素をリストの先頭に追加した新しいリストを返します。

> (cons 0 (list 1 2 3))
(0 1 2 3)

> (cons 1 (quote ()))
(1)

> (cons (quote a) (quote (b c)))
(a b c)

実用例

階乗の計算

> (define factorial (lambda (n) (if (= n 0) 1 (* n (factorial (- n 1))))))
<function>

> (factorial 5)
120

> (factorial 10)
3628800

フィボナッチ数列

> (define fib (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))
<function>

> (fib 10)
55

> (fib 15)
610

リストの長さを求める

> (define length (lambda (lst) (if (= lst (quote ())) 0 (+ 1 (length (cdr lst))))))
<function>

> (length (list 1 2 3 4 5))
5

リストの合計

> (define sum (lambda (lst) (if (= lst (quote ())) 0 (+ (car lst) (sum (cdr lst))))))
<function>

> (sum (list 1 2 3 4 5))
15

最大値を求める

> (define max2 (lambda (a b) (if (> a b) a b)))
<function>

> (max2 10 20)
20

> (max2 30 15)
30

map関数の実装

> (define map (lambda (f lst) (if (= lst (quote ())) (quote ()) (cons (f (car lst)) (map f (cdr lst))))))
<function>

> (define double (lambda (x) (* x 2)))
<function>

> (map double (list 1 2 3 4 5))
(2 4 6 8 10)

エラーハンドリング

処理系は以下のようなエラーを検出して報告します:

> (+ 1 x)
Undefined symbol: x

> (/ 10 0)
Runtime Error: Division by zero

> (car 123)
Runtime Error: car requires a non-empty list

> (lambda x (* x x))
Runtime Error: lambda parameters must be a list

> (1 2 3)
Runtime Error: Cannot apply non-function

アーキテクチャ

主要コンポーネント

  1. トークナイザー(Tokenizer)

    • 入力文字列を字句解析してトークン列に変換
  2. パーサー(Parser)

    • トークン列を構文解析してS式(LispValue)に変換
  3. 評価器(Evaluator)

    • S式を評価して結果を計算
  4. 環境(Environment)

    • 変数と関数のバインディングを管理
    • レキシカルスコープをサポート

データフロー

入力文字列
    ↓
トークナイザー
    ↓
トークン列
    ↓
パーサー
    ↓
S式(LispValue)
    ↓
評価器(環境を使用)
    ↓
評価結果

制限事項

この実装は教育目的のミニマルな処理系であり、以下の制限があります:

  • マクロシステムなし
  • ガベージコレクションの最適化なし
  • 末尾呼び出し最適化なし(スタックオーバーフローの可能性)
  • 文字列型のサポートなし
  • ファイル入出力なし
  • エラーメッセージが限定的

拡張のアイデア

この処理系を拡張する場合、以下のような機能追加が考えられます:

  • 文字列データ型のサポート
  • let / let* バインディング
  • cond による多分岐
  • and / or 論理演算
  • begin による逐次評価
  • set! による変数への再代入
  • マクロシステム
  • ファイルからのコード読み込み
  • 末尾呼び出し最適化
  • より詳細なエラーメッセージ(行番号など)

ライセンス

このコードはパブリックドメインとして提供されています。自由に使用、改変、配布できます。

参考資料

About

Bitz Lisp

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages