mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-27 16:49: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 `()`.
|
||||
|
||||
`{}(v)`: function called when formatting a value in a text interpolation for printing
|
||||
|
||||
#### Built-in functions
|
||||
|
||||
##### Pair methods
|
||||
|
|
@ -847,7 +849,7 @@ This only works on strings:
|
|||
|
||||
##### 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.
|
||||
|
||||
|
|
|
|||
49
anselme.lua
49
anselme.lua
|
|
@ -10,19 +10,18 @@ local anselme = {
|
|||
}
|
||||
package.loaded[...] = anselme
|
||||
|
||||
i = require("inspect") -- luacheck: ignore
|
||||
|
||||
-- load libs
|
||||
local preparse = require((...):gsub("anselme$", "parser.preparser"))
|
||||
local postparse = require((...):gsub("anselme$", "parser.postparser"))
|
||||
local expression = require((...):gsub("anselme$", "parser.expression"))
|
||||
local eval = require((...):gsub("anselme$", "interpreter.expression"))
|
||||
local run_line = require((...):gsub("anselme$", "interpreter.interpreter")).run_line
|
||||
local to_lua = require((...):gsub("anselme$", "interpreter.common")).to_lua
|
||||
local identifier_pattern = require((...):gsub("anselme$", "parser.common")).identifier_pattern
|
||||
local merge_state = require((...):gsub("anselme$", "interpreter.common")).merge_state
|
||||
local stdfuncs = require((...):gsub("anselme$", "stdlib.functions"))
|
||||
local bootscript = require((...):gsub("anselme$", "stdlib.bootscript"))
|
||||
local anselme_root = (...):gsub("anselme$", "")
|
||||
local preparse = require(anselme_root.."parser.preparser")
|
||||
local postparse = require(anselme_root.."parser.postparser")
|
||||
local expression = require(anselme_root.."parser.expression")
|
||||
local eval = require(anselme_root.."interpreter.expression")
|
||||
local run_line = require(anselme_root.."interpreter.interpreter").run_line
|
||||
local to_lua = require(anselme_root.."interpreter.common").to_lua
|
||||
local identifier_pattern = require(anselme_root.."parser.common").identifier_pattern
|
||||
local merge_state = require(anselme_root.."interpreter.common").merge_state
|
||||
local stdfuncs = require(anselme_root.."stdlib.functions")
|
||||
local bootscript = require(anselme_root.."stdlib.bootscript")
|
||||
|
||||
-- wrappers for love.filesystem / luafilesystem
|
||||
local function list_directory(path)
|
||||
|
|
@ -179,11 +178,13 @@ local vm_mt = {
|
|||
|
||||
--- wrapper for loading a whole set of scripts
|
||||
-- should be preferred to other loading functions if possible
|
||||
-- requires LÖVE or LuaFileSystem
|
||||
-- will load in path, in order:
|
||||
-- * config.ans, which contains various optional configuration options:
|
||||
-- * 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, 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)
|
||||
|
|
@ -199,8 +200,14 @@ local vm_mt = {
|
|||
local checkpoint_alias = self:eval("config.alias 🔖")
|
||||
local reached_alias = self:eval("config.alias 🏁")
|
||||
local main_file = self:eval("config.main file")
|
||||
local language = self:eval("config.language")
|
||||
-- set aliases
|
||||
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
|
||||
if main_file then
|
||||
local s, e = self:loadfile(path.."/"..main_file..".ans")
|
||||
|
|
@ -224,7 +231,7 @@ local vm_mt = {
|
|||
|
||||
--- load code
|
||||
-- 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
|
||||
-- returns nil, err in case of error
|
||||
loadstring = function(self, str, name, source)
|
||||
|
|
@ -248,7 +255,7 @@ local vm_mt = {
|
|||
if not s then return s, err end
|
||||
return self
|
||||
end,
|
||||
loaddirectory = function(self, path, name)
|
||||
loaddirectory = function(self, path, name) -- requires LÖVE or LuaFileSystem
|
||||
if not name then name = "" end
|
||||
name = name == "" and "" or name.."."
|
||||
for _, item in ipairs(list_directory(path)) do
|
||||
|
|
@ -276,6 +283,18 @@ local vm_mt = {
|
|||
return self
|
||||
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
|
||||
-- signature: full signature of the function
|
||||
-- fn: function (Lua function or table, see examples in stdlib/functions.lua)
|
||||
|
|
@ -374,7 +393,7 @@ local vm_mt = {
|
|||
-- expr: expression to evaluate
|
||||
-- namespace(default=""): namespace to evaluate the expression in
|
||||
-- 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
|
||||
eval = function(self, expr, 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?
|
||||
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.
|
||||
* 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"?
|
||||
One of the different forms of a same function with a given fqm. No idea why I chose "variant".
|
||||
* Why emojis?
|
||||
|
|
@ -54,9 +56,6 @@ Disadvantages:
|
|||
* idk if it's worth the trouble
|
||||
* 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: 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
|
||||
functions = {
|
||||
|
|
@ -124,6 +124,24 @@ functions = {
|
|||
return v
|
||||
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
|
||||
["name(p::pair)"] = {
|
||||
mode = "untyped raw",
|
||||
|
|
@ -188,7 +206,7 @@ functions = {
|
|||
},
|
||||
-- other methods
|
||||
["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, b::number)"] = function(a, b) return math.random(a, b) end,
|
||||
["raw(v)"] = {
|
||||
|
|
@ -251,6 +269,8 @@ functions = {
|
|||
}
|
||||
|
||||
package.loaded[...] = functions
|
||||
local common = require((...):gsub("stdlib%.functions$", "interpreter.common"))
|
||||
truthy, compare, is_of_type = common.truthy, common.compare, common.is_of_type
|
||||
local icommon = require((...):gsub("stdlib%.functions$", "interpreter.common"))
|
||||
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"))
|
||||
|
|
|
|||
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
|
||||
if args.script then
|
||||
local vm = anselme()
|
||||
if args.lang then
|
||||
assert(vm:loadlanguage(args.lang))
|
||||
end
|
||||
local state, err = vm:loadfile(args.script, "script")
|
||||
if state then
|
||||
local istate, e = vm:run("script")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue