unwelcome if statement on luajit - lua

lua 5.3.5 accepts the code below,
function isOdd (n)
if n & 1 == 1
then return true
else return false
end
end
print(isOdd(1), isOdd(2))
Why does luajit 2.0.5 refuse it?
line 2: 'then' expected near '&'

Because native bitwise operators are new to Lua 5.3, and LuaJIT is basically Lua 5.1. Use bit.band instead:
This module is a LuaJIT built-in — you don't need to download or install Lua BitOp. The Lua BitOp site has full documentation for all Lua BitOp API functions.
Please make sure to require the module before using any of its functions:
local bit = require("bit")
Source

Related

Why doesn't love2d use my custom-defined pairs metamethod?

I have the following code in the file main.lua:
local table = {data={a=1,b=2,c=3}}
setmetatable(table, table)
function table:__pairs()
return pairs(self.data)
end
function table:__tostring()
return "a table"
end
print(table)
for e in pairs(table) do
print(e)
end
When I run lua main.lua I get the output
a table
a
b
c
When I run love ~/path/to/project I get the output
a table
__tostring
data
__pairs
Why does love use other metamethods correctly, but not pairs?
I have LOVE 11.3 (Mysterious Mysteries) and Lua 5.3.5
Love2D uses LuaJIT as its default interpreter, which is fixed to Lua 5.1. And while you can rebuild Love2D for the standard Lua 5.1 interpreter, making it use modern versions of the standard Lua interpreter would require substantial code hacking, since 5.2+ aren't backwards compatible.
And Lua 5.1 doesn't have the pairs metamethod.

Why can LuaJIT/Openresty use deprecated 'arg' language feature?

My understanding is that LuaJIT uses the Lua 5.1 syntax. In Lua 5.1, the 'arg' feature was removed from the language.
However, the following code works.
// test.lua
local function foo()
for k,v in pairs(arg) do
print(k .. " " .. v)
end
end
foo()
I would expect arg to be nil, but it exists and is doing the Lua 5.0 functionality.
Running resty test.lua hello world results in:
0 test.lua
1 hello
2 world
-1 /usr/local/bin/resty
Why does this work? Are there exceptions to the 5.1 syntax that Openresty and LuaJIT can use?
You're mixing two different things.
The arg table you see here is not a "deprecated Lua feature". It's a table of arguments given to Lua interpreter, explicitly pushed to the global arg variable by the interpreter, and it's still there in the latest Lua and LuaJIT versions.
The feature you've heard was removed - that's about replacing implicit arg parameter with vararg expression in vararg functions. I.e. the extra arguments to functions now available through ... syntax, and not as a table of collected values through implicit arg parameter.

Running a lua script as a gel script

I have the following lua script that separates a string in its proper words:
names = "aa bb cc dd"
words = {}
for word in names:gmatch("%w+") do table.insert(words, word) end
for k,v in pairs(words) do print(k,v) end
I am using a program called Graphite, which is a platform for computer graphics and more. In its readme it is written:
You can write a LUA script and run it with Graphite. Just load the
script using GEL -> execute file.
Having very small experience with LUA and zero knowledge about what GEL is, I am having trouble running a script. After some googling I found this: http://gema.sourceforge.net/new/gel.shtml#3_1 ,
but it is still not so clear to me what the connection between gel and lua is. In this website it is described as: a Lua binding for Gema, a general purpose text processing utility.
The above script for example works as intended in the lua interpreter. On the other hand, when I try to execute it as a .gel script (because the software mentioned above requires a .gel script) it returns a syntax error.
Any idea on how to make it run as a .gel script? Or any other comment that might help?
If you read the documentation more closely, you'll notice:
Embed the lua functions in the gema file using the new syntax "![" "!]"
They also have an example provided:
![
function inflog(x)
if x>0 then return math.log(x)
else return "-infty"
end
end
!]
<N>=#lua{return inflog($0)}
Following the same example, the following should work:
![
function split(names)
words = {}
for word in names:gmatch("%w+") do table.insert(words, word) end
for k, v in ipairs(words) do print(k, v) end
return words
end
!]
<N>=#lua{return split($0)}

Lua - why is string after function call allowed?

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:
What exactly is meant by calling a string value?
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?
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.
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.
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.
I'm writing answer to my own question just in case anyone else stumbles upon the similar problem in the future and also looks for solution.
Manual
Lua manual (in its section 3.4.10 – Function Calls) basically states, that there are three different ways of providing arguments to Lua function.
Arguments have the following syntax: args ::= ‘(’ [explist] ‘)’
args ::= tableconstructor
args ::= LiteralString
All argument expressions are evaluated before the call. A call of the form f{fields} is syntactic sugar for f({fields}); that is, the argument list is a single new table. A call of the form f'string' (or f"string" or f[[string]]) is syntactic sugar for f('string'); that is, the argument list is a single literal string.
Explanation
As lhf pointed out in his answer, both myfunc()"!" and myfunc(){1,2,3} are valid Lua expressions. It means the Lua compiler is doing nothing wrong, considering it doesn't know the function return value at a compile time.
The original example code given in the question:
print("Hello " .. myfunc() "!")
Could be then rewritten as:
print("Hello " .. (myfunc()) ("!"))
Which (when executed) translates to:
print("Hello " .. ("everyone") ("!"))
And thus resulting in the runtime error message attempt to call a string value (which could be rewritten as: the string everyone is not a function, so you can't call it).
Solution
As far as I understand, these two alternative ways of supplying arguments have no real benefit over the standard func(arg) syntax. That's why I ended up modyfing the Lua parser files. The disadventage of keeping this alternative syntax was too big. Here is what I've done (relevant for v5.3.4):
In file lparser.c i searched for function:
static void suffixedexp (LexState *ls, expdesc *v)
Inside this function i changed the case statement:
case '(': case TK_STRING: case '{':to case '(':
Warning! By doing this I have modified the Lua language, so as lhf stated in his comment, it can no longer be called pure Lua. If you are unsure whether it is exactly what you want, I can't recommend this approach.
With this slight modification compiler detects the two above mentioned alternative syntaxes as errors. Of course, I can no longer use them inside Lua scripts, but for my specific application it's just fine.
All I need to do is to note this change somewhere to find it in case of upgrading Lua to higher version.

How to correctly redefine print in Lua 5.3?

I frequently use print function for debugging in conjunction with os.exit(). I don't want to type os.exit() each time I use print, so I want to redefine this function.
> function pprint(...)
>> for _,a in ipairs(arg) do
>> print(a)
>> end
>> os.exit()
>> end
> pprint('hello',1,2,3)
hello
1
2
3
[johndoe#dell-john ~]$
Although this works in Lua 5.1, it does not work in Lua 5.3 and, for some reason, Torch. I looked up the Lua 5.3 docs for "triple dots" expression but couldn't find the reference on how to access ... arguments. Can you explain what was changed and how to redefine print for Lua 5.3?
Automatic creation of the arg table for vararg functions was deprecated in Lua 5.1 and removed in Lua 5.2.
As mentioned by Egor, use
for _,a in ipairs({...}) do
instead of
for _,a in ipairs(arg) do
Or add
local arg={...}
at the start of the function.
for _,a in ipairs({...}) do is wrong ,it does not support nil
right rewrite
local arg = table.pack(...)
for i = 1 ,arg.n do
old_print(arg[i])
end

Resources