diff --git a/anselme/ast/Function.lua b/anselme/ast/Function.lua index 71e778b..b72cbc8 100644 --- a/anselme/ast/Function.lua +++ b/anselme/ast/Function.lua @@ -123,23 +123,26 @@ Function = Overloadable { -- Note: when serializing and reloading a function, its upvalues will not be linked anymore to their original definition. -- The reloaded function will not be able to affect variables defined outside its body. - -- Only the upvalues that explicitely appear in the function body will be saved, so we don't have to keep a copy of the whole environment. - -- TODO: we should also store variables that have been defined in the function scope, even if they are not referred directly in the body + -- 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) - return { parameters = self.parameters, expression = self.expression, upvalues = self.upvalues } + local state = require("anselme.serializer_state") + return { parameters = self.parameters, expression = self.expression, upvalues = self.upvalues, scope = self.scope.variables:to_struct(state) } end, _deserialize = function(self) local state = require("anselme.serializer_state") local scope if self.upvalues then -- rebuild scope: exported + normal layer so any upvalue that happen to be exported stay there - -- (and link again to current scope to allow internal vars that are not considered explicit upvalues to still work, like _translations) + -- (and link again to current scope to allow internal vars that are not serialized to still work, like _translations) scope = Environment:new(state, Environment:new(state, state.scope:capture(), nil, true)) for _, var in pairs(self.upvalues) do scope:define(state, var:get_symbol(), var:get(state)) end + for _, var in self.scope:iter() do + scope:define(state, var:get_symbol(), var:get(state)) + end end - return Function:new(self.parameters, self.expression, Environment:new(state, scope), self.upvalues) + return Function:new(self.parameters, self.expression, Environment:new(state, scope), self.upvalues):set_source("saved") end } diff --git a/anselme/ast/abstract/Node.lua b/anselme/ast/abstract/Node.lua index 2d1e0e2..4fd10d6 100644 --- a/anselme/ast/abstract/Node.lua +++ b/anselme/ast/abstract/Node.lua @@ -61,7 +61,6 @@ traverse = { local Node Node = class { type = "node", - source = "?", mutable = false, hide_in_stacktrace = false, @@ -79,6 +78,7 @@ Node = class { end return self end, + source = "?", -- call function callback with args ... on the children Nodes of this Node -- by default, assumes no children Nodes diff --git a/test/results/serialize function env.ans b/test/results/serialize function env.ans new file mode 100644 index 0000000..d4cd224 --- /dev/null +++ b/test/results/serialize function env.ans @@ -0,0 +1,7 @@ +--# run #-- +--- text --- +| {}"" {}"5" {}"" | +--- return --- +() +--# saved #-- +{} \ No newline at end of file diff --git a/test/tests/serialize function env.ans b/test/tests/serialize function env.ans new file mode 100644 index 0000000..9e3c5b0 --- /dev/null +++ b/test/tests/serialize function env.ans @@ -0,0 +1,5 @@ +:x = $ + 2+z +x.:z = 3 + +|{x!serialize!deserialize!}