Closed rarris closed 9 months ago
@ghaith @riederm
as rares described the array initialization is the problem
1: channel:=10(global_const), 8(global_const)
-> doesn't work
2: channel:=(10(global_const), 8(global_const))
-> works after we added the ()
3: arr : ARRAY [1..2] OF DINT := 1, 2, 3;
-> works without the ()
the problem is how our parser works
why option 3 works, if our parser matches the ARRAY keyword, no matter what comes after :=
we will generate an ExpressionList for it, until we match for semicolon -> this is the reason we don't need to use () for the initializer
why option 1 does't work!, there is no ARRAY keyword in this context, we would only parse for an ExpressionList if we match (
the question is how should we handle this ? should we modify the parser and also generate an ExpressionList for something like this -> 1,2,3;
until we match semicolon, this would fix the error
or
is this an valid error and () is needed in this case
yes thats the parsers fault ...
channel:=10(global_const), 8(global_const)
the parser eagerly eats the assignment on the left side and creates an expression list like this:
ExpressionList [
Assignment(
Reference,
RepeatExpression),
RepeatExpression
]
I think we lack some validation here, the validator should give you a clear indication that he second Repeat-Expression must be assigned to a struct-field (I think if you use an assignment for one field, you need to use the assignment for all fields. You could just provide the values in the order of declaration, but mixing explicit and implicit assignments makes things pretty hard.
The corect AST would be:
Assignment(
Reference,
ExpressionList [
MultipliedStatement,
MultipliedStatement]
)
On the other hand, this only makes sense, if this is the last assignment in the struct initialization ...
config : ARRAY[1..2] OF struct1 :=
(var1:=1),
(var1:=1, channel:=10(global_const), 8(global_const));
^ ^
these two comas are in the same scope?!
I think this would not work:
config : ARRAY[1..2] OF struct1 :=
(var1:=1),
(var1:=1, channel:=10(global_const), 8(global_const), last_field := 3);
^ ^ ^
how can we know that the channel-assignment started an expression list that only lasts for 2 segments?
:question: is this worth the parser effort, when some simple brackets creates an unambiguous situation? :question:
so in short, my vote is:
this is a valid error and () is needed in this case
. Without brackets, the coma starts the assignment to the next struct field.
what do you guys think?
my first thought was also that this is an error
array initialization without ()
feels a little bit unnatural to me, normally you would see something like {1,2,3,...}
in other languages
and i don't think the effort would be worth it
error: Array initializer must be an initializer list!
┌─ main.st:29:2
│
29 │ arr := 1, 2;
│ ^^^ Array initializer must be an initializer list!
error: Expected identifier or '('
┌─ main.st:29:12
│
29 │ arr := 1, 2;
│ ^ Expected identifier or '('
current implementation of the validation will report the error like C
apparently we have another type of struct initialization ...
PROGRAM mainProg
VAR
var_init : ARRAY[0..15] OF STRUCT1 := (name:='text'),(node:=1),(myArr:=(x1:=FALSE,x2:=TRUE));
END_VAR
END_PROGRAM
TYPE STRUCT1 :
STRUCT
var10 : BOOL;
name : STRING[31];
node : DINT;
number : DINT;
myArr : ARRAY[0..10] OF STRUCT2;
END_STRUCT
END_TYPE
TYPE STRUCT2 :
STRUCT
x1 : BOOL;
x2 : BOOL;
x3 : DINT;
x4 : DINT;
END_STRUCT
END_TYPE
error: Cannot generate literal initializer for 'mainProg.var_init': Value cannot be derived Error: SyntaxError { message: "Some initial values were not generated", range: [SourceRange { range: 0..0 }], err_no: codegen__general }
error: Cannot generate literal initializer for 'mainProg.config': Value cannot be derived Error: SyntaxError { message: "Some initial values were not generated", range: [SourceRange { range: 0..0 }], err_no: codegen__general }
struct array initialization is the problem - channel:=10(global_const), 8(global_const)