Ero
Jump to navigation
Jump to search
- This article is not detailed enough and needs to be expanded. Please help us by adding some more information.
- This is still a work in progress. It may be changed in the future.
| Designed by | User:InLuaIKnow |
|---|---|
| Appeared in | 2026 |
| Computational class | Unknown |
| Major implementations | Lua |
is a esolang written in Lua.
:|: statement terminator
:.(opcode) makes a statement
|:: signals that arguments are after this
>> argument seperator.
Example(s):
:.1|::1>>"Hello,world!":|: :.8|::1>>1:|:
:.1|::1>>1:|::.1|::2>>1:|::.2|::1>>2>>3:|::.8|::1>>3:|:
Current intrepeter
--|:: intrepeter
local reg={}
local pc = 1
local functions = {[1]=print,[2]=error,[3]=io.read}
local opc = {
[1]=function(a,b)--sets a reg
reg[a]=b
end;
[2]=function(a,b,c)--add
reg[c]=(reg[a]+reg[b])
end;
[3]=function(a,b,c)--sub
reg[c]=(reg[a]-reg[b])
end;
[4]=function(a,b,c)--mul
reg[c]=(reg[a]*reg[b])
end;
[5]=function(a,b,c)--div
reg[c]=(reg[a]/reg[b])
end;
[6]=function(a,b,c)--pow
reg[c]=(reg[a]^reg[b])
end;
[7]=function(a,b,c)--mod
reg[c]=(reg[a]%reg[b])
end;
[8]=function(r,a,...)--call
local args = {}
for i,v in ipairs({...}) do
args[i]=reg[v]
end
reg[r]=functions[a](table.unpack(args))
end;
[9]=function(n)--jump
pc=pc+n-1
end;
[10]=function(r,n)--jump if true
if reg[r] == true then
pc=pc+n-1
end
end;
[11]=function(o,a,b,r)--compare
if o==">" then
reg[r]=reg[a]>reg[b]
elseif o=="<" then
reg[r]=reg[a]<reg[b]
elseif o=="==" then
reg[r]=reg[a]==reg[b]
elseif o=="!=" then
reg[r]=reg[a]~=reg[b]
else
error("invalid op")
end
end;
[12]=function(a,r)--not
reg[r]=(not reg[a])
end;
[13]=function(a,b,r)--or
reg[r]=reg[a] or reg[b]
end;
[14]=function(a,b,r)--and
reg[r]=reg[a] and reg[b]
end;
}
function compile(source)
local inst = {}
for stmt in source:gmatch("(.-):|:") do
local opco = stmt:match("^%:.([0-9]+)|::")
if opco then
opco = tonumber(opco)
-- print(opco)
local argst = stmt:match("|::(.*)")
local args = {}
-- print(argst)
if argst then
local argcount = 0
for argf in argst:gmatch("([^>>]+)") do
-- print(argf)
argcount=argcount+1
local fl = argf:sub(1,1)..argf:sub(-1)
local num = tonumber(argf)
if num then
args[#args+1] = math.floor(num)
elseif fl=="" or fl=='""' then
args[#args+1] = argf:sub(2,-2)
elseif argf=="true" then args[#args+1] = true elseif argf=="false" then args[#args+1] = false
else error("invalid argument #"..argcount) end
end
end
inst[#inst+1]={opcode=opco, args=args}
end
end
return inst
end
function intrepet(p)
pc = 1
while pc <= #p do
local instr = p[pc]
local op = opc[instr.opcode]
if op then
op(table.unpack(instr.args))
end
pc = pc + 1
end
end
if arg[1] == nil then
print("|:: (Ero), the esoteric language")
print("!:quit to exit.")
while true do
io.write(">")
local inp=io.read()
if inp=="!:quit" then return end
local ok,res =pcall(compile,inp)
--print(ok,table.concat(res," "))
if not ok then io.stderr:write("compilation error: "..res.."\n") else
local o2, re2 = pcall(intrepet,res)
if not o2 then io.stderr:write("runtime error: "..re2.."\n") end
end
end
elseif arg[2]=="-c" then -- compile to fully binary file
local infile = arg[1]
local outfile = arg[3] or (infile .. ".bin")
local f = io.open(infile, "r")
if not f then
io.stderr:write("Cannot open input file: "..infile.."\n")
return
end
local src = f:read("a")
f:close()
local ok, inst = pcall(compile, src)
if not ok then
io.stderr:write("compilation error: "..inst.."\n")
return
end
local f2 = io.open(outfile, "wb")
if not f2 then
io.stderr:write("can not open output file: "..outfile.."\n")
return
end
local function write_number(n)
f2:write(string.pack(">d", n)) -- big-endian double
end
local function write_boolean(b)
f2:write(string.char(b and 1 or 0))
end
local function write_string(s)
local len = #s
f2:write(string.pack(">H", len)) -- 2 bytes length
f2:write(s)
end
for _, instr in ipairs(inst) do
f2:write(string.char(instr.opcode or 0))
local args = instr.args or {}
f2:write(string.char(#args))
for _, a in ipairs(args) do
if type(a) == "number" then
f2:write(string.char(0)) -- type marker: 0=number
write_number(math.floor(a))
elseif type(a) == "boolean" then
f2:write(string.char(1)) -- type marker: 1=boolean
write_boolean(a)
elseif type(a) == "string" then
f2:write(string.char(2)) -- type marker: 2=string
write_string(a)
else
error("unsupported arg type: "..type(a))
end
end
end
f2:close()
print("compiled: "..outfile)
elseif arg[2]=="-oc" then -- open fully binary compiled file
local infile = arg[1]
local f = io.open(infile, "rb")
if not f then
io.stderr:write("can not open compiled file: "..infile.."\n")
return
end
local data = f:read("a")
f:close()
local pos = 1
local insts = {}
local function read_number()
local n
n, pos = string.unpack(">d", data, pos)
return n
end
local function read_boolean()
local b = data:byte(pos)
pos = pos + 1
return b ~= 0
end
local function read_string()
local len
len, pos = string.unpack(">H", data, pos)
local s = data:sub(pos, pos+len-1)
pos = pos + len
return s
end
while pos <= #data do
local opcode = data:byte(pos)
pos = pos + 1
local argcount = data:byte(pos)
pos = pos + 1
local args = {}
for i=1,argcount do
local typ = data:byte(pos)
pos = pos + 1
if typ == 0 then
args[i] = read_number()
elseif typ == 1 then
args[i] = read_boolean()
elseif typ == 2 then
args[i] = read_string()
else
error("unknown arg type in")
end
end
insts[#insts+1] = {opcode=opcode, args=args}
end
intrepet(insts)
else
local h=io.open(arg[1],"r")
local c=h:read("a")h:close()
local ok,res =pcall(compile,c)
if not ok then io.stderr:write("compilation error:",res) else intrepet(res) end
end
