1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 08:39:30 +00:00

Script/checkpoint system first draft

This commit is contained in:
Étienne Fildadut 2023-12-31 00:47:55 +01:00
parent 0a835a65d8
commit 4125a4c99b
6 changed files with 116 additions and 8 deletions

View file

@ -19,6 +19,7 @@ Closure = Runtime(Overloadable) {
-- to allow future define in the function (fn.:var = "foo")
state.scope:push()
self.scope = state.scope:capture()
state.scope:define(ast.Symbol:new("_calling_environment"), self.scope)
state.scope:pop()
end,
@ -38,20 +39,33 @@ Closure = Runtime(Overloadable) {
return self.func.parameters:format(state)
end,
call_dispatched = function(self, state, args)
local calling_environment = state.scope:capture()
state.scope:push(self.scope)
state.scope:set(ast.Identifier:new("_calling_environment"), calling_environment)
local exp = self.func:call_dispatched(state, args)
state.scope:pop()
return exp
end,
resume = function(self, state, target)
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:set(ast.Identifier:new("_calling_environment"), calling_environment)
resume_manager:push(state, target)
local exp = self.func:call(state, ast.ArgumentTuple:new())
resume_manager:pop(state)
state.scope:pop()
return exp
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

View file

@ -2,7 +2,7 @@ local ast = require("anselme.ast")
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 {
type = "variable metadata",
@ -180,6 +180,7 @@ local Environment = ast.abstract.Runtime {
end,
-- returns a list {[symbol]=val,...} of all exported variables (evaluated) in the current strict layer
-- TODO currently unused
list_exported = function(self, state)
assert(self.export, "not an export scope layer")
local r = {}
@ -219,6 +220,6 @@ local Environment = ast.abstract.Runtime {
}
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

View file

@ -6,13 +6,20 @@ return {
"_==_", "(a, b)",
function(state, a, b)
if a.mutable ~= b.mutable then return Boolean:new(false)
elseif a.mutable then
return Boolean:new(a == b)
else
return Boolean:new(a:hash() == b:hash())
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)",
function(state, a)

View file

@ -1,5 +1,5 @@
local ast = require("anselme.ast")
local ArgumentTuple = ast.ArgumentTuple
local ArgumentTuple, Boolean = ast.ArgumentTuple, ast.Boolean
local resume_manager = require("anselme.state.resume_manager")
@ -18,5 +18,33 @@ return {
function(state, anchor, quote)
return quote:call(state, ArgumentTuple:new())
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
},
}

View file

@ -20,8 +20,7 @@ return function(main_state)
"type_check"
})
local boot = parser(require("anselme.stdlib.boot_script"), "boot.ans")
boot:eval(main_state)
parser(require("anselme.stdlib.boot_script"), "boot.ans"):eval(main_state)
load(main_state, {
"number",
@ -32,4 +31,6 @@ return function(main_state)
"checkpoint",
"persist",
})
parser(require("anselme.stdlib.script_script"), "script.ans"):eval(main_state)
end

View file

@ -0,0 +1,57 @@
return [[
:@script = $(name, fn)
:&current 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!
]]