mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
Script/checkpoint system first draft
This commit is contained in:
parent
0a835a65d8
commit
4125a4c99b
6 changed files with 116 additions and 8 deletions
|
|
@ -19,6 +19,7 @@ Closure = Runtime(Overloadable) {
|
||||||
-- to allow future define in the function (fn.:var = "foo")
|
-- to allow future define in the function (fn.:var = "foo")
|
||||||
state.scope:push()
|
state.scope:push()
|
||||||
self.scope = state.scope:capture()
|
self.scope = state.scope:capture()
|
||||||
|
state.scope:define(ast.Symbol:new("_calling_environment"), self.scope)
|
||||||
state.scope:pop()
|
state.scope:pop()
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
@ -38,20 +39,33 @@ Closure = Runtime(Overloadable) {
|
||||||
return self.func.parameters:format(state)
|
return self.func.parameters:format(state)
|
||||||
end,
|
end,
|
||||||
call_dispatched = function(self, state, args)
|
call_dispatched = function(self, state, args)
|
||||||
|
local calling_environment = state.scope:capture()
|
||||||
state.scope:push(self.scope)
|
state.scope:push(self.scope)
|
||||||
|
state.scope:set(ast.Identifier:new("_calling_environment"), calling_environment)
|
||||||
local exp = self.func:call_dispatched(state, args)
|
local exp = self.func:call_dispatched(state, args)
|
||||||
state.scope:pop()
|
state.scope:pop()
|
||||||
return exp
|
return exp
|
||||||
end,
|
end,
|
||||||
resume = function(self, state, target)
|
resume = function(self, state, target)
|
||||||
if self.func.parameters.min_arity > 0 then error("can't resume function with parameters") end
|
if self.func.parameters.min_arity > 0 then error("can't resume function with parameters") end
|
||||||
|
local calling_environment = state.scope:capture()
|
||||||
state.scope:push(self.scope)
|
state.scope:push(self.scope)
|
||||||
|
state.scope:set(ast.Identifier:new("_calling_environment"), calling_environment)
|
||||||
resume_manager:push(state, target)
|
resume_manager:push(state, target)
|
||||||
local exp = self.func:call(state, ast.ArgumentTuple:new())
|
local exp = self.func:call(state, ast.ArgumentTuple:new())
|
||||||
resume_manager:pop(state)
|
resume_manager:pop(state)
|
||||||
state.scope:pop()
|
state.scope:pop()
|
||||||
return exp
|
return exp
|
||||||
end,
|
end,
|
||||||
|
get_level = function(self, state, level) -- TODO make generic to all calls? only closures?
|
||||||
|
local env = state.scope:capture()
|
||||||
|
while level > 0 do
|
||||||
|
assert(env:defined(state, ast.Identifier:new("_calling_environment")))
|
||||||
|
env = env:get(state, ast.Identifier:new("_calling_environment"))
|
||||||
|
level = level - 1
|
||||||
|
end
|
||||||
|
return env
|
||||||
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = Closure
|
package.loaded[...] = Closure
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ local ast = require("anselme.ast")
|
||||||
|
|
||||||
local operator_priority = require("anselme.common").operator_priority
|
local operator_priority = require("anselme.common").operator_priority
|
||||||
|
|
||||||
local Branched, ArgumentTuple, Overload, Overloadable, Table, Call, ParameterTuple, Function, FunctionParameter, Identifier
|
local Branched, ArgumentTuple, Overload, Overloadable, Table
|
||||||
|
|
||||||
local VariableMetadata = ast.abstract.Runtime {
|
local VariableMetadata = ast.abstract.Runtime {
|
||||||
type = "variable metadata",
|
type = "variable metadata",
|
||||||
|
|
@ -180,6 +180,7 @@ local Environment = ast.abstract.Runtime {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- returns a list {[symbol]=val,...} of all exported variables (evaluated) in the current strict layer
|
-- returns a list {[symbol]=val,...} of all exported variables (evaluated) in the current strict layer
|
||||||
|
-- TODO currently unused
|
||||||
list_exported = function(self, state)
|
list_exported = function(self, state)
|
||||||
assert(self.export, "not an export scope layer")
|
assert(self.export, "not an export scope layer")
|
||||||
local r = {}
|
local r = {}
|
||||||
|
|
@ -219,6 +220,6 @@ local Environment = ast.abstract.Runtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = Environment
|
package.loaded[...] = Environment
|
||||||
Branched, ArgumentTuple, Overload, Overloadable, Table, Call, ParameterTuple, Function, FunctionParameter, Identifier = ast.Branched, ast.ArgumentTuple, ast.Overload, ast.abstract.Overloadable, ast.Table, ast.Call, ast.ParameterTuple, ast.Function, ast.FunctionParameter, ast.Identifier
|
Branched, ArgumentTuple, Overload, Overloadable, Table = ast.Branched, ast.ArgumentTuple, ast.Overload, ast.abstract.Overloadable, ast.Table
|
||||||
|
|
||||||
return Environment
|
return Environment
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,20 @@ return {
|
||||||
"_==_", "(a, b)",
|
"_==_", "(a, b)",
|
||||||
function(state, a, b)
|
function(state, a, b)
|
||||||
if a.mutable ~= b.mutable then return Boolean:new(false)
|
if a.mutable ~= b.mutable then return Boolean:new(false)
|
||||||
elseif a.mutable then
|
|
||||||
return Boolean:new(a == b)
|
|
||||||
else
|
else
|
||||||
return Boolean:new(a:hash() == b:hash())
|
return Boolean:new(a:hash() == b:hash())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"_!=_", "(a, b)",
|
||||||
|
function(state, a, b)
|
||||||
|
if a.mutable ~= b.mutable then return Boolean:new(true)
|
||||||
|
else
|
||||||
|
return Boolean:new(a:hash() ~= b:hash())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"!_", "(a)",
|
"!_", "(a)",
|
||||||
function(state, a)
|
function(state, a)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
local ast = require("anselme.ast")
|
local ast = require("anselme.ast")
|
||||||
local ArgumentTuple = ast.ArgumentTuple
|
local ArgumentTuple, Boolean = ast.ArgumentTuple, ast.Boolean
|
||||||
|
|
||||||
local resume_manager = require("anselme.state.resume_manager")
|
local resume_manager = require("anselme.state.resume_manager")
|
||||||
|
|
||||||
|
|
@ -18,5 +18,33 @@ return {
|
||||||
function(state, anchor, quote)
|
function(state, anchor, quote)
|
||||||
return quote:call(state, ArgumentTuple:new())
|
return quote:call(state, ArgumentTuple:new())
|
||||||
end
|
end
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"resume", "(function::closure, anchor::anchor)",
|
||||||
|
function(state, func, anchor)
|
||||||
|
return func:resume(state, anchor)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resuming", "()",
|
||||||
|
function(state)
|
||||||
|
return Boolean:new(resume_manager:resuming(state))
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resuming", "(level::number)",
|
||||||
|
function(state, level)
|
||||||
|
local env = ast.Closure:get_level(state, level:to_lua(state))
|
||||||
|
state.scope:push(env)
|
||||||
|
local r = Boolean:new(resume_manager:resuming(state))
|
||||||
|
state.scope:pop()
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resume target", "()",
|
||||||
|
function(state)
|
||||||
|
return resume_manager:get(state)
|
||||||
|
end
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@ return function(main_state)
|
||||||
"type_check"
|
"type_check"
|
||||||
})
|
})
|
||||||
|
|
||||||
local boot = parser(require("anselme.stdlib.boot_script"), "boot.ans")
|
parser(require("anselme.stdlib.boot_script"), "boot.ans"):eval(main_state)
|
||||||
boot:eval(main_state)
|
|
||||||
|
|
||||||
load(main_state, {
|
load(main_state, {
|
||||||
"number",
|
"number",
|
||||||
|
|
@ -32,4 +31,6 @@ return function(main_state)
|
||||||
"checkpoint",
|
"checkpoint",
|
||||||
"persist",
|
"persist",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
parser(require("anselme.stdlib.script_script"), "script.ans"):eval(main_state)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
57
anselme/stdlib/script_script.lua
Normal file
57
anselme/stdlib/script_script.lua
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
return [[
|
||||||
|
:@script = $(name, fn)
|
||||||
|
:¤t checkpoint => "{name}.checkpoint"!persist(false)
|
||||||
|
:&reached => "{name}.reached"!persist(*{})
|
||||||
|
:resumed from = ()
|
||||||
|
|
||||||
|
fn.:check = $(anchor::anchor)
|
||||||
|
reached(anchor) = (reached(anchor) | 0) + 1
|
||||||
|
fn.:checkpoint = $(anchor::anchor)
|
||||||
|
current checkpoint = anchor
|
||||||
|
resumed from != anchor ~
|
||||||
|
reached(anchor) = (reached(anchor) | 0) + 1
|
||||||
|
fn.:checkpoint = $(anchor::anchor, on resume::function)
|
||||||
|
current checkpoint = anchor
|
||||||
|
resumed from == anchor | resuming(1) ~
|
||||||
|
on resume!
|
||||||
|
~
|
||||||
|
reached(anchor) = (reached(anchor) | 0) + 1
|
||||||
|
|
||||||
|
:f = $
|
||||||
|
current checkpoint ~
|
||||||
|
resumed from = current checkpoint
|
||||||
|
fn!resume(current checkpoint)
|
||||||
|
~
|
||||||
|
resumed from = ()
|
||||||
|
fn!
|
||||||
|
run += 1
|
||||||
|
f.:&run => "{name}.run"!persist(0)
|
||||||
|
|
||||||
|
f!type("script")
|
||||||
|
|
||||||
|
:is script = is("script")
|
||||||
|
|
||||||
|
:@$_!(s::is script)
|
||||||
|
s!value!
|
||||||
|
|
||||||
|
:@$_._(s::is script, k::string)
|
||||||
|
:v = s!value
|
||||||
|
v.fn!has upvalue(k) ~
|
||||||
|
@v.fn.(k)
|
||||||
|
~
|
||||||
|
@v.(k)
|
||||||
|
|
||||||
|
:@$_._(s::is script, k::string) = val
|
||||||
|
:v = s!value
|
||||||
|
v.fn!has upvalue(k) ~
|
||||||
|
v.fn.(k) = val
|
||||||
|
~
|
||||||
|
v.(k) = val
|
||||||
|
|
||||||
|
:@$from(s::is script, a::anchor)
|
||||||
|
s.current checkpoint = a
|
||||||
|
@s!
|
||||||
|
:@$from(s::is script)
|
||||||
|
s.current checkpoint = ()
|
||||||
|
@s!
|
||||||
|
]]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue