diff --git a/lua/entities/gmod_wire_expression2/base/compiler.lua b/lua/entities/gmod_wire_expression2/base/compiler.lua index 2db5b428d2..200089e709 100644 --- a/lua/entities/gmod_wire_expression2/base/compiler.lua +++ b/lua/entities/gmod_wire_expression2/base/compiler.lua @@ -1868,12 +1868,18 @@ local CompileVisitors = { ---@type E2Lambda local f = expr(state) - if not f then - state:forceThrow("Trying to call function that doesn't exist!") - elseif f.arg_sig ~= sig then - state:forceThrow("Incorrect arguments passed to lambda, expected (" .. f.arg_sig .. ") got (" .. sig .. ")") + if f.arg_sig ~= sig then + if f == E2Lib.NoLambda then + f.fn() + else + state:forceThrow("Incorrect arguments passed to lambda, expected (" .. f.arg_sig .. ") got (" .. sig .. ")") + end elseif f.ret ~= ret_type then - state:forceThrow("Expected type " .. (ret_type or "void") .. " from lambda, got " .. (f.ret or "void")) + if f == E2Lib.NoLambda then + f.fn() + else + state:forceThrow("Expected type " .. (ret_type or "void") .. " from lambda, got " .. (f.ret or "void")) + end else local rargs = {} for k = 1, nargs do diff --git a/lua/entities/gmod_wire_expression2/core/e2lib.lua b/lua/entities/gmod_wire_expression2/core/e2lib.lua index 1dc22b8fc1..a676b4edd3 100644 --- a/lua/entities/gmod_wire_expression2/core/e2lib.lua +++ b/lua/entities/gmod_wire_expression2/core/e2lib.lua @@ -81,12 +81,20 @@ function Function:__tostring() return "function(" .. self.arg_sig .. ")" .. ((self.ret and (": " .. self.ret)) or "") end +---@param args string +---@param ret string? +---@param fn fun(args: any[]): any function Function.new(args, ret, fn) return setmetatable({ arg_sig = args, ret = ret, fn = fn }, Function) end E2Lib.Lambda = Function +local noLambda = Function.new("", nil, function() + E2Lib.RuntimeContext:forceThrow("Trying to call function that doesn't exist") +end) +E2Lib.NoLambda = noLambda + --- Call the function without doing any type checking. --- Only use this when you check self:Args() yourself to ensure you have the correct signature function. function Function:UnsafeCall(args) diff --git a/lua/entities/gmod_wire_expression2/core/functions.lua b/lua/entities/gmod_wire_expression2/core/functions.lua index f6ef3c829a..96813c5f5d 100644 --- a/lua/entities/gmod_wire_expression2/core/functions.lua +++ b/lua/entities/gmod_wire_expression2/core/functions.lua @@ -4,13 +4,27 @@ Format: { arg_sig: string, ret: string, fn: fun(args: any[]): any } ]] -registerType("function", "f", nil, +local noLambda = E2Lib.NoLambda + +local function is_invalid(v) + return not istable(v) or getmetatable(v) ~= E2Lib.Lambda +end + +-- Do this manually or otherwise registerType will needlessly copy noFunction for each zero +WireLib.DT.FUNCTION = { + Zero = function() + return noLambda + end, + Validator = function(v) + return not is_invalid(v) + end +} + +registerType("function", "f", noLambda, function(self) self.entity:Error("You may not input a function") end, function(self) self.entity:Error("You may not output a function") end, nil, - function(v) - return not istable(v) or getmetatable(v) ~= E2Lib.Lambda - end + is_invalid ) __e2setcost(1) @@ -46,8 +60,12 @@ e2function string function:getReturnType() return this.ret or "" end +e2function function nofunction() + return noLambda +end + e2function string toString(function func) return tostring(func) end -e2function string function:toString() = e2function string toString(function func) \ No newline at end of file +e2function string function:toString() = e2function string toString(function func)