Skip to content

Instantly share code, notes, and snippets.

@Rusketh
Created January 8, 2017 16:53
Show Gist options
  • Save Rusketh/be8532c74566d1f6a41f06b4abc3c106 to your computer and use it in GitHub Desktop.
Save Rusketh/be8532c74566d1f6a41f06b4abc3c106 to your computer and use it in GitHub Desktop.
/*================================================= =============================
E2 Virtual Code, by Rusketh.
WARNING: THIS EXT IS VERY ABUSABLE!
================================================== ============================*/
E2Lib.RegisterExtension("virtualcode", false)
registerType("code", "vc", {},
nil,
nil,
function(retval)
if type(retval) ~= "table" then error("Return value is not a table, but a "..type(retval).."!",0) end
end,
function(v)
return type(v) ~= "table"
end
)
/*================================================= =============================
Compiler
================================================== ============================*/
local function PreProcess(self, buffer, params)
local lines = string.Explode("\n", buffer)
for i,line in ipairs(lines) do
self.readline = i
line = string.TrimRight(line)
line = self:RemoveComments(line)
lines[i] = line
end
return string.Implode("\n", lines)
end
function Compile(self, root, Entity)
self.context = {}
self:InitScope() //Creates global scope!
self.inputs = Entity.inports[3]
self.outputs = Entity.outports[3]
self.prfcounter = 0
self.prfcounters = {}
self.tvars = {}
self.funcs = Entity.funcs
self.dvars = {}
self.funcs_ret = Entity.funcs_ret
for name,v in pairs(self.inputs) do
self:SetGlobalVariableType(name, wire_expression_types[v][1], {nil, {0, 0}})
end
for name,v in pairs(self.outputs) do
self:SetGlobalVariableType(name, wire_expression_types[v][1], {nil, {0, 0}})
end
for name,v in pairs(Entity.persists[3]) do
self:SetGlobalVariableType(name, wire_expression_types[v][1], {nil, {0, 0}})
end
local script = Compiler["Instr" .. string.upper(root[1])](self, root)
return script, self
end
local function VirtualCode(Buffer, self)
local Code = setmetatable({}, PreProcessor)
local Status, Buffer = pcall(PreProcess, Code, Buffer)
if !Status then Code.E = Buffer return Code end
Code.Buffer = Buffer
local Status, Tokens = Tokenizer.Execute(Buffer)
if !Status then Code.E = Tokens return Code end
local Status, Tree = Parser.Execute(Tokens)
if !Status then Code.E = Tree return Code end
setmetatable(Code, Compiler)
local Status, Script, Inst = pcall(Compile, Code, Tree, self.entity)
if !Status then Code.E = Script return Code end
Code.Script = Script
Code.Prf = Inst.prfcounter
return Code
end
/*================================================= =============================
E2 Part
================================================== ============================*/
registerOperator("ass", "vc", "vc", function(self, args)
local op1, op2, scope = args[2], args[3], args[4]
local rv2 = op2[1](self, op2)
self.Scopes[scope][op1] = rv2
self.Scopes[scope].vclk[op1] = true
return rv2
end)
__e2setcost(100) -- Under Estimated!
e2function code code(string code)
local Code = VirtualCode(code, self)
if !Code.E then self.prf = self.prf + (Code.Prf * 2) end
return Code
end
__e2setcost(1)
e2function string code:error()
return this.E or this.SE or ""
end
__e2setcost(5)
e2function number code:execute()
if this.E then return 0 end
this.SE = nil -- No script Error
local Entity = self.entity
local Context = Entity.context
local OldScopes = self:SaveScopes()
self:InitScope() -- Create a new Scope Enviroment
self:PushScope()
local Status, Error = pcall(this.Script[1], Context, this.Script)
self:PopScope()
self:LoadScopes(OldScopes)
if !Status then
if Error == "exit" then
elseif Error == "perf" then
Entity:Error("Expression 2 (" .. Entity.name .. "): tick quota exceeded", "tick quota exceeded")
else
this.SCE = Error
return 0 -- Script Error!
end
end
return 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment