mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-28 00:59:31 +00:00
Add alias() to define alias after definition; add frFR language file
This commit is contained in:
parent
198c06e2e8
commit
61e3143e9e
6 changed files with 91 additions and 23 deletions
|
|
@ -819,6 +819,8 @@ This only works on strings:
|
||||||
|
|
||||||
`a(b)`: evaluate b (number), returns the value with this index in a (list). Use 1-based indexing. If b is a string, will search the first pair in the list with this string as its name. Operator is named `()`.
|
`a(b)`: evaluate b (number), returns the value with this index in a (list). Use 1-based indexing. If b is a string, will search the first pair in the list with this string as its name. Operator is named `()`.
|
||||||
|
|
||||||
|
`{}(v)`: function called when formatting a value in a text interpolation for printing
|
||||||
|
|
||||||
#### Built-in functions
|
#### Built-in functions
|
||||||
|
|
||||||
##### Pair methods
|
##### Pair methods
|
||||||
|
|
@ -847,7 +849,7 @@ This only works on strings:
|
||||||
|
|
||||||
##### Various
|
##### Various
|
||||||
|
|
||||||
`{}(v)`: function called when formatting a value in a text interpolation for printing
|
`alias(identifier::string, alias::string)`: define an alias `alias` for variable `identifier`. Expect fully qualified names.
|
||||||
|
|
||||||
`rand([m[, n]])`: when called whitout arguments, returns a random float in [0,1). Otherwise, returns a random number in [m,n]; m=1 if not given.
|
`rand([m[, n]])`: when called whitout arguments, returns a random float in [0,1). Otherwise, returns a random number in [m,n]; m=1 if not given.
|
||||||
|
|
||||||
|
|
|
||||||
49
anselme.lua
49
anselme.lua
|
|
@ -10,19 +10,18 @@ local anselme = {
|
||||||
}
|
}
|
||||||
package.loaded[...] = anselme
|
package.loaded[...] = anselme
|
||||||
|
|
||||||
i = require("inspect") -- luacheck: ignore
|
|
||||||
|
|
||||||
-- load libs
|
-- load libs
|
||||||
local preparse = require((...):gsub("anselme$", "parser.preparser"))
|
local anselme_root = (...):gsub("anselme$", "")
|
||||||
local postparse = require((...):gsub("anselme$", "parser.postparser"))
|
local preparse = require(anselme_root.."parser.preparser")
|
||||||
local expression = require((...):gsub("anselme$", "parser.expression"))
|
local postparse = require(anselme_root.."parser.postparser")
|
||||||
local eval = require((...):gsub("anselme$", "interpreter.expression"))
|
local expression = require(anselme_root.."parser.expression")
|
||||||
local run_line = require((...):gsub("anselme$", "interpreter.interpreter")).run_line
|
local eval = require(anselme_root.."interpreter.expression")
|
||||||
local to_lua = require((...):gsub("anselme$", "interpreter.common")).to_lua
|
local run_line = require(anselme_root.."interpreter.interpreter").run_line
|
||||||
local identifier_pattern = require((...):gsub("anselme$", "parser.common")).identifier_pattern
|
local to_lua = require(anselme_root.."interpreter.common").to_lua
|
||||||
local merge_state = require((...):gsub("anselme$", "interpreter.common")).merge_state
|
local identifier_pattern = require(anselme_root.."parser.common").identifier_pattern
|
||||||
local stdfuncs = require((...):gsub("anselme$", "stdlib.functions"))
|
local merge_state = require(anselme_root.."interpreter.common").merge_state
|
||||||
local bootscript = require((...):gsub("anselme$", "stdlib.bootscript"))
|
local stdfuncs = require(anselme_root.."stdlib.functions")
|
||||||
|
local bootscript = require(anselme_root.."stdlib.bootscript")
|
||||||
|
|
||||||
-- wrappers for love.filesystem / luafilesystem
|
-- wrappers for love.filesystem / luafilesystem
|
||||||
local function list_directory(path)
|
local function list_directory(path)
|
||||||
|
|
@ -179,11 +178,13 @@ local vm_mt = {
|
||||||
|
|
||||||
--- wrapper for loading a whole set of scripts
|
--- wrapper for loading a whole set of scripts
|
||||||
-- should be preferred to other loading functions if possible
|
-- should be preferred to other loading functions if possible
|
||||||
|
-- requires LÖVE or LuaFileSystem
|
||||||
-- will load in path, in order:
|
-- will load in path, in order:
|
||||||
-- * config.ans, which contains various optional configuration options:
|
-- * config.ans, which contains various optional configuration options:
|
||||||
-- * alias 👁️: string, default alias for 👁️
|
-- * alias 👁️: string, default alias for 👁️
|
||||||
-- * alias 🏁: string, default alias for 🏁
|
-- * alias 🏁: string, default alias for 🏁
|
||||||
-- * alias 🔖: string, default alias for 🔖
|
-- * alias 🔖: string, default alias for 🔖
|
||||||
|
-- * language: string, built-in language file to load
|
||||||
-- * main file: string, name (without .ans extension) of a file that will be loaded into the root namespace
|
-- * 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
|
-- * 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)
|
-- * 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)
|
||||||
|
|
@ -199,8 +200,14 @@ local vm_mt = {
|
||||||
local checkpoint_alias = self:eval("config.alias 🔖")
|
local checkpoint_alias = self:eval("config.alias 🔖")
|
||||||
local reached_alias = self:eval("config.alias 🏁")
|
local reached_alias = self:eval("config.alias 🏁")
|
||||||
local main_file = self:eval("config.main file")
|
local main_file = self:eval("config.main file")
|
||||||
|
local language = self:eval("config.language")
|
||||||
-- set aliases
|
-- set aliases
|
||||||
self:setaliases(seen_alias, checkpoint_alias, reached_alias)
|
self:setaliases(seen_alias, checkpoint_alias, reached_alias)
|
||||||
|
-- load language
|
||||||
|
if language then
|
||||||
|
local s, e = self:loadlanguage(language)
|
||||||
|
if not s then return s, e end
|
||||||
|
end
|
||||||
-- load main file
|
-- load main file
|
||||||
if main_file then
|
if main_file then
|
||||||
local s, e = self:loadfile(path.."/"..main_file..".ans")
|
local s, e = self:loadfile(path.."/"..main_file..".ans")
|
||||||
|
|
@ -224,7 +231,7 @@ local vm_mt = {
|
||||||
|
|
||||||
--- load code
|
--- load code
|
||||||
-- similar to Lua's code loading functions.
|
-- similar to Lua's code loading functions.
|
||||||
-- name(default=""): namespace to load the code in. Will define a new function if needed.
|
-- name(default=""): namespace to load the code in. Will define a new function is specified; otherwise, code will be parsed but not executable from an expression.
|
||||||
-- return self in case of success
|
-- return self in case of success
|
||||||
-- returns nil, err in case of error
|
-- returns nil, err in case of error
|
||||||
loadstring = function(self, str, name, source)
|
loadstring = function(self, str, name, source)
|
||||||
|
|
@ -248,7 +255,7 @@ local vm_mt = {
|
||||||
if not s then return s, err end
|
if not s then return s, err end
|
||||||
return self
|
return self
|
||||||
end,
|
end,
|
||||||
loaddirectory = function(self, path, name)
|
loaddirectory = function(self, path, name) -- requires LÖVE or LuaFileSystem
|
||||||
if not name then name = "" end
|
if not name then name = "" end
|
||||||
name = name == "" and "" or name.."."
|
name = name == "" and "" or name.."."
|
||||||
for _, item in ipairs(list_directory(path)) do
|
for _, item in ipairs(list_directory(path)) do
|
||||||
|
|
@ -276,6 +283,18 @@ local vm_mt = {
|
||||||
return self
|
return self
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
--- load & execute a built-in language file
|
||||||
|
-- return self in case of success
|
||||||
|
-- returns nil, err in case of error
|
||||||
|
loadlanguage = function(self, lang)
|
||||||
|
local code = require(anselme_root.."stdlib.languages."..lang)
|
||||||
|
local s, e = self:loadstring(code, "anselme."..lang, lang)
|
||||||
|
if not s then return s, e end
|
||||||
|
s, e = self:eval("anselme."..lang)
|
||||||
|
if e then return s, e end
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
|
||||||
--- define functions from Lua
|
--- define functions from Lua
|
||||||
-- signature: full signature of the function
|
-- signature: full signature of the function
|
||||||
-- fn: function (Lua function or table, see examples in stdlib/functions.lua)
|
-- fn: function (Lua function or table, see examples in stdlib/functions.lua)
|
||||||
|
|
@ -374,7 +393,7 @@ local vm_mt = {
|
||||||
-- expr: expression to evaluate
|
-- expr: expression to evaluate
|
||||||
-- namespace(default=""): namespace to evaluate the expression in
|
-- namespace(default=""): namespace to evaluate the expression in
|
||||||
-- tags(default={}): defaults tag when evaluating the expression
|
-- tags(default={}): defaults tag when evaluating the expression
|
||||||
-- return value in case of success
|
-- return value in case of success (nil if nothing returned)
|
||||||
-- returns nil, err in case of error
|
-- returns nil, err in case of error
|
||||||
eval = function(self, expr, namespace, tags)
|
eval = function(self, expr, namespace, tags)
|
||||||
local interpreter, err = self:run("0", namespace, tags)
|
local interpreter, err = self:run("0", namespace, tags)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ Reserved symbols that are still not used as a line type: `^+-=</[]*{}|\_!?.,;)"&
|
||||||
* What does "fqm" means?
|
* What does "fqm" means?
|
||||||
It means "fully qualified matriname", which is the same as a fully qualified name, but considers the hierarchy to be mostly mother-daugher based.
|
It means "fully qualified matriname", which is the same as a fully qualified name, but considers the hierarchy to be mostly mother-daugher based.
|
||||||
It has nothing to do with the fact I'm inept at writing acronyms and realized I wrote it wrong after using it for a whole year.
|
It has nothing to do with the fact I'm inept at writing acronyms and realized I wrote it wrong after using it for a whole year.
|
||||||
|
* Why are built-in anselme scripts stored in Lua files?
|
||||||
|
I believe it was to avoid reimplementing the require() file search algorithm myself.
|
||||||
* What's a "variant"?
|
* What's a "variant"?
|
||||||
One of the different forms of a same function with a given fqm. No idea why I chose "variant".
|
One of the different forms of a same function with a given fqm. No idea why I chose "variant".
|
||||||
* Why emojis?
|
* Why emojis?
|
||||||
|
|
@ -54,9 +56,6 @@ Disadvantages:
|
||||||
* idk if it's worth the trouble
|
* idk if it's worth the trouble
|
||||||
* could do something like `$ ()(l::list(?), i::number)::?`, but then can't return nil on not found...
|
* could do something like `$ ()(l::list(?), i::number)::?`, but then can't return nil on not found...
|
||||||
|
|
||||||
TODO: allow to define aliases after the initial definition
|
|
||||||
~ alias(number, "nombre")
|
|
||||||
|
|
||||||
TODO: ensure that most stuff in the state stays consistent after an error was thrown
|
TODO: ensure that most stuff in the state stays consistent after an error was thrown
|
||||||
|
|
||||||
TODO: way to migrate save files
|
TODO: way to migrate save files
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
local truthy, anselme, compare, is_of_type
|
local truthy, anselme, compare, is_of_type, identifier_pattern, format_identifier
|
||||||
|
|
||||||
local functions
|
local functions
|
||||||
functions = {
|
functions = {
|
||||||
|
|
@ -124,6 +124,24 @@ functions = {
|
||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
-- alias
|
||||||
|
["alias(identifier::string, alias::string)"] = {
|
||||||
|
value = function(identifier, alias)
|
||||||
|
-- check identifiers
|
||||||
|
local fqm = identifier:match("^"..identifier_pattern.."$")
|
||||||
|
if not fqm then error(("%q is not a valid identifier"):format(identifier)) end
|
||||||
|
fqm = format_identifier(fqm)
|
||||||
|
local aliasfqm = alias:match("^"..identifier_pattern.."$")
|
||||||
|
if not aliasfqm then error(("%q is not a valid identifier for an alias"):format(alias)) end
|
||||||
|
aliasfqm = format_identifier(aliasfqm)
|
||||||
|
-- define alias
|
||||||
|
local aliases = anselme.running.state.aliases
|
||||||
|
if aliases[aliasfqm] ~= nil and aliases[aliasfqm] ~= fqm then
|
||||||
|
error(("trying to define alias %q for %q, but already exist and refer to %q"):format(aliasfqm, fqm, aliases[alias]))
|
||||||
|
end
|
||||||
|
aliases[aliasfqm] = fqm
|
||||||
|
end
|
||||||
|
},
|
||||||
-- pair methods
|
-- pair methods
|
||||||
["name(p::pair)"] = {
|
["name(p::pair)"] = {
|
||||||
mode = "untyped raw",
|
mode = "untyped raw",
|
||||||
|
|
@ -188,7 +206,7 @@ functions = {
|
||||||
},
|
},
|
||||||
-- other methods
|
-- other methods
|
||||||
["error(m::string)"] = function(m) error(m, 0) end,
|
["error(m::string)"] = function(m) error(m, 0) end,
|
||||||
["rand"] = function() return math.random() end,
|
["rand()"] = function() return math.random() end,
|
||||||
["rand(a::number)"] = function(a) return math.random(a) end,
|
["rand(a::number)"] = function(a) return math.random(a) end,
|
||||||
["rand(a::number, b::number)"] = function(a, b) return math.random(a, b) end,
|
["rand(a::number, b::number)"] = function(a, b) return math.random(a, b) end,
|
||||||
["raw(v)"] = {
|
["raw(v)"] = {
|
||||||
|
|
@ -251,6 +269,8 @@ functions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
package.loaded[...] = functions
|
package.loaded[...] = functions
|
||||||
local common = require((...):gsub("stdlib%.functions$", "interpreter.common"))
|
local icommon = require((...):gsub("stdlib%.functions$", "interpreter.common"))
|
||||||
truthy, compare, is_of_type = common.truthy, common.compare, common.is_of_type
|
truthy, compare, is_of_type = icommon.truthy, icommon.compare, icommon.is_of_type
|
||||||
|
local pcommon = require((...):gsub("stdlib%.functions$", "parser.common"))
|
||||||
|
identifier_pattern, format_identifier = pcommon.identifier_pattern, pcommon.format_identifier
|
||||||
anselme = require((...):gsub("stdlib%.functions$", "anselme"))
|
anselme = require((...):gsub("stdlib%.functions$", "anselme"))
|
||||||
|
|
|
||||||
25
stdlib/languages/frFR.lua
Normal file
25
stdlib/languages/frFR.lua
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
return [[
|
||||||
|
(Types)
|
||||||
|
~ "nil".alias("nul")
|
||||||
|
~ "number".alias("nombre")
|
||||||
|
~ "string".alias("texte")
|
||||||
|
~ "list".alias("liste")
|
||||||
|
~ "pair".alias("paire")
|
||||||
|
|
||||||
|
(Built-in functions)
|
||||||
|
(~ "alias".alias("alias")
|
||||||
|
~ "name".alias("nom")
|
||||||
|
~ "value".alias("valeur")
|
||||||
|
~ "len".alias("longueur")
|
||||||
|
~ "insert".alias("ajouter")
|
||||||
|
~ "remove".alias("retirer")
|
||||||
|
~ "find".alias("trouver")
|
||||||
|
~ "error".alias("erreur")
|
||||||
|
~ "rand".alias("aléa")
|
||||||
|
~ "raw".alias("brut")
|
||||||
|
(~ "type".alias("type")
|
||||||
|
~ "is of type".alias("est de type")
|
||||||
|
~ "cycle".alias("cycler")
|
||||||
|
~ "random".alias("aléatoire")
|
||||||
|
~ "next".alias("séquence")
|
||||||
|
]]
|
||||||
|
|
@ -75,6 +75,9 @@ table.sort(files)
|
||||||
-- test script
|
-- test script
|
||||||
if args.script then
|
if args.script then
|
||||||
local vm = anselme()
|
local vm = anselme()
|
||||||
|
if args.lang then
|
||||||
|
assert(vm:loadlanguage(args.lang))
|
||||||
|
end
|
||||||
local state, err = vm:loadfile(args.script, "script")
|
local state, err = vm:loadfile(args.script, "script")
|
||||||
if state then
|
if state then
|
||||||
local istate, e = vm:run("script")
|
local istate, e = vm:run("script")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue