moonlets.lua
· 3.9 KiB · Lua
Brut
Playground
-- slow, inefficient, and partial implemention of a fraglets
-- interpreter. Basically enough to run a factorial program
-- Also, I changed the syntax.
local fraglets = {}
local function print_pool()
print("--- fraglets ---")
for i, fraglet in ipairs(fraglets) do
print(table.concat(fraglet, " "))
end
print()
end
local program = [[
nul factorial(n): [in $n] --> [out $n!].
res 1.
matchp in split t1 2 * match t1 lt f1 c1.
matchp f1 split finish * nul.
matchp c1 exch c2 nul.
matchp c2 exch c3 *.
matchp c3 split continue.
matchp finish match res out.
matchp continue split match t2 match res mult res * split match t2 sum in -1 * copy t2.
nul test.
in 5.
]]
local fraglet, symbol = {}, {}
local function push_symbol()
if #symbol ~= 0 then
table.insert(fraglet, table.concat(symbol))
symbol = {}
end
end
local function push_fraglet()
push_symbol()
if #fraglet ~= 0 then
table.insert(fraglets, fraglet)
fraglet = {}
end
end
for char in program:gmatch(".") do
if char:find("%s") then push_symbol()
elseif char == "." then push_fraglet()
else table.insert(symbol, char)
end
end
push_fraglet()
local ops = {}
local function merge(t1, t2, start)
for i = start, #t2 do
table.insert(t1, t2[i])
end
return t1
end
local function swap_and_delete(index, pool)
pool[index] = pool[#pool]
pool[#pool] = nil
end
function ops.nul(fraglet, index, pool)
swap_and_delete(index, pool)
return true
end
function ops.matchp(fraglet, index, pool)
for i, other_fraglet in ipairs(pool) do
if i ~= index and fraglet[2] == other_fraglet[1] then
pool[i] = merge(merge({}, fraglet, 3), other_fraglet, 2)
return true, index + 1
end
end
return false, index
end
function ops.split(fraglet, index, pool)
local left, right = {}, {}
local split = 0
for i, v in ipairs(fraglet) do
split = i
if v == "*" then break end
if i ~= 1 then
table.insert(left, v)
end
end
if #left == 0 then return false end
for i = split + 1, #fraglet do
table.insert(right, fraglet[i])
end
pool[index] = left
if #right > 0 then
table.insert(pool, right)
end
return true
end
function ops.match(fraglet, index, pool)
if ops.matchp(fraglet, index, pool) then
swap_and_delete(index, pool)
return true
end
return false
end
function ops.lt(fraglet, index, pool)
if tonumber(fraglet[4]) < tonumber(fraglet[5]) then
pool[index] = merge({fraglet[2]}, fraglet, 4)
else
pool[index] = merge({fraglet[3]}, fraglet, 4)
end
return true
end
function ops.exch(fraglet, index, pool)
pool[index][3], pool[index][4] = pool[index][4], pool[index][3]
table.remove(pool[index], 1)
return true
end
function ops.copy(fraglet, index, pool)
table.remove(fraglet, 1)
local copy = {}
for _, v in ipairs(fraglet) do
table.insert(copy, v)
end
table.insert(pool, copy)
return true
end
function ops.mult(fraglet, index, pool)
local tag, x, y = fraglet[2], tonumber(fraglet[3]), tonumber(fraglet[4])
if x and y then
pool[index] = {tag, tostring(x * y)}
return true
end
return false
end
function ops.sum(fraglet, index, pool)
local tag, x, y = fraglet[2], tonumber(fraglet[3]), tonumber(fraglet[4])
if x and y then
pool[index] = {tag, tostring(x + y)}
return true
end
return false
end
local i, reaction = 1, true
print("=== initial ===")
print_pool()
while reaction do
i, reaction = 1, false
while i <= #fraglets do
local op = fraglets[i][1]
if ops[op] then
if ops[op](fraglets[i], i, fraglets) then
print_pool()
reaction = true
end
end
i = i + 1
end
end
print("=== final ===")
print_pool()
1 | -- slow, inefficient, and partial implemention of a fraglets |
2 | -- interpreter. Basically enough to run a factorial program |
3 | -- Also, I changed the syntax. |
4 | local fraglets = {} |
5 | local function print_pool() |
6 | print("--- fraglets ---") |
7 | for i, fraglet in ipairs(fraglets) do |
8 | print(table.concat(fraglet, " ")) |
9 | end |
10 | print() |
11 | end |
12 | |
13 | local program = [[ |
14 | nul factorial(n): [in $n] --> [out $n!]. |
15 | |
16 | res 1. |
17 | matchp in split t1 2 * match t1 lt f1 c1. |
18 | matchp f1 split finish * nul. |
19 | matchp c1 exch c2 nul. |
20 | matchp c2 exch c3 *. |
21 | matchp c3 split continue. |
22 | |
23 | matchp finish match res out. |
24 | matchp continue split match t2 match res mult res * split match t2 sum in -1 * copy t2. |
25 | |
26 | nul test. |
27 | in 5. |
28 | ]] |
29 | |
30 | local fraglet, symbol = {}, {} |
31 | |
32 | local function push_symbol() |
33 | if #symbol ~= 0 then |
34 | table.insert(fraglet, table.concat(symbol)) |
35 | symbol = {} |
36 | end |
37 | end |
38 | |
39 | local function push_fraglet() |
40 | push_symbol() |
41 | if #fraglet ~= 0 then |
42 | table.insert(fraglets, fraglet) |
43 | fraglet = {} |
44 | end |
45 | end |
46 | |
47 | for char in program:gmatch(".") do |
48 | if char:find("%s") then push_symbol() |
49 | elseif char == "." then push_fraglet() |
50 | else table.insert(symbol, char) |
51 | end |
52 | end |
53 | push_fraglet() |
54 | |
55 | local ops = {} |
56 | |
57 | local function merge(t1, t2, start) |
58 | for i = start, #t2 do |
59 | table.insert(t1, t2[i]) |
60 | end |
61 | return t1 |
62 | end |
63 | |
64 | local function swap_and_delete(index, pool) |
65 | pool[index] = pool[#pool] |
66 | pool[#pool] = nil |
67 | end |
68 | |
69 | function ops.nul(fraglet, index, pool) |
70 | swap_and_delete(index, pool) |
71 | return true |
72 | end |
73 | |
74 | function ops.matchp(fraglet, index, pool) |
75 | for i, other_fraglet in ipairs(pool) do |
76 | if i ~= index and fraglet[2] == other_fraglet[1] then |
77 | pool[i] = merge(merge({}, fraglet, 3), other_fraglet, 2) |
78 | return true, index + 1 |
79 | end |
80 | end |
81 | return false, index |
82 | end |
83 | |
84 | function ops.split(fraglet, index, pool) |
85 | local left, right = {}, {} |
86 | local split = 0 |
87 | |
88 | for i, v in ipairs(fraglet) do |
89 | split = i |
90 | |
91 | if v == "*" then break end |
92 | if i ~= 1 then |
93 | table.insert(left, v) |
94 | end |
95 | end |
96 | |
97 | if #left == 0 then return false end |
98 | |
99 | for i = split + 1, #fraglet do |
100 | table.insert(right, fraglet[i]) |
101 | end |
102 | |
103 | pool[index] = left |
104 | if #right > 0 then |
105 | table.insert(pool, right) |
106 | end |
107 | |
108 | return true |
109 | end |
110 | |
111 | function ops.match(fraglet, index, pool) |
112 | if ops.matchp(fraglet, index, pool) then |
113 | swap_and_delete(index, pool) |
114 | return true |
115 | end |
116 | return false |
117 | end |
118 | |
119 | function ops.lt(fraglet, index, pool) |
120 | if tonumber(fraglet[4]) < tonumber(fraglet[5]) then |
121 | pool[index] = merge({fraglet[2]}, fraglet, 4) |
122 | else |
123 | pool[index] = merge({fraglet[3]}, fraglet, 4) |
124 | end |
125 | return true |
126 | end |
127 | |
128 | function ops.exch(fraglet, index, pool) |
129 | pool[index][3], pool[index][4] = pool[index][4], pool[index][3] |
130 | table.remove(pool[index], 1) |
131 | return true |
132 | end |
133 | |
134 | function ops.copy(fraglet, index, pool) |
135 | table.remove(fraglet, 1) |
136 | local copy = {} |
137 | for _, v in ipairs(fraglet) do |
138 | table.insert(copy, v) |
139 | end |
140 | table.insert(pool, copy) |
141 | return true |
142 | end |
143 | |
144 | function ops.mult(fraglet, index, pool) |
145 | local tag, x, y = fraglet[2], tonumber(fraglet[3]), tonumber(fraglet[4]) |
146 | if x and y then |
147 | pool[index] = {tag, tostring(x * y)} |
148 | return true |
149 | end |
150 | return false |
151 | end |
152 | |
153 | function ops.sum(fraglet, index, pool) |
154 | local tag, x, y = fraglet[2], tonumber(fraglet[3]), tonumber(fraglet[4]) |
155 | if x and y then |
156 | pool[index] = {tag, tostring(x + y)} |
157 | return true |
158 | end |
159 | return false |
160 | end |
161 | |
162 | local i, reaction = 1, true |
163 | print("=== initial ===") |
164 | print_pool() |
165 | while reaction do |
166 | i, reaction = 1, false |
167 | while i <= #fraglets do |
168 | local op = fraglets[i][1] |
169 | if ops[op] then |
170 | if ops[op](fraglets[i], i, fraglets) then |
171 | print_pool() |
172 | reaction = true |
173 | end |
174 | end |
175 | i = i + 1 |
176 | end |
177 | end |
178 | print("=== final ===") |
179 | print_pool() |