refactor: move benchmark directory under test and update all references
The benchmark directory is relocated from the project root into the test directory, and all scripts, documentation links, and gitignore paths are updated accordingly. The test runner is also refactored to explicitly walk subdirectories (core, io, language, limit) instead of using a single test root, and a new test/README.md is added to document the test suite structure. Additionally, the constructor test for the Foo class is updated to add a zero-arity constructor and adjust expected output strings.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
var a = "a"
|
||||
var b = "b"
|
||||
var c = "c"
|
||||
|
||||
// Assignment is right-associative.
|
||||
a = b = c
|
||||
IO.print(a) // expect: c
|
||||
IO.print(b) // expect: c
|
||||
IO.print(c) // expect: c
|
||||
@@ -0,0 +1,8 @@
|
||||
var a = "before"
|
||||
IO.print(a) // expect: before
|
||||
|
||||
a = "after"
|
||||
IO.print(a) // expect: after
|
||||
|
||||
IO.print(a = "arg") // expect: arg
|
||||
IO.print(a) // expect: arg
|
||||
@@ -0,0 +1,2 @@
|
||||
var a = "a"
|
||||
(a) = "value" // expect error
|
||||
@@ -0,0 +1,3 @@
|
||||
var a = "a"
|
||||
var b = "b"
|
||||
a + b = "value" // expect error
|
||||
@@ -0,0 +1,3 @@
|
||||
var a = "a"
|
||||
var b = "b"
|
||||
b is a = "value" // expect error
|
||||
@@ -0,0 +1,10 @@
|
||||
new Fn {
|
||||
var a = "before"
|
||||
IO.print(a) // expect: before
|
||||
|
||||
a = "after"
|
||||
IO.print(a) // expect: after
|
||||
|
||||
IO.print(a = "arg") // expect: arg
|
||||
IO.print(a) // expect: arg
|
||||
}.call()
|
||||
@@ -0,0 +1,2 @@
|
||||
var a = "a"
|
||||
!a = "value" // expect error
|
||||
@@ -0,0 +1,11 @@
|
||||
// Chained assignment.
|
||||
var a = "a"
|
||||
var b = "b"
|
||||
a = b = "chain"
|
||||
IO.print(a) // expect: chain
|
||||
IO.print(a) // expect: chain
|
||||
|
||||
// Assignment on RHS of variable.
|
||||
var c = a = "var"
|
||||
IO.print(a) // expect: var
|
||||
IO.print(c) // expect: var
|
||||
@@ -0,0 +1 @@
|
||||
unknown = "what" // expect error
|
||||
@@ -0,0 +1,23 @@
|
||||
// << have higher precedence than |.
|
||||
IO.print(2 | 1 << 1) // expect: 2
|
||||
IO.print(1 << 1 | 2) // expect: 2
|
||||
|
||||
// << has higher precedence than &.
|
||||
IO.print(2 & 1 << 1) // expect: 2
|
||||
IO.print(1 << 1 & 2) // expect: 2
|
||||
|
||||
// << has higher precedence than ^.
|
||||
IO.print(2 ^ 1 << 1) // expect: 0
|
||||
IO.print(1 << 1 ^ 2) // expect: 0
|
||||
|
||||
// & has higher precedence than |.
|
||||
IO.print(1 & 1 | 2) // expect: 3
|
||||
IO.print(2 | 1 & 1) // expect: 3
|
||||
|
||||
// & has higher precedence than ^.
|
||||
IO.print(1 & 1 ^ 2) // expect: 3
|
||||
IO.print(2 ^ 1 & 1) // expect: 3
|
||||
|
||||
// ^ has higher precedence than |.
|
||||
IO.print(1 ^ 1 | 1) // expect: 1
|
||||
IO.print(1 | 1 ^ 1) // expect: 1
|
||||
@@ -0,0 +1,9 @@
|
||||
var f
|
||||
for (i in [1, 2, 3]) {
|
||||
var j = 4
|
||||
f = new Fn { IO.print(i + j) }
|
||||
break
|
||||
}
|
||||
|
||||
f.call()
|
||||
// expect: 5
|
||||
@@ -0,0 +1,9 @@
|
||||
var f
|
||||
while (true) {
|
||||
var i = "i"
|
||||
f = new Fn { IO.print(i) }
|
||||
break
|
||||
}
|
||||
|
||||
f.call()
|
||||
// expect: i
|
||||
@@ -0,0 +1,18 @@
|
||||
for (i in 0..10) {
|
||||
IO.print(i)
|
||||
|
||||
{
|
||||
var a = "a"
|
||||
{
|
||||
var b = "b"
|
||||
{
|
||||
var c = "c"
|
||||
if (i > 1) break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expect: 0
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
@@ -0,0 +1,10 @@
|
||||
for (i in [1, 2, 3, 4, 5]) {
|
||||
IO.print(i)
|
||||
if (i > 2) break
|
||||
IO.print(i)
|
||||
}
|
||||
// expect: 1
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
@@ -0,0 +1,7 @@
|
||||
var done = false
|
||||
while (!done) {
|
||||
new Fn {
|
||||
break // expect error
|
||||
}
|
||||
done = true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
var done = false
|
||||
while (!done) {
|
||||
class Foo {
|
||||
method {
|
||||
break // expect error
|
||||
}
|
||||
}
|
||||
done = true
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
var i = 0
|
||||
while (true) {
|
||||
i = i + 1
|
||||
IO.print(i)
|
||||
if (i > 2) break
|
||||
IO.print(i)
|
||||
}
|
||||
// expect: 1
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
@@ -0,0 +1,19 @@
|
||||
for (i in 0..2) {
|
||||
IO.print("outer ", i)
|
||||
if (i > 1) break
|
||||
|
||||
for (j in 0..2) {
|
||||
IO.print("inner ", j)
|
||||
if (j > 1) break
|
||||
}
|
||||
}
|
||||
|
||||
// expect: outer 0
|
||||
// expect: inner 0
|
||||
// expect: inner 1
|
||||
// expect: inner 2
|
||||
// expect: outer 1
|
||||
// expect: inner 0
|
||||
// expect: inner 1
|
||||
// expect: inner 2
|
||||
// expect: outer 2
|
||||
@@ -0,0 +1,25 @@
|
||||
var i = 0
|
||||
while (true) {
|
||||
IO.print("outer ", i)
|
||||
if (i > 1) break
|
||||
|
||||
var j = 0
|
||||
while (true) {
|
||||
IO.print("inner ", j)
|
||||
if (j > 1) break
|
||||
|
||||
j = j + 1
|
||||
}
|
||||
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
// expect: outer 0
|
||||
// expect: inner 0
|
||||
// expect: inner 1
|
||||
// expect: inner 2
|
||||
// expect: outer 1
|
||||
// expect: inner 0
|
||||
// expect: inner 1
|
||||
// expect: inner 2
|
||||
// expect: outer 2
|
||||
@@ -0,0 +1 @@
|
||||
break // expect error
|
||||
@@ -0,0 +1,14 @@
|
||||
class Foo {
|
||||
static sayName {
|
||||
IO.print(Foo)
|
||||
}
|
||||
|
||||
sayName {
|
||||
IO.print(Foo)
|
||||
}
|
||||
|
||||
static toString { "Foo!" }
|
||||
}
|
||||
|
||||
Foo.sayName // expect: Foo!
|
||||
(new Foo).sayName // expect: Foo!
|
||||
@@ -0,0 +1,6 @@
|
||||
class Foo {}
|
||||
|
||||
var foo = new Foo
|
||||
IO.print(foo is Foo) // expect: true
|
||||
|
||||
// TODO: Test precedence and grammar of what follows "new".
|
||||
@@ -0,0 +1,2 @@
|
||||
class // expect error
|
||||
Foo {}
|
||||
@@ -0,0 +1,6 @@
|
||||
class Foo {
|
||||
static // expect error
|
||||
method {} // expect error
|
||||
}
|
||||
|
||||
// The second error is cascaded.
|
||||
@@ -0,0 +1,11 @@
|
||||
// Empty body.
|
||||
class A {}
|
||||
|
||||
// Newline body.
|
||||
class B {
|
||||
|
||||
}
|
||||
|
||||
// No newline after last method.
|
||||
class C {
|
||||
method {} }
|
||||
@@ -0,0 +1,25 @@
|
||||
var f = null
|
||||
var g = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
f = new Fn {
|
||||
IO.print(local)
|
||||
local = "after f"
|
||||
IO.print(local)
|
||||
}
|
||||
|
||||
g = new Fn {
|
||||
IO.print(local)
|
||||
local = "after g"
|
||||
IO.print(local)
|
||||
}
|
||||
}
|
||||
|
||||
f.call()
|
||||
// expect: local
|
||||
// expect: after f
|
||||
|
||||
g.call()
|
||||
// expect: after f
|
||||
// expect: after g
|
||||
@@ -0,0 +1,9 @@
|
||||
var f = null
|
||||
|
||||
new Fn {|param|
|
||||
f = new Fn {
|
||||
IO.print(param)
|
||||
}
|
||||
}.call("param")
|
||||
|
||||
f.call() // expect: param
|
||||
@@ -0,0 +1,13 @@
|
||||
// This is a regression test. There was a bug where if an upvalue for an
|
||||
// earlier local (here "a") was captured *after* a later one ("b"), then Wren
|
||||
// would crash because it walked to the end of the upvalue list (correct), but
|
||||
// then didn't handle not finding the variable.
|
||||
|
||||
new Fn {
|
||||
var a = "a"
|
||||
var b = "b"
|
||||
new Fn {
|
||||
IO.print(b) // expect: b
|
||||
IO.print(a) // expect: a
|
||||
}.call()
|
||||
}.call()
|
||||
@@ -0,0 +1,12 @@
|
||||
var F = null
|
||||
|
||||
class Foo {
|
||||
method(param) {
|
||||
F = new Fn {
|
||||
IO.print(param)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(new Foo).method("param")
|
||||
F.call() // expect: param
|
||||
@@ -0,0 +1,10 @@
|
||||
var f = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
f = new Fn {
|
||||
IO.print(local)
|
||||
}
|
||||
}
|
||||
|
||||
f.call() // expect: local
|
||||
@@ -0,0 +1,14 @@
|
||||
var foo = null
|
||||
|
||||
{
|
||||
var local = "local"
|
||||
class Foo {
|
||||
method {
|
||||
IO.print(local)
|
||||
}
|
||||
}
|
||||
|
||||
foo = new Foo
|
||||
}
|
||||
|
||||
foo.method // expect: local
|
||||
@@ -0,0 +1,21 @@
|
||||
var f = null
|
||||
|
||||
new Fn {
|
||||
var a = "a"
|
||||
new Fn {
|
||||
var b = "b"
|
||||
new Fn {
|
||||
var c = "c"
|
||||
f = new Fn {
|
||||
IO.print(a)
|
||||
IO.print(b)
|
||||
IO.print(c)
|
||||
}
|
||||
}.call()
|
||||
}.call()
|
||||
}.call()
|
||||
|
||||
f.call()
|
||||
// expect: a
|
||||
// expect: b
|
||||
// expect: c
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
var local = "local"
|
||||
new Fn {
|
||||
IO.print(local) // expect: local
|
||||
}.call()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
var local = "local"
|
||||
class Foo {
|
||||
method {
|
||||
IO.print(local)
|
||||
}
|
||||
}
|
||||
|
||||
(new Foo).method // expect: local
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
var f = null
|
||||
|
||||
{
|
||||
var a = "a"
|
||||
f = new Fn {
|
||||
IO.print(a)
|
||||
IO.print(a)
|
||||
}
|
||||
}
|
||||
|
||||
f.call()
|
||||
// expect: a
|
||||
// expect: a
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
var f = null
|
||||
|
||||
{
|
||||
var a = "a"
|
||||
f = new Fn { IO.print(a) }
|
||||
}
|
||||
|
||||
{
|
||||
// Since a is out of scope, the local slot will be reused by b. Make sure
|
||||
// that f still closes over a.
|
||||
var b = "b"
|
||||
f.call() // expect: a
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Maximum number of closed-over variables (directly and/or indirect).
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
var foo = "closure"
|
||||
new Fn {
|
||||
{
|
||||
IO.print(foo) // expect: closure
|
||||
var foo = "shadow"
|
||||
IO.print(foo) // expect: shadow
|
||||
}
|
||||
IO.print(foo) // expect: closure
|
||||
}.call()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// In middle of line.
|
||||
IO.print/* ... */(/* */"ok"/* */) // expect: ok
|
||||
|
||||
// Nested.
|
||||
IO.print(/* in /* nest */ out */"ok") // expect: ok
|
||||
@@ -0,0 +1,2 @@
|
||||
IO.print("ok") // expect: ok
|
||||
/* comment */
|
||||
@@ -0,0 +1,2 @@
|
||||
IO.print("ok") // expect: ok
|
||||
// comment
|
||||
@@ -0,0 +1 @@
|
||||
// comment
|
||||
@@ -0,0 +1 @@
|
||||
// comment
|
||||
@@ -0,0 +1,11 @@
|
||||
// Unicode characters are allowed in comments.
|
||||
//
|
||||
// Latin 1 Supplement: £§¶ÜÞ
|
||||
// Latin Extended-A: ĐĦŋœ
|
||||
// Latin Extended-B: ƂƢƩǁ
|
||||
// Other stuff: ឃᢆ᯽₪ℜ↩⊗┺░
|
||||
// Emoji: ☃☺♣
|
||||
|
||||
// TODO: What about combining characters?
|
||||
|
||||
IO.print("ok") // expect: ok
|
||||
@@ -0,0 +1,3 @@
|
||||
// expect error line 3
|
||||
IO.print("nope") /*
|
||||
oops
|
||||
@@ -0,0 +1,4 @@
|
||||
// expect error line 4
|
||||
IO.print("nope") /* /* /*
|
||||
*/
|
||||
oops
|
||||
@@ -0,0 +1 @@
|
||||
1 ? 2 ? 3 : 4 : 5 // expect error
|
||||
@@ -0,0 +1,2 @@
|
||||
true ? 1 // expect error
|
||||
"next expression"
|
||||
@@ -0,0 +1 @@
|
||||
? 1 : 2 // expect error
|
||||
@@ -0,0 +1 @@
|
||||
(true ? 1 :) // expect error
|
||||
@@ -0,0 +1 @@
|
||||
true 1 : 2 // expect error
|
||||
@@ -0,0 +1 @@
|
||||
(true ? : 2) // expect error
|
||||
@@ -0,0 +1,7 @@
|
||||
// Newline after '?'.
|
||||
IO.print(true ?
|
||||
"yes" : "no") // expect: yes
|
||||
|
||||
// Newline after ':'.
|
||||
IO.print(false ? "yes" :
|
||||
"no") // expect: no
|
||||
@@ -0,0 +1,55 @@
|
||||
class Foo {
|
||||
static bar { true }
|
||||
static baz { 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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// Associativity.
|
||||
IO.print(true ? 2 : true ? 4 : 5) // expect: 2
|
||||
IO.print(false ? 2 : true ? 4 : 5) // expect: 4
|
||||
@@ -0,0 +1,2 @@
|
||||
true ? IO.print("ok") : IO.print("no") // expect: ok
|
||||
false ? IO.print("no") : IO.print("ok") // expect: ok
|
||||
@@ -0,0 +1,8 @@
|
||||
class Foo {
|
||||
toString { "Foo" }
|
||||
}
|
||||
|
||||
// Classes inherit the argument-less "new" one by default.
|
||||
var foo = new Foo
|
||||
IO.print(foo is Foo) // expect: true
|
||||
IO.print(foo.toString) // expect: Foo
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
+(other) { "Foo " + other }
|
||||
}
|
||||
|
||||
IO.print(new Foo + "value") // expect: Foo value
|
||||
|
||||
// TODO: Other expressions following a constructor, like new Foo.bar("arg").
|
||||
@@ -0,0 +1,19 @@
|
||||
class Foo {
|
||||
new { IO.print("none") }
|
||||
new() { IO.print("zero") }
|
||||
new(a) { IO.print(a) }
|
||||
new(a, b) { IO.print(a + b) }
|
||||
|
||||
toString { "Foo" }
|
||||
}
|
||||
|
||||
// Can overload by arity.
|
||||
new Foo // expect: none
|
||||
new Foo() // expect: zero
|
||||
new Foo("one") // expect: one
|
||||
new Foo("one", "two") // expect: onetwo
|
||||
|
||||
// Returns the new instance.
|
||||
var foo = new Foo // expect: none
|
||||
IO.print(foo is Foo) // expect: true
|
||||
IO.print(foo.toString) // expect: Foo
|
||||
@@ -0,0 +1,40 @@
|
||||
class A {
|
||||
new(arg) {
|
||||
IO.print("new A ", arg)
|
||||
_field = arg
|
||||
}
|
||||
|
||||
aField { _field }
|
||||
}
|
||||
|
||||
class B is A {
|
||||
new(arg1, arg2) {
|
||||
super(arg2)
|
||||
IO.print("new B ", arg1)
|
||||
_field = arg1
|
||||
}
|
||||
|
||||
bField { _field }
|
||||
}
|
||||
|
||||
class C is B {
|
||||
new {
|
||||
super("one", "two")
|
||||
IO.print("new C")
|
||||
_field = "c"
|
||||
}
|
||||
|
||||
cField { _field }
|
||||
}
|
||||
|
||||
var c = new C
|
||||
// expect: new A two
|
||||
// expect: new B one
|
||||
// expect: new C
|
||||
IO.print(c is A) // expect: true
|
||||
IO.print(c is B) // expect: true
|
||||
IO.print(c is C) // expect: true
|
||||
|
||||
IO.print(c.aField) // expect: two
|
||||
IO.print(c.bField) // expect: one
|
||||
IO.print(c.cField) // expect: c
|
||||
@@ -0,0 +1,7 @@
|
||||
{} // By itself.
|
||||
|
||||
// In a statement.
|
||||
if (true) {}
|
||||
if (false) {} else {}
|
||||
|
||||
IO.print("ok") // expect: ok
|
||||
@@ -0,0 +1,25 @@
|
||||
var fiber
|
||||
var closure
|
||||
|
||||
{
|
||||
var a = "before"
|
||||
fiber = new Fiber {
|
||||
IO.print(a)
|
||||
Fiber.yield()
|
||||
a = "after"
|
||||
Fiber.yield()
|
||||
IO.print(a)
|
||||
a = "final"
|
||||
}
|
||||
|
||||
closure = new Fn {
|
||||
IO.print(a)
|
||||
}
|
||||
}
|
||||
|
||||
fiber.call() // expect: before
|
||||
closure.call() // expect: before
|
||||
fiber.call()
|
||||
closure.call() // expect: after
|
||||
fiber.call() // expect: after
|
||||
closure.call() // expect: final
|
||||
@@ -0,0 +1,16 @@
|
||||
class Foo {
|
||||
new { _field = "Foo field" }
|
||||
|
||||
closeOverGet {
|
||||
return new Fn { _field }
|
||||
}
|
||||
|
||||
closeOverSet {
|
||||
return new Fn { _field = "new value" }
|
||||
}
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
IO.print(foo.closeOverGet.call()) // expect: Foo field
|
||||
foo.closeOverSet.call()
|
||||
IO.print(foo.closeOverGet.call()) // expect: new value
|
||||
@@ -0,0 +1,5 @@
|
||||
class Foo {
|
||||
write { IO.print(_field) }
|
||||
}
|
||||
|
||||
(new Foo).write // expect: null
|
||||
@@ -0,0 +1,5 @@
|
||||
class Foo {
|
||||
static bar {
|
||||
new Fn { _field = "wat" } // expect error
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class Foo {
|
||||
static bar {
|
||||
_field = "wat" // expect error
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Refering to an instance method in a nested static class should *not* walk
|
||||
// out to find the nearest enclosing instance method. We could make that work,
|
||||
// but it's confusing to users, and would require some tricky work to make sure
|
||||
// the enclosing instance is closed over.
|
||||
|
||||
class Outer {
|
||||
foo {
|
||||
class Inner {
|
||||
static bar {
|
||||
_field = "nope" // expect error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
class Foo {
|
||||
set(a, b, c, d, e) {
|
||||
_a = a
|
||||
_b = b
|
||||
_c = c
|
||||
_d = d
|
||||
_e = e
|
||||
}
|
||||
|
||||
write {
|
||||
IO.print(_a)
|
||||
IO.print(_b)
|
||||
IO.print(_c)
|
||||
IO.print(_d)
|
||||
IO.print(_e)
|
||||
}
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
foo.set(1, 2, 3, 4, 5)
|
||||
foo.write
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
// expect: 4
|
||||
// expect: 5
|
||||
@@ -0,0 +1,18 @@
|
||||
class Outer {
|
||||
method {
|
||||
_field = "outer"
|
||||
IO.print(_field) // expect: outer
|
||||
|
||||
class Inner {
|
||||
method {
|
||||
_field = "inner"
|
||||
IO.print(_field) // expect: inner
|
||||
}
|
||||
}
|
||||
|
||||
(new Inner).method
|
||||
IO.print(_field) // expect: outer
|
||||
}
|
||||
}
|
||||
|
||||
(new Outer).method
|
||||
@@ -0,0 +1,37 @@
|
||||
// This test exists mainly to make sure the GC traces instance fields.
|
||||
class Node {
|
||||
set(left, value, right) {
|
||||
_left = left
|
||||
_value = value
|
||||
_right = right
|
||||
}
|
||||
|
||||
write {
|
||||
if (_left is Node) {
|
||||
_left.write
|
||||
}
|
||||
|
||||
IO.print(_value)
|
||||
|
||||
if (_right is Node) {
|
||||
_right.write
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var a = new Node
|
||||
a.set(null, "a", null)
|
||||
var b = new Node
|
||||
b.set(null, "b", null)
|
||||
var c = new Node
|
||||
c.set(a, "c", b)
|
||||
a = null
|
||||
b = null
|
||||
var d = new Node
|
||||
d.set(c, "d", null)
|
||||
c = null
|
||||
d.write
|
||||
// expect: a
|
||||
// expect: c
|
||||
// expect: b
|
||||
// expect: d
|
||||
@@ -0,0 +1 @@
|
||||
_field = "wat" // expect error
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
write { IO.print(_field) } // Compile a use of the field...
|
||||
init { _field = "value" } // ...before an assignment to it.
|
||||
}
|
||||
|
||||
var foo = new Foo
|
||||
// But invoke them in the right order.
|
||||
foo.init
|
||||
foo.write // expect: value
|
||||
@@ -0,0 +1,10 @@
|
||||
var list = []
|
||||
|
||||
for (i in [1, 2, 3]) {
|
||||
list.add(new Fn { IO.print(i) })
|
||||
}
|
||||
|
||||
for (f in list) f.call()
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
@@ -0,0 +1,11 @@
|
||||
var list = []
|
||||
|
||||
for (i in [1, 2, 3]) {
|
||||
var j = i + 1
|
||||
list.add(new Fn { IO.print(j) })
|
||||
}
|
||||
|
||||
for (f in list) f.call()
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
// expect: 4
|
||||
@@ -0,0 +1,2 @@
|
||||
for // expect error
|
||||
(i in [1, 2, 3]) IO.print(i)
|
||||
@@ -0,0 +1,2 @@
|
||||
for (i // expect error
|
||||
in [1]) IO.print(i)
|
||||
@@ -0,0 +1,10 @@
|
||||
var f = new Fn {
|
||||
IO.print("evaluate sequence")
|
||||
return [1, 2, 3]
|
||||
}
|
||||
|
||||
for (i in f.call()) IO.print(i)
|
||||
// expect: evaluate sequence
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
@@ -0,0 +1,9 @@
|
||||
var f = new Fn {
|
||||
for (i in [1, 2, 3]) {
|
||||
return new Fn { IO.print(i) }
|
||||
}
|
||||
}
|
||||
|
||||
var g = f.call()
|
||||
g.call()
|
||||
// expect: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
var f = new Fn {
|
||||
for (i in [1, 2, 3]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
IO.print(f.call())
|
||||
// expect: 1
|
||||
@@ -0,0 +1,14 @@
|
||||
// Single-expression body.
|
||||
for (i in [1]) IO.print(i)
|
||||
// expect: 1
|
||||
|
||||
// Block body.
|
||||
for (i in [1]) {
|
||||
IO.print(i)
|
||||
}
|
||||
// expect: 1
|
||||
|
||||
// Newline after "in".
|
||||
for (i in
|
||||
[1]) IO.print(i)
|
||||
// expect: 1
|
||||
@@ -0,0 +1,32 @@
|
||||
class Iter {
|
||||
new(value) { _value = value }
|
||||
iterate(iterator) { _value }
|
||||
iteratorValue(iterator) { "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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
var f = new Fn {}
|
||||
IO.print(f.call()) // expect: null
|
||||
@@ -0,0 +1,4 @@
|
||||
var f = new Fn {
|
||||
// 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") } // expect error
|
||||
@@ -0,0 +1 @@
|
||||
new Fn {|| null } // expect error
|
||||
@@ -0,0 +1,50 @@
|
||||
var f0 = new Fn { 0 }
|
||||
IO.print(f0.call()) // expect: 0
|
||||
|
||||
var f1 = new Fn {|a| a }
|
||||
IO.print(f1.call(1)) // expect: 1
|
||||
|
||||
var f2 = new Fn {|a, b| a + b }
|
||||
IO.print(f2.call(1, 2)) // expect: 3
|
||||
|
||||
var f3 = new Fn {|a, b, c| a + b + c }
|
||||
IO.print(f3.call(1, 2, 3)) // expect: 6
|
||||
|
||||
var f4 = new Fn {|a, b, c, d| a + b + c + d }
|
||||
IO.print(f4.call(1, 2, 3, 4)) // expect: 10
|
||||
|
||||
var f5 = new Fn {|a, b, c, d, e| a + b + c + d + e }
|
||||
IO.print(f5.call(1, 2, 3, 4, 5)) // expect: 15
|
||||
|
||||
var f6 = new Fn {|a, b, c, d, e, f| a + b + c + d + e + f }
|
||||
IO.print(f6.call(1, 2, 3, 4, 5, 6)) // expect: 21
|
||||
|
||||
var f7 = new Fn {|a, b, c, d, e, f, g| a + b + c + d + e + f + g }
|
||||
IO.print(f7.call(1, 2, 3, 4, 5, 6, 7)) // expect: 28
|
||||
|
||||
var f8 = new Fn {|a, b, c, d, e, f, g, h| a + b + c + d + e + f + g + h }
|
||||
IO.print(f8.call(1, 2, 3, 4, 5, 6, 7, 8)) // expect: 36
|
||||
|
||||
var f9 = new Fn {|a, b, c, d, e, f, g, h, i| a + b + c + d + e + f + g + h + i }
|
||||
IO.print(f9.call(1, 2, 3, 4, 5, 6, 7, 8, 9)) // expect: 45
|
||||
|
||||
var f10 = new Fn {|a, b, c, d, e, f, g, h, i, j| a + b + c + d + e + f + g + h + i + j }
|
||||
IO.print(f10.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // expect: 55
|
||||
|
||||
var f11 = new Fn {|a, b, c, d, e, f, g, h, i, j, k| a + b + c + d + e + f + g + h + i + j + k }
|
||||
IO.print(f11.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)) // expect: 66
|
||||
|
||||
var f12 = new Fn {|a, b, c, d, e, f, g, h, i, j, k, l| a + b + c + d + e + f + g + h + i + j + k + l }
|
||||
IO.print(f12.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) // expect: 78
|
||||
|
||||
var f13 = new Fn {|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 }
|
||||
IO.print(f13.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)) // expect: 91
|
||||
|
||||
var f14 = new Fn {|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 }
|
||||
IO.print(f14.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)) // expect: 105
|
||||
|
||||
var f15 = new Fn {|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 }
|
||||
IO.print(f15.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)) // expect: 120
|
||||
|
||||
var f16 = new Fn {|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 }
|
||||
IO.print(f16.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) // expect: 136
|
||||
@@ -0,0 +1,25 @@
|
||||
// Single expression body.
|
||||
new Fn { IO.print("ok") }.call() // expect: ok
|
||||
|
||||
// Curly body.
|
||||
new Fn {
|
||||
IO.print("ok") // expect: ok
|
||||
}.call()
|
||||
|
||||
// Multiple statements.
|
||||
new Fn {
|
||||
IO.print("1") // expect: 1
|
||||
IO.print("2") // expect: 2
|
||||
}.call()
|
||||
|
||||
// Extra newlines.
|
||||
new Fn {
|
||||
|
||||
|
||||
IO.print("1") // expect: 1
|
||||
|
||||
|
||||
IO.print("2") // expect: 2
|
||||
|
||||
|
||||
}.call()
|
||||
@@ -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")
|
||||
@@ -0,0 +1,6 @@
|
||||
// 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
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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
|
||||
@@ -0,0 +1 @@
|
||||
if (true) "ok" else // expect error
|
||||
@@ -0,0 +1,2 @@
|
||||
if // expect error
|
||||
(true) IO.print("bad")
|
||||
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
// Sprinkle some carriage returns to ensure they are ignored anywhere:
|
||||
IO␍.print("one"␍)
|
||||
IO.print␍("two")
|
||||
|
||||
// Generate a compile error so we can test that the line number is correct.
|
||||
+ * // expect error
|
||||
@@ -0,0 +1,23 @@
|
||||
class Foo {
|
||||
getter {
|
||||
IO.print("getter")
|
||||
}
|
||||
|
||||
setter=(value) {
|
||||
IO.print("setter")
|
||||
}
|
||||
|
||||
method(a) {
|
||||
IO.print("method")
|
||||
}
|
||||
}
|
||||
|
||||
class Bar is Foo {
|
||||
test {
|
||||
getter // expect: getter
|
||||
setter = "value" // expect: setter
|
||||
method("arg") // expect: method
|
||||
}
|
||||
}
|
||||
|
||||
(new Bar).test
|
||||
@@ -0,0 +1,23 @@
|
||||
class Foo {
|
||||
getter {
|
||||
IO.print("getter")
|
||||
}
|
||||
|
||||
setter=(value) {
|
||||
IO.print("setter")
|
||||
}
|
||||
|
||||
method(a) {
|
||||
IO.print("method")
|
||||
}
|
||||
|
||||
test {
|
||||
getter // expect: getter
|
||||
setter = "value" // expect: setter
|
||||
method("arg") // expect: method
|
||||
}
|
||||
}
|
||||
|
||||
(new Foo).test
|
||||
|
||||
// TODO: Need to decide how these interact with globals.
|
||||
@@ -0,0 +1,17 @@
|
||||
class Foo {
|
||||
bar { "getter" }
|
||||
|
||||
test {
|
||||
IO.print(bar) // expect: getter
|
||||
|
||||
{
|
||||
IO.print(bar) // expect: getter
|
||||
var bar = "local"
|
||||
IO.print(bar) // expect: local
|
||||
}
|
||||
|
||||
IO.print(bar) // expect: getter
|
||||
}
|
||||
}
|
||||
|
||||
(new Foo).test
|
||||
@@ -0,0 +1,20 @@
|
||||
class Foo {
|
||||
bar=(value) {
|
||||
IO.print("setter")
|
||||
return value
|
||||
}
|
||||
|
||||
test {
|
||||
bar = "value" // expect: setter
|
||||
|
||||
{
|
||||
bar = "value" // expect: setter
|
||||
var bar = "local"
|
||||
bar = "value" // no expectation
|
||||
}
|
||||
|
||||
bar = "value" // expect: setter
|
||||
}
|
||||
}
|
||||
|
||||
(new Foo).test
|
||||
@@ -0,0 +1,47 @@
|
||||
class Outer {
|
||||
getter {
|
||||
IO.print("outer getter")
|
||||
}
|
||||
|
||||
setter=(value) {
|
||||
IO.print("outer setter")
|
||||
}
|
||||
|
||||
method(a) {
|
||||
IO.print("outer method")
|
||||
}
|
||||
|
||||
test {
|
||||
getter // expect: outer getter
|
||||
setter = "value" // expect: outer setter
|
||||
method("arg") // expect: outer method
|
||||
|
||||
class Inner {
|
||||
getter {
|
||||
IO.print("inner getter")
|
||||
}
|
||||
|
||||
setter=(value) {
|
||||
IO.print("inner setter")
|
||||
}
|
||||
|
||||
method(a) {
|
||||
IO.print("inner method")
|
||||
}
|
||||
|
||||
test {
|
||||
getter // expect: inner getter
|
||||
setter = "value" // expect: inner setter
|
||||
method("arg") // expect: inner method
|
||||
}
|
||||
}
|
||||
|
||||
(new Inner).test
|
||||
|
||||
getter // expect: outer getter
|
||||
setter = "value" // expect: outer setter
|
||||
method("arg") // expect: outer method
|
||||
}
|
||||
}
|
||||
|
||||
(new Outer).test
|
||||
@@ -0,0 +1,21 @@
|
||||
class Foo {
|
||||
static getter {
|
||||
IO.print("getter")
|
||||
}
|
||||
|
||||
static setter=(value) {
|
||||
IO.print("setter")
|
||||
}
|
||||
|
||||
static method(a) {
|
||||
IO.print("method")
|
||||
}
|
||||
|
||||
static test {
|
||||
getter // expect: getter
|
||||
setter = "value" // expect: setter
|
||||
method("arg") // expect: method
|
||||
}
|
||||
}
|
||||
|
||||
Foo.test
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user