feat: unify block, function, and method body parsing to support single-expression implicit returns

Refactor `finishBlock` in `wren_compiler.c` to detect single-expression bodies (no newline after `{`) and leave a value on the stack, enabling implicit returns for methods and functions. Add `finishBody` wrapper to handle constructor flag. Update all benchmark and test `.wren` files to remove explicit `return` keywords from getters and single-expression methods, relying on the new implicit return behavior. Remove old `return_null_if_brace.wren` test, add `newline_body.wren`, `newline_in_expression_block.wren`, and `no_newline_before_close.wren` tests for edge cases.
This commit is contained in:
Bob Nystrom
2014-04-03 14:48:19 +00:00
parent de2650b0ba
commit a1365c4183
34 changed files with 1165 additions and 1187 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ class Foo {
IO.print(Foo.toString)
}
static toString { return "Foo!" }
static toString { "Foo!" }
}
Foo.sayName // expect: Foo!
+2 -2
View File
@@ -1,6 +1,6 @@
class Foo {
static bar { return true }
static baz { return 1 }
static bar { true }
static baz { 1 }
}
// Condition precedence.
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
toString { return "Foo" }
toString { "Foo" }
}
// Classes inherit the argument-less "new" one by default.
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
+ other { return "Foo " + other }
+ other { "Foo " + other }
}
IO.print(new Foo + "value") // expect: Foo value
+1 -1
View File
@@ -3,7 +3,7 @@ class Foo {
new(a) { IO.print(a) }
new(a, b) { IO.print(a + b) }
toString { return "Foo" }
toString { "Foo" }
}
// Can overload by arity.
+3 -3
View File
@@ -4,7 +4,7 @@ class A {
_field = arg
}
aField { return _field }
aField { _field }
}
class B is A {
@@ -14,7 +14,7 @@ class B is A {
_field = arg1
}
bField { return _field }
bField { _field }
}
class C is B {
@@ -24,7 +24,7 @@ class C is B {
_field = "c"
}
cField { return _field }
cField { _field }
}
var c = new C
@@ -1,6 +1,4 @@
var f = new Fn {
if (true) { return }
IO.print("bad")
// Hi.
}
IO.print(f.call) // expect: null
@@ -0,0 +1,5 @@
new Fn { IO.print("ok") // expect error
}.call // expect error
// The second error is cascaded here. If it starts failing, just remove that
// expectation.
@@ -0,0 +1,2 @@
new Fn {
IO.print("ok") }.call // expect error
+1 -5
View File
@@ -6,11 +6,7 @@ new Fn {
IO.print("ok") // expect: ok
}.call
// No trailing newline.
new Fn {
IO.print("ok") }.call // expect: ok
// Multiple expressions.
// Multiple statements.
new Fn {
IO.print("1") // expect: 1
IO.print("2") // expect: 2
+2 -2
View File
@@ -1,7 +1,7 @@
class Iter {
new(value) { _value = value }
iterate(iterator) { return _value }
iteratorValue(iterator) { return "value" }
iterate(iterator) { _value }
iteratorValue(iterator) { "value" }
}
// False and null are false.
@@ -1,5 +1,5 @@
class Foo {
bar { return "getter" }
bar { "getter" }
test {
IO.print(bar) // expect: getter
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
toString { return "Foo.toString" }
toString { "Foo.toString" }
}
// Calls toString on argument.
+1 -1
View File
@@ -9,7 +9,7 @@ IO.print([1, [2, [3], 4], 5]) // expect: [1, [2, [3], 4], 5]
// Calls toString on elements.
class Foo {
toString { return "Foo.toString" }
toString { "Foo.toString" }
}
IO.print([1, new Foo, 2]) // expect: [1, Foo.toString, 2]
+17 -17
View File
@@ -1,21 +1,21 @@
class Foo {
method { return 0 }
method(a) { return a }
method(a, b) { return a + b }
method(a, b, c) { return a + b + c }
method(a, b, c, d) { return a + b + c + d }
method(a, b, c, d, e) { return a + b + c + d + e }
method(a, b, c, d, e, f) { return a + b + c + d + e + f }
method(a, b, c, d, e, f, g) { return a + b + c + d + e + f + g }
method(a, b, c, d, e, f, g, h) { return a + b + c + d + e + f + g + h }
method(a, b, c, d, e, f, g, h, i) { return a + b + c + d + e + f + g + h + i }
method(a, b, c, d, e, f, g, h, i, j) { return a + b + c + d + e + f + g + h + i + j }
method(a, b, c, d, e, f, g, h, i, j, k) { return a + b + c + d + e + f + g + h + i + j + k}
method(a, b, c, d, e, f, g, h, i, j, k, l) { return a + b + c + d + e + f + g + h + i + j + k + l}
method(a, b, c, d, e, f, g, h, i, j, k, l, m) { return a + b + c + d + e + f + g + h + i + j + k + l + m}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n) { return a + b + c + d + e + f + g + h + i + j + k + l + m + n}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) { return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) { return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p}
method { 0 }
method(a) { a }
method(a, b) { a + b }
method(a, b, c) { a + b + c }
method(a, b, c, d) { a + b + c + d }
method(a, b, c, d, e) { a + b + c + d + e }
method(a, b, c, d, e, f) { a + b + c + d + e + f }
method(a, b, c, d, e, f, g) { a + b + c + d + e + f + g }
method(a, b, c, d, e, f, g, h) { a + b + c + d + e + f + g + h }
method(a, b, c, d, e, f, g, h, i) { a + b + c + d + e + f + g + h + i }
method(a, b, c, d, e, f, g, h, i, j) { a + b + c + d + e + f + g + h + i + j }
method(a, b, c, d, e, f, g, h, i, j, k) { a + b + c + d + e + f + g + h + i + j + k}
method(a, b, c, d, e, f, g, h, i, j, k, l) { a + b + c + d + e + f + g + h + i + j + k + l}
method(a, b, c, d, e, f, g, h, i, j, k, l, m) { a + b + c + d + e + f + g + h + i + j + k + l + m}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n) { a + b + c + d + e + f + g + h + i + j + k + l + m + n}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) { a + b + c + d + e + f + g + h + i + j + k + l + m + n + o}
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) { a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p}
}
var foo = new Foo
+1000 -1000
View File
File diff suppressed because it is too large Load Diff
+15 -15
View File
@@ -1,20 +1,20 @@
class Foo {
+ other { return "infix + " + other }
- other { return "infix - " + other }
* other { return "infix * " + other }
/ other { return "infix / " + other }
% other { return "infix % " + other }
< other { return "infix < " + other }
> other { return "infix > " + other }
<= other { return "infix <= " + other }
>= other { return "infix >= " + other }
== other { return "infix == " + other }
!= other { return "infix != " + other }
& other { return "infix & " + other }
| other { return "infix | " + other }
+ other { "infix + " + other }
- other { "infix - " + other }
* other { "infix * " + other }
/ other { "infix / " + other }
% other { "infix % " + other }
< other { "infix < " + other }
> other { "infix > " + other }
<= other { "infix <= " + other }
>= other { "infix >= " + other }
== other { "infix == " + other }
!= other { "infix != " + other }
& other { "infix & " + other }
| other { "infix | " + other }
! { return "prefix !" }
- { return "prefix -" }
! { "prefix !" }
- { "prefix -" }
}
var foo = new Foo
+4 -4
View File
@@ -1,9 +1,9 @@
class Foo {
bar { return "on instance" }
static bar { return "on metaclass" }
bar { "on instance" }
static bar { "on metaclass" }
bar(arg) { return "on instance " + arg }
static bar(arg) { return "on metaclass " + arg }
bar(arg) { "on instance " + arg }
static bar(arg) { "on metaclass " + arg }
}
IO.print((new Foo).bar) // expect: on instance
+1 -1
View File
@@ -1,6 +1,6 @@
class Foo {
new(value) { _value = value }
toString { return _value }
toString { _value }
bar = value {
_value = value
return value
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
bar = value { return value }
bar = value { value }
}
var foo = new Foo
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
bar = value { return value }
bar = value { value }
}
var foo = new Foo
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
bar = value { return value }
bar = value { value }
}
var foo = new Foo
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
bar = value { return value }
bar = value { value }
}
var foo = new Foo
+1 -1
View File
@@ -1,5 +1,5 @@
class Foo {
bar = value { return "result" }
bar = value { "result" }
}
var foo = new Foo
+3 -6
View File
@@ -1,13 +1,10 @@
class Base {
toString { return "Base" }
toString { "Base" }
}
class Derived is Base {
getClosure {
return new Fn { super.toString }
}
toString { return "Derived" }
getClosure { new Fn { super.toString } }
toString { "Derived" }
}
var closure = (new Derived).getClosure
+2 -5
View File
@@ -1,9 +1,6 @@
class Foo {
getClosure {
return new Fn { toString }
}
toString { return "Foo" }
getClosure { new Fn { toString } }
toString { "Foo" }
}
var closure = (new Foo).getClosure
+2 -2
View File
@@ -9,14 +9,14 @@ class Outer {
method {
IO.print(this) // expect: Inner
}
toString { return "Inner" }
toString { "Inner" }
}
(new Inner).method
}.call
}
toString { return "Outer" }
toString { "Outer" }
}
(new Outer).method
+2 -11
View File
@@ -1,15 +1,6 @@
class Foo {
getClosure {
return new Fn {
return new Fn {
return new Fn {
return toString
}
}
}
}
toString { return "Foo" }
getClosure { new Fn { new Fn { new Fn { toString } } } }
toString { "Foo" }
}
var closure = (new Foo).getClosure
+2 -2
View File
@@ -1,6 +1,6 @@
class Foo {
bar { return this }
baz { return "baz" }
bar { this }
baz { "baz" }
}
IO.print((new Foo).bar.baz) // expect: baz
+1 -1
View File
@@ -4,7 +4,7 @@ class Foo {
IO.print(this.bar) // expect: bar
}
static bar { return "bar" }
static bar { "bar" }
}
Foo.test