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:
@@ -7,7 +7,7 @@ class Foo {
|
||||
IO.print(Foo.toString)
|
||||
}
|
||||
|
||||
static toString { return "Foo!" }
|
||||
static toString { "Foo!" }
|
||||
}
|
||||
|
||||
Foo.sayName // expect: Foo!
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Foo {
|
||||
static bar { return true }
|
||||
static baz { return 1 }
|
||||
static bar { true }
|
||||
static baz { 1 }
|
||||
}
|
||||
|
||||
// Condition precedence.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
toString { return "Foo" }
|
||||
toString { "Foo" }
|
||||
}
|
||||
|
||||
// Classes inherit the argument-less "new" one by default.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
+ other { return "Foo " + other }
|
||||
+ other { "Foo " + other }
|
||||
}
|
||||
|
||||
IO.print(new Foo + "value") // expect: Foo value
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
toString { return "Foo.toString" }
|
||||
toString { "Foo.toString" }
|
||||
}
|
||||
|
||||
// Calls toString on argument.
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -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
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
class Foo {
|
||||
new(value) { _value = value }
|
||||
toString { return _value }
|
||||
toString { _value }
|
||||
bar = value {
|
||||
_value = value
|
||||
return value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
bar = value { return value }
|
||||
bar = value { value }
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
bar = value { return value }
|
||||
bar = value { value }
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
bar = value { return value }
|
||||
bar = value { value }
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
bar = value { return value }
|
||||
bar = value { value }
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Foo {
|
||||
bar = value { return "result" }
|
||||
bar = value { "result" }
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Foo {
|
||||
bar { return this }
|
||||
baz { return "baz" }
|
||||
bar { this }
|
||||
baz { "baz" }
|
||||
}
|
||||
|
||||
IO.print((new Foo).bar.baz) // expect: baz
|
||||
|
||||
@@ -4,7 +4,7 @@ class Foo {
|
||||
IO.print(this.bar) // expect: bar
|
||||
}
|
||||
|
||||
static bar { return "bar" }
|
||||
static bar { "bar" }
|
||||
}
|
||||
|
||||
Foo.test
|
||||
|
||||
Reference in New Issue
Block a user