User:Iconmaster/iscom.lua
Jump to navigation
Jump to search
This is an implementation of ISCOM in Lua.
------------------------------------- -- -- ISCOM interpreter -- Made by Joshua Robbins, 3/23/11 -- Interprets ISCOM src. -- ------------------------------------- --Variable setup bit = require("bit") socket = require("socket") mem = {} ip = 1 numclass = "[%[%]0-9a-zA-Z%#%@%$%_]+" opclass = "[%+%-%*%/%%%&%|%!%<%>%=%~%^%{%}]" code = {} const = {} if arg then while #arg ~= 0 do c = table.remove(arg,1) if c == "-f" then src = io.open(table.remove(arg,1),"r"):read("*a") elseif c == "-d" then DEBUG = true else src = c end end end if not src then src = io.read("*l") end function getmem(addr) local nests,num,i nests = #(addr:match("^%[*")) num = addr:match("[0-9a-zA-Z#@$_]+") if const[num] then num = const[num] end if not num then return 0 end num = num:gsub("_","-") if num == "#" then num = ip end if num == "@" then num = fin() end if num == "$" then num = port end num = tonumber(num) if nests == 0 then return num end for i=1,nests do num = mem[num] or 0 end return num end function setmem(addr,val) local nests,num,i nests = #(addr:match("^%[*")) num = addr:match("[0-9#@$_A-Za-z]+") if const[num] then num = const[num] end num = num:gsub("_","-") if num == "#" then ip = val - 1 return end if num == "@" then fout(val) return end if num == "$" then port=val fin=ins[port] fout=outs[port] return end num = tonumber(num) if nests == 0 then mem[num]=val end for i=1,nests do num = mem[num] or 0 end mem[num]=val end -- the operator table. ops = {} ops["+"] = function(n1,n2) return n1 + n2 end ops["-"] = function(n1,n2) return n1 - n2 end ops["*"] = function(n1,n2) return n1 * n2 end ops["/"] = function(n1,n2) return math.floor(n1 / n2) end ops["%"] = function(n1,n2) return n1 % n2 end ops["&"] = function(n1,n2) return bit.band(n1,n2) end ops["|"] = function(n1,n2) return bit.bor(n1,n2) end ops["!"] = function(n1) if n1~=0 then return 0 else return 1 end end ops[":"] = function(n1) return bit.bnot(n1) end ops["^"] = function(n1,n2) return bit.bxor(n1,n2) end ops["="] = function(n1,n2) if n1 == n2 then return 1 else return 0 end end ops["~"] = function(n1,n2) if n1 ~= n2 then return 1 else return 0 end end ops["<"] = function(n1,n2) if n1 < n2 then return 1 else return 0 end end ops[">"] = function(n1,n2) if n1 > n2 then return 1 else return 0 end end ops["{"] = function(n1,n2) return bit.rol(n1,n2) end ops["}"] = function(n1,n2) return bit.ror(n1,n2) end --The Default Port Table. ins = {} outs = {} port = 0 cfn = "" socport = 0 socstate = 0 socaddr = "" sendbuf = "" randmax = 100 lbls = {} ins[0] = function() local ret if bfr then ret = bfr:sub(1,1) bfr = bfr:sub(2) if bfr == "" then bfr = nil end return ret:byte() else bfr = io.read("*l") .. "\n" ret = bfr:sub(1,1) bfr = bfr:sub(2) if bfr == "" then bfr = nil end return ret:byte() end end outs[0]= function(n) io.write(string.char(n)) end ins[1] = function() return io.read("*n") end outs[1]= function(n) io.write(tostring(n)) end ins[2] = function() return #cfn end outs[2]= function(n) if cfn == 10 then cfn = "" else cfn = cfn .. string.char(n) end cfile = io.open(cfn,"r+") end ins[3] = function() if cfn then return cfile:seek() else return 0 end end outs[3]= function(n) if cfn then cfile:seek("set",n) end end ins[4] = function() if not cfile then cfile = io.open(cfn,"w+") end c = cfile:read(1) if c then return c:byte() else return -1 end end outs[4]= function(n) if not cfile then cfile = io.open(cfn,"w+") end cfile:write(string.char(n)) end ins[5] = function() if not cfile then cfile = io.open(cfn,"w+") end c = cfile:read("*n") return c or -1 end outs[5]= function(n) if not cfile then cfile = io.open(cfn,"w+") end cfile:write(tostring(n)) end ins[6] = function() return socstate end outs[6]= function(n) socstate = n if socstate == 0 and soc then soc:close() soc = nil if cli then cli:close() cli = nil end elseif socstate == 1 then soc = socket.connect(socaddr,socport) elseif socstate == 2 then soc = socket.bind(socaddr,socport) cli = soc:accept() end end ins[7] = function() return #socaddr end outs[7]= function(n) if n == 10 then socaddr = "" else socaddr = socaddr .. string.char(n) end end ins[8] = function() return socport end outs[8]= function(n) socport = n end ins[9] = function() if socstate == 1 then --client if not soc then return -1 end c = soc:receive(1) if c then return c:byte() else return -1 end elseif socstate == 2 then --server if not cli then return -1 end c = cli:receive(1) if c then return c:byte() else return -1 end end end outs[9]= function(n) if socstate == 1 then --client if not soc then return end if n == -1 then soc:send(sendbuf) sendbuf = "" return end sendbuf = sendbuf .. string.char(n) elseif socstate == 2 then --server if not cli then return end if n == -1 then cli:send(sendbuf) sendbuf = "" return end sendbuf = sendbuf .. string.char(n) end end ins[10] = function() return socket.gettime() end outs[10]= function(n) socket.sleep(n) end ins[11] = function() return math.random(randmax) end outs[11]= function(n) randmax = n end fin = ins[0] fout=outs[0] --parse src function parse(src) local code,ocode = {},{} local ii,src2,i,v src = src:gsub("\"([^\"]*)\"",function(t) local c,s s = "" for c in t:gmatch(".") do s = s .. " @='" .. c .. " " end return s end,nil) src = src:gsub("%b()","") src = src:gsub("\'(.)",function(m) return tostring(m:byte()) end) ii = 0 src2 = src for i in src2:gmatch("%S+") do if i:match("^;;") then if i:match("=") then src = src:gsub(i,"") a,b = i:match(";;([^=]*)=(.*)") const[a] = b else src = src:gsub(i,"") const[i:sub(3)] = tostring(ii + 1) lbls[ii] = i end else ii = ii + 1 end end ii = nil src2 = nil ocode = {} for i in src:gmatch("%S+") do table.insert(code,i) table.insert(ocode,i) end for i,v in ipairs(code) do if v:sub(1,1)=="?" then code[i] = {"?",v:match("("..numclass..")("..opclass..")("..numclass..")")} else cellto = v:match("^"..numclass) if cellto then v = v:sub(#cellto+2) op = v:match("^"..opclass) if op then code[i] = {"+",cellto,{op,v:match(numclass)}} v = v:sub(2) for op,num in v:gmatch("("..opclass..")("..numclass..")") do table.insert(code[i],{op,num}) end else code[i] = {"=",cellto,v:match(numclass)} end end end end return code,ocode end code,ocode = parse(src) function step() if ip>#code then return false end cmd = code[ip] if cmd[1]=="+" then num = getmem("["..cmd[2]) for i,v in ipairs(cmd) do if type(v)=="table" then num = ops[v[1]](num,getmem(v[2])) end end setmem(cmd[2],num) elseif cmd[1]=="=" then setmem(cmd[2],getmem(cmd[3])) elseif cmd[1]=="?" then if ops[cmd[3]](getmem(cmd[2]),getmem(cmd[4]))==0 then ip = ip + 1 end end ip=ip+1 return true end if DEBUG then tracking = {} function track() io.write("#: " .. ip .. " $: " .. port .. " [#]: " .. (ocode[ip] or "nil") .. " " .. (lbls[ip-1] or "") .. " ") for i,v in pairs(tracking) do io.write(i .. ": " .. getmem(v) .. " ") end io.write("\n") end while true do io.write(">>") dc = io.read("*l") dcmd = {} for s in dc:gmatch("%S+") do table.insert(dcmd,s) end if #dcmd == 0 then if not step() then print("program done.") else if verbose then track() end end elseif ops[dcmd[1]] then print(ops[dcmd[1]](getmem(dcmd[2]),getmem(dcmd[3]))) elseif getmem(dcmd[1]) and dcmd[2] and getmem(dcmd[2]) then for i=getmem(dcmd[1]),getmem(dcmd[2]) do io.write((mem[i] or 0) .. " ") end io.write("\n") elseif getmem(dcmd[1]) then print(mem[getmem(dcmd[1])] or 0) elseif dcmd[1] == "r" then track() elseif dcmd[1] == "j" then ip = getmem(dcmd[2]) elseif dcmd[1] == "p" then port = getmem(dcmd[2]) fin = ins[port] fout = outs[port] elseif dcmd[1] == "s" then setmem(dcmd[2],getmem(dcmd[3])) elseif dcmd[1] == "l" then if dcmd[2] and dcmd[3] then for i=getmem(dcmd[2]),getmem(dcmd[3]) do print(i .. ": " .. ocode[i] .. " " .. (lbls[i-1] or "")) end elseif dcmd[2] then print(getmem(dcmd[2]) .. ": " .. ocode[getmem(dcmd[2])] .. " " .. (lbls[getmem(dcmd[2])-1] or "")) else for i=1,#code do print(i .. ": " .. ocode[i] .. " " .. (lbls[i-1] or "")) end end elseif dcmd[1] == "c" then if dcmd[2] and dcmd[3] then const[dcmd[2]] = dcmd[3] elseif dcmd[2] then print(const[dcmd[2]]) else for i,v in pairs(const) do print(i.."="..v) end end elseif dcmd[1] == "g" then if dcmd[2] == nil then dcmd[2] = #code else dcmd[2] = getmem(dcmd[2]) end while ip <= dcmd[2] do if not step() then print("program done.") break else if verbose then track() end end end print("Finished executing segment.") elseif dcmd[1] == "w" then ncode,nocode = parse(table.concat(dcmd," ",2)) t = {} for i,v in ipairs(code) do table.insert(t,v) end for i,v in ipairs(ncode) do table.insert(t,v) end code = t t = {} for i,v in ipairs(ocode) do table.insert(t,v) end for i,v in ipairs(nocode) do table.insert(t,v) end ocode = t elseif dcmd[1] == "i" then dcmd[2] = getmem(dcmd[2]) ncode,nocode = parse(table.concat(dcmd," ",3)) t = {} for i,v in ipairs(code) do table.insert(t,v) end for i,v in ipairs(ncode) do table.insert(t,dcmd[2],v) end code = t t = {} for i,v in ipairs(ocode) do table.insert(t,v) end for i,v in ipairs(nocode) do table.insert(t,dcmd[2],v) end ocode = t elseif dcmd[1] == "d" then for i=1,getmem(dcmd[3]) do table.remove(code,getmem(dcmd[2])) table.remove(ocode,getmem(dcmd[2])) end elseif dcmd[1] == "q" then os.exit() elseif dcmd[1] == "b" then mem = {} ip = 1 port = 0 fin = ins[0] fout=outs[0] cfn = "" socport = 0 socstate = 0 socaddr = "" sendbuf = "" randmax = 100 elseif dcmd[1] == "v" then verbose = not verbose elseif dcmd[1] == "t" then if dcmd[2] and dcmd[3] then tracking[dcmd[2]] = dcmd[3] elseif dcmd[2] then tracking[dcmd[2]] = nil else tracking = {} end end end else while step() do end end