diff --git a/interpreter/expression.lua b/interpreter/expression.lua index 28bf5d5..d3600ec 100644 --- a/interpreter/expression.lua +++ b/interpreter/expression.lua @@ -1,6 +1,5 @@ local expression local to_lua, from_lua, eval_text, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events, flatten_list -local copy local run @@ -445,6 +444,5 @@ expression = require((...):gsub("interpreter%.expression$", "parser.expression") flatten_list = require((...):gsub("interpreter%.expression$", "parser.common")).flatten_list local common = require((...):gsub("expression$", "common")) to_lua, from_lua, eval_text, is_of_type, truthy, format, pretty_type, get_variable, tags, eval_text_callback, events = common.to_lua, common.from_lua, common.eval_text, common.is_of_type, common.truthy, common.format, common.pretty_type, common.get_variable, common.tags, common.eval_text_callback, common.events -copy = require((...):gsub("interpreter%.expression$", "common")).copy return eval diff --git a/parser/expression.lua b/parser/expression.lua index 0d875f6..0f6910f 100644 --- a/parser/expression.lua +++ b/parser/expression.lua @@ -169,6 +169,8 @@ 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("^%!(.*)$") end -- find compatible variant local variant, err = find_function(state, namespace, name, args, explicit_call) @@ -314,18 +316,27 @@ local function expression(s, state, namespace, current_priority, operating_on) end end -- index / call - if s:match("^%b()") then - local content, r = s:match("^(%b())(.*)$") - content = content:gsub("^%(", ""):gsub("%)$", "") - -- get arguments + if s:match("^%b()") or s:match("^%!") then local args = operating_on - 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 } + 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 } + end + -- call with no arg, no explicit call + elseif s:match("^%!") then + r = s:match("^%!(.*)$") end - local variant, err = find_function(state, namespace, "()", args, true) + local variant, err = find_function(state, namespace, "()", args, explicit_call) if not variant then return variant, err end return expression(r, state, namespace, current_priority, variant) end diff --git a/stdlib/functions.lua b/stdlib/functions.lua index 7b2bf5c..f64f05b 100644 --- a/stdlib/functions.lua +++ b/stdlib/functions.lua @@ -119,6 +119,9 @@ functions = { return v end }, + ["()(fn::function reference, l...)"] = { + -- bypassed, this case is manually handled in the expression interpreter + }, -- format ["{}(v)"] = { mode = "raw", diff --git a/test/tests/function reference call explicit call.ans b/test/tests/function reference call explicit call.ans new file mode 100644 index 0000000..2c117ed --- /dev/null +++ b/test/tests/function reference call explicit call.ans @@ -0,0 +1,12 @@ +$ fn + 1 + ยง c + 2 + +:c = &fn + +~ c! + +~ c() + +~ c! diff --git a/test/tests/function reference call explicit call.lua b/test/tests/function reference call explicit call.lua new file mode 100644 index 0000000..399cf6e --- /dev/null +++ b/test/tests/function reference call explicit call.lua @@ -0,0 +1,40 @@ +local _={} +_[17]={} +_[16]={} +_[15]={} +_[14]={} +_[13]={} +_[12]={text="2",tags=_[17]} +_[11]={text="2",tags=_[16]} +_[10]={text="1",tags=_[15]} +_[9]={text="2",tags=_[14]} +_[8]={text="1",tags=_[13]} +_[7]={_[12]} +_[6]={_[10],_[11]} +_[5]={_[8],_[9]} +_[4]={"return"} +_[3]={"text",_[7]} +_[2]={"text",_[6]} +_[1]={"text",_[5]} +return {_[1],_[2],_[3],_[4]} +--[[ +{ "text", { { + tags = {}, + text = "1" + }, { + tags = {}, + text = "2" + } } } +{ "text", { { + tags = {}, + text = "1" + }, { + tags = {}, + text = "2" + } } } +{ "text", { { + tags = {}, + text = "2" + } } } +{ "return" } +]]-- \ No newline at end of file diff --git a/test/tests/function reference call.lua b/test/tests/function reference call.lua index 125e47e..98f117f 100644 --- a/test/tests/function reference call.lua +++ b/test/tests/function reference call.lua @@ -17,24 +17,24 @@ _[41]={} _[40]={} _[39]={} _[38]={} -_[37]={text="8",tags=_[55]} -_[36]={text="8: ",tags=_[54]} -_[35]={text="7",tags=_[53]} -_[34]={text="7: ",tags=_[52]} -_[33]={text="13",tags=_[51]} -_[32]={text="13: ",tags=_[50]} -_[31]={text="5",tags=_[49]} -_[30]={text="5: ",tags=_[48]} -_[29]={text="4",tags=_[47]} -_[28]={text="4: ",tags=_[46]} -_[27]={text="4",tags=_[45]} -_[26]={text="4: ",tags=_[44]} -_[25]={text="5",tags=_[43]} -_[24]={text="5: ",tags=_[42]} -_[23]={text="3",tags=_[41]} -_[22]={text="3: ",tags=_[40]} -_[21]={text="3",tags=_[39]} -_[20]={text="3: ",tags=_[38]} +_[37]={tags=_[55],text="8"} +_[36]={tags=_[54],text="8: "} +_[35]={tags=_[53],text="7"} +_[34]={tags=_[52],text="7: "} +_[33]={tags=_[51],text="13"} +_[32]={tags=_[50],text="13: "} +_[31]={tags=_[49],text="5"} +_[30]={tags=_[48],text="5: "} +_[29]={tags=_[47],text="4"} +_[28]={tags=_[46],text="4: "} +_[27]={tags=_[45],text="4"} +_[26]={tags=_[44],text="4: "} +_[25]={tags=_[43],text="5"} +_[24]={tags=_[42],text="5: "} +_[23]={tags=_[41],text="3"} +_[22]={tags=_[40],text="3: "} +_[21]={tags=_[39],text="3"} +_[20]={tags=_[38],text="3: "} _[19]={_[36],_[37]} _[18]={_[34],_[35]} _[17]={_[32],_[33]}