feat: add conditional operator and fn toString to wren compiler and core

Add TOKEN_QUESTION token type and implement conditional() parsing function in wren_compiler.c to support the ternary conditional operator (condition ? then : else). Register fn_toString native in wren_core.c to return "<fn>" string for function objects. Include comprehensive test suite covering precedence, short-circuit evaluation, and error cases for missing tokens.
This commit is contained in:
Bob Nystrom
2014-02-15 19:36:01 +00:00
parent d335116799
commit 73b92ca7f3
12 changed files with 106 additions and 0 deletions
@@ -0,0 +1 @@
1 ? 2 ? 3 : 4 : 5 // expect error
+2
View File
@@ -0,0 +1,2 @@
true ? 1 // expect error
"next expression"
+1
View File
@@ -0,0 +1 @@
? 1 : 2 // expect error
+1
View File
@@ -0,0 +1 @@
true ? 1 : // expect error
+1
View File
@@ -0,0 +1 @@
true 1 : 2 // expect error
+1
View File
@@ -0,0 +1 @@
true ? : 2 // expect error
+59
View File
@@ -0,0 +1,59 @@
class Foo {
static bar { return true }
static baz { return 1 }
}
// Condition precedence.
IO.print(true ? 1 : 2) // expect: 1
IO.print((true) ? 1 : 2) // expect: 1
IO.print([true][0] ? 1 : 2) // expect: 1
IO.print(Foo.bar ? 1 : 2) // expect: 1
IO.print(3..4 ? 1 : 2) // expect: 1
IO.print(3 * 4 ? 1 : 2) // expect: 1
IO.print(3 + 4 ? 1 : 2) // expect: 1
IO.print(true || false ? 1 : 2) // expect: 1
IO.print(!false ? 1 : 2) // expect: 1
IO.print(~0 ? 1 : 2) // expect: 1
IO.print(3 is Num ? 1 : 2) // expect: 1
IO.print(new Foo ? 1 : 2) // expect: 1
IO.print(fn true ? 1 : 2) // expect: <fn>
var a = 0
IO.print(a = 3 ? 1 : 2) // expect: 1
IO.print(a) // expect: 1
// Then branch precedence.
IO.print(true ? (1) : 2) // expect: 1
IO.print(true ? [1][0] : 2) // expect: 1
IO.print(true ? Foo.baz : 2) // expect: 1
IO.print(true ? 3..4 : 2) // expect: 3..4
IO.print(true ? 3 * 4 : 2) // expect: 12
IO.print(true ? 3 + 4 : 2) // expect: 7
IO.print(true ? 1 || false : 2) // expect: 1
IO.print(true ? !true : 2) // expect: false
IO.print(true ? ~0 : 2) // expect: 4294967295
IO.print(true ? 3 is Bool : 2) // expect: false
IO.print(true ? new Foo : 2) // expect: instance of Foo
// TODO: Is this what we want?
IO.print(true ? fn 1 : 2) // expect: <fn>
IO.print(true ? a = 5 : 2) // expect: 5
IO.print(a) // expect: 5
// Else branch precedence.
IO.print(false ? 1 : (2)) // expect: 2
IO.print(false ? 1 : [2][0]) // expect: 2
IO.print(false ? 2 : Foo.baz) // expect: 1
IO.print(false ? 1 : 3..4) // expect: 3..4
IO.print(false ? 1 : 3 * 4) // expect: 12
IO.print(false ? 1 : 3 + 4) // expect: 7
IO.print(false ? 1 : 2 || false) // expect: 2
IO.print(false ? 1 : !false) // expect: true
IO.print(false ? 1 : ~0) // expect: 4294967295
IO.print(false ? 1 : 3 is Num) // expect: true
IO.print(false ? 1 : new Foo) // expect: instance of Foo
IO.print(false ? 1 : fn 2) // expect: <fn>
// Associativity.
IO.print(true ? 2 : true ? 4 : 5) // expect: 2
IO.print(false ? 2 : true ? 4 : 5) // expect: 4
+2
View File
@@ -0,0 +1,2 @@
true ? IO.print("ok") : IO.print("no") // expect: ok
false ? IO.print("no") : IO.print("ok") // expect: ok
+1
View File
@@ -0,0 +1 @@
IO.print(fn {}) // expect: <fn>