diff --git a/Sources/LoxCore/Interpreter.swift b/Sources/LoxCore/Interpreter.swift index 064ce85..a8a1310 100644 --- a/Sources/LoxCore/Interpreter.swift +++ b/Sources/LoxCore/Interpreter.swift @@ -253,8 +253,8 @@ final class Interpreter: ExprVisitor, StmtVisitor { func visitCallExpr(_ expr: Expr.Call) -> ExprVisitorReturn { let calleeResult = evaluate(expr: expr.callee) - guard let callee = calleeResult?.value else { - return calleeResult + guard let callee = calleeResult?.value, let function = callee as? Callable else { + return .failure(InterpreterError.runtime(expr.paren, "Can only call functions and classes.")) } var arguments: Array = [] @@ -266,10 +266,6 @@ final class Interpreter: ExprVisitor, StmtVisitor { arguments.append(arg) } - guard let function = callee as? Callable else { - return .failure(InterpreterError.runtime(expr.paren, "Can only call functions and classes.")) - } - guard arguments.count == function.arity else { return .failure(InterpreterError.runtime(expr.paren, "Expected \(function.arity) arguments but got \(arguments.count).")) } diff --git a/Sources/LoxCore/Parser.swift b/Sources/LoxCore/Parser.swift index 22dd963..6bcb83b 100644 --- a/Sources/LoxCore/Parser.swift +++ b/Sources/LoxCore/Parser.swift @@ -44,7 +44,8 @@ final class Parser { private func declaration() -> Stmt? { do { - if match(.fun) { + if check(.fun) && checkNext(.identifier) { + try consume(.fun, message: "") return try function(kind: "function") } if match(.Var) { @@ -374,7 +375,8 @@ final class Parser { return Expr.Grouping(expression: expr) } - if match(.fun) { + if check(.fun) && checkNext(.leftParen) { + try consume(.fun, message: "") return try functionBody(kind: "function") } @@ -422,6 +424,12 @@ extension Parser { return peek().type == tokenType } + func checkNext(_ tokenType: TokenType) -> Bool { + if isAtEnd() { return false } + if tokens[current + 1].type == .eof { return false } + return tokens[current + 1].type == tokenType + } + func advance() -> Token { if !isAtEnd() { current += 1 diff --git a/temptest.lox b/temptest.lox index e834633..0092fe3 100644 --- a/temptest.lox +++ b/temptest.lox @@ -1,13 +1,15 @@ -fun repeat(times, fn) { - for (var i = 0; i < times; i = i + 1) { - fn(); - } -} - -var times = 10; -repeat(times, fun () { - print("Repeating " + times + " times."); -}); +fun () {}; + +// fun repeat(times, fn) { +// for (var i = 0; i < times; i = i + 1) { +// fn(); +// } +// } + +// var times = 10; +// repeat(times, fun () { +// print("Repeating " + times + " times."); +// }); // fun sayHi(first, last) { // print "Hi, " + first + " " + last + "!"; diff --git a/test/constructor/default_arguments.lox b/test/constructor/default_arguments.lox index 9b24d12..21d073a 100755 --- a/test/constructor/default_arguments.lox +++ b/test/constructor/default_arguments.lox @@ -1,4 +1,3 @@ class Foo {} -var foo = Foo(1, 2, 3); -print foo; // expect: Foo instance +var foo = Foo(1, 2, 3); // expect runtime error: Expected 0 arguments but got 3. diff --git a/test/constructor/extra_arguments.lox b/test/constructor/extra_arguments.lox index 4d5f2c9..bee6ebc 100755 --- a/test/constructor/extra_arguments.lox +++ b/test/constructor/extra_arguments.lox @@ -1,11 +1,8 @@ class Foo { init(a, b) { - print "init"; // expect: init this.a = a; this.b = b; } } -var foo = Foo(1, 2, 3, 4); -print foo.a; // expect: 1 -print foo.b; // expect: 2 +var foo = Foo(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. \ No newline at end of file diff --git a/test/constructor/missing_arguments.lox b/test/constructor/missing_arguments.lox index 29ddd15..cf26928 100755 --- a/test/constructor/missing_arguments.lox +++ b/test/constructor/missing_arguments.lox @@ -2,4 +2,4 @@ class Foo { init(a, b) {} } -var foo = Foo(1); // expect runtime error: Not enough arguments. +var foo = Foo(1); // expect runtime error: Expected 2 arguments but got 1. diff --git a/test/function/body_must_be_block.lox b/test/function/body_must_be_block.lox index 745a8d0..16f0337 100755 --- a/test/function/body_must_be_block.lox +++ b/test/function/body_must_be_block.lox @@ -1,3 +1,5 @@ -// [line 3] Error at '123': Expect '{' before block. -// [c line 4] Error at end: Expect '}' after block. +// original was -> [line 3] Error at '123': Expect '{' before block. +// but because we support lambdas the error is slightly different: +// [line 5] Error at '123': Expect '{' before function body. +// ?? [c line 4] Error at end: Expect '}' after block. fun f() 123; diff --git a/test/function/extra_arguments.lox b/test/function/extra_arguments.lox index 83291d8..350ac63 100755 --- a/test/function/extra_arguments.lox +++ b/test/function/extra_arguments.lox @@ -1,6 +1,6 @@ fun f(a, b) { - print a; // expect: 1 - print b; // expect: 2 + print a; + print b; } -f(1, 2, 3, 4); +f(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. diff --git a/test/function/missing_arguments.lox b/test/function/missing_arguments.lox index 802970f..2acee00 100755 --- a/test/function/missing_arguments.lox +++ b/test/function/missing_arguments.lox @@ -1,3 +1,3 @@ fun f(a, b) {} -f(1); // expect runtime error: Not enough arguments. +f(1); // expect runtime error: Expected 2 arguments but got 1. diff --git a/test/function/print.lox b/test/function/print.lox new file mode 100755 index 0000000..ddf2804 --- /dev/null +++ b/test/function/print.lox @@ -0,0 +1,2 @@ +fun foo() {} +print foo; // expect: diff --git a/test/method/extra_arguments.lox b/test/method/extra_arguments.lox index 1cc70f4..76f3fab 100755 --- a/test/method/extra_arguments.lox +++ b/test/method/extra_arguments.lox @@ -1,8 +1,8 @@ class Foo { method(a, b) { - print a; // expect: 1 - print b; // expect: 2 + print a; + print b; } } -Foo().method(1, 2, 3, 4); +Foo().method(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. diff --git a/test/method/missing_arguments.lox b/test/method/missing_arguments.lox index 97405f0..734f455 100755 --- a/test/method/missing_arguments.lox +++ b/test/method/missing_arguments.lox @@ -2,4 +2,4 @@ class Foo { method(a, b) {} } -Foo().method(1); // expect runtime error: Not enough arguments. +Foo().method(1); // expect runtime error: Expected 2 arguments but got 1. diff --git a/test/operator/add_bool_string.lox b/test/operator/add_bool_string.lox index 04739d5..0c8c87a 100755 --- a/test/operator/add_bool_string.lox +++ b/test/operator/add_bool_string.lox @@ -1 +1,2 @@ -true + "s"; // expect runtime error: Operands must be two numbers or two strings. +// No error here, Chapter 7 challenge 2 implemented. +// true + "s"; expect runtime error: Operands must be two numbers or two strings. \ No newline at end of file diff --git a/test/super/extra_arguments.lox b/test/super/extra_arguments.lox index e8158a3..b6b0735 100755 --- a/test/super/extra_arguments.lox +++ b/test/super/extra_arguments.lox @@ -6,11 +6,9 @@ class Base { class Derived < Base { foo() { - print "Derived.foo()"; - super.foo("a", "b", "c", "d"); + print "Derived.foo()"; // expect: Derived.foo() + super.foo("a", "b", "c", "d"); // expect runtime error: Expected 2 arguments but got 4. } } Derived().foo(); -// expect: Derived.foo() -// expect: Base.foo(a, b) diff --git a/test/super/missing_arguments.lox b/test/super/missing_arguments.lox index ba3ac18..e055a6e 100755 --- a/test/super/missing_arguments.lox +++ b/test/super/missing_arguments.lox @@ -6,7 +6,7 @@ class Base { class Derived < Base { foo() { - super.foo(1); // expect runtime error: Not enough arguments. + super.foo(1); // expect runtime error: Expected 2 arguments but got 1. } } diff --git a/test/unexpected_character.lox b/test/unexpected_character.lox index 5e51396..9ca1244 100755 --- a/test/unexpected_character.lox +++ b/test/unexpected_character.lox @@ -1,3 +1,3 @@ -// [line 3] Error: Unexpected character. +// [line 3] Error: Unexpected character. '|' // [java line 3] Error at 'b': Expect ')' after arguments. foo(a | b); diff --git a/tools/test_chap10challenge2_and_chap7challenge2patch.diff b/tools/test_chap10challenge2_and_chap7challenge2patch.diff new file mode 100644 index 0000000..299d525 --- /dev/null +++ b/tools/test_chap10challenge2_and_chap7challenge2patch.diff @@ -0,0 +1,30 @@ +diff --git a/test/function/body_must_be_block.lox b/test/function/body_must_be_block.lox +index 745a8d0..16f0337 100755 +--- a/test/function/body_must_be_block.lox ++++ b/test/function/body_must_be_block.lox +@@ -1,3 +1,5 @@ +-// [line 3] Error at '123': Expect '{' before block. +-// [c line 4] Error at end: Expect '}' after block. ++// original was -> [line 3] Error at '123': Expect '{' before block. ++// but because we support lambdas the error is slightly different: ++// [line 5] Error at '123': Expect '{' before function body. ++// ?? [c line 4] Error at end: Expect '}' after block. + fun f() 123; +diff --git a/test/operator/add_bool_string.lox b/test/operator/add_bool_string.lox +index 04739d5..0c8c87a 100755 +--- a/test/operator/add_bool_string.lox ++++ b/test/operator/add_bool_string.lox +@@ -1 +1,2 @@ +-true + "s"; // expect runtime error: Operands must be two numbers or two strings. ++// No error here, Chapter 7 challenge 2 implemented. ++// true + "s"; expect runtime error: Operands must be two numbers or two strings. +\ No newline at end of file +diff --git a/test/unexpected_character.lox b/test/unexpected_character.lox +index 5e51396..9ca1244 100755 +--- a/test/unexpected_character.lox ++++ b/test/unexpected_character.lox +@@ -1,3 +1,3 @@ +-// [line 3] Error: Unexpected character. ++// [line 3] Error: Unexpected character. '|' + // [java line 3] Error at 'b': Expect ')' after arguments. + foo(a | b);