Skip to content

Model specific behavior of CompileString #89

@b0mbie

Description

@b0mbie

It's something a bit niche, but CompileString has very specific conditions about what type of value it returns based on the handleError argument. If that argument is unspecified, nil or true, then the function returns either the compiled function or nil to indicate an error which has been handled by the game:

] lua_run_cl print("Error return type:", type(CompileString("end", "bad")))

[ERROR] bad:1: '<eof>' expected near 'end'
  1. unknown - LuaCmd:1

Error return type:	nil
] lua_run_cl print("Error return type:", type(CompileString("end", "bad", nil)))

[ERROR] bad:1: '<eof>' expected near 'end'
  1. unknown - LuaCmd:1

Error return type:	nil
] lua_run_cl print("Error return type:", type(CompileString("end", "bad", true)))

[ERROR] bad:1: '<eof>' expected near 'end'
  1. unknown - LuaCmd:1

Error return type:	nil

... and, if handleError is false, then the function returns either the compiled function or string:

] lua_run_cl print("Error return type:", type(CompileString("end", "bad", false)))
Error return type:	string

Possible solution

The wiki only specifies the return type as function, which probably warrants an edit to the actual wiki page to change the return type to "string or function or nil", but I'm not sure if that's possible?

The exact behavior could be modeled with a change to handleError's type and some @overloads for CompileString:

---![(Shared)](https://github.com/user-attachments/assets/a356f942-57d7-4915-a8cc-559870a980fc) This function will compile the code argument as lua code and return a function that will execute that code.
---
--- Please note that this function will not automatically execute the given code after compiling it.
---
---[View wiki](https://wiki.facepunch.com/gmod/Global.CompileString)
---@param code string The code to compile.
---@param identifier string An identifier in case an error is thrown. (The same identifier can be used multiple times)
---@param handleError? true If false this function will return an error string instead of throwing an error.
---@return function? # A function that, when called, will execute the given code.
---
--- Returns the error string if there was a Lua error and third argument is false.
---@overload fun(code: string, identifier: string, handleError: false): function|string
---@overload fun(code: string, identifier: string, handleError: boolean): function|string|nil
function _G.CompileString(code, identifier, handleError) end

With this, the following example checks out:

local handleError = ...
local _ = CompileString("end", "error handled maybe", handleError) -- `string|function|nil` (can't know the exact value of `handleError` so assume both cases are possible)
local _ = CompileString("end", "error handled", true) -- `function?` (explicit handling by the game)
local _ = CompileString("end", "error handled by default") -- `function?` (`handleError = true` by default)
local _ = CompileString("end", "error handled by default", nil) -- `function?` (ditto)
local _ = CompileString("end", "error not handled", false) -- `function|string` (explicit handling by the caller)

I don't like how handleError is documented as just having a type of "true" by default - it might be overkill, but it's nice to have this very specific behavior modeled in the type system.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions