-- 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()