1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# -*- coding: utf-8 -*-

import re

class forth():

    def __init__(self, text):
        self.Stack = []
        self.FunctionList = {}
        self.VariableList = {}
        self.ParsedCode = []

        pc = self.perse(text)

        #空文字列を取り除く
        for x in pc:
            if x != '':
                self.ParsedCode.append(x)

        pass

    def __del__(self):
        pass


    def perse(self, text):
        ret = ""
        for x in text.split("\n"):
            t = x.split("#")
            ret += t[0] + " "

        return re.split("\s+", ret)

    def execute(self):
        cl = self.ParsedCode
        pc = [0]
        nc = [0]
        self._execute(cl, pc, nc)


    def _execute(self, cl, pc , nc):
        while(pc[0] < len(cl)):
            if (self.operator(cl, pc, nc)):
                pass    #operatorが評価されたので、スタックに積まない
            else:
                try:
                    #数値化できれば数値化する
                    i = int(cl[pc[0]])
                    self.Stack.append(i)
                except:
                    #数値化できないので、文字列として積む
                    self.Stack.append(cl[pc[0]])

            pc[0] += 1

    def operator(self, cl, pc, nc):

        #stack の回転関数 上からn個をm回回転させる n>mが前提
        def rot_p(n,m):
            front = self.Stack[:len(self.Stack) - n]
            back = self.Stack[-n:]
            self.Stack = front + back[-m:] + back[:n - m]

        ope = cl[pc[0]]

        #四則演算系
        if ope == "+":
            self.Stack.append(self.Stack.pop() + self.Stack.pop())
        elif ope == "-":
            rot_p(2,1)
            self.Stack.append(self.Stack.pop() - self.Stack.pop())
        elif ope == "*":
            self.Stack.append(self.Stack.pop() * self.Stack.pop())
        elif ope == "/":
            rot_p(2,1)
            self.Stack.append(self.Stack.pop() / self.Stack.pop())

        #比較演算系
        elif ope == "<":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() < self.Stack.pop()))
        elif ope == "<=":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() <= self.Stack.pop()))
        elif ope == ">":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() > self.Stack.pop()))
        elif ope == ">=":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() >= self.Stack.pop()))
        elif ope == "==" or ope == "=":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() == self.Stack.pop()))
        elif ope == "<>" or ope == "!=":
            rot_p(2,1)
            self.Stack.append(int(self.Stack.pop() != self.Stack.pop()))

        #ビット演算系
        elif ope == "|":
            self.Stack.append(int(self.Stack.pop() | self.Stack.pop()))
        elif ope == "&":
            self.Stack.append(int(self.Stack.pop() & self.Stack.pop()))
        elif ope == "^":
            self.Stack.append(int(self.Stack.pop() ^ self.Stack.pop()))
        elif ope == "~":
            self.Stack.append(int(~self.Stack.pop()))


        #論理演算系 めんどくさいのでドモルガンの定理を利用
        elif ope == "or":
            self.Stack.append(int(not self.Stack.pop() and not self.Stack.pop()))
        elif ope == "and":
            self.Stack.append(int(not self.Stack.pop() or not self.Stack.pop()))
        elif ope == "not":
            self.Stack.append(int(not self.Stack.pop))

        #スタック操作系
        elif ope == "dup":
            s = self.Stack.pop()
            self.Stack.append(s)
            self.Stack.append(s)
        elif ope == "load":
            n = self.Stack.pop()
            self.Stack.append(self.Stack[-n])
        elif ope == "drop":
            self.Stack.pop()
        elif ope == "swap":
            rot_p(2,1)
        elif ope == "rot":
            rot_p(3,1)
        elif ope == "over":
            self.Stack.append(self.Stack[-2])
        elif ope == "dump":
            print self.Stack



        #表示系
        elif ope == ".":
            print self.Stack.pop()

        elif ope =="if":
            if self.Stack.pop():
                nc[0] += 1
                pass
            else:
                #elseか、endifまで読み飛ばす
                n = 0
                while(True):
                    pc[0] += 1
                    o = cl[pc[0]]
                    if o == "if":
                        n += 1
                    elif o == "else":
                        if n == 0:
                            nc[0] += 1
                            break
                    elif o == "endif":
                        if n == 0:
                            break
                        else:
                            n -= 1
        elif ope == "else":
            #endif まで読み飛ばす
            n = 0
            while(True):
                pc[0] += 1
                o = cl[pc[0]]
                if o == "if":
                    n += 1
                elif o == "endif":
                    if n == 0:
                        break
                    else:
                        n -= 1
        elif ope == "endif":
            pass

        #手続きの宣言
        elif ope == ":" :   #これdefか何かに変える?
            pc[0] += 1
            name = cl[pc[0]]
            self.FunctionList[name] = []
            while(True):
                pc[0] += 1
                c = cl[pc[0]]
                if c == ";":
                    break
                else:
                    self.FunctionList[name].append(c)
        elif self.FunctionList.has_key(ope):
            self._execute(self.FunctionList[ope],[0],[0])

        #変数の代入と参照
        elif ope == "!":
            name = self.Stack.pop()
            self.VariableList[name] = self.Stack.pop()
        elif ope == "@":
            name = self.Stack.pop()
            self.Stack.append(self.VariableList[name])


        #while文
        elif ope == "while":
            if self.Stack.pop():
                pass
            else:
                #対応するrepeat まで読み飛ばす
                n = 0
                while(True):
                    pc[0] += 1
                    o = cl[pc[0]]
                    if o == "while":
                        n += 1
                    elif o == "repeat":
                        if n == 0:
                            break
                        else:
                            n -= 1
        elif ope == "repeat":
            #whileの一個前まで戻る
            n = 0
            while(True):
                pc[0] -= 1
                o = cl[pc[0]]
                if o == "while":
                    if n == 0:
                        #一個前に戻す
                        pc[0] -= 1
                        break
                    else:
                        n -= 1
                elif o == "repeat":
                        n += 1
        else:
            return False


        return True



f = forth(
'''
1 20 - .                    # 1-20をして表示する
1 10 < .                    # 1<10をして表示する

1 if                        # スタックの一番上を評価する
    here is TRUE . . .      # trueならここが実行される
    0 if
        NOTCOMING .         # こない
    endif
else
    here is FALSE . . .     # falseならばここが実行される
endif

100 n !                     # nに100を代入する
n @ .                       # nを参照して表示する
: hoge n @ 1 - n ! ;        # void hoge(){n = n - 1} を定義する
hoge hoge hoge              # hogeを三回実行する
n @ .                       # nを表示してみる(97が表示される)

                            # 0~9までカウントする
0 n !                       # nに0を代入する
1                           # スタックの一番上が真ならwhileを実行
while
    n @ .                   # nの値を表示する
    n @ 1 + n !             # n=n+1
    n @ 10 <                # n < 10 をpushする
repeat                      # whileに戻る


: square dup * ;            # 二乗する関数を定義する
10 square .

: fac                       # 再帰で階乗を書いてみる。スタックを二個引数に取る
    dump                    # 突入時にメモリダンプしてみる
    dup
    if
        over over *
        over 1 -
        fac
        rot drop drop       # ローカル変数を開放する(?)
        dump
    else
        drop
    endif
;

1 10 fac .                  # 1*10!の意味
''')

f.execute()