最小限Forth + ワード定義機能付きForth

さて昨日に引き続き、WebDBPressのVol.60がある人はP24をご覧ください。1 2 + 3 * で(1 + 2) * 3が計算できるForthの挙動を実際に試してみるための最小限のコードを書いてみました。31行だけどこれで1 2 + 3 *がちゃんと実行できます。はてさて。最小限ってことで1,2,3以外の数は解釈できないんですけど(笑)そこら辺が気になる人は一般の数値で動くようにするのを演習だと思えばいいんじゃないかなと。

# -*- encoding: utf-8 -*-
"""
mini-Forth
Forth解説のための最小限のForth実装
"""

data = "1 2 + 3 * print"
tokens = data.split()
stack = []
cur = 0
while cur < len(tokens):
    if t in "123":
        stack.append(int(t))

    elif t == "+":
        x = stack.pop()
        y = stack.pop()
        stack.append(x + y)

    elif t == "*":
        x = stack.pop()
        y = stack.pop()
        stack.append(x + y)

    elif t == "print":
        x = stack.pop()
        print "print:", x

    else:
        raise NotImplementedError(t)

ところで僕は「ワードの定義もないんじゃプログラミング言語っていうよりただの電卓だよね」ということでそういうバージョンを作ってみた。

# -*- encoding: utf-8 -*-
"""
mini-Forth
Forth解説のための最小限のForth実装
"""

data = ": dp dup print ; 1 2 dp + 3 * print"
stack = []
words = {}

def evaluate(tokens):
    cur = 0
    while cur < len(tokens):
        t = tokens[cur]
        cur += 1
        prevstack = stack[:]

        if t in "123":
            stack.append(int(t))

        elif t == "+":
            x = stack.pop()
            y = stack.pop()
            stack.append(x + y)

        elif t == "*":
            x = stack.pop()
            y = stack.pop()
            stack.append(x + y)

        elif t == "print":
            x = stack.pop()
            print "print:", x

        elif t == "dup":
            x = stack.pop()
            stack.append(x)
            stack.append(x)

        elif t == ":":
            buf = []
            while True:
                t = tokens[cur]
                cur += 1
                if t == ";": break
                buf.append(t)
            words[buf[0]] = buf[1:]

        elif words.has_key(t):
            evaluate(words[t])

        else:
            raise NotImplementedError(t)

        print "%s->(%s)->%s" % (prevstack, t, stack)



tokens = data.split()
evaluate(tokens)