From c9ac66bf7090b633680ffe515e94fd15a7aa0e55 Mon Sep 17 00:00:00 2001 From: codehz Date: Tue, 9 Apr 2024 22:52:03 +0800 Subject: [PATCH 1/3] add __call metamethod support --- lualib/nelua/analyzer.lua | 26 +++++++++++++++++++++++++- lualib/nelua/cgenerator.lua | 7 ++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lualib/nelua/analyzer.lua b/lualib/nelua/analyzer.lua index 50e10db5..40eb4f6c 100644 --- a/lualib/nelua/analyzer.lua +++ b/lualib/nelua/analyzer.lua @@ -1318,6 +1318,14 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call local attr = node.attr if calleetype then local sideeffect + local origintype = calleetype + if calleetype.is_record and calleetype.metafields.__call ~= nil then + calleetype = calleetype.metafields.__call.type + if not calleetype.is_procedure then + node:raisef("invalid metamethod __call in '%s'", calleetype) + end + attr.ismetacall = true + end if calleetype.is_procedure then -- function call local argattrs = {} for i=1,#argnodes do @@ -1355,6 +1363,18 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call end table.remove(pseudoargtypes, 1) table.remove(pseudoargattrs, 1) + elseif attr.ismetacall then + attr.ismethod = true + selftype = funcargtypes[1] + if not selftype then + node:raisef("in metamethod call '%s' at argument 'self': the function cannot have arguments", calleename) + end + local ok, err = selftype:is_convertible_from_type(types.PointerType(origintype), nil, true, argattrs) + if not ok then + node:raisef("in method call '%s' at argument 'self': %s", calleename, err) + end + table.remove(pseudoargtypes, 1) + table.remove(pseudoargattrs, 1) end if not mulargstype and #argnodes > #pseudoargattrs then if not (#argnodes == #pseudoargattrs+1 and argnodes[#argnodes].is_Varargs) then @@ -1503,7 +1523,11 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call end end end - attr.calleesym = calleesym + if attr.ismetacall then + attr.calleesym = calleetype.symbol + else + attr.calleesym = calleesym + end if calleetype then attr.type, attr.value = calleetype:get_return_type_and_value(1) sideeffect = calleetype.sideeffect diff --git a/lualib/nelua/cgenerator.lua b/lualib/nelua/cgenerator.lua index d15ef050..da7ee680 100644 --- a/lualib/nelua/cgenerator.lua +++ b/lualib/nelua/cgenerator.lua @@ -556,6 +556,7 @@ local function visitor_Call(context, node, emitter, argnodes, callee, calleeobjn local tmpcount = 0 local tmpargs = {} local calleesym = attr.calleesym + local originsym = attr.originsym local calleeobj = calleeobjnode local calleeobjtype local selftype = attr.ismethod and calleetype.argtypes[1] @@ -625,7 +626,11 @@ local function visitor_Call(context, node, emitter, argnodes, callee, calleeobjn emitter:add_value(callee) end emitter:add_text('(') - emitter:add_converted_val(selftype, calleeobj, calleeobjtype) + if attr.ismetacall then + emitter:add_converted_val(selftype, node[2], calleeobjtype) + else + emitter:add_converted_val(selftype, calleeobj, calleeobjtype) + end else emitter:add_value(callee) emitter:add_text('(') From b6dd2152ddf70fb6f35b9badea2fb9a405f45a9d Mon Sep 17 00:00:00 2001 From: codehz Date: Tue, 9 Apr 2024 23:18:14 +0800 Subject: [PATCH 2/3] simplify --- lualib/nelua/analyzer.lua | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lualib/nelua/analyzer.lua b/lualib/nelua/analyzer.lua index 40eb4f6c..76c1313f 100644 --- a/lualib/nelua/analyzer.lua +++ b/lualib/nelua/analyzer.lua @@ -1325,6 +1325,7 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call node:raisef("invalid metamethod __call in '%s'", calleetype) end attr.ismetacall = true + calleeobjnode = node[2] end if calleetype.is_procedure then -- function call local argattrs = {} @@ -1363,18 +1364,6 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call end table.remove(pseudoargtypes, 1) table.remove(pseudoargattrs, 1) - elseif attr.ismetacall then - attr.ismethod = true - selftype = funcargtypes[1] - if not selftype then - node:raisef("in metamethod call '%s' at argument 'self': the function cannot have arguments", calleename) - end - local ok, err = selftype:is_convertible_from_type(types.PointerType(origintype), nil, true, argattrs) - if not ok then - node:raisef("in method call '%s' at argument 'self': %s", calleename, err) - end - table.remove(pseudoargtypes, 1) - table.remove(pseudoargattrs, 1) end if not mulargstype and #argnodes > #pseudoargattrs then if not (#argnodes == #pseudoargattrs+1 and argnodes[#argnodes].is_Varargs) then From ab5183346148e3501aec6221b394e50093c23111 Mon Sep 17 00:00:00 2001 From: codehz Date: Tue, 9 Apr 2024 23:20:33 +0800 Subject: [PATCH 3/3] remove unused --- lualib/nelua/cgenerator.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lualib/nelua/cgenerator.lua b/lualib/nelua/cgenerator.lua index da7ee680..440fc666 100644 --- a/lualib/nelua/cgenerator.lua +++ b/lualib/nelua/cgenerator.lua @@ -556,7 +556,6 @@ local function visitor_Call(context, node, emitter, argnodes, callee, calleeobjn local tmpcount = 0 local tmpargs = {} local calleesym = attr.calleesym - local originsym = attr.originsym local calleeobj = calleeobjnode local calleeobjtype local selftype = attr.ismethod and calleetype.argtypes[1]