forked from sogilis/Forth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
forth
executable file
·118 lines (92 loc) · 2.54 KB
/
forth
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
#!/usr/bin/env lua
-------------------------------------------------------------------
-- Ceci est une implémentation basique du langage Forth en Lua --
-------------------------------------------------------------------
--
-- Données
---------------
local stack = {} -- pile d'exécution
local symbol_table = {} -- table des symboles (fonctions)
--
-- Procédures
------------------
local push, pop, dispatch, main_loop
-- pop() --> dépile la dernière valeur de la pile `stack`
-- push(a, ...) --> empile toutes les valeurs passées en paramètre dans `stack`
-- dispatch(...) --> procédure appelée pour dispatcher les symboles lus
-- main_loop() --> exécute la boucle principale
--
-- Implémentation des fonctions de base de Forth
-----------------------------------------------------
symbol_table['+'] = function(...)
local a, b = pop(), pop()
push(a + b)
end -- add
symbol_table['.'] = function(...)
io.write(tostring(pop()), " ")
end -- pop
--
-- Dispatch
----------------
-- dispatcher takes:
-- disp: the current dispatcher function
-- word: a string to process
-- it can return a function value which will replace the actual dispatcher.
function dispatch(disp, word)
-- print(word)
if symbol_table[word] then -- Si `word` est dans la table des symboles,
-- appeler la fonction correspondante
return symbol_table[word](disp)
elseif word:find("^%d+$") then -- Si c'est un nombre, empiler `word`
push(tonumber(word))
else -- Sinon, erreur
error(word.." invalid symbol")
end
end -- dispatch
--
-- Boucle principale
-------------------------
function main_loop()
local input = true
local disp = dispatch
while input do
io.write("> ")
io.flush()
input = io.read()
if input then
local res, msg = pcall(function()
for word in string.gmatch(input, "%s*(%S+)%s*") do
local res = disp(disp, word)
if res ~= nil then
disp = res
end
end
end)
if res then
io.write("ok\n")
else
io.write(msg, "\n")
end
end
end
end -- main_loop
--
-- Fonctions concernant la pile
------------------------------------
function pop(n)
return table.remove(stack)
end -- pop
function push(...)
for i = 1, select("#", ...) do
stack[#stack+1] = select(i, ...)
end
end -- push
--
-- Exécution
-----------------
-- Compatibilité Lua 5.1 / 5.2
if unpack and not table.unpack then
table.unpack = unpack
end
-- Exécution
main_loop()