mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-28 00:59:31 +00:00
Replace persistent variable system
Previous system linked the variable name with the saved value, meaning the variable could not be renamed or moved outside the global scope. Instead we propose to store all persistent values in a global table, identifying each by a key. To still allow nice manipulation with identifiers, the alias syntax replace the persistent syntax for symbols - an aliases symbol will act as if a function call was used in place of the identifier when it appear.
This commit is contained in:
parent
56ed6c912b
commit
e71bff9562
13 changed files with 169 additions and 58 deletions
|
|
@ -74,6 +74,7 @@ local ScopeStack = class {
|
|||
-- methods that call the associated method from the current scope, see ast.Environment for details
|
||||
define = function(self, symbol, exp) self.current:define(self.state, symbol, exp) end,
|
||||
define_overloadable = function(self, symbol, exp) return self.current:define_overloadable(self.state, symbol, exp) end,
|
||||
define_alias = function(self, symbol, exp) return self.current:define_alias(self.state, symbol, exp) end,
|
||||
defined = function(self, identifier) return self.current:defined(self.state, identifier) end,
|
||||
defined_in_current = function(self, symbol) return self.current:defined_in_current(self.state, symbol) end,
|
||||
set = function(self, identifier, exp) self.current:set(self.state, identifier, exp) end,
|
||||
|
|
@ -140,12 +141,6 @@ local ScopeStack = class {
|
|||
return self.current
|
||||
end,
|
||||
|
||||
-- return a table { [symbol] = value } of persistent variables defined on the root scope on this branch
|
||||
list_persistent_global = function(self)
|
||||
local env = self.stack[1]
|
||||
return env:list_persistent(self.state)
|
||||
end,
|
||||
|
||||
_debug_state = function(self, filter)
|
||||
filter = filter or ""
|
||||
local s = "current branch id: "..self.state.branch_id.."\n"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ local ScopeStack = require("state.ScopeStack")
|
|||
local tag_manager = require("state.tag_manager")
|
||||
local event_manager = require("state.event_manager")
|
||||
local translation_manager = require("state.translation_manager")
|
||||
local persistent_manager = require("state.persistent_manager")
|
||||
local uuid = require("common").uuid
|
||||
local parser = require("parser")
|
||||
local binser = require("lib.binser")
|
||||
|
|
@ -30,6 +31,7 @@ State = class {
|
|||
|
||||
event_manager:setup(self)
|
||||
tag_manager:setup(self)
|
||||
persistent_manager:setup(self)
|
||||
translation_manager:setup(self)
|
||||
end
|
||||
end,
|
||||
|
|
@ -93,28 +95,22 @@ State = class {
|
|||
|
||||
---## Saving and loading persistent variables
|
||||
|
||||
--- Return a serialized (string) representation of all global persistent variables in this State.
|
||||
--- Return a serialized (string) representation of all persistent variables in this State.
|
||||
--
|
||||
-- This can be loaded back later using `:load`.
|
||||
save = function(self)
|
||||
local list = self.scope:list_persistent_global()
|
||||
return binser.serialize(anselme.versions.save, list)
|
||||
local struct = persistent_manager:capture(self)
|
||||
return binser.serialize(anselme.versions.save, struct)
|
||||
end,
|
||||
--- Load a string generated by `:save`.
|
||||
--
|
||||
-- Variables that do not exist currently in the global scope will be defined, those that do will be overwritten with the loaded data.
|
||||
-- Variables that already exist will be overwritten with the loaded data.
|
||||
load = function(self, save)
|
||||
local version, list = binser.deserializeN(save, 2)
|
||||
local version, struct = binser.deserializeN(save, 2)
|
||||
if version ~= anselme.versions.save then print("Loading a save file generated by a different Anselme version, things may break!") end
|
||||
self.scope:push_global()
|
||||
for sym, val in pairs(list) do
|
||||
if self.scope:defined_in_current(sym) then
|
||||
self.scope:set(sym:to_identifier(), val)
|
||||
else
|
||||
self.scope:define(sym, val)
|
||||
end
|
||||
for key, val in struct:iter() do
|
||||
persistent_manager:set(self, key, val)
|
||||
end
|
||||
self.scope:pop()
|
||||
end,
|
||||
|
||||
---## Current script state
|
||||
|
|
|
|||
47
state/persistent_manager.lua
Normal file
47
state/persistent_manager.lua
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
local class = require("class")
|
||||
|
||||
local ast = require("ast")
|
||||
local Table, Identifier
|
||||
|
||||
local persistent_identifier, persistent_symbol
|
||||
|
||||
local persistent_manager = class {
|
||||
init = false,
|
||||
|
||||
setup = function(self, state)
|
||||
state.scope:define(persistent_symbol, Table:new(state))
|
||||
end,
|
||||
|
||||
-- set the persistant variable `key` to `value` (evaluated)
|
||||
set = function(self, state, key, value)
|
||||
local persistent = state.scope:get(persistent_identifier)
|
||||
persistent:set(state, key, value)
|
||||
end,
|
||||
-- get the persistant variable `key`'s value
|
||||
-- if `default` is given, will set the variable to this if not currently set
|
||||
get = function(self, state, key, default)
|
||||
local persistent = state.scope:get(persistent_identifier)
|
||||
if not persistent:has(state, key) then
|
||||
if default then
|
||||
persistent:set(state, key, default)
|
||||
else
|
||||
error("persistent key does not exist")
|
||||
end
|
||||
end
|
||||
return persistent:get(state, key)
|
||||
end,
|
||||
|
||||
-- returns a struct of the current persisted variables
|
||||
capture = function(self, state)
|
||||
local persistent = state.scope:get(persistent_identifier)
|
||||
return persistent:to_struct(state)
|
||||
end
|
||||
}
|
||||
|
||||
package.loaded[...] = persistent_manager
|
||||
Table, Identifier = ast.Table, ast.Identifier
|
||||
|
||||
persistent_identifier = Identifier:new("_persistent") -- Table of { [key] = Call, ... }
|
||||
persistent_symbol = persistent_identifier:to_symbol()
|
||||
|
||||
return persistent_manager
|
||||
Loading…
Add table
Add a link
Reference in a new issue