mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
LuaFunction cleanup: replace by LuaCall
This commit is contained in:
parent
85d17e9519
commit
51ad18c5a4
22 changed files with 192 additions and 162 deletions
|
|
@ -1,30 +1,20 @@
|
||||||
-- note: functions only appear in non-evaluated nodes! once evaluated, they always become closures
|
-- note: functions only appear in non-evaluated nodes! once evaluated, they always become closures
|
||||||
|
|
||||||
local ast = require("anselme.ast")
|
local ast = require("anselme.ast")
|
||||||
local Overloadable = ast.abstract.Overloadable
|
local ReturnBoundary, Environment, Identifier
|
||||||
local ReturnBoundary, Environment, Identifier, Symbol
|
|
||||||
|
|
||||||
local operator_priority = require("anselme.common").operator_priority
|
local operator_priority = require("anselme.common").operator_priority
|
||||||
|
|
||||||
local resume_manager, calling_environment_manager
|
local resume_manager, calling_environment_manager
|
||||||
|
|
||||||
local function list_cache_upvalues(v, state, list, scope)
|
|
||||||
if Identifier:is(v) then
|
|
||||||
list[v.name] = scope:precache(state, v)
|
|
||||||
elseif Symbol:is(v) then
|
|
||||||
list[v.string] = scope:precache(state, v:to_identifier())
|
|
||||||
end
|
|
||||||
v:traverse(list_cache_upvalues, state, list, scope)
|
|
||||||
end
|
|
||||||
|
|
||||||
local Function
|
local Function
|
||||||
Function = Overloadable {
|
Function = ast.abstract.Overloadable {
|
||||||
type = "function",
|
type = "function",
|
||||||
|
|
||||||
parameters = nil, -- ParameterTuple
|
parameters = nil, -- ParameterTuple
|
||||||
expression = nil, -- function content
|
expression = nil, -- function content
|
||||||
scope = nil, -- Environment; captured scope for closure (evaluated functions); not set when not evaluated
|
scope = nil, -- Environment; captured scope for closure (evaluated functions); not set when not evaluated
|
||||||
upvalues = nil, -- {[name]=variable metadata}; not set when not evaluated. Contain _at least_ all the upvalues explicitely defined in the function code.
|
upvalues = nil, -- {variable metadata, ...}; not set when not evaluated. Contain _at least_ all the upvalues explicitely defined in the function code.
|
||||||
|
|
||||||
init = function(self, parameters, expression, scope, upvalues)
|
init = function(self, parameters, expression, scope, upvalues)
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
@ -64,10 +54,15 @@ Function = Overloadable {
|
||||||
state.scope:pop()
|
state.scope:pop()
|
||||||
|
|
||||||
-- list & cache upvalues so they aren't affected by future redefinition in a parent scope
|
-- list & cache upvalues so they aren't affected by future redefinition in a parent scope
|
||||||
local upvalues = {}
|
local used_identifiers = {}
|
||||||
self.expression:traverse(list_cache_upvalues, state, upvalues, scope)
|
self.parameters:list_used_identifiers(used_identifiers)
|
||||||
|
self.expression:list_used_identifiers(used_identifiers)
|
||||||
if scope:defined(state, Identifier:new("_")) then
|
if scope:defined(state, Identifier:new("_")) then
|
||||||
scope:get(state, Identifier:new("_")):traverse(list_cache_upvalues, state, upvalues, scope)
|
scope:get(state, Identifier:new("_")):list_used_identifiers(used_identifiers)
|
||||||
|
end
|
||||||
|
local upvalues = {}
|
||||||
|
for _, identifier in ipairs(used_identifiers) do
|
||||||
|
table.insert(upvalues, scope:precache(state, identifier))
|
||||||
end
|
end
|
||||||
|
|
||||||
return Function:new(self.parameters:eval(state), self.expression, scope, upvalues)
|
return Function:new(self.parameters:eval(state), self.expression, scope, upvalues)
|
||||||
|
|
@ -83,7 +78,7 @@ Function = Overloadable {
|
||||||
return self.parameters:hash()
|
return self.parameters:hash()
|
||||||
end,
|
end,
|
||||||
call_dispatched = function(self, state, args)
|
call_dispatched = function(self, state, args)
|
||||||
assert(self.scope, "can't call unevaluated function")
|
assert(self._evaluated, "can't call unevaluated function")
|
||||||
|
|
||||||
-- push captured closure scope
|
-- push captured closure scope
|
||||||
local calling_environment = state.scope:capture()
|
local calling_environment = state.scope:capture()
|
||||||
|
|
@ -102,7 +97,7 @@ Function = Overloadable {
|
||||||
end,
|
end,
|
||||||
resume = function(self, state, target)
|
resume = function(self, state, target)
|
||||||
if self.parameters.min_arity > 0 then error("can't resume function with parameters") end
|
if self.parameters.min_arity > 0 then error("can't resume function with parameters") end
|
||||||
assert(self.scope, "can't resume unevaluated function")
|
assert(self._evaluated, "can't resume unevaluated function")
|
||||||
|
|
||||||
-- push captured closure scope
|
-- push captured closure scope
|
||||||
local calling_environment = state.scope:capture()
|
local calling_environment = state.scope:capture()
|
||||||
|
|
@ -126,28 +121,45 @@ Function = Overloadable {
|
||||||
-- Only the upvalues that explicitely appear in the function body and variables directly defined in the function scope will be saved, so we don't have to keep a full copy of the whole environment.
|
-- Only the upvalues that explicitely appear in the function body and variables directly defined in the function scope will be saved, so we don't have to keep a full copy of the whole environment.
|
||||||
_serialize = function(self)
|
_serialize = function(self)
|
||||||
local state = require("anselme.serializer_state")
|
local state = require("anselme.serializer_state")
|
||||||
return { parameters = self.parameters, expression = self.expression, upvalues = self.upvalues, scope = self.scope.variables:to_struct(state) }
|
return self.parameters, self.expression, self.scope.variables:to_struct(state), self.upvalues
|
||||||
end,
|
end,
|
||||||
_deserialize = function(self)
|
_deserialize = function(parameters, expression, variables, upvalues)
|
||||||
local state = require("anselme.serializer_state")
|
local r = Function:new(parameters, expression):set_source("saved")
|
||||||
local scope
|
r._deserialize_data = { variables = variables, upvalues = upvalues }
|
||||||
if self.upvalues then
|
return r
|
||||||
-- rebuild scope: exported + normal layer so any upvalue that happen to be exported stay there
|
end,
|
||||||
-- (and link again to current scope to allow internal vars that are not serialized to still work, like _translations)
|
-- we need variables to be fully deserialized before rebuild the function scope
|
||||||
scope = Environment:new(state, Environment:new(state, state.scope:capture(), nil, true))
|
_post_deserialize = function(self, state, cache)
|
||||||
for _, var in pairs(self.upvalues) do
|
if self._deserialize_data then
|
||||||
scope:define(state, var:get_symbol(), var:get(state))
|
local upvalues, variables = self._deserialize_data.upvalues, self._deserialize_data.variables
|
||||||
|
self._deserialize_data = nil
|
||||||
|
-- rebuild upvalues: exported + normal layer so any upvalue that happen to be exported stay there
|
||||||
|
-- (and link again to global scope to allow internal vars that are not serialized to still work, like _translations)
|
||||||
|
state.scope:push_global()
|
||||||
|
state.scope:push_export()
|
||||||
|
state.scope:push()
|
||||||
|
self.upvalues = {}
|
||||||
|
for _, var in ipairs(upvalues) do
|
||||||
|
state.scope:define(var:get_symbol(), var:get(state))
|
||||||
|
table.insert(self.upvalues, state.scope.current:precache(state, var:get_symbol():to_identifier()))
|
||||||
end
|
end
|
||||||
for _, var in self.scope:iter() do
|
-- rebuild function variables
|
||||||
scope:define(state, var:get_symbol(), var:get(state))
|
state.scope:push()
|
||||||
|
self.scope = state.scope:capture()
|
||||||
|
for _, var in variables:iter() do
|
||||||
|
self.scope:define(state, var:get_symbol(), var:get(state))
|
||||||
end
|
end
|
||||||
|
state.scope:pop()
|
||||||
|
state.scope:pop()
|
||||||
|
state.scope:pop()
|
||||||
|
state.scope:pop()
|
||||||
|
self._evaluated = true
|
||||||
end
|
end
|
||||||
return Function:new(self.parameters, self.expression, Environment:new(state, scope), self.upvalues):set_source("saved")
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = Function
|
package.loaded[...] = Function
|
||||||
ReturnBoundary, Environment, Identifier, Symbol = ast.ReturnBoundary, ast.Environment, ast.Identifier, ast.Symbol
|
ReturnBoundary, Environment, Identifier = ast.ReturnBoundary, ast.Environment, ast.Identifier
|
||||||
|
|
||||||
resume_manager = require("anselme.state.resume_manager")
|
resume_manager = require("anselme.state.resume_manager")
|
||||||
calling_environment_manager = require("anselme.state.calling_environment_manager")
|
calling_environment_manager = require("anselme.state.calling_environment_manager")
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,13 @@ Identifier = ast.abstract.Node {
|
||||||
return state.scope:get(self)
|
return state.scope:get(self)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
list_used_identifiers = function(self, t)
|
||||||
|
if not t[self.name] then
|
||||||
|
t[self.name] = true
|
||||||
|
table.insert(t, self)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
to_string = function(self)
|
to_string = function(self)
|
||||||
return String:new(self.name)
|
return String:new(self.name)
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
60
anselme/ast/LuaCall.lua
Normal file
60
anselme/ast/LuaCall.lua
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
local ast = require("anselme.ast")
|
||||||
|
local unpack = table.unpack or unpack
|
||||||
|
local calling_environment_manager
|
||||||
|
|
||||||
|
local LuaCall
|
||||||
|
LuaCall = ast.abstract.Runtime {
|
||||||
|
type = "lua call",
|
||||||
|
hide_in_stacktrace = true,
|
||||||
|
_evaluated = false,
|
||||||
|
|
||||||
|
parameters = nil, -- ParameterTuple, may be unevaluated
|
||||||
|
func = nil, -- lua function
|
||||||
|
|
||||||
|
init = function(self, parameters, func)
|
||||||
|
self.parameters = parameters
|
||||||
|
self.func = func
|
||||||
|
end,
|
||||||
|
|
||||||
|
make_function = function(self, state, parameters, func)
|
||||||
|
local fn = ast.Function:new(parameters, LuaCall:new(parameters, func))
|
||||||
|
return fn:eval(state)
|
||||||
|
end,
|
||||||
|
|
||||||
|
traverse = function(self, fn, ...)
|
||||||
|
fn(self.parameters, ...)
|
||||||
|
end,
|
||||||
|
|
||||||
|
_hash = function(self)
|
||||||
|
return ("%s<%s;%s>"):format(self.type, self.parameters:hash(), tostring(self.func))
|
||||||
|
end,
|
||||||
|
|
||||||
|
_format = function(self, ...)
|
||||||
|
return "<lua function>"
|
||||||
|
end,
|
||||||
|
|
||||||
|
_eval = function(self, state)
|
||||||
|
-- get arguments
|
||||||
|
local lua_args = { state }
|
||||||
|
for _, param in ipairs(self.parameters.list) do
|
||||||
|
table.insert(lua_args, state.scope:get(param.identifier))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- run function, in calling environment
|
||||||
|
state.scope:push(calling_environment_manager:get_level(state, 1))
|
||||||
|
local r = self.func(unpack(lua_args))
|
||||||
|
assert(r, "lua function returned no value")
|
||||||
|
state.scope:pop()
|
||||||
|
|
||||||
|
return r
|
||||||
|
end,
|
||||||
|
|
||||||
|
to_lua = function(self, state)
|
||||||
|
return self.func
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
package.loaded[...] = LuaCall
|
||||||
|
calling_environment_manager = require("anselme.state.calling_environment_manager")
|
||||||
|
|
||||||
|
return LuaCall
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
local ast = require("anselme.ast")
|
|
||||||
local Overloadable = ast.abstract.Overloadable
|
|
||||||
|
|
||||||
local operator_priority = require("anselme.common").operator_priority
|
|
||||||
local unpack = table.unpack or unpack
|
|
||||||
|
|
||||||
local calling_environment_manager
|
|
||||||
|
|
||||||
local LuaFunction
|
|
||||||
LuaFunction = ast.abstract.Runtime(Overloadable) {
|
|
||||||
type = "lua function",
|
|
||||||
|
|
||||||
parameters = nil, -- ParameterTuple
|
|
||||||
func = nil, -- lua function
|
|
||||||
|
|
||||||
init = function(self, parameters, func)
|
|
||||||
self.parameters = parameters
|
|
||||||
self.func = func
|
|
||||||
end,
|
|
||||||
|
|
||||||
traverse = function(self, fn, ...)
|
|
||||||
fn(self.parameters, ...)
|
|
||||||
end,
|
|
||||||
|
|
||||||
_hash = function(self)
|
|
||||||
return ("%s<%s;%s>"):format(self.type, self.parameters:hash(), tostring(self.func))
|
|
||||||
end,
|
|
||||||
|
|
||||||
_format = function(self, ...)
|
|
||||||
if self.parameters.assignment then
|
|
||||||
return "$"..self.parameters:format(...).."; <lua function>"
|
|
||||||
else
|
|
||||||
return "$"..self.parameters:format(...).." <lua function>"
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
_format_priority = function(self)
|
|
||||||
return operator_priority["$_"]
|
|
||||||
end,
|
|
||||||
|
|
||||||
compatible_with_arguments = function(self, state, args)
|
|
||||||
return args:match_parameter_tuple(state, self.parameters)
|
|
||||||
end,
|
|
||||||
format_signature = function(self, state)
|
|
||||||
return "$"..self.parameters:format_short(state)
|
|
||||||
end,
|
|
||||||
hash_signature = function(self)
|
|
||||||
return self.parameters:hash()
|
|
||||||
end,
|
|
||||||
call_dispatched = function(self, state, args)
|
|
||||||
local calling_environment = state.scope:capture()
|
|
||||||
calling_environment_manager:push(state, calling_environment)
|
|
||||||
|
|
||||||
local lua_args = { state }
|
|
||||||
|
|
||||||
state.scope:push()
|
|
||||||
|
|
||||||
args:bind_parameter_tuple(state, self.parameters)
|
|
||||||
for _, param in ipairs(self.parameters.list) do
|
|
||||||
table.insert(lua_args, state.scope:get(param.identifier))
|
|
||||||
end
|
|
||||||
|
|
||||||
state.scope:pop()
|
|
||||||
|
|
||||||
local r = self.func(unpack(lua_args))
|
|
||||||
assert(r, "lua function returned no value")
|
|
||||||
|
|
||||||
calling_environment_manager:pop(state)
|
|
||||||
return r
|
|
||||||
end,
|
|
||||||
|
|
||||||
_eval = function(self, state)
|
|
||||||
return LuaFunction:new(self.parameters:eval(state), self.func)
|
|
||||||
end,
|
|
||||||
|
|
||||||
to_lua = function(self, state)
|
|
||||||
return self.func
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
package.loaded[...] = LuaFunction
|
|
||||||
calling_environment_manager = require("anselme.state.calling_environment_manager")
|
|
||||||
|
|
||||||
return LuaFunction
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
local ast = require("anselme.ast")
|
local ast = require("anselme.ast")
|
||||||
local Identifier
|
local Identifier, Symbol
|
||||||
|
|
||||||
local String = ast.abstract.Node {
|
local String = ast.abstract.Node {
|
||||||
type = "string",
|
type = "string",
|
||||||
|
|
@ -25,10 +25,13 @@ local String = ast.abstract.Node {
|
||||||
|
|
||||||
to_identifier = function(self)
|
to_identifier = function(self)
|
||||||
return Identifier:new(self.string)
|
return Identifier:new(self.string)
|
||||||
|
end,
|
||||||
|
to_symbol = function(self)
|
||||||
|
return Symbol:new(self.string)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = String
|
package.loaded[...] = String
|
||||||
Identifier = ast.Identifier
|
Identifier, Symbol = ast.Identifier, ast.Symbol
|
||||||
|
|
||||||
return String
|
return String
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ local Translatable = ast.abstract.Node {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
list_translatable = function(self, t)
|
list_translatable = function(self, t)
|
||||||
|
t = t or {}
|
||||||
table.insert(t, self)
|
table.insert(t, self)
|
||||||
|
return t
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@ traverse = {
|
||||||
merge = function(self, state, cache)
|
merge = function(self, state, cache)
|
||||||
self:merge(state, cache)
|
self:merge(state, cache)
|
||||||
end,
|
end,
|
||||||
|
post_deserialize = function(self, state, cache)
|
||||||
|
self:post_deserialize(state, cache)
|
||||||
|
end,
|
||||||
hash = function(self, t)
|
hash = function(self, t)
|
||||||
table.insert(t, self:hash())
|
table.insert(t, self:hash())
|
||||||
end,
|
end,
|
||||||
|
|
@ -55,6 +58,9 @@ traverse = {
|
||||||
for hash, target in pairs(self:list_resume_targets()) do
|
for hash, target in pairs(self:list_resume_targets()) do
|
||||||
add_to_node._list_resume_targets_cache[hash] = target
|
add_to_node._list_resume_targets_cache[hash] = target
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
|
list_used_identifiers = function(self, t)
|
||||||
|
self:list_used_identifiers(t)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +140,7 @@ Node = class {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- generate a list of translatable nodes that appear in this node
|
-- generate a list of translatable nodes that appear in this node
|
||||||
-- should only be called on non-evaluated nodes
|
-- should only be called on non-evaluated nodes (non-evaluated nodes don't contain cycles)
|
||||||
-- if a node is translatable, redefine this to add it to the table - note that it shouldn't call :traverse or :list_translatable on its children, as nested translations should not be needed
|
-- if a node is translatable, redefine this to add it to the table - note that it shouldn't call :traverse or :list_translatable on its children, as nested translations should not be needed
|
||||||
list_translatable = function(self, t)
|
list_translatable = function(self, t)
|
||||||
t = t or {}
|
t = t or {}
|
||||||
|
|
@ -142,6 +148,14 @@ Node = class {
|
||||||
return t
|
return t
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
-- generate a list of identifiers that are used in this node
|
||||||
|
-- should only be called on non-evaluated nodes
|
||||||
|
-- the list contains at least all used nodes; some unused nodes may be present
|
||||||
|
-- redefine on identifier nodes to add an identifier to the table
|
||||||
|
list_used_identifiers = function(self, t)
|
||||||
|
self:traverse(traverse.list_used_identifiers, t)
|
||||||
|
end,
|
||||||
|
|
||||||
-- generate anselme code that can be used as a base for a translation file
|
-- generate anselme code that can be used as a base for a translation file
|
||||||
-- will include every translatable element found in this node and its children
|
-- will include every translatable element found in this node and its children
|
||||||
generate_translation_template = function(self)
|
generate_translation_template = function(self)
|
||||||
|
|
@ -388,8 +402,21 @@ Node = class {
|
||||||
package.loaded["anselme.serializer_state"] = state
|
package.loaded["anselme.serializer_state"] = state
|
||||||
local r = binser.deserializeN(str, 1, index)
|
local r = binser.deserializeN(str, 1, index)
|
||||||
package.loaded["anselme.serializer_state"] = nil
|
package.loaded["anselme.serializer_state"] = nil
|
||||||
|
r:post_deserialize(state, {})
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
|
-- call :_post_deserialize on all children nodes
|
||||||
|
-- automatically called after a sucesfull deserialization, intended to perform finishing touches for deserialization
|
||||||
|
-- notably, there is no guarantee that children nodes are already deserialized when _deserialize is called on a node
|
||||||
|
-- anything that require such a guarantee should be done here
|
||||||
|
post_deserialize = function(self, state, cache)
|
||||||
|
if not cache[self] then
|
||||||
|
cache[self] = true
|
||||||
|
self:_post_deserialize(state, cache)
|
||||||
|
self:traverse(traverse.post_deserialize, state, cache)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
_post_deserialize = function(self, state, cache) end,
|
||||||
|
|
||||||
__tostring = function(self) return self:format() end,
|
__tostring = function(self) return self:format() end,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ local ast = require("anselme.ast")
|
||||||
local to_anselme = require("anselme.common.to_anselme")
|
local to_anselme = require("anselme.common.to_anselme")
|
||||||
local unpack = table.unpack or unpack
|
local unpack = table.unpack or unpack
|
||||||
|
|
||||||
local LuaFunction, Environment, Node
|
local LuaCall, Environment, Node
|
||||||
|
|
||||||
local parameter_tuple = require("anselme.parser.expression.contextual.parameter_tuple")
|
local parameter_tuple = require("anselme.parser.expression.contextual.parameter_tuple")
|
||||||
local symbol = require("anselme.parser.expression.primary.symbol")
|
local symbol = require("anselme.parser.expression.primary.symbol")
|
||||||
|
|
@ -64,7 +64,7 @@ local ScopeStack = class {
|
||||||
return to_anselme(original_func(unpack(lua_args)))
|
return to_anselme(original_func(unpack(lua_args)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:define_overloadable(sym, LuaFunction:new(parameters, func):eval(self.state))
|
self:define_overloadable(sym, LuaCall:make_function(self.state, parameters, func))
|
||||||
elseif Node:issub(value) then
|
elseif Node:issub(value) then
|
||||||
self:define(sym, value)
|
self:define(sym, value)
|
||||||
else
|
else
|
||||||
|
|
@ -150,6 +150,6 @@ local ScopeStack = class {
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = ScopeStack
|
package.loaded[...] = ScopeStack
|
||||||
LuaFunction, Environment, Node = ast.LuaFunction, ast.Environment, ast.abstract.Node
|
LuaCall, Environment, Node = ast.LuaCall, ast.Environment, ast.abstract.Node
|
||||||
|
|
||||||
return ScopeStack
|
return ScopeStack
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ return {
|
||||||
"attached block", "(level::is number=1, keep return=false)",
|
"attached block", "(level::is number=1, keep return=false)",
|
||||||
function(state, level, keep_return)
|
function(state, level, keep_return)
|
||||||
-- level 2: env of the function that called the function that called attached block
|
-- level 2: env of the function that called the function that called attached block
|
||||||
local env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
|
local env = calling_environment_manager:get_level(state, level:to_lua(state))
|
||||||
local block = env:get(state, block_identifier).expression
|
local block = env:get(state, block_identifier).expression
|
||||||
local fn
|
local fn
|
||||||
if keep_return:truthy() then
|
if keep_return:truthy() then
|
||||||
|
|
@ -28,7 +28,7 @@ return {
|
||||||
"attached block", "(level::is number=1, keep return=false, default)",
|
"attached block", "(level::is number=1, keep return=false, default)",
|
||||||
function(state, level, keep_return, default)
|
function(state, level, keep_return, default)
|
||||||
-- level 2: env of the function that called the function that called attached block
|
-- level 2: env of the function that called the function that called attached block
|
||||||
local env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
|
local env = calling_environment_manager:get_level(state, level:to_lua(state))
|
||||||
if env:defined(state, block_identifier) then
|
if env:defined(state, block_identifier) then
|
||||||
local block = env:get(state, block_identifier).expression
|
local block = env:get(state, block_identifier).expression
|
||||||
local fn
|
local fn
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,10 @@ return {
|
||||||
return func:call(state, ArgumentTuple:new())
|
return func:call(state, ArgumentTuple:new())
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"resuming", "()",
|
|
||||||
function(state)
|
|
||||||
return Boolean:new(resume_manager:resuming(state))
|
|
||||||
end
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"resuming", "(level::is number=0)",
|
"resuming", "(level::is number=0)",
|
||||||
function(state, level)
|
function(state, level)
|
||||||
local env = calling_environment_manager:get_level(state, level:to_lua(state)+1)
|
local env = calling_environment_manager:get_level(state, level:to_lua(state))
|
||||||
state.scope:push(env)
|
state.scope:push(env)
|
||||||
local r = Boolean:new(resume_manager:resuming(state))
|
local r = Boolean:new(resume_manager:resuming(state))
|
||||||
state.scope:pop()
|
state.scope:pop()
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ return [[
|
||||||
fn.:check = $(anchor::is anchor)
|
fn.:check = $(anchor::is anchor)
|
||||||
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
|
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
|
||||||
fn.:checkpoint = $(anchor::is anchor, on resume=attached block(default=()))
|
fn.:checkpoint = $(anchor::is anchor, on resume=attached block(default=()))
|
||||||
|
:resuming = resuming(1) /* calling function is resuming */
|
||||||
if(on resume)
|
if(on resume)
|
||||||
fn.current checkpoint = anchor
|
fn.current checkpoint = anchor
|
||||||
if(resume target == anchor | resuming(4))
|
if(resume target == anchor | resuming)
|
||||||
on resume!
|
on resume!
|
||||||
else!
|
else!
|
||||||
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
|
fn.reached(anchor) = (fn.reached(anchor) | 0) + 1
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
local ast = require("anselme.ast")
|
local ast = require("anselme.ast")
|
||||||
local Nil, List, Table, Number, LuaFunction, ParameterTuple, Boolean = ast.Nil, ast.List, ast.Table, ast.Number, ast.LuaFunction, ast.ParameterTuple, ast.Boolean
|
local Nil, List, Table, Number, LuaCall, ParameterTuple, Boolean = ast.Nil, ast.List, ast.Table, ast.Number, ast.LuaCall, ast.ParameterTuple, ast.Boolean
|
||||||
|
|
||||||
return {
|
return {
|
||||||
-- tuple
|
-- tuple
|
||||||
|
|
@ -122,7 +122,7 @@ return {
|
||||||
"iter", "(s::is struct)",
|
"iter", "(s::is struct)",
|
||||||
function(state, struct)
|
function(state, struct)
|
||||||
local iter = struct:iter()
|
local iter = struct:iter()
|
||||||
return LuaFunction:new(ParameterTuple:new(), function()
|
return LuaCall:make_function(state, ParameterTuple:new(), function()
|
||||||
local k = iter()
|
local k = iter()
|
||||||
if k == nil then return Nil:new()
|
if k == nil then return Nil:new()
|
||||||
else return k end
|
else return k end
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
--- text ---
|
--- text ---
|
||||||
| {}"" {}"42" {}"" |
|
| {}"" {}"42" {}"" |
|
||||||
--- error ---
|
--- error ---
|
||||||
[0m[31m[0m[31m[0m[31midentifier "z" is undefined in branch 46991f07-7340-4104-9f35-c1fb62e95088[0m
|
[0m[31m[0m[31m[0m[31midentifier "z" is undefined in branch 1c25ebb8-5027-4ccf-105b9-370d83e78fd7[0m
|
||||||
↳ from [4mtest/tests/exported variable nested.ans:12:3[0m in identifier: [2mz[0m[0m
|
↳ from [4mtest/tests/exported variable nested.ans:12:3[0m in identifier: [2mz[0m[0m
|
||||||
↳ from [4mtest/tests/exported variable nested.ans:12:1[0m in text interpolation: [2m| {z} |[0m[0m
|
↳ from [4mtest/tests/exported variable nested.ans:12:1[0m in text interpolation: [2m| {z} |[0m[0m
|
||||||
↳ from [4m?[0m in block: [2m:f = ($() _)…[0m
|
↳ from [4m?[0m in block: [2m:f = ($() _)…[0m
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
--# run #--
|
--# run #--
|
||||||
--- error ---
|
--- error ---
|
||||||
[0m[31m[0m[31m[0m[31m[0m[31m[0m[31m[0m[31mcan't call overload iter: no function match arguments (42), possible functions were:
|
[0m[31m[0m[31m[0m[31m[0m[31m[0m[31m[0m[31mcan't call overload iter: no function match arguments (value), possible functions were:
|
||||||
• $(table::is table) (from stdlib/for.ans:46:1):
|
• $(table::is table) (from stdlib/for.ans:46:1):
|
||||||
type check failure for parameter table
|
type check failure for parameter table
|
||||||
• $(tuple::is sequence) (from stdlib/for.ans:37:1):
|
• $(tuple::is sequence) (from stdlib/for.ans:37:1):
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
--- text ---
|
--- text ---
|
||||||
| {}"" {}"idk" {}" is esperanto" |
|
| {}"" {}"idk" {}" is esperanto" |
|
||||||
--- error ---
|
--- error ---
|
||||||
[0m[31m[0m[31mcan't call overload a: no function match arguments (type(5, "nope")), possible functions were:
|
[0m[31m[0m[31mcan't call overload a: no function match arguments (value), possible functions were:
|
||||||
• $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:7:1):
|
• $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:7:1):
|
||||||
type check failure for parameter name
|
type check failure for parameter name
|
||||||
• $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:4:1):
|
• $(name::($(x) type(x) == t)) (from test/tests/function custom type dispatch error.ans:4:1):
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
--- text ---
|
--- text ---
|
||||||
| {}"a" |
|
| {}"a" |
|
||||||
--- text ---
|
--- text ---
|
||||||
|
| {}"c" |
|
||||||
|
--- text ---
|
||||||
| {}"b" |
|
| {}"b" |
|
||||||
--- text ---
|
--- text ---
|
||||||
| {}"c" |
|
| {}"c" |
|
||||||
--- text ---
|
--- text ---
|
||||||
| {}"a" |
|
| {}"c" |
|
||||||
--- text ---
|
|
||||||
| {}"b" |
|
|
||||||
--- return ---
|
--- return ---
|
||||||
()
|
()
|
||||||
--# saved #--
|
--# saved #--
|
||||||
{"a.checkpoint":false, "a.run":2, "b.checkpoint":false, "b.run":2, "c.checkpoint":false, "c.run":1}
|
{"a.checkpoint":false, "a.run":1, "b.checkpoint":false, "b.run":1, "c.checkpoint":false, "c.run":3}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
--# run #--
|
--# run #--
|
||||||
--- error ---
|
--- error ---
|
||||||
[0m[31m[0m[31m[0m[31midentifier "b" is undefined in branch 46991f07-7340-4104-9f35-c1fb62e95088[0m
|
[0m[31m[0m[31m[0m[31midentifier "b" is undefined in branch 1c25ebb8-5027-4ccf-105b9-370d83e78fd7[0m
|
||||||
↳ from [4mtest/tests/function scope wrong.ans:4:7[0m in identifier: [2mb[0m[0m
|
↳ from [4mtest/tests/function scope wrong.ans:4:7[0m in identifier: [2mb[0m[0m
|
||||||
↳ from [4mtest/tests/function scope wrong.ans:4:1[0m in text interpolation: [2m| a: {b} |[0m[0m
|
↳ from [4mtest/tests/function scope wrong.ans:4:1[0m in text interpolation: [2m| a: {b} |[0m[0m
|
||||||
↳ from [4m?[0m in block: [2m:a = ($() _)…[0m
|
↳ from [4m?[0m in block: [2m:a = ($() _)…[0m
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,23 @@
|
||||||
--# run #--
|
--# run #--
|
||||||
--- error ---
|
--- error ---
|
||||||
[0m[31m[0m[31m[0m[31mcan't call overload _._: no function match arguments (overload([($(b) _), ($(x) _), ($() _)]), "a"), possible functions were:
|
[0m[31m[0m[31m[0m[31mcan't call overload _._: no function match arguments (value, "a"), possible functions were:
|
||||||
• $(s::is script, k::is symbol) = val (from stdlib/script.ans:44:1):
|
• $(s::is script, k::is symbol) = val (from stdlib/script.ans:45:1):
|
||||||
expected 3 arguments, received 2
|
expected 3 arguments, received 2
|
||||||
• $(s::is script, k::is string) = val (from stdlib/script.ans:42:1):
|
• $(s::is script, k::is string) = val (from stdlib/script.ans:43:1):
|
||||||
expected 3 arguments, received 2
|
expected 3 arguments, received 2
|
||||||
• $(s::is script, k::is string) (from stdlib/script.ans:40:1):
|
• $(s::is script, k::is string) (from stdlib/script.ans:41:1):
|
||||||
type check failure for parameter s
|
type check failure for parameter s
|
||||||
• $(c::is function, s::is symbol) = v (from test/tests/function separate variable from variants.ans:10:4):
|
• $(c::is function, s::is symbol) = v (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
expected 3 arguments, received 2
|
expected 3 arguments, received 2
|
||||||
• $(c::is function, s::is string) = v (from test/tests/function separate variable from variants.ans:10:4):
|
• $(c::is function, s::is string) = v (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
expected 3 arguments, received 2
|
expected 3 arguments, received 2
|
||||||
• $(c::is function, s::is string) (from test/tests/function separate variable from variants.ans:10:4):
|
• $(c::is function, s::is string) (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
|
type check failure for parameter c
|
||||||
|
• $(c::is environment, s::is symbol) = v (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
|
expected 3 arguments, received 2
|
||||||
|
• $(c::is environment, s::is string) = v (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
|
expected 3 arguments, received 2
|
||||||
|
• $(c::is environment, s::is string) (from test/tests/function separate variable from variants.ans:10:4):
|
||||||
type check failure for parameter c[0m
|
type check failure for parameter c[0m
|
||||||
↳ from [4mtest/tests/function separate variable from variants.ans:10:4[0m in call: [2mf . "a"[0m[0m
|
↳ from [4mtest/tests/function separate variable from variants.ans:10:4[0m in call: [2mf . "a"[0m[0m
|
||||||
↳ from [4mtest/tests/function separate variable from variants.ans:10:1[0m in text interpolation: [2m| {f . "a"} = 2 |[0m[0m
|
↳ from [4mtest/tests/function separate variable from variants.ans:10:1[0m in text interpolation: [2m| {f . "a"} = 2 |[0m[0m
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
↳ from [4mtest/tests/merge nested mutable error bis.ans:14:7[0m in call: [2merror("abort")[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error bis.ans:14:7[0m in call: [2merror("abort")[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:18[0m in call: [2m_[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error bis.ans:3:18[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:30:6[0m in call: [2mfn![0m[0m
|
↳ from [4mstdlib/script.ans:31:6[0m in call: [2mfn![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:28:3[0m in block: [2mresume target = ()…[0m[0m
|
↳ from [4mstdlib/script.ans:29:3[0m in block: [2mresume target = ()…[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:28:7[0m in call: [2melse![0m[0m
|
↳ from [4mstdlib/script.ans:29:7[0m in call: [2melse![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:24:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
↳ from [4mstdlib/script.ans:25:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:24:9[0m in call: [2m_[0m[0m
|
↳ from [4mstdlib/script.ans:25:9[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:38:9[0m in call: [2mvalue(s)![0m[0m
|
↳ from [4mstdlib/script.ans:39:9[0m in call: [2mvalue(s)![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:37:1[0m in block: [2mvalue(s)![0m[0m
|
↳ from [4mstdlib/script.ans:38:1[0m in block: [2mvalue(s)![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:37:20[0m in call: [2m_[0m[0m
|
↳ from [4mstdlib/script.ans:38:20[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error bis.ans:19:2[0m in call: [2mf![0m[0m
|
↳ from [4mtest/tests/merge nested mutable error bis.ans:19:2[0m in call: [2mf![0m[0m
|
||||||
↳ from [4m?[0m in block: [2m:a = *[1]…[0m
|
↳ from [4m?[0m in block: [2m:a = *[1]…[0m
|
||||||
--# post run check #--
|
--# post run check #--
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
↳ from [4mtest/tests/merge nested mutable error.ans:14:7[0m in call: [2merror("abort")[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error.ans:14:7[0m in call: [2merror("abort")[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error.ans:3:1[0m in block: [2minsert(a, b)…[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error.ans:3:18[0m in call: [2m_[0m[0m
|
↳ from [4mtest/tests/merge nested mutable error.ans:3:18[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:30:6[0m in call: [2mfn![0m[0m
|
↳ from [4mstdlib/script.ans:31:6[0m in call: [2mfn![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:28:3[0m in block: [2mresume target = ()…[0m[0m
|
↳ from [4mstdlib/script.ans:29:3[0m in block: [2mresume target = ()…[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:28:7[0m in call: [2melse![0m[0m
|
↳ from [4mstdlib/script.ans:29:7[0m in call: [2melse![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:24:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
↳ from [4mstdlib/script.ans:25:2[0m in block: [2mif(fn . "current checkpoint")…[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:24:9[0m in call: [2m_[0m[0m
|
↳ from [4mstdlib/script.ans:25:9[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mstdlib/script.ans:38:9[0m in call: [2mvalue(s)![0m[0m
|
↳ from [4mstdlib/script.ans:39:9[0m in call: [2mvalue(s)![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:37:1[0m in block: [2mvalue(s)![0m[0m
|
↳ from [4mstdlib/script.ans:38:1[0m in block: [2mvalue(s)![0m[0m
|
||||||
↳ from [4mstdlib/script.ans:37:20[0m in call: [2m_[0m[0m
|
↳ from [4mstdlib/script.ans:38:20[0m in call: [2m_[0m[0m
|
||||||
↳ from [4mtest/tests/merge nested mutable error.ans:19:2[0m in call: [2mf![0m[0m
|
↳ from [4mtest/tests/merge nested mutable error.ans:19:2[0m in call: [2mf![0m[0m
|
||||||
↳ from [4m?[0m in block: [2m:a = *[1]…[0m
|
↳ from [4m?[0m in block: [2m:a = *[1]…[0m
|
||||||
--# post run check #--
|
--# post run check #--
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
:z = 1
|
||||||
:x = $
|
:x = $
|
||||||
2+z
|
2+z
|
||||||
x.:z = 3
|
x.:z = 3
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
:choice = 1
|
:@choice = 1
|
||||||
|
|
||||||
:$ jump button
|
:$ jump button
|
||||||
1 # | A
|
1 # | A
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue