User:Iconmaster/iscom.lua

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