diff --git a/benchmark/fib.wren b/benchmark/fib.wren index 62e1c86d..637dfe99 100644 --- a/benchmark/fib.wren +++ b/benchmark/fib.wren @@ -1,8 +1,5 @@ var fib = fn(n) { - if (n < 2) { - return n - } - + if (n < 2) return n return fib.call(n - 1) + fib.call(n - 2) } diff --git a/src/wren_vm.c b/src/wren_vm.c index f83c156a..4c7e8acd 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -997,9 +997,7 @@ static bool runInterpreter(WrenVM* vm) int offset = READ_SHORT(); Value condition = POP(); - // False is the only falsey value. - // TODO: Null should be falsey too. - if (IS_FALSE(condition)) ip += offset; + if (IS_FALSE(condition) || IS_NULL(condition)) ip += offset; DISPATCH(); } @@ -1008,18 +1006,16 @@ static bool runInterpreter(WrenVM* vm) int offset = READ_SHORT(); Value condition = PEEK(); - // False is the only falsey value. - // TODO: Null should be falsey too. - if (!IS_FALSE(condition)) - { - // Discard the condition and evaluate the right hand side. - POP(); - } - else + if (IS_FALSE(condition) || IS_NULL(condition)) { // Short-circuit the right hand side. ip += offset; } + else + { + // Discard the condition and evaluate the right hand side. + POP(); + } DISPATCH(); } @@ -1028,9 +1024,7 @@ static bool runInterpreter(WrenVM* vm) int offset = READ_SHORT(); Value condition = PEEK(); - // False is the only falsey value. - // TODO: Null should be falsey too. - if (IS_FALSE(condition)) + if (IS_FALSE(condition) || IS_NULL(condition)) { // Discard the condition and evaluate the right hand side. POP(); diff --git a/test/for/truth.wren b/test/for/truth.wren new file mode 100644 index 00000000..57e2a038 --- /dev/null +++ b/test/for/truth.wren @@ -0,0 +1,8 @@ +// False and null are false. +if (false) IO.print("bad") else IO.print("false") // expect: false +if (null) IO.print("bad") else IO.print("null") // expect: null + +// Everything else is true. +if (true) IO.print(true) // expect: true +if (0) IO.print(0) // expect: 0 +if ("") IO.print("empty") // expect: empty diff --git a/test/if.wren b/test/if.wren deleted file mode 100644 index 023b7fb8..00000000 --- a/test/if.wren +++ /dev/null @@ -1,28 +0,0 @@ -// Evaluate the 'then' expression if the condition is true. -if (true) IO.print("good") // expect: good -if (false) IO.print("bad") - -// Evaluate the 'else' expression if the condition is false. -if (true) IO.print("good") else IO.print("bad") // expect: good -if (false) IO.print("bad") else IO.print("good") // expect: good - -// Allow blocks for branches. -if (true) { IO.print("block") } // expect: block -if (false) null else { IO.print("block") } // expect: block - -// Assignment in if condition. -var a = false -if (a = true) IO.print(a) // expect: true - -// Newline after "if". -if -(true) IO.print("good") // expect: good - -// Newline after "else". -if (false) IO.print("bad") else -IO.print("good") // expect: good - -// Only false is falsy. -if (0) IO.print(0) // expect: 0 -if (null) IO.print(null) // expect: null -if ("") IO.print("empty") // expect: empty diff --git a/test/if/dangling_else.wren b/test/if/dangling_else.wren new file mode 100644 index 00000000..a1c50de8 --- /dev/null +++ b/test/if/dangling_else.wren @@ -0,0 +1,3 @@ +// A dangling else binds to the right-most if. +if (true) if (false) IO.print("bad") else IO.print("good") // expect: good +if (false) if (true) IO.print("bad") else IO.print("bad") diff --git a/test/if/else.wren b/test/if/else.wren new file mode 100644 index 00000000..47d7e0ea --- /dev/null +++ b/test/if/else.wren @@ -0,0 +1,10 @@ +// Evaluate the 'else' expression if the condition is false. +if (true) IO.print("good") else IO.print("bad") // expect: good +if (false) IO.print("bad") else IO.print("good") // expect: good + +// Allow block body. +if (false) null else { IO.print("block") } // expect: block + +// Newline after "else". +if (false) IO.print("bad") else +IO.print("good") // expect: good diff --git a/test/if/if.wren b/test/if/if.wren new file mode 100644 index 00000000..67d1cc6a --- /dev/null +++ b/test/if/if.wren @@ -0,0 +1,14 @@ +// Evaluate the 'then' expression if the condition is true. +if (true) IO.print("good") // expect: good +if (false) IO.print("bad") + +// Allow block body. +if (true) { IO.print("block") } // expect: block + +// Assignment in if condition. +var a = false +if (a = true) IO.print(a) // expect: true + +// Newline after "if". +if +(true) IO.print("good") // expect: good diff --git a/test/if/truth.wren b/test/if/truth.wren new file mode 100644 index 00000000..86f05ab4 --- /dev/null +++ b/test/if/truth.wren @@ -0,0 +1,32 @@ +class Iter { + new(value) { _value = value } + iterate(iterator) { return _value } + iteratorValue(iterator) { return "value" } +} + +// False and null are false. +for (n in new Iter(false)) { + IO.print("bad") + break +} + +for (n in new Iter(null)) { + IO.print("bad") + break +} + +// Everything else is true. +for (n in new Iter(true)) { + IO.print("true") // expect: true + break +} + +for (n in new Iter(0)) { + IO.print(0) // expect: 0 + break +} + +for (n in new Iter("")) { + IO.print("string") // expect: string + break +} diff --git a/test/and.wren b/test/logical_operator/and.wren similarity index 77% rename from test/and.wren rename to test/logical_operator/and.wren index d05d0561..db8c9618 100644 --- a/test/and.wren +++ b/test/logical_operator/and.wren @@ -18,9 +18,3 @@ IO.print(true) && // expect: true // Swallow a trailing newline. IO.print(true && true) // expect: true - -// Only false is falsy. -IO.print(0 && true) // expect: true -IO.print(null && true) // expect: true -IO.print("" && true) // expect: true -IO.print(false && true) // expect: false diff --git a/test/logical_operator/and_truth.wren b/test/logical_operator/and_truth.wren new file mode 100644 index 00000000..4c4e365a --- /dev/null +++ b/test/logical_operator/and_truth.wren @@ -0,0 +1,8 @@ +// False and null are false. +IO.print(false && "bad") // expect: false +IO.print(null && "bad") // expect: null + +// Everything else is true. +IO.print(true && "ok") // expect: ok +IO.print(0 && "ok") // expect: ok +IO.print("" && "ok") // expect: ok diff --git a/test/or.wren b/test/logical_operator/or.wren similarity index 77% rename from test/or.wren rename to test/logical_operator/or.wren index c35a4c9d..3e4779e3 100644 --- a/test/or.wren +++ b/test/logical_operator/or.wren @@ -18,9 +18,3 @@ IO.print(false) || // expect: false // Swallow a trailing newline. IO.print(true || true) // expect: true - -// Only false is falsy. -IO.print(0 || true) // expect: 0 -IO.print(null || true) // expect: null -IO.print(("" || true) == "") // expect: true -IO.print(false || true) // expect: true diff --git a/test/logical_operator/or_truth.wren b/test/logical_operator/or_truth.wren new file mode 100644 index 00000000..fd6aa2fc --- /dev/null +++ b/test/logical_operator/or_truth.wren @@ -0,0 +1,8 @@ +// False and null are false. +IO.print(false || "ok") // expect: ok +IO.print(null || "ok") // expect: ok + +// Everything else is true. +IO.print(true || "ok") // expect: true +IO.print(0 || "ok") // expect: 0 +IO.print("s" || "ok") // expect: s diff --git a/test/while/truth.wren b/test/while/truth.wren new file mode 100644 index 00000000..32a625b2 --- /dev/null +++ b/test/while/truth.wren @@ -0,0 +1,26 @@ +// False and null are false. +while (false) { + IO.print("bad") + break +} + +while (null) { + IO.print("bad") + break +} + +// Everything else is true. +while (true) { + IO.print("true") // expect: true + break +} + +while (0) { + IO.print(0) // expect: 0 + break +} + +while ("") { + IO.print("string") // expect: string + break +}