added tests

This commit is contained in:
Moritz Gmeiner 2024-09-01 19:15:55 +02:00
commit 660464638f
255 changed files with 7220 additions and 3 deletions

View file

@ -0,0 +1,9 @@
var a = "a";
var b = "b";
var c = "c";
// Assignment is right-associative.
a = b = c;
print a; // expect: c
print b; // expect: c
print c; // expect: c

View file

@ -0,0 +1,8 @@
var a = "before";
print a; // expect: before
a = "after";
print a; // expect: after
print a = "arg"; // expect: arg
print a; // expect: arg

View file

@ -0,0 +1,2 @@
var a = "a";
(a) = "value"; // Error at '=': Invalid assignment target.

View file

@ -0,0 +1,3 @@
var a = "a";
var b = "b";
a + b = "value"; // Error at '=': Invalid assignment target.

View file

@ -0,0 +1,10 @@
{
var a = "before";
print a; // expect: before
a = "after";
print a; // expect: after
print a = "arg"; // expect: arg
print a; // expect: arg
}

View file

@ -0,0 +1,2 @@
var a = "a";
!a = "value"; // Error at '=': Invalid assignment target.

View file

@ -0,0 +1,5 @@
// Assignment on RHS of variable.
var a = "before";
var c = a = "var";
print a; // expect: var
print c; // expect: var

View file

@ -0,0 +1,7 @@
class Foo {
Foo() {
this = "value"; // Error at '=': Invalid assignment target.
}
}
Foo();

View file

@ -0,0 +1 @@
unknown = "what"; // Error: Undefined variable 'unknown'.

View file

@ -0,0 +1,7 @@
{} // By itself.
// In a statement.
if (true) {}
if (false) {} else {}
print "ok"; // expect: ok

View file

@ -0,0 +1,8 @@
var a = "outer";
{
var a = "inner";
print a; // expect: inner
}
print a; // expect: outer

View file

@ -0,0 +1,23 @@
print true == true; // expect: true
print true == false; // expect: false
print false == true; // expect: false
print false == false; // expect: true
// Not equal to other types.
print true == 1; // expect: false
print false == 0; // expect: false
print true == "true"; // expect: false
print false == "false"; // expect: false
print false == ""; // expect: false
print true != true; // expect: false
print true != false; // expect: true
print false != true; // expect: true
print false != false; // expect: false
// Not equal to other types.
print true != 1; // expect: true
print false != 0; // expect: true
print true != "true"; // expect: true
print false != "false"; // expect: true
print false != ""; // expect: true

View file

@ -0,0 +1,3 @@
print !true; // expect: false
print !false; // expect: true
print !!true; // expect: true

View file

@ -0,0 +1,11 @@
for (var i = 0; i < 10; i = i + 1) {
if (i == 5)
break;
print i;
}
// expect: 0
// expect: 1
// expect: 2
// expect: 3
// expect: 4

View file

@ -0,0 +1,2 @@
break;
// expect: error

View file

@ -0,0 +1,15 @@
var i = 0;
while (i < 10) {
if (i == 5)
break;
print i;
i = i + 1;
}
// expect: 0
// expect: 1
// expect: 2
// expect: 3
// expect: 4

View file

@ -0,0 +1 @@
true(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1 @@
nil(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1 @@
123(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1,4 @@
class Foo {}
var foo = Foo();
foo(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1 @@
"str"(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1,3 @@
class Foo {}
print Foo; // expect: Foo

View file

@ -0,0 +1 @@
class Foo < Foo {} // Error at 'Foo': A class can't inherit from itself.

View file

@ -0,0 +1,22 @@
class Foo {
inFoo() {
print "in foo";
}
}
class Bar < Foo {
inBar() {
print "in bar";
}
}
class Baz < Bar {
inBaz() {
print "in baz";
}
}
var baz = Baz();
baz.inFoo(); // expect: in foo
baz.inBar(); // expect: in bar
baz.inBaz(); // expect: in baz

View file

@ -0,0 +1,8 @@
class A {}
fun f() {
class B < A {}
return B;
}
print f(); // expect: B

View file

@ -0,0 +1,4 @@
{
class Foo < Foo {} // Error at 'Foo': A class can't inherit from itself.
}
// [c line 5] Error at end: Expect '}' after block.

View file

@ -0,0 +1,9 @@
{
class Foo {
returnSelf() {
return Foo;
}
}
print Foo().returnSelf(); // expect: Foo
}

View file

@ -0,0 +1,7 @@
class Foo {
returnSelf() {
return Foo;
}
}
print Foo().returnSelf(); // expect: Foo

View file

@ -0,0 +1,27 @@
var f;
var g;
{
var local = "local";
fun f_() {
print local;
local = "after f";
print local;
}
f = f_;
fun g_() {
print local;
local = "after g";
print local;
}
g = g_;
}
f();
// expect: local
// expect: after f
g();
// expect: after f
// expect: after g

View file

@ -0,0 +1,13 @@
var a = "global";
{
fun assign() {
a = "assigned";
}
var a = "inner";
assign();
print a; // expect: inner
}
print a; // expect: assigned

View file

@ -0,0 +1,11 @@
var f;
fun foo(param) {
fun f_() {
print param;
}
f = f_;
}
foo("param");
f(); // expect: param

View file

@ -0,0 +1,15 @@
// 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 it
// would crash because it walked to the end of the upvalue list (correct), but
// then didn't handle not finding the variable.
fun f() {
var a = "a";
var b = "b";
fun g() {
print b; // expect: b
print a; // expect: a
}
g();
}
f();

View file

@ -0,0 +1,13 @@
var f;
class Foo {
method(param) {
fun f_() {
print param;
}
f = f_;
}
}
Foo().method("param");
f(); // expect: param

View file

@ -0,0 +1,11 @@
var f;
{
var local = "local";
fun f_() {
print local;
}
f = f_;
}
f(); // expect: local

View file

@ -0,0 +1,25 @@
var f;
fun f1() {
var a = "a";
fun f2() {
var b = "b";
fun f3() {
var c = "c";
fun f4() {
print a;
print b;
print c;
}
f = f4;
}
f3();
}
f2();
}
f1();
f();
// expect: a
// expect: b
// expect: c

View file

@ -0,0 +1,7 @@
{
var local = "local";
fun f() {
print local; // expect: local
}
f();
}

View file

@ -0,0 +1,14 @@
var f;
{
var a = "a";
fun f_() {
print a;
print a;
}
f = f_;
}
f();
// expect: a
// expect: a

View file

@ -0,0 +1,16 @@
{
var f;
{
var a = "a";
fun f_() { print a; }
f = f_;
}
{
// 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(); // expect: a
}
}

View file

@ -0,0 +1,12 @@
{
var foo = "closure";
fun f() {
{
print foo; // expect: closure
var foo = "shadow";
print foo; // expect: shadow
}
print foo; // expect: closure
}
f();
}

View file

@ -0,0 +1,13 @@
// This is a regression test. There was a bug where the VM would try to close
// an upvalue even if the upvalue was never created because the codepath for
// the closure was not executed.
{
var a = "a";
if (false) {
fun foo() { a; }
}
}
// If we get here, we didn't segfault when a went out of scope.
print "ok"; // expect: ok

View file

@ -0,0 +1,28 @@
// This is a regression test. When closing upvalues for discarded locals, it
// wouldn't make sure it discarded the upvalue for the correct stack slot.
//
// Here we create two locals that can be closed over, but only the first one
// actually is. When "b" goes out of scope, we need to make sure we don't
// prematurely close "a".
var closure;
{
var a = "a";
{
var b = "b";
fun returnA() {
return a;
}
closure = returnA;
if (false) {
fun returnB() {
return b;
}
}
}
print closure(); // expect: a
}

View file

@ -0,0 +1,2 @@
print "ok"; // expect: ok
// comment

View file

@ -0,0 +1 @@
// comment

View file

@ -0,0 +1 @@
// comment

View file

@ -0,0 +1,9 @@
// Unicode characters are allowed in comments.
//
// Latin 1 Supplement: £§¶ÜÞ
// Latin Extended-A: ĐĦŋœ
// Latin Extended-B: ƂƢƩǁ
// Other stuff: ឃᢆ᯽₪ℜ↩⊗┺░
// Emoji: ☃☺♣
print "ok"; // expect: ok

View file

@ -0,0 +1,11 @@
class Foo {
init(a, b) {
print "init"; // expect: init
this.a = a;
this.b = b;
}
}
var foo = Foo(1, 2);
print foo.a; // expect: 1
print foo.b; // expect: 2

View file

@ -0,0 +1,11 @@
class Foo {
init() {
print "init";
return;
print "nope";
}
}
var foo = Foo(); // expect: init
print foo.init(); // expect: init
// expect: Foo instance

View file

@ -0,0 +1,15 @@
class Foo {
init(arg) {
print "Foo.init(" + arg + ")";
this.field = "init";
}
}
var foo = Foo("one"); // expect: Foo.init(one)
foo.field = "field";
var foo2 = foo.init("two"); // expect: Foo.init(two)
print foo2; // expect: Foo instance
// Make sure init() doesn't create a fresh instance.
print foo.field; // expect: init

View file

@ -0,0 +1,4 @@
class Foo {}
var foo = Foo();
print foo; // expect: Foo instance

View file

@ -0,0 +1,3 @@
class Foo {}
var foo = Foo(1, 2, 3); // expect runtime error: Expected 0 arguments but got 3.

View file

@ -0,0 +1,10 @@
class Foo {
init() {
print "init";
return;
print "nope";
}
}
var foo = Foo(); // expect: init
print foo; // expect: Foo instance

View file

@ -0,0 +1,8 @@
class Foo {
init(a, b) {
this.a = a;
this.b = b;
}
}
var foo = Foo(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4.

View file

@ -0,0 +1,12 @@
class Foo {
init(arg) {
print "Foo.init(" + arg + ")";
this.field = "init";
}
}
fun init() {
print "not initializer";
}
init(); // expect: not initializer

View file

@ -0,0 +1,5 @@
class Foo {
init(a, b) {}
}
var foo = Foo(1); // expect runtime error: Expected 2 arguments but got 1.

View file

@ -0,0 +1,10 @@
class Foo {
init() {
fun init() {
return "bar";
}
print init(); // expect: bar
}
}
print Foo(); // expect: Foo instance

View file

@ -0,0 +1,5 @@
class Foo {
init() {
return "result"; // Error at 'return': Can't return a value from an initializer.
}
}

View file

@ -0,0 +1,16 @@
for (var i = 0; i < 10; i = i + 1) {
if (i == 5)
continue;
print i;
}
// expect: 0
// expect: 1
// expect: 2
// expect: 3
// expect: 4
// expect: 6
// expect: 7
// expect: 8
// expect: 9

View file

@ -0,0 +1,2 @@
continue;
// expect: error

View file

@ -0,0 +1,21 @@
var i = 0;
while (i < 10) {
if (i == 5) {
i = i + 1;
continue;
}
print i;
i = i + 1;
}
// expect: 0
// expect: 1
// expect: 2
// expect: 3
// expect: 4
// expect: 6
// expect: 7
// expect: 8
// expect: 9

View file

View file

@ -0,0 +1,15 @@
class Foo {}
fun bar(a, b) {
print "bar";
print a;
print b;
}
var foo = Foo();
foo.bar = bar;
foo.bar(1, 2);
// expect: bar
// expect: 1
// expect: 2

View file

@ -0,0 +1,6 @@
class Foo {}
var foo = Foo();
foo.bar = "not fn";
foo.bar(); // expect runtime error: Can only call functions and classes.

View file

@ -0,0 +1,25 @@
// Bound methods have identity equality.
class Foo {
method(a) {
print "method";
print a;
}
other(a) {
print "other";
print a;
}
}
var foo = Foo();
var method = foo.method;
// Setting a property shadows the instance method.
foo.method = foo.other;
foo.method(1);
// expect: other
// expect: 1
// The old method handle still points to the original method.
method(2);
// expect: method
// expect: 2

View file

@ -0,0 +1 @@
true.foo; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1,2 @@
class Foo {}
Foo.bar; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1,3 @@
fun foo() {}
foo.bar; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1 @@
nil.foo; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1 @@
123.foo; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1 @@
"str".foo; // expect runtime error: Only instances have properties.

View file

@ -0,0 +1,170 @@
class Foo {}
var foo = Foo();
fun setFields() {
foo.bilberry = "bilberry";
foo.lime = "lime";
foo.elderberry = "elderberry";
foo.raspberry = "raspberry";
foo.gooseberry = "gooseberry";
foo.longan = "longan";
foo.mandarine = "mandarine";
foo.kiwifruit = "kiwifruit";
foo.orange = "orange";
foo.pomegranate = "pomegranate";
foo.tomato = "tomato";
foo.banana = "banana";
foo.juniper = "juniper";
foo.damson = "damson";
foo.blackcurrant = "blackcurrant";
foo.peach = "peach";
foo.grape = "grape";
foo.mango = "mango";
foo.redcurrant = "redcurrant";
foo.watermelon = "watermelon";
foo.plumcot = "plumcot";
foo.papaya = "papaya";
foo.cloudberry = "cloudberry";
foo.rambutan = "rambutan";
foo.salak = "salak";
foo.physalis = "physalis";
foo.huckleberry = "huckleberry";
foo.coconut = "coconut";
foo.date = "date";
foo.tamarind = "tamarind";
foo.lychee = "lychee";
foo.raisin = "raisin";
foo.apple = "apple";
foo.avocado = "avocado";
foo.nectarine = "nectarine";
foo.pomelo = "pomelo";
foo.melon = "melon";
foo.currant = "currant";
foo.plum = "plum";
foo.persimmon = "persimmon";
foo.olive = "olive";
foo.cranberry = "cranberry";
foo.boysenberry = "boysenberry";
foo.blackberry = "blackberry";
foo.passionfruit = "passionfruit";
foo.mulberry = "mulberry";
foo.marionberry = "marionberry";
foo.plantain = "plantain";
foo.lemon = "lemon";
foo.yuzu = "yuzu";
foo.loquat = "loquat";
foo.kumquat = "kumquat";
foo.salmonberry = "salmonberry";
foo.tangerine = "tangerine";
foo.durian = "durian";
foo.pear = "pear";
foo.cantaloupe = "cantaloupe";
foo.quince = "quince";
foo.guava = "guava";
foo.strawberry = "strawberry";
foo.nance = "nance";
foo.apricot = "apricot";
foo.jambul = "jambul";
foo.grapefruit = "grapefruit";
foo.clementine = "clementine";
foo.jujube = "jujube";
foo.cherry = "cherry";
foo.feijoa = "feijoa";
foo.jackfruit = "jackfruit";
foo.fig = "fig";
foo.cherimoya = "cherimoya";
foo.pineapple = "pineapple";
foo.blueberry = "blueberry";
foo.jabuticaba = "jabuticaba";
foo.miracle = "miracle";
foo.dragonfruit = "dragonfruit";
foo.satsuma = "satsuma";
foo.tamarillo = "tamarillo";
foo.honeydew = "honeydew";
}
setFields();
fun printFields() {
print foo.apple; // expect: apple
print foo.apricot; // expect: apricot
print foo.avocado; // expect: avocado
print foo.banana; // expect: banana
print foo.bilberry; // expect: bilberry
print foo.blackberry; // expect: blackberry
print foo.blackcurrant; // expect: blackcurrant
print foo.blueberry; // expect: blueberry
print foo.boysenberry; // expect: boysenberry
print foo.cantaloupe; // expect: cantaloupe
print foo.cherimoya; // expect: cherimoya
print foo.cherry; // expect: cherry
print foo.clementine; // expect: clementine
print foo.cloudberry; // expect: cloudberry
print foo.coconut; // expect: coconut
print foo.cranberry; // expect: cranberry
print foo.currant; // expect: currant
print foo.damson; // expect: damson
print foo.date; // expect: date
print foo.dragonfruit; // expect: dragonfruit
print foo.durian; // expect: durian
print foo.elderberry; // expect: elderberry
print foo.feijoa; // expect: feijoa
print foo.fig; // expect: fig
print foo.gooseberry; // expect: gooseberry
print foo.grape; // expect: grape
print foo.grapefruit; // expect: grapefruit
print foo.guava; // expect: guava
print foo.honeydew; // expect: honeydew
print foo.huckleberry; // expect: huckleberry
print foo.jabuticaba; // expect: jabuticaba
print foo.jackfruit; // expect: jackfruit
print foo.jambul; // expect: jambul
print foo.jujube; // expect: jujube
print foo.juniper; // expect: juniper
print foo.kiwifruit; // expect: kiwifruit
print foo.kumquat; // expect: kumquat
print foo.lemon; // expect: lemon
print foo.lime; // expect: lime
print foo.longan; // expect: longan
print foo.loquat; // expect: loquat
print foo.lychee; // expect: lychee
print foo.mandarine; // expect: mandarine
print foo.mango; // expect: mango
print foo.marionberry; // expect: marionberry
print foo.melon; // expect: melon
print foo.miracle; // expect: miracle
print foo.mulberry; // expect: mulberry
print foo.nance; // expect: nance
print foo.nectarine; // expect: nectarine
print foo.olive; // expect: olive
print foo.orange; // expect: orange
print foo.papaya; // expect: papaya
print foo.passionfruit; // expect: passionfruit
print foo.peach; // expect: peach
print foo.pear; // expect: pear
print foo.persimmon; // expect: persimmon
print foo.physalis; // expect: physalis
print foo.pineapple; // expect: pineapple
print foo.plantain; // expect: plantain
print foo.plum; // expect: plum
print foo.plumcot; // expect: plumcot
print foo.pomegranate; // expect: pomegranate
print foo.pomelo; // expect: pomelo
print foo.quince; // expect: quince
print foo.raisin; // expect: raisin
print foo.rambutan; // expect: rambutan
print foo.raspberry; // expect: raspberry
print foo.redcurrant; // expect: redcurrant
print foo.salak; // expect: salak
print foo.salmonberry; // expect: salmonberry
print foo.satsuma; // expect: satsuma
print foo.strawberry; // expect: strawberry
print foo.tamarillo; // expect: tamarillo
print foo.tamarind; // expect: tamarind
print foo.tangerine; // expect: tangerine
print foo.tomato; // expect: tomato
print foo.watermelon; // expect: watermelon
print foo.yuzu; // expect: yuzu
}
printFields();

View file

@ -0,0 +1,9 @@
class Foo {
bar(arg) {
print arg;
}
}
var bar = Foo().bar;
print "got method"; // expect: got method
bar("arg"); // expect: arg

View file

@ -0,0 +1,19 @@
class Foo {
sayName(a) {
print this.name;
print a;
}
}
var foo1 = Foo();
foo1.name = "foo1";
var foo2 = Foo();
foo2.name = "foo2";
// Store the method reference on another object.
foo2.fn = foo1.sayName;
// Still retains original receiver.
foo2.fn(1);
// expect: foo1
// expect: 1

View file

@ -0,0 +1,9 @@
class Foo {}
var foo = Foo();
print foo.bar = "bar value"; // expect: bar value
print foo.baz = "baz value"; // expect: baz value
print foo.bar; // expect: bar value
print foo.baz; // expect: baz value

View file

@ -0,0 +1,2 @@
undefined1.bar // expect runtime error: Undefined variable 'undefined1'.
= undefined2;

View file

@ -0,0 +1 @@
true.foo = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1,2 @@
class Foo {}
Foo.bar = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1,3 @@
fun foo() {}
foo.bar = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1 @@
nil.foo = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1 @@
123.foo = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1 @@
"str".foo = "value"; // expect runtime error: Only instances have fields.

View file

@ -0,0 +1,4 @@
class Foo {}
var foo = Foo();
foo.bar; // expect runtime error: Undefined property 'bar'.

View file

@ -0,0 +1,2 @@
// [line 2] Error at 'class': Expect expression.
for (;;) class Foo {}

View file

@ -0,0 +1,22 @@
var f1;
var f2;
var f3;
for (var i = 1; i < 4; i = i + 1) {
var j = i;
fun f() {
print i;
print j;
}
if (j == 1) f1 = f;
else if (j == 2) f2 = f;
else f3 = f;
}
f1(); // expect: 4
// expect: 1
f2(); // expect: 4
// expect: 2
f3(); // expect: 4
// expect: 3

View file

@ -0,0 +1,2 @@
// [line 2] Error at 'fun': Expect expression.
for (;;) fun foo() {}

View file

@ -0,0 +1,10 @@
fun f() {
for (;;) {
var i = "i";
fun g() { print i; }
return g;
}
}
var h = f();
h(); // expect: i

View file

@ -0,0 +1,9 @@
fun f() {
for (;;) {
var i = "i";
return i;
}
}
print f();
// expect: i

View file

@ -0,0 +1,26 @@
{
var i = "before";
// New variable is in inner scope.
for (var i = 0; i < 1; i = i + 1) {
print i; // expect: 0
// Loop body is in second inner scope.
var i = -1;
print i; // expect: -1
}
}
{
// New variable shadows outer variable.
for (var i = 0; i > 0; i = i + 1) {}
// Goes out of scope after loop.
var i = "after";
print i; // expect: after
// Can reuse an existing variable.
for (i = 0; i < 1; i = i + 1) {
print i; // expect: 0
}
}

View file

@ -0,0 +1,3 @@
// [line 3] Error at '{': Expect expression.
// [line 3] Error at ')': Expect ';' after expression.
for (var a = 1; {}; a = a + 1) {}

View file

@ -0,0 +1,2 @@
// [line 2] Error at '{': Expect expression.
for (var a = 1; a < 2; {}) {}

View file

@ -0,0 +1,3 @@
// [line 3] Error at '{': Expect expression.
// [line 3] Error at ')': Expect ';' after expression.
for ({}; a < 2; a = a + 1) {}

View file

@ -0,0 +1,50 @@
// Single-expression body.
for (var c = 0; c < 3;) print c = c + 1;
// expect: 1
// expect: 2
// expect: 3
// Block body.
for (var a = 0; a < 3; a = a + 1) {
print a;
}
// expect: 0
// expect: 1
// expect: 2
// No clauses.
fun foo() {
for (;;) return "done";
}
print foo(); // expect: done
// No variable.
var i = 0;
for (; i < 2; i = i + 1) print i;
// expect: 0
// expect: 1
// No condition.
fun bar() {
for (var i = 0;; i = i + 1) {
print i;
if (i >= 2) return;
}
}
bar();
// expect: 0
// expect: 1
// expect: 2
// No increment.
for (var i = 0; i < 2;) {
print i;
i = i + 1;
}
// expect: 0
// expect: 1
// Statement bodies.
for (; false;) if (true) 1; else 2;
for (; false;) while (true) 1;
for (; false;) for (;;) 1;

View file

@ -0,0 +1,2 @@
// [line 2] Error at 'var': Expect expression.
for (;;) var foo;

View file

@ -0,0 +1,3 @@
// [line 3] Error at '123': Expect '{' before function body.
// [c line 4] Error at end: Expect '}' after block.
fun f() 123;

View file

@ -0,0 +1,2 @@
fun f() {}
print f(); // expect: nil

View file

@ -0,0 +1,6 @@
fun f(a, b) {
print a;
print b;
}
f(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4.

View file

@ -0,0 +1,13 @@
{
fun isEven(n) {
if (n == 0) return true;
return isOdd(n - 1); // expect runtime error: Undefined variable 'isOdd'.
}
fun isOdd(n) {
if (n == 0) return false;
return isEven(n - 1);
}
isEven(4);
}

View file

@ -0,0 +1,8 @@
{
fun fib(n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
}
print fib(8); // expect: 21
}

View file

@ -0,0 +1,3 @@
fun f(a, b) {}
f(1); // expect runtime error: Expected 2 arguments but got 1.

View file

@ -0,0 +1,3 @@
// [line 3] Error at 'c': Expect ')' after parameters.
// [c line 4] Error at end: Expect '}' after block.
fun foo(a, b c, d, e, f) {}

View file

@ -0,0 +1,12 @@
fun isEven(n) {
if (n == 0) return true;
return isOdd(n - 1);
}
fun isOdd(n) {
if (n == 0) return false;
return isEven(n - 1);
}
print isEven(4); // expect: true
print isOdd(3); // expect: true

Some files were not shown because too many files have changed in this diff Show more