/* note that the semicolons here are needed for the assert, not the if/else blocks */
assert if(1){};
assert !if(0){throw __FLC};
assert !if(0){throw __FLC}else{};
assert if(0){throw __FLC} else if(1){} else{throw __FLC};
assert if(0){throw __FLC}
else if(true)<<<_FI /*trued the second time*/;; _FI
else {throw __FCL};
assert true /* Just checking tail consumption */;
assert !if(0){throw __FLC}
else if(1-2+1){throw __FLC}
else {};
var a;
if(0){throw __FLC}
else if(0){throw __FLC}
else{a=4*2-1} /* note no semicolon needed here */
assert 7 === a;
assert 7 === a /* make sure previous one wasn't skipped */;
a = 0;
//pragma(trace-token-stack 1);
if(0) throw __FLC; else if(1) a = 1; else throw __FLC;
//pragma(trace-token-stack 0);
assert 1 === a;
a = -1;
if(1) a = 0; else if(1) {throw __FLC} else {throw __FLC}
assert 0 === a;
a = 0;
if(0) throw __FLC; else if(0) {throw __FLC} else a = 1 ? 2 : 3;
assert 2 === a;
a = 0;
if(0) throw __FLC; else if(0) {throw __FLC} else {a = 0 ? 2 : 3}
assert 3 === a;
assert var ex = catch{
if(0) 1; else if(0) else a = 1 ? 2 : 3;
// --------------^^^^
};
assert 'CWAL_SCR_SYNTAX' === ex.codeString();
assert 0 < ex.message.indexOf('consecutive non-operators');
a = 0;
assert true === if(1) 1; else throw __FLC;
assert false === if(0) throw __FLC; else if(0) throw __FLC;
a = 1;
assert 1 === a /* make sure final if() DTRT */;
a = 0;
assert false === if(0) throw __FLC; else if(0) {0};
a = 1;
assert 1 === a /* make sure final if() DTRT */;
a = 0;
assert true === if(0) throw __FLC; else if(1) {0};
a = 1;
assert 1 === a /* make sure final if() DTRT */;
a = 0;
assert true === if(0) 1; else if(1) 0;
a = 1;
assert 1 === a /* make sure final if() DTRT */;
a = 0;
assert true === if(1) 1; else if(1) {throw __FLC};
a = 1;
assert 1 === a /* make sure final if() DTRT */;
a = 0;
assert true === if(1) 1; else if(1) throw __FLC;
a = 1;
assert 1 === a /* make sure final if() DTRT */;
// checking newline-as-EOX handling...
if(1){}
var b;
assert typeinfo(islocal b);
if(0){} else{}
var b2;
assert typeinfo(islocal b2);
if(0){} else if(0){}
var b3;
assert typeinfo(islocal b3);
if(0){}
var c;
assert typeinfo(islocal c);
/*
When using heredocs as if/else bodies, a semicolon/newline
between the heredoc's closing token and the "else" part is
optional. Typing it seems to feel more intuitive, but internally
heredocs are normally treated like script blocks, and a semicolon
after a script block has a different meaning here:
if(1){...}; else{...} // syntax error
NEVERMIND: i don't like this semicolon inconsistency. But now it's
doucmented :/
*/
var x;
if(1)<<<X x=1 X
else<<<Y Y // semicolon and EOL are equivalent at the END {} of LHS if/else
assert 1===x;
x = 0;
if(0)<<<X X
else<<<Y x=1 Y; // semicolon and EOL are equivalent at the END of the construct
assert 1===x;
if(0){// see comments above
x = 0;
if(1)<<<X x=1 X; // semicolon is a syntax error here for consistency with {blocks}.
else<<<Y Y
assert 1===x;
}
assert !catch{0 ? if(1) 1; else{2} : 1} /*no syntax error*/;
assert !catch{0 ? if(0) 1; else{2} : 1} /*no syntax error*/;
assert !catch{1 ? if(1) 1; else{2} : 1} /*no syntax error*/;
assert !catch{1 ? if(0) 1; else{2} : 1} /*no syntax error*/;
assert catch{1 ? if(0) 1; else 2 : 1}
/*
Not exactly a bug: "unexpected ':'". The problem is one of scope:
the if/else parts run in a new scope and it's there that the else
encounters ':', but the ternary op state does not span scopes (we
explicitely save/reset/restore it when pushing/popping
scopes). Terminating the 'else' body with a semicolon OR using a {}
body instead of non-{} body resolves it.
*/;