diff --git a/README.md b/README.md index 7716090..479d3e3 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ Functions can return a value using a [return line](#lines-that-can-t-have-childr Functions always have the following variables defined in its namespace by default: `πŸ‘οΈ`: number, number of times the function was executed before -`🏁`: string, name of last reached checkpoint +`πŸ”–`: string, name of last reached checkpoint * `Β§`: checkpoint. Followed by an [identifier](#identifiers), then eventually an [alias](#aliases). Define a checkpoint. Also define a new namespace for its children. @@ -235,7 +235,8 @@ $ inane dialog Checkpoints always have the following variable defined in its namespace by default: -`πŸ‘οΈ`: number, number of times the checkpoint was reached or executed before +`πŸ‘οΈ`: number, number of times the checkpoint was executed before +`🏁`: number, number of times the checkpoint was reached before (including times where it was resumed from and executed) * `#`: tag line. Can be followed by an [expression](#expressions); otherwise nil expression is assumed. The results of the [expression](#expressions) will be added to the tags send along with any event sent from its children. Can be nested. @@ -474,7 +475,7 @@ Hi {player name}! Salut {nom du joueur} ! ``` -Variables that are defined automatically by Anselme (`πŸ‘οΈ` and `🏁` in checkpoints and functions) can be automatically aliased using `vm:setaliases("πŸ‘οΈalias", "🏁alias")`. See [API](#api-reference). +Variables that are defined automatically by Anselme (`πŸ‘οΈ`, `πŸ”–` and `🏁` in checkpoints and functions) can be automatically aliased using `vm:setaliases("πŸ‘οΈalias", "πŸ”–alias", 🏁alias")`. See [API](#api-reference). ### Expressions diff --git a/anselme.lua b/anselme.lua index 4b63c23..ff8360b 100644 --- a/anselme.lua +++ b/anselme.lua @@ -173,6 +173,7 @@ local vm_mt = { -- * config.ans, which contains various optional configuration options: -- * alias πŸ‘οΈ: string, default alias for πŸ‘οΈ -- * alias 🏁: string, default alias for 🏁 + -- * alias πŸ”–: string, default alias for πŸ”– -- * main file: string, name (without .ans extension) of a file that will be loaded into the root namespace -- * main file, if defined in config.ans -- * every other file in the path and subdirectories, using their path as namespace (i.e., contents of path/world1/john.ans will be defined in a function world1.john) @@ -185,10 +186,11 @@ local vm_mt = { if not s then return s, e end end local seen_alias = self:eval("config.alias πŸ‘οΈ") - local checkpoint_alias = self:eval("config.alias 🏁") + local checkpoint_alias = self:eval("config.alias πŸ”–") + local reached_alias = self:eval("config.alias 🏁") local main_file = self:eval("config.main file") -- set aliases - self:setaliases(seen_alias, checkpoint_alias) + self:setaliases(seen_alias, checkpoint_alias, reached_alias) -- load main file if main_file then local s, e = self:loadfile(path.."/"..main_file..".ans") @@ -254,12 +256,13 @@ local vm_mt = { return self end, - --- set aliases for built-in variables πŸ‘οΈ and 🏁 that will be defined on every new checkpoint and function + --- set aliases for built-in variables πŸ‘οΈ, πŸ”– and 🏁 that will be defined on every new checkpoint and function -- nil for no alias -- return self - setaliases = function(self, seen, checkpoint) + setaliases = function(self, seen, checkpoint, reached) self.state.builtin_aliases["πŸ‘οΈ"] = seen - self.state.builtin_aliases["🏁"] = checkpoint + self.state.builtin_aliases["πŸ”–"] = checkpoint + self.state.builtin_aliases["🏁"] = reached return self end, @@ -387,7 +390,8 @@ return setmetatable(anselme, { local state = { builtin_aliases = { -- ["πŸ‘οΈ"] = "seen", - -- ["🏁"] = "checkpoint" + -- ["πŸ”–"] = "checkpoint", + -- ["🏁"] = "reached" }, aliases = { -- ["bonjour.salutation"] = "hello.greeting", diff --git a/interpreter/expression.lua b/interpreter/expression.lua index 0bee0db..bdbbf0d 100644 --- a/interpreter/expression.lua +++ b/interpreter/expression.lua @@ -112,11 +112,11 @@ local function eval(state, exp) end -- eval function local r, e - if exp.explicit_call or state.variables[fn.value.namespace.."🏁"].value == "" then + if exp.explicit_call or state.variables[fn.value.namespace.."πŸ”–"].value == "" then r, e = run(state, fn.value.child) -- resume at last checkpoint else - local expr, err = expression(state.variables[fn.value.namespace.."🏁"].value, state, "") + local expr, err = expression(state.variables[fn.value.namespace.."πŸ”–"].value, state, "") if not expr then return expr, err end r, e = eval(state, expr) end diff --git a/interpreter/interpreter.lua b/interpreter/interpreter.lua index 1210edf..1db25b0 100644 --- a/interpreter/interpreter.lua +++ b/interpreter/interpreter.lua @@ -135,11 +135,11 @@ local function run_line(state, line) end end elseif line.type == "checkpoint" then - state.variables[line.namespace.."πŸ‘οΈ"] = { + state.variables[line.namespace.."🏁"] = { type = "number", - value = state.variables[line.namespace.."πŸ‘οΈ"].value + 1 + value = state.variables[line.namespace.."🏁"].value + 1 } - state.variables[line.parent_function.namespace.."🏁"] = { + state.variables[line.parent_function.namespace.."πŸ”–"] = { type = "string", value = line.name } @@ -183,11 +183,15 @@ run_block = function(state, block, resume_from_there, i, j) type = "number", value = state.variables[parent_line.namespace.."πŸ‘οΈ"].value + 1 } + state.variables[parent_line.namespace.."🏁"] = { + type = "number", + value = state.variables[parent_line.namespace.."🏁"].value + 1 + } -- don't update checkpoint if an already more precise checkpoint is set -- (since we will go up the whole checkpoint hierarchy when resuming from a nested checkpoint) - local current_checkpoint = state.variables[parent_line.parent_function.namespace.."🏁"].value + local current_checkpoint = state.variables[parent_line.parent_function.namespace.."πŸ”–"].value if not current_checkpoint:match("^"..escape(parent_line.name)) then - state.variables[parent_line.parent_function.namespace.."🏁"] = { + state.variables[parent_line.parent_function.namespace.."πŸ”–"] = { type = "string", value = parent_line.name } diff --git a/parser/preparser.lua b/parser/preparser.lua index 1c3c892..1e20570 100644 --- a/parser/preparser.lua +++ b/parser/preparser.lua @@ -132,17 +132,34 @@ local function parse_line(line, state, namespace) state.aliases[alias] = fqm..".πŸ‘οΈ" end if r.type == "function" then - -- define 🏁 variable - if not state.variables[fqm..".🏁"] then - state.variables[fqm..".🏁"] = { + -- define πŸ”– variable + if not state.variables[fqm..".πŸ”–"] then + state.variables[fqm..".πŸ”–"] = { type = "string", value = "" } end - -- define alias for 🏁 - local checkpoint_alias = state.builtin_aliases["🏁"] + -- define alias for πŸ”– + local checkpoint_alias = state.builtin_aliases["πŸ”–"] if checkpoint_alias then local alias = ("%s.%s"):format(fqm, checkpoint_alias) + if state.aliases[alias] ~= nil and state.aliases[alias] then + return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(alias, fqm..".πŸ”–", state.aliases[alias], line.source) + end + state.aliases[alias] = fqm..".πŸ”–" + end + elseif r.type == "checkpoint" then + -- define 🏁 variable + if not state.variables[fqm..".🏁"] then + state.variables[fqm..".🏁"] = { + type = "number", + value = 0 + } + end + -- define alias for 🏁 + local reached_alias = state.builtin_aliases["🏁"] + if reached_alias then + local alias = ("%s.%s"):format(fqm, reached_alias) if state.aliases[alias] ~= nil and state.aliases[alias] then return nil, ("trying to define alias %q for variable %q, but already exist and refer to different variable %q; at %s"):format(alias, fqm..".🏁", state.aliases[alias], line.source) end diff --git a/test/run.lua b/test/run.lua index 290722c..fc4de96 100644 --- a/test/run.lua +++ b/test/run.lua @@ -107,7 +107,7 @@ else local namespace = filebase:match("([^/]*)$") math.randomseed(0) local vm = anselme() - vm:setaliases("seen", "checkpoint") + vm:setaliases("seen", "checkpoint", "reached") vm:loadfunction { -- custom event test ["wait"] = { diff --git a/test/tests/checkpoint reached seen.ans b/test/tests/checkpoint reached seen.ans new file mode 100644 index 0000000..b27048c --- /dev/null +++ b/test/tests/checkpoint reached seen.ans @@ -0,0 +1,8 @@ +Β§ p + seen! + +Seen: {p.seen} + +Reached: {p.reached} + +@p ~ !p.seen diff --git a/test/tests/checkpoint reached seen.lua b/test/tests/checkpoint reached seen.lua new file mode 100644 index 0000000..0980bd2 --- /dev/null +++ b/test/tests/checkpoint reached seen.lua @@ -0,0 +1,46 @@ +local _={} +_[21]={} +_[20]={} +_[19]={} +_[18]={} +_[17]={} +_[16]={data="Reached: 2",tags=_[21]} +_[15]={data="Seen: 1",tags=_[20]} +_[14]={data="seen!",tags=_[19]} +_[13]={data="Reached: 1",tags=_[18]} +_[12]={data="Seen: 0",tags=_[17]} +_[11]={_[16]} +_[10]={_[15]} +_[9]={_[14]} +_[8]={_[13]} +_[7]={_[12]} +_[6]={"return"} +_[5]={"text",_[11]} +_[4]={"text",_[10]} +_[3]={"text",_[9]} +_[2]={"text",_[8]} +_[1]={"text",_[7]} +return {_[1],_[2],_[3],_[4],_[5],_[6]} +--[[ +{ "text", { { + data = "Seen: 0", + tags = {} + } } } +{ "text", { { + data = "Reached: 1", + tags = {} + } } } +{ "text", { { + data = "seen!", + tags = {} + } } } +{ "text", { { + data = "Seen: 1", + tags = {} + } } } +{ "text", { { + data = "Reached: 2", + tags = {} + } } } +{ "return" } +]]-- \ No newline at end of file