V version: V 0.1.27 1bf13f8
OS: Linux
What did you do?
fn main() {
a := if 1 < 2 {
b := 3
b + 4
} else {
5
}
println(a)
}
What did you expect to see?
Either successful compilation or a meaningful error from the V compiler
What did you see instead?
==================
/home/elias/.cache/v/sandbox.tmp.c: In function ‘main’:
/home/elias/.cache/v/sandbox.tmp.c:9445:24: error: expected ‘)’ before ‘b’
9445 | int a = (1 < 2 ? ( int b = 3;
| ~ ^~
| )
/home/elias/.cache/v/sandbox.tmp.c:9446:13: error: expected expression before ‘:’ token
9446 | , b + 4 ) : ( 5 ) );
| ^
/home/elias/.cache/v/sandbox.tmp.c: In function ‘vcalloc’:
/home/elias/.cache/v/sandbox.tmp.c:4493:1: warning: control reaches end of non-void function [-Wreturn-type]
4493 | }
| ^
...
==================
(Use `v -cg` to print the entire error message)
builder error: C error.
If/Match expressions are transpiled to C ternary operations, these cannot contain statements.
This should compile, this will be fixed.
I was looking at this exact issue today in relation to returning concat/multi-expressions from if/match expressions. This seemed like it would require a lot of rewriting to replace the ternary operation with if/else statements. Are you planning on working on this any time soon?
This can be fixed by using a tmp variable in most cases
Unless we have something like
if 1 < 2 {
b := 3
b + 4
} else {
5
}
+
if 1 < 2 {
b := 3
b + 41
} else {
51
}
which is crazy and can be not allowed by the compiler
So if an if expression has more than one statement, a tmp variable and a simple if are used instead of ?: in C.
Yes, so all cases where the expression is used in the right-hand-side will need to write the if-else statement before the left-hand-side.
Eg. return if true { 1 } else { 2 }
This is currently a nice single line in C. After the fix it should write the expression before the return:
int tmp;
if (true) {
tmp = 1;
} else {
tmp = 2;
}
return tmp;
I am suspecting there will be cases where this creates complications in cgen.
You didn't read my proposal thoroughly :)
if an if expression has more than one statement
In your example there's one statement, so nothing will change.
In fact, it even kind of works with multiple statements with C's weird , operator, just not for variable assignments.
The 1 and 2 were just placeholders :) imagine there being statements/variable declarations inside the blocks.
This already works:
fn main() {
a := if 1 < 2 {
println('hello')
4
} else {
5
}
println(a)
}
And I suspect it might even work with var declarations, it's jus generating bad C for some reason
int a = (1 < 2 ? ( int b = 3;
no it doesn't work with declarations, I tried :)
Doesn't work/compile:
void main() {
int foo = (2 > 1) ? (int bar = 2, bar + 1) : 3;
}
Works:
void main() {
int bar;
int foo = (2 > 1) ? (bar = 2, bar + 1) : 3;
}
if 1 < 2 {
b := 3
b + 4
} else {
5
}
+
if 1 < 2 {
b := 3
b + 41
} else {
51
}
I don't think this example is crazy. You could for example generate C code like this:
int b1, b2;
((1 < 2) ? (b1 = 3, b + 4) : 5)
+ ((1 < 2) ? (b2 = 3, b + 41) : 51);
or even
bool v1 = 1 < 2;
int v2;
if (v1) {
int v3 = 3;
v2 = v3 + 4;
} else {
v2 = 5;
}
bool v4 = 1 < 2;
int v5;
if (v4) {
int v6 = 3;
v5 = v6 + 41;
} else {
v5 = 51;
}
int v7 = v2 + v5;
which should easily be possible by walking the AST. For translation to X64 machine code you need something similar to this anyway.
I agree with @eyelash - it'll be needed anyway for the ASM backend.
Closing as this issue has been fixed in #4860. Testing on V 0.1.27 034bf46 works too.
Most helpful comment
This should compile, this will be fixed.