From 9bd97591150264dd9dfd2f679cdf69d4186cf38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Reuh=20Fildadut?= Date: Mon, 6 Dec 2021 01:45:19 +0100 Subject: [PATCH] Rename overloaded operators (add underscores) * add suffix unary operators * add _! operator * _._ and _&_ operator overloading * allow calling function references with _! and access variables with _._ * rename . method operator to ! * various cleaning & improvements Documentation will follow at some point. --- interpreter/expression.lua | 27 +- parser/common.lua | 39 ++- parser/expression.lua | 297 ++++++++++-------- parser/postparser.lua | 2 +- stdlib/functions.lua | 61 ++-- stdlib/languages/enUS.lua | 6 + test/tests/binary operator overload.ans | 4 +- test/tests/binop assignement.ans | 7 + test/tests/binop assignement.lua | 22 ++ .../checkpoint merging mutable value.ans | 6 +- test/tests/function reference chain call.ans | 13 + test/tests/function reference chain call.lua | 30 ++ test/tests/function ufcs arg.ans | 4 +- test/tests/function ufcs args.ans | 2 +- test/tests/named varag.ans | 4 +- test/tests/unary operator overload.ans | 4 +- 16 files changed, 350 insertions(+), 178 deletions(-) create mode 100644 stdlib/languages/enUS.lua create mode 100644 test/tests/binop assignement.ans create mode 100644 test/tests/binop assignement.lua create mode 100644 test/tests/function reference chain call.ans create mode 100644 test/tests/function reference chain call.lua diff --git a/interpreter/expression.lua b/interpreter/expression.lua index d3600ec..d3e4379 100644 --- a/interpreter/expression.lua +++ b/interpreter/expression.lua @@ -164,10 +164,15 @@ local function eval(state, exp) end -- function reference: call the referenced function local variants = exp.variants - if exp.called_name == "()" and args[1].type == "function reference" then + local paren_call = exp.paren_call + if args[1] and args[1].type == "function reference" and (exp.called_name == "()" or exp.called_name == "_!") then -- remove func ref as first arg local refv = args[1].value table.remove(args, 1) + -- set paren_call for _! + if exp.called_name == "_!" then + paren_call = false + end -- get variants of the referenced function variants = {} for _, ffqm in ipairs(refv) do @@ -333,7 +338,7 @@ local function eval(state, exp) if selected_variant.variant then local fn = selected_variant.variant if fn.type == "checkpoint" then - local r, e = run(state, fn.child, not exp.explicit_call) + local r, e = run(state, fn.child, not paren_call) if not r then return r, e end return r elseif fn.type == "function" then @@ -361,9 +366,14 @@ local function eval(state, exp) final_args[#final_args+1] = v end -- execute function - -- raw mode: pass raw anselme values to the Lua function + -- raw mode: pass raw anselme values to the Lua function; support return nil, err in case of error if lua_fn.mode == "raw" then - ret = lua_fn.value(unpack(final_args)) + local r, e = lua_fn.value(unpack(final_args)) + if r then + ret = r + else + return nil, ("%s; in Lua function %q"):format(e, exp.called_name) + end -- untyped raw mode: same as raw, but strips custom types from the arguments elseif lua_fn.mode == "untyped raw" then -- extract value from custom types @@ -372,7 +382,12 @@ local function eval(state, exp) final_args[i] = arg.value[1] end end - ret = lua_fn.value(unpack(final_args)) + local r, e = lua_fn.value(unpack(final_args)) + if r then + ret = r + else + return nil, ("%s; in Lua function %q"):format(e, exp.called_name) + end -- normal mode: convert args to Lua and convert back Lua value to Anselme elseif lua_fn.mode == nil then local l_lua = {} @@ -397,7 +412,7 @@ local function eval(state, exp) else local e -- eval function from start - if exp.explicit_call or checkpoint.value == "" then + if paren_call or checkpoint.value == "" then ret, e = run(state, fn.child) -- resume at last checkpoint else diff --git a/parser/common.lua b/parser/common.lua index b9d1e7d..c85b0ff 100644 --- a/parser/common.lua +++ b/parser/common.lua @@ -25,20 +25,28 @@ common = { identifier_pattern = "%s*[^0-9%s"..disallowed_set.."][^"..disallowed_set.."]*", -- names allowed for a function that aren't valid identifiers, mainly for overloading operators special_functions_names = { - -- operators not included here: + -- operators not included here and why: -- * assignment operators (:=, +=, -=, //=, /=, *=, %=, ^=): handled with its own syntax (function assignment) -- * list operator (,): is used when calling every functions, sounds like more trouble than it's worth -- * |, & and ~ operators: are lazy and don't behave like regular functions - -- * # operator: need to set tag state before evaluating the left arg - -- * . operator: don't behave like regular functions either - ";", - "!=", "==", ">=", "<=", "<", ">", - "+", "-", - "*", "//", "/", "%", - "::", ":", - "!", - "^", - "()", "{}" + -- * # operator: need to set tag state _before_ evaluating the left arg + + -- prefix unop + "-_", "!_", + "&_", + -- binop + "_;_", + "_!=_", "_==_", "_>=_", "_<=_", "_<_", "_>_", + "_+_", "_-_", + "_*_", "_//_", "_/_", "_%_", + "_::_", "_:_", + "_^_", + "_._", "_!_", + -- suffix unop + "_!", + -- special + "()", + "{}" }, -- escapement code and their value in strings -- I don't think there's a point in supporting form feed, carriage return, and other printer and terminal related codes @@ -248,7 +256,7 @@ common = { --- same as find_function_variant_from_fqm, but will search every function from the current namespace and up using find -- returns directly a function expression in case of success -- return nil, err otherwise - find_function = function(state, namespace, name, arg, explicit_call) + find_function = function(state, namespace, name, arg, paren_call, implicit_call) local variants = {} local err = ("compatible function %q variant not found"):format(name) local l = common.find_all(state.aliases, state.functions, namespace, name) @@ -264,9 +272,10 @@ common = { if #variants > 0 then return { type = "function call", - called_name = name, - explicit_call = explicit_call, - variants = variants, + called_name = name, -- name of the called function + paren_call = paren_call, -- was call with parantheses? + implicit_call = implicit_call, -- was call implicitely (no ! or parentheses)? + variants = variants, -- list of potential variants argument = { -- wrap everything in a list literal to simplify later things (otherwise may be nil, single value, list constructor) type = "list_brackets", expression = arg diff --git a/parser/expression.lua b/parser/expression.lua index 0f6910f..82fe714 100644 --- a/parser/expression.lua +++ b/parser/expression.lua @@ -1,4 +1,4 @@ -local identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all +local identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all, split --- binop priority local binops_prio = { @@ -12,10 +12,11 @@ local binops_prio = { [8] = { "::", ":" }, [9] = {}, -- unary operators [10] = { "^" }, - [11] = { "." } + [11] = { ".", "!" }, + [12] = {} } -- unop priority -local unops_prio = { +local prefix_unops_prio = { [1] = {}, [2] = {}, [3] = {}, @@ -27,6 +28,21 @@ local unops_prio = { [9] = { "-", "!" }, [10] = {}, [11] = {}, + [12] = { "&" } +} +local suffix_unops_prio = { + [1] = {}, + [2] = {}, + [3] = {}, + [4] = {}, + [5] = {}, + [6] = {}, + [7] = {}, + [8] = {}, + [9] = {}, + [10] = {}, + [11] = { "!" }, + [12] = {} } local function get_text_in_litteral(s, start_pos) @@ -132,33 +148,30 @@ local function expression(s, state, namespace, current_priority, operating_on) right = val } -- find compatible variant - local variant, err = find_function(state, namespace, ":", args, true) + local variant, err = find_function(state, namespace, "_:_", args, true) if not variant then return variant, err end return expression(r, state, namespace, current_priority, variant) end -- variables - local var, vfqm = find(state.aliases, state.variables, namespace, name) - if var then - return expression(r, state, namespace, current_priority, { - type = "variable", - name = vfqm - }) - end - -- suffix call: detect if prefix is valid variable, suffix call is handled in the binop section below - local sname, suffix = name:match("^(.*)(%."..identifier_pattern..")$") - if sname then - local svar, svfqm = find(state.aliases, state.variables, namespace, sname) - if svar then - return expression(suffix..r, state, namespace, current_priority, { + -- if name isn't a valid variable, suffix call: detect if a prefix is valid variable, suffix _._ call is handled in the binop section below + local nl = split(name) + for i=#nl, 1, -1 do + local name_prefix = table.concat(nl, ".", 1, i) + local var, vfqm = find(state.aliases, state.variables, namespace, name_prefix) + if var then + if i < #nl then + r = "."..table.concat(nl, ".", i+1, #nl)..r + end + return expression(r, state, namespace, current_priority, { type = "variable", - name = svfqm + name = vfqm }) end end -- function call - local args, explicit_call + local args, paren_call, implicit_call if r:match("^%b()") then - explicit_call = true + paren_call = true local content, rem = r:match("^(%b())(.*)$") content = content:gsub("^%(", ""):gsub("%)$", "") r = rem @@ -169,38 +182,50 @@ local function expression(s, state, namespace, current_priority, operating_on) if not args then return args, err end if err:match("[^%s]") then return nil, ("unexpected %q at end of argument list"):format(err) end end - elseif r:match("^%!") then -- optional, to call with no arg, no explicit call - r = r:match("^%!(.*)$") + else -- implicit call; will be changed if there happens to be a ! after in the suffix operator code + implicit_call = true end -- find compatible variant - local variant, err = find_function(state, namespace, name, args, explicit_call) + local variant, err = find_function(state, namespace, name, args, paren_call, implicit_call) if not variant then return variant, err end return expression(r, state, namespace, current_priority, variant) - -- function reference - elseif s:match("^%&"..identifier_pattern) then - local name, r = s:match("^%&("..identifier_pattern..")(.-)$") - name = format_identifier(name) - -- get all functions this name can reference - local lfnqm = find_all(state.aliases, state.functions, namespace, name) - if #lfnqm > 0 then - return expression(r, state, namespace, current_priority, { - type = "function reference", - names = lfnqm - }) - end - return nil, ("can't find function %q to reference"):format(name) end - -- unops - for prio, oplist in ipairs(unops_prio) do + -- prefix unops + for prio, oplist in ipairs(prefix_unops_prio) do for _, op in ipairs(oplist) do local escaped = escape(op) if s:match("^"..escaped) then - local right, r = expression(s:match("^"..escaped.."(.*)$"), state, namespace, prio) - if not right then return nil, ("invalid expression after unop %q: %s"):format(op, r) end - -- find variant - local variant, err = find_function(state, namespace, op, right, true) - if not variant then return variant, err end - return expression(r, state, namespace, current_priority, variant) + local sright = s:match("^"..escaped.."(.*)$") + -- function reference + if op == "&" and sright:match("^"..identifier_pattern) then + local name, r = sright:match("^("..identifier_pattern..")(.-)$") + name = format_identifier(name) + -- get all functions this name can reference + -- try prefixes until we find a valid function name + local nl = split(name) + for i=#nl, 1, -1 do + local name_prefix = table.concat(nl, ".", 1, i) + local lfnqm = find_all(state.aliases, state.functions, namespace, name_prefix) + if #lfnqm > 0 then + if i < #nl then + r = "."..table.concat(nl, ".", i+1, #nl)..r + end + return expression(r, state, namespace, current_priority, { + type = "function reference", + names = lfnqm + }) + end + end + return nil, ("can't find function %q to reference"):format(name) + -- normal prefix unop + else + local right, r = expression(sright, state, namespace, prio) + if not right then return nil, ("invalid expression after unop %q: %s"):format(op, r) end + -- find variant + local variant, err = find_function(state, namespace, op.."_", right, true) + if not variant then return variant, err end + return expression(r, state, namespace, current_priority, variant) + end end end end @@ -214,12 +239,12 @@ local function expression(s, state, namespace, current_priority, operating_on) if s:match("^"..escaped) then local sright = s:match("^"..escaped.."(.*)$") -- suffix call - if op == "." and sright:match("^"..identifier_pattern) then + if op == "!" and sright:match("^"..identifier_pattern) then local name, r = sright:match("^("..identifier_pattern..")(.-)$") name = format_identifier(name) - local args, explicit_call + local args, paren_call if r:match("^%b()") then - explicit_call = true + paren_call = true local content, rem = r:match("^(%b())(.*)$") content = content:gsub("^%(", ""):gsub("%)$", "") r = rem @@ -242,101 +267,127 @@ local function expression(s, state, namespace, current_priority, operating_on) } end -- find compatible variant - local variant, err = find_function(state, namespace, name, args, explicit_call) + local variant, err = find_function(state, namespace, name, args, paren_call) + if not variant then return variant, err end + return expression(r, state, namespace, current_priority, variant) + -- namespace + elseif op == "." and sright:match("^"..identifier_pattern) then + local name, r = sright:match("^("..identifier_pattern..")(.-)$") + name = format_identifier(name) + -- find variant + local args = { + type = "list", + left = operating_on, + right = { type = "string", text = { name } } + } + local variant, err = find_function(state, namespace, "_._", args, true) if not variant then return variant, err end return expression(r, state, namespace, current_priority, variant) -- other binops else local right, r = expression(sright, state, namespace, prio) - if not right then return nil, ("invalid expression after binop %q: %s"):format(op, r) end - -- list constructor - if op == "," then - return expression(r, state, namespace, current_priority, { - type = "list", - left = operating_on, - right = right - }) - -- special binops - elseif op == ":=" or op == "+=" or op == "-=" or op == "//=" or op == "/=" or op == "*=" or op == "%=" or op == "^=" then - -- rewrite assignment + arithmetic operators into a normal assignment - if op ~= ":=" then + if right then + -- list constructor (can't do this through a function call since we need to build a list for its arguments) + if op == "," then + return expression(r, state, namespace, current_priority, { + type = "list", + left = operating_on, + right = right + }) + -- special binops + elseif op == ":=" or op == "+=" or op == "-=" or op == "//=" or op == "/=" or op == "*=" or op == "%=" or op == "^=" then + -- rewrite assignment + arithmetic operators into a normal assignment + if op ~= ":=" then + local args = { + type = "list", + left = operating_on, + right = right + } + local variant, err = find_function(state, namespace, "_"..op:match("^(.*)%=$").."_", args, true) + if not variant then return variant, err end + right = variant + end + -- assign to a function + if operating_on.type == "function call" then + -- remove non-assignment functions + for i=#operating_on.variants, 1, -1 do + if not operating_on.variants[i].assignment then + table.remove(operating_on.variants, i) + end + end + if #operating_on.variants == 0 then + return nil, ("trying to perform assignment on function %s with no compatible assignment variant"):format(operating_on.called_name) + end + -- rewrite function to perform assignment + operating_on.assignment = right + return expression(r, state, namespace, current_priority, operating_on) + elseif operating_on.type ~= "variable" then + return nil, ("trying to perform assignment on a %s expression"):format(operating_on.type) + end + -- assign to a variable + return expression(r, state, namespace, current_priority, { + type = ":=", + left = operating_on, + right = right + }) + elseif op == "&" or op == "|" or op == "~" or op == "#" then + return expression(r, state, namespace, current_priority, { + type = op, + left = operating_on, + right = right + }) + -- normal binop + else + -- find variant local args = { type = "list", left = operating_on, right = right } - local variant, err = find_function(state, namespace, op:match("^(.*)%=$"), args, true) + local variant, err = find_function(state, namespace, "_"..op.."_", args, true) if not variant then return variant, err end - right = variant + return expression(r, state, namespace, current_priority, variant) end - -- assign to a function - if operating_on.type == "function call" then - -- remove non-assignment functions - for i=#operating_on.variants, 1, -1 do - if not operating_on.variants[i].assignment then - table.remove(operating_on.variants, i) - end - end - if #operating_on.variants == 0 then - return nil, ("trying to perform assignment on function %s with no compatible assignment variant"):format(operating_on.called_name) - end - -- rewrite function to perform assignment - operating_on.assignment = right - return expression(r, state, namespace, current_priority, operating_on) - elseif operating_on.type ~= "variable" then - return nil, ("trying to perform assignment on a %s expression"):format(operating_on.type) - end - -- assign to a variable - return expression(r, state, namespace, current_priority, { - type = ":=", - left = operating_on, - right = right - }) - elseif op == "&" or op == "|" or op == "~" or op == "#" then - return expression(r, state, namespace, current_priority, { - type = op, - left = operating_on, - right = right - }) - -- normal binop - else - -- find variant - local args = { - type = "list", - left = operating_on, - right = right - } - local variant, err = find_function(state, namespace, op, args, true) - if not variant then return variant, err end - return expression(r, state, namespace, current_priority, variant) end end end end end end - -- index / call - if s:match("^%b()") or s:match("^%!") then - local args = operating_on - local explicit_call, r - -- call with args, explicit call - if s:match("^%b()") then - explicit_call = true - local content - content, r = s:match("^(%b())(.*)$") - content = content:gsub("^%(", ""):gsub("%)$", "") - -- get arguments - if content:match("[^%s]") then - local right, r_paren = expression(content, state, namespace) - if not right then return right, r_paren end - if r_paren:match("[^%s]") then return nil, ("unexpected %q at end of index/call expression"):format(r_paren) end - args = { type = "list", left = args, right = right } + -- suffix unop + for prio, oplist in ipairs(suffix_unops_prio) do + if prio > current_priority then + for _, op in ipairs(oplist) do + local escaped = escape(op) + if s:match("^"..escaped) then + local r = s:match("^"..escaped.."(.*)$") + -- remove ! after a previously-assumed implicit function call + if op == "!" and operating_on.type == "function call" and operating_on.implicit_call then + operating_on.implicit_call = false + return expression(r, state, namespace, current_priority, operating_on) + -- normal suffix unop + else + local variant, err = find_function(state, namespace, "_"..op, operating_on, true) + if not variant then return variant, err end + return expression(r, state, namespace, current_priority, variant) + end + end end - -- call with no arg, no explicit call - elseif s:match("^%!") then - r = s:match("^%!(.*)$") end - local variant, err = find_function(state, namespace, "()", args, explicit_call) + end + -- index / call + if s:match("^%b()") then + local args = operating_on + local content, r = s:match("^(%b())(.*)$") + content = content:gsub("^%(", ""):gsub("%)$", "") + -- get arguments + if content:match("[^%s]") then + local right, r_paren = expression(content, state, namespace) + if not right then return right, r_paren end + if r_paren:match("[^%s]") then return nil, ("unexpected %q at end of index/call expression"):format(r_paren) end + args = { type = "list", left = args, right = right } + end + local variant, err = find_function(state, namespace, "()", args, true) if not variant then return variant, err end return expression(r, state, namespace, current_priority, variant) end @@ -347,6 +398,6 @@ end package.loaded[...] = expression local common = require((...):gsub("expression$", "common")) -identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all = common.identifier_pattern, common.format_identifier, common.find, common.escape, common.find_function, common.parse_text, common.find_all +identifier_pattern, format_identifier, find, escape, find_function, parse_text, find_all, split = common.identifier_pattern, common.format_identifier, common.find, common.escape, common.find_function, common.parse_text, common.find_all, common.split return expression diff --git a/parser/postparser.lua b/parser/postparser.lua index 6922f89..a595b36 100644 --- a/parser/postparser.lua +++ b/parser/postparser.lua @@ -29,7 +29,7 @@ local function parse(state) end param.default = default_exp -- extract type annotation from default value - if default_exp.type == "function call" and default_exp.called_name == "::" then + if default_exp.type == "function call" and default_exp.called_name == "_::_" then param.type_annotation = default_exp.argument.expression.right end end diff --git a/stdlib/functions.lua b/stdlib/functions.lua index f64f05b..b0d3645 100644 --- a/stdlib/functions.lua +++ b/stdlib/functions.lua @@ -1,14 +1,14 @@ -local truthy, anselme, compare, is_of_type, identifier_pattern, format_identifier +local truthy, anselme, compare, is_of_type, identifier_pattern, format_identifier, find, get_variable local functions functions = { -- discard left - [";(a, b)"] = { + ["_;_(a, b)"] = { mode = "raw", value = function(a, b) return b end }, -- comparaison - ["==(a, b)"] = { + ["_==_(a, b)"] = { mode = "raw", value = function(a, b) return { @@ -17,7 +17,7 @@ functions = { } end }, - ["!=(a, b)"] = { + ["_!=_(a, b)"] = { mode = "raw", value = function(a, b) return { @@ -26,21 +26,21 @@ functions = { } end }, - [">(a::number, b::number)"] = function(a, b) return a > b end, - ["<(a::number, b::number)"] = function(a, b) return a < b end, - [">=(a::number, b::number)"] = function(a, b) return a >= b end, - ["<=(a::number, b::number)"] = function(a, b) return a <= b end, + ["_>_(a::number, b::number)"] = function(a, b) return a > b end, + ["_<_(a::number, b::number)"] = function(a, b) return a < b end, + ["_>=_(a::number, b::number)"] = function(a, b) return a >= b end, + ["_<=_(a::number, b::number)"] = function(a, b) return a <= b end, -- arithmetic - ["+(a::number, b::number)"] = function(a, b) return a + b end, - ["+(a::string, b::string)"] = function(a, b) return a .. b end, - ["-(a::number, b::number)"] = function(a, b) return a - b end, - ["-(a::number)"] = function(a) return -a end, - ["*(a::number, b::number)"] = function(a, b) return a * b end, - ["/(a::number, b::number)"] = function(a, b) return a / b end, - ["//(a::number, b::number)"] = function(a, b) return math.floor(a / b) end, - ["^(a::number, b::number)"] = function(a, b) return a ^ b end, + ["_+_(a::number, b::number)"] = function(a, b) return a + b end, + ["_+_(a::string, b::string)"] = function(a, b) return a .. b end, + ["_-_(a::number, b::number)"] = function(a, b) return a - b end, + ["-_(a::number)"] = function(a) return -a end, + ["_*_(a::number, b::number)"] = function(a, b) return a * b end, + ["_/_(a::number, b::number)"] = function(a, b) return a / b end, + ["_//_(a::number, b::number)"] = function(a, b) return math.floor(a / b) end, + ["_^_(a::number, b::number)"] = function(a, b) return a ^ b end, -- boolean - ["!(a)"] = { + ["!_(a)"] = { mode = "raw", value = function(a) return { @@ -50,7 +50,7 @@ functions = { end }, -- pair - [":(a, b)"] = { + ["_:_(a, b)"] = { mode = "raw", value = function(a, b) return { @@ -60,7 +60,7 @@ functions = { end }, -- type - ["::(a, b)"] = { + ["_::_(a, b)"] = { mode = "raw", value = function(a, b) return { @@ -69,6 +69,22 @@ functions = { } end }, + -- namespace + ["_._(r::function reference, name::string)"] = { + mode = "raw", + value = function(r, n) + local state = anselme.running.state + local rval = r.value + local name = n.value + for _, ffqm in ipairs(rval) do + local var, vfqm = find(state.aliases, state.variables, ffqm..".", name) + if var then + return get_variable(state, vfqm) + end + end + return nil, ("can't find variable %q in function reference (searched in namespaces: %s)"):format(name, table.concat(rval, ", ")) + end + }, -- index ["()(l::list, i::number)"] = { mode = "untyped raw", @@ -122,6 +138,9 @@ functions = { ["()(fn::function reference, l...)"] = { -- bypassed, this case is manually handled in the expression interpreter }, + ["_!(fn::function reference, l...)"] = { + -- bypassed, this case is manually handled in the expression interpreter + }, -- format ["{}(v)"] = { mode = "raw", @@ -281,7 +300,7 @@ functions = { package.loaded[...] = functions local icommon = require((...):gsub("stdlib%.functions$", "interpreter.common")) -truthy, compare, is_of_type = icommon.truthy, icommon.compare, icommon.is_of_type +truthy, compare, is_of_type, get_variable = icommon.truthy, icommon.compare, icommon.is_of_type, icommon.get_variable local pcommon = require((...):gsub("stdlib%.functions$", "parser.common")) -identifier_pattern, format_identifier = pcommon.identifier_pattern, pcommon.format_identifier +identifier_pattern, format_identifier, find = pcommon.identifier_pattern, pcommon.format_identifier, pcommon.find anselme = require((...):gsub("stdlib%.functions$", "anselme")) diff --git a/stdlib/languages/enUS.lua b/stdlib/languages/enUS.lua new file mode 100644 index 0000000..7f7d0e3 --- /dev/null +++ b/stdlib/languages/enUS.lua @@ -0,0 +1,6 @@ +return [[ +(Built-in variables) +:alias ๐Ÿ‘๏ธ = "seen" +:alias ๐Ÿ”– = "checkpoint" +:alias ๐Ÿ = "reached" +]] diff --git a/test/tests/binary operator overload.ans b/test/tests/binary operator overload.ans index d6987a2..bf8025e 100644 --- a/test/tests/binary operator overload.ans +++ b/test/tests/binary operator overload.ans @@ -1,7 +1,7 @@ -$ -(a, b) +$ _-_(a, b) @"generic minus" -$ -(a::string, b::string) +$ _-_(a::string, b::string) @a + " minus " + b {2-5} diff --git a/test/tests/binop assignement.ans b/test/tests/binop assignement.ans new file mode 100644 index 0000000..6fbeacd --- /dev/null +++ b/test/tests/binop assignement.ans @@ -0,0 +1,7 @@ +:c = 1 + +{c} + +~ c += 2 + +{c} \ No newline at end of file diff --git a/test/tests/binop assignement.lua b/test/tests/binop assignement.lua new file mode 100644 index 0000000..95ace50 --- /dev/null +++ b/test/tests/binop assignement.lua @@ -0,0 +1,22 @@ +local _={} +_[9]={} +_[8]={} +_[7]={tags=_[9],text="3"} +_[6]={tags=_[8],text="1"} +_[5]={_[7]} +_[4]={_[6]} +_[3]={"return"} +_[2]={"text",_[5]} +_[1]={"text",_[4]} +return {_[1],_[2],_[3]} +--[[ +{ "text", { { + tags = {}, + text = "1" + } } } +{ "text", { { + tags = {}, + text = "3" + } } } +{ "return" } +]]-- \ No newline at end of file diff --git a/test/tests/checkpoint merging mutable value.ans b/test/tests/checkpoint merging mutable value.ans index 65c0489..0d968f4 100644 --- a/test/tests/checkpoint merging mutable value.ans +++ b/test/tests/checkpoint merging mutable value.ans @@ -4,19 +4,19 @@ 1,2: {l} -~ l.insert(3) +~ l!insert(3) 1,2,3: {l} ยง a -~ l.insert(4) +~ l!insert(4) 1,2,3,4: {l} ยง b -~ l.insert(5) +~ l!insert(5) 1,2,3,4,5: {l} diff --git a/test/tests/function reference chain call.ans b/test/tests/function reference chain call.ans new file mode 100644 index 0000000..c3460bf --- /dev/null +++ b/test/tests/function reference chain call.ans @@ -0,0 +1,13 @@ +$ fn + @1 + +$ add(x) + @x+2 + +:c = &fn + +{c!} + +{fn!add} + +{c!!add} diff --git a/test/tests/function reference chain call.lua b/test/tests/function reference chain call.lua new file mode 100644 index 0000000..79b4a0f --- /dev/null +++ b/test/tests/function reference chain call.lua @@ -0,0 +1,30 @@ +local _={} +_[13]={} +_[12]={} +_[11]={} +_[10]={text="3",tags=_[13]} +_[9]={text="3",tags=_[12]} +_[8]={text="1",tags=_[11]} +_[7]={_[10]} +_[6]={_[9]} +_[5]={_[8]} +_[4]={"return"} +_[3]={"text",_[7]} +_[2]={"text",_[6]} +_[1]={"text",_[5]} +return {_[1],_[2],_[3],_[4]} +--[[ +{ "text", { { + tags = {}, + text = "1" + } } } +{ "text", { { + tags = {}, + text = "3" + } } } +{ "text", { { + tags = {}, + text = "3" + } } } +{ "return" } +]]-- \ No newline at end of file diff --git a/test/tests/function ufcs arg.ans b/test/tests/function ufcs arg.ans index 873e827..ef35aaf 100644 --- a/test/tests/function ufcs arg.ans +++ b/test/tests/function ufcs arg.ans @@ -1,6 +1,6 @@ $ f(a) {a} -~ "ok".f +~ "ok"!f -~ "ok".f() +~ "ok"!f() diff --git a/test/tests/function ufcs args.ans b/test/tests/function ufcs args.ans index 0443ef1..f70e5db 100644 --- a/test/tests/function ufcs args.ans +++ b/test/tests/function ufcs args.ans @@ -1,4 +1,4 @@ $ f(a, b) {a}{b} -~ "o".f("k") +~ "o"!f("k") diff --git a/test/tests/named varag.ans b/test/tests/named varag.ans index 79bab8a..3d7ed1d 100644 --- a/test/tests/named varag.ans +++ b/test/tests/named varag.ans @@ -1,8 +1,8 @@ $ f(l...) - ~ l.len + ~ l!len :a = 0 ~ a := l(1) - ~ l.remove(1) + ~ l!remove(1) @a + f(l=l) ~~ @0 diff --git a/test/tests/unary operator overload.ans b/test/tests/unary operator overload.ans index 05efc5d..ead4a01 100644 --- a/test/tests/unary operator overload.ans +++ b/test/tests/unary operator overload.ans @@ -1,7 +1,7 @@ -$ -(f) +$ -_(f) @"generic minus" -$ -(f::string) +$ -_(f::string) @"minus "+f {-5}