mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49:31 +00:00
[language] replace constant symbols with a constant value check function
This commit is contained in:
parent
b534a3c4a2
commit
aaff625b6c
15 changed files with 31 additions and 37 deletions
|
|
@ -31,12 +31,9 @@ local VariableMetadata = ast.abstract.Runtime {
|
|||
return self.symbol
|
||||
end,
|
||||
set = function(self, state, value)
|
||||
if self.symbol.constant then
|
||||
error(("trying to change the value of constant %s"):format(self.symbol.string:format(state)), 0)
|
||||
end
|
||||
if self.symbol.value_check then
|
||||
local r = self.symbol.value_check:call(state, ArgumentTuple:new(value))
|
||||
if not r:truthy() then error(("value check failure for %s; %s does not satisfy %s"):format(self.symbol.string:format(state), value, self.symbol.value_check:format(state)), 0) end
|
||||
if not r:truthy() then error(("can not set %s = %s; %s value check failed"):format(self.symbol.string:format(state), value, self.symbol.value_check:format_short(state)), 0) end
|
||||
end
|
||||
if self.symbol.alias then
|
||||
local assign_args = ArgumentTuple:new()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ Symbol = ast.abstract.Node {
|
|||
type = "symbol",
|
||||
|
||||
string = nil,
|
||||
constant = nil, -- bool
|
||||
alias = nil, -- bool
|
||||
exported = nil, -- bool
|
||||
value_check = nil, -- exp
|
||||
|
|
@ -18,7 +17,6 @@ Symbol = ast.abstract.Node {
|
|||
init = function(self, str, modifiers)
|
||||
modifiers = modifiers or {}
|
||||
self.string = str
|
||||
self.constant = modifiers.constant
|
||||
self.value_check = modifiers.value_check
|
||||
self.alias = modifiers.alias
|
||||
self.confined_to_branch = modifiers.confined_to_branch
|
||||
|
|
@ -26,7 +24,7 @@ Symbol = ast.abstract.Node {
|
|||
end,
|
||||
with = function(self, modifiers)
|
||||
modifiers = modifiers or {}
|
||||
for _, k in ipairs{"constant", "value_check", "alias", "exported", "confined_to_branch"} do
|
||||
for _, k in ipairs{"value_check", "alias", "exported", "confined_to_branch"} do
|
||||
if modifiers[k] == nil then
|
||||
modifiers[k] = self[k]
|
||||
end
|
||||
|
|
@ -48,9 +46,6 @@ Symbol = ast.abstract.Node {
|
|||
|
||||
_hash = function(self)
|
||||
local prefix = ""
|
||||
if self.constant then
|
||||
prefix = prefix .. ":"
|
||||
end
|
||||
if self.alias then
|
||||
prefix = prefix .. "&"
|
||||
end
|
||||
|
|
@ -66,9 +61,6 @@ Symbol = ast.abstract.Node {
|
|||
|
||||
_format = function(self, state, prio, ...)
|
||||
local s = ":"
|
||||
if self.constant then
|
||||
s = s .. ":"
|
||||
end
|
||||
if self.alias then
|
||||
s = s .. "&"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -159,19 +159,18 @@ end
|
|||
|
||||
return primary {
|
||||
match = function(self, str)
|
||||
return str:match("^%::?&?@?%$")
|
||||
return str:match("^%:&?@?%$")
|
||||
end,
|
||||
|
||||
parse = function(self, source, options, str)
|
||||
local source_start = source:clone()
|
||||
local mod_const, mod_alias, mod_exported, rem = source:consume(str:match("^(%:(:?)(&?)(@?)%$)(.-)$"))
|
||||
local mod_alias, mod_exported, rem = source:consume(str:match("^(%:(&?)(@?)%$)(.-)$"))
|
||||
|
||||
-- get modifiers
|
||||
local constant, exported, alias
|
||||
if mod_const == ":" then constant = true end
|
||||
local exported, alias
|
||||
if mod_alias == "&" then alias = true end
|
||||
if mod_exported == "@" then exported = true end
|
||||
local modifiers = { constant = constant, exported = exported, alias = alias }
|
||||
local modifiers = { exported = exported, alias = alias }
|
||||
|
||||
-- search for a valid signature
|
||||
local symbol, parameters
|
||||
|
|
|
|||
|
|
@ -8,18 +8,17 @@ local Nil = ast.Nil
|
|||
|
||||
return primary {
|
||||
match = function(self, str)
|
||||
if str:match("^%::?&?@?") then
|
||||
if str:match("^%:&?@?") then
|
||||
return identifier:match(str:match("^%::?&?@?(.-)$"))
|
||||
end
|
||||
return false
|
||||
end,
|
||||
|
||||
parse = function(self, source, options, str)
|
||||
local mod_const, mod_alias, mod_export, rem = source:consume(str:match("^(%:(:?)(&?)(@?))(.-)$"))
|
||||
local constant, alias, value_check_exp, exported
|
||||
local mod_alias, mod_export, rem = source:consume(str:match("^(%:(&?)(@?))(.-)$"))
|
||||
local alias, value_check_exp, exported
|
||||
|
||||
-- get modifier
|
||||
if mod_const == ":" then constant = true end
|
||||
if mod_alias == "&" then alias = true end
|
||||
if mod_export == "@" then exported = true end
|
||||
|
||||
|
|
@ -35,6 +34,6 @@ return primary {
|
|||
value_check_exp = exp.arguments.positional[2]
|
||||
end
|
||||
|
||||
return ident:to_symbol{ constant = constant, alias = alias, exported = exported, value_check = value_check_exp }:set_source(source), rem
|
||||
return ident:to_symbol{ alias = alias, exported = exported, value_check = value_check_exp }:set_source(source), rem
|
||||
end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ local ScopeStack = class {
|
|||
-- for lua functions: define_lua("name", "(x, y, z=5)", function(x, y, z) ... end), where arguments and return values of the function are automatically converted between anselme and lua values
|
||||
-- for other lua values: define_lua("name", value)
|
||||
-- for anselme AST: define_lua("name", value)
|
||||
-- name can be prefixed with symbol modifiers, for example ":name" for a constant variable
|
||||
-- name can be prefixed with symbol modifiers, for example "@name" for an exported variable
|
||||
-- if `raw_mode` is true, no anselme-to/from-lua conversion will be performed in the function
|
||||
-- the function will receive the state followed by AST nodes as arguments, and is expected to return an AST node
|
||||
define_lua = function(self, name, value, func, raw_mode)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ State = class {
|
|||
-- * for other lua values: `define("name", value)`
|
||||
-- * for anselme AST: `define("name", value)`
|
||||
--
|
||||
-- `name` can be prefixed with symbol modifiers, for example ":name" for a constant variable.
|
||||
-- `name` can be prefixed with symbol modifiers, for example "@name" for an exported variable.
|
||||
--
|
||||
-- If `raw_mode` is true, no anselme-to/from-lua conversion will be performed in the function.
|
||||
-- The function will receive the state followed by AST nodes as arguments, and is expected to return an AST node.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@ local ast = require("anselme.ast")
|
|||
local Nil, Boolean, LuaCall, ParameterTuple, FunctionParameter, Identifier, Overloadable, Overload, Call, Quote = ast.Nil, ast.Boolean, ast.LuaCall, ast.ParameterTuple, ast.FunctionParameter, ast.Identifier, ast.abstract.Overloadable, ast.Overload, ast.Call, ast.Quote
|
||||
|
||||
return {
|
||||
{
|
||||
"constant", "(exp)",
|
||||
function(state, exp)
|
||||
return Boolean:new(false)
|
||||
end
|
||||
},
|
||||
|
||||
{
|
||||
"is tuple", "(exp)",
|
||||
function(state, exp)
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ Define a value in the global scope, converting it from Lua to Anselme if needed.
|
|||
* for other lua values: `define("name", value)`
|
||||
* for anselme AST: `define("name", value)`
|
||||
|
||||
`name` can be prefixed with symbol modifiers, for example ":name" for a constant variable.
|
||||
`name` can be prefixed with symbol modifiers, for example "@name" for an exported variable.
|
||||
|
||||
If `raw_mode` is true, no anselme-to/from-lua conversion will be performed in the function.
|
||||
The function will receive the state followed by AST nodes as arguments, and is expected to return an AST node.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
--# run #--
|
||||
--- error ---
|
||||
[0m[31m[0m[31mtrying to change the value of constant a[0m
|
||||
[0m[31m[0m[31mcan not set a = 52; constant value check failed[0m
|
||||
↳ from [4mtest/tests/constant variable.ans:5:3[0m in call: [2ma = 52[0m[0m
|
||||
↳ from [4mtest/tests/constant variable.ans:1:1[0m in block: [2m::a = 3…[0m
|
||||
↳ from [4mtest/tests/constant variable.ans:1:1[0m in block: [2m:a::constant = 3…[0m
|
||||
--# saved #--
|
||||
{}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
--- text ---
|
||||
| {}"" {}"type(12, \"kg\")" {}"" |
|
||||
--- error ---
|
||||
[0m[31m[0m[31mvalue check failure for weigh; 32 does not satisfy $(x) type(x) == t[0m
|
||||
[0m[31m[0m[31mcan not set weigh = 32; $(x) type(x) == t value check failed[0m
|
||||
↳ from [4mtest/tests/constrained variable assignement.ans:9:7[0m in call: [2mweigh = 32[0m[0m
|
||||
↳ from [4mtest/tests/constrained variable assignement.ans:1:1[0m in block: [2m:weigh::is("kg") = type(5, "kg")…[0m
|
||||
--# saved #--
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
--- text ---
|
||||
| {}"d=" {}"2" {}" (2)" |
|
||||
--- error ---
|
||||
[0m[31m[0m[31mtrying to change the value of constant d[0m
|
||||
[0m[31m[0m[31mcan not set d = 5; constant value check failed[0m
|
||||
↳ from [4mtest/tests/symbol alias constant.ans:12:3[0m in call: [2md = 5[0m[0m
|
||||
↳ from [4mtest/tests/symbol alias constant.ans:1:1[0m in block: [2m:l = *[1, 2, 3]…[0m
|
||||
--# saved #--
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
::a = *[3]
|
||||
:a::constant = *[3]
|
||||
|
||||
|{a}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
::a = 3
|
||||
:a::constant = 3
|
||||
|
||||
{a}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
::a = [1:2]
|
||||
:a::constant = [1:2]
|
||||
|
||||
|false = {a == [5:2]}
|
||||
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|true = {a == [1:2]}
|
||||
|
||||
::b = [1,2,3]
|
||||
:b::constant = [1,2,3]
|
||||
|
||||
|false = {b == a}
|
||||
|
||||
|
|
@ -24,6 +24,6 @@
|
|||
|
||||
|true = {c!to tuple == b}
|
||||
|
||||
::d = [1,2,3]
|
||||
:d::constant = [1,2,3]
|
||||
|
||||
|true = {d == b}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
:l = *[1,2,3]
|
||||
|
||||
::&c => l(2)
|
||||
:&c::constant => l(2)
|
||||
|
||||
| c={c} (2)
|
||||
| l={l} (*[1,2,3])
|
||||
|
||||
::&d = "{l(2)}"
|
||||
:&d::constant = "{l(2)}"
|
||||
|
||||
| d={c} (2)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue