1
0
Fork 0
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:
Étienne Fildadut 2024-04-24 16:15:58 +02:00
parent b534a3c4a2
commit aaff625b6c
15 changed files with 31 additions and 37 deletions

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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)

View file

@ -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.

View file

@ -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)

View file

@ -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.

View file

@ -1,7 +1,7 @@
--# run #--
--- error ---
trying to change the value of constant a
can not set a = 52; constant value check failed
↳ from test/tests/constant variable.ans:5:3 in call: a = 52
↳ from test/tests/constant variable.ans:1:1 in block: ::a = 3…
↳ from test/tests/constant variable.ans:1:1 in block: :a::constant = 3…
--# saved #--
{}

View file

@ -4,7 +4,7 @@
--- text ---
| {}"" {}"type(12, \"kg\")" {}"" |
--- error ---
value check failure for weigh; 32 does not satisfy $(x) type(x) == t
can not set weigh = 32; $(x) type(x) == t value check failed
↳ from test/tests/constrained variable assignement.ans:9:7 in call: weigh = 32
↳ from test/tests/constrained variable assignement.ans:1:1 in block: :weigh::is("kg") = type(5, "kg")…
--# saved #--

View file

@ -5,7 +5,7 @@
--- text ---
| {}"d=" {}"2" {}" (2)" |
--- error ---
trying to change the value of constant d
can not set d = 5; constant value check failed
↳ from test/tests/symbol alias constant.ans:12:3 in call: d = 5
↳ from test/tests/symbol alias constant.ans:1:1 in block: :l = *[1, 2, 3]…
--# saved #--

View file

@ -1,4 +1,4 @@
::a = *[3]
:a::constant = *[3]
|{a}

View file

@ -1,4 +1,4 @@
::a = 3
:a::constant = 3
{a}

View file

@ -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}

View file

@ -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)