Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua - why is string after function call allowed?

Tags:

lua

luac

I'm trying to implement a simple C++ function, which checks a syntax of Lua script. For that I'm using Lua's compiler function luaL_loadbufferx() and checking its return value afterwards.

Recently, I have ran into a problem, because the code, that I thought should be marked invalid, was not detected and instead the script failed later at a runtime (eg. in lua_pcall()).

Example Lua code (can be tested on official Lua demo):

function myfunc()
   return "everyone"
end

-- Examples of unexpected behaviour:
-- The following lines pass the compile time check without errors.
print("Hello " .. myfunc() "!") -- Runtime error: attempt to call a string value
print("Hello " .. myfunc() {1,2,3}) -- Runtime error: attempt to call a string value

-- Other examples:
-- The following lines contain examples of invalid syntax, which IS detected by compiler.
print("Hello " myfunc() .. "!") -- Compile error: ')' expected near 'myfunc'
print("Hello " .. myfunc() 5) -- Compile error: ')' expected near '5'
print("Hello " .. myfunc() .. ) -- Compile error: unexpected symbol near ')'

The goal is obviously to catch all syntax errors at compile time. So my questions are:

  1. What exactly is meant by calling a string value?
  2. Why is this syntax allowed in the first place? Is it some Lua feature I'm unaware of, or the luaL_loadbufferx() is faulty in this particular example?
  3. Is it possible to detect such errors by any other method without running it? Unfortunately, my function doesn't have access to global variables at compile time, so I can't just just run the code directly via lua_pcall().

Note: I'm using Lua version 5.3.4 (manual here).

Thank you very much for your help.

like image 579
Electrix Avatar asked Jul 07 '17 17:07

Electrix


2 Answers

Both myfunc() "!" and myfunc(){1,2,3} are valid Lua expressions.

Lua allows calls of the form exp string. See functioncall and prefixexp in the Syntax of Lua.

So myfunc() "!" is a valid function call that calls whatever myfunc returns and call it with the string "!".

The same thing happens for a call of the form exp table-literal.

like image 132
lhf Avatar answered Oct 16 '22 02:10

lhf


Another approach is to change string's metatable making a call to a string valid.

local mt = getmetatable ""
mt.__call = function (self, args) return self .. args end
print(("x") "y") -- outputs `xy`

Now those valid syntax calls to a string will result in string concatenation instead of runtime errors.

like image 23
Tymur Gubayev Avatar answered Oct 16 '22 00:10

Tymur Gubayev