Crash when using results of if statement
Closed this issue · 2 comments
if (true) then {["a",1]} else {["b",2]} params ["_l", "_n"];
(if (true) then {["a",1]} else {["b",2]}) params ["_l", "_n"];
First line causes error, second passes.
Traceback (most recent call last):
File "V:\sqf\sqflint.py", line 92, in <module>
_main()
File "V:\sqf\sqflint.py", line 88, in _main
main(sys.argv[1:])
File "V:\sqf\sqflint.py", line 82, in main
return analyze(code, writer)
File "V:\sqf\sqflint.py", line 25, in analyze
exceptions = sqf.analyzer.analyze(result).exceptions
File "V:\sqf\sqf\analyzer.py", line 399, in analyze
analyzer.execute_code(file, extra_scope={'_this': arg})
File "V:\sqf\sqf\analyzer.py", line 139, in execute_code
outcome = super().execute_code(code, params, extra_scope, namespace_name)
File "V:\sqf\sqf\base_interpreter.py", line 131, in execute_code
outcome = self.value(self.execute_single(statement))
File "V:\sqf\sqf\analyzer.py", line 267, in execute_single
t = self.execute_token(token)
File "V:\sqf\sqf\analyzer.py", line 100, in execute_token
result = self.execute_single(statement=token)
File "V:\sqf\sqf\analyzer.py", line 287, in execute_single
outcome = return_type()
TypeError: __init__() missing 2 required positional arguments: 'then' and 'else_'
I'm honestly a little surprised the above code works in arma, as the following code throws an error in arma:
x = if (true) then {2} else {3} * 5;
Mathematical binary commands have a higher priority than other binary commands. (Also else
has a higher priority than other binary commands for the if-then-else
construct to work, but still lower than mathematical binary commands).
This is why:
["a", "b", "c", "d", "e"] select 2 + 1
["a", "b", "c", "d", "e"] select 3
"d"
params
is just another binary command here.
The precedence of the operators is defined in the code here. The numbers I am using are from this blog post from foxhound.
The issue here is that params
is both a unary and binary operator, and, during parsing, it currently does not know which one is to be used. I favored using unary strength instead of the binary (elif n_token in UNARY_OPERATORS:
is before elif n_token in BINARY_OPERATORS:
), which is a problem in this case because it makes it stronger than else
. The crash is caused by the parser parsing
if (true) then {["a",1]} else {["b",2]} params ["_l", "_n"];
as
if (true) then {["a",1]} else ({["b",2]} params ["_l", "_n"];)
instead of
(if (true) then {["a",1]} else {["b",2]}) params ["_l", "_n"];
The easy fix for this is failing gracefully for bad code with if-then constructs like the above; the complete fix is to use binary or unary binding strength correctly for both unary and binary operators.