diff --git a/Call.cpp b/Call.cpp index 17f0240..3a05daa 100644 --- a/Call.cpp +++ b/Call.cpp @@ -5,19 +5,17 @@ #include "Class.hpp" #include -Value LoxFunction::call(Interpreter& interpreter, const std::vector>& arguments) { +Value LoxFunction::call(const Interpreter& parent, const std::vector>& arguments) { + Interpreter interpreter{ parent }; + interpreter.environment = Environment::makeShared(closure); for (size_t i = 0; i != arguments.size(); ++i) { - closure->define(params.at(i), arguments.at(i)->accept(interpreter)); + interpreter.environment->define(params.at(i), arguments.at(i)->accept(parent)); } - auto environment = Environment::makeShared(/* interpreter.environment, */ closure); - std::swap(environment, interpreter.environment); try { body->accept(interpreter); - std::swap(environment, interpreter.environment); return isInitializer ? closure->getAt(0, "this") : std::monostate{}; } catch (const Return& r) { - std::swap(environment, interpreter.environment); return isInitializer ? closure->getAt(0, "this") : r.get(); } } diff --git a/Call.hpp b/Call.hpp index 6d75db0..b8e5fc4 100644 --- a/Call.hpp +++ b/Call.hpp @@ -14,7 +14,7 @@ class LoxInstance; class LoxCallable { public: - virtual Value call(Interpreter&, const std::vector>&) = 0; + virtual Value call(const Interpreter&, const std::vector>&) = 0; virtual const size_t arity() const = 0; virtual const std::string toString() const = 0; }; @@ -31,14 +31,14 @@ class LoxFunction : public LoxCallable { LoxFunction(const StmtFunction& declaration, std::shared_ptr closure, bool isInitializer) : name{ declaration.getName() }, params{ declaration.getParams() }, body { declaration.getBody() }, closure{ closure }, isInitializer{ isInitializer } {} - virtual Value call(Interpreter&, const std::vector>&) override; + virtual Value call(const Interpreter&, const std::vector>&) override; virtual const size_t arity() const override { return params.size(); } virtual const std::string toString() const override { return "'; } std::shared_ptr bind(std::shared_ptr); }; class Clock : public LoxCallable { - virtual Value call(Interpreter&, const std::vector>&) override { + virtual Value call(const Interpreter&, const std::vector>&) override { return static_cast(clock()); } virtual const size_t arity() const override { return 0; } diff --git a/Class.hpp b/Class.hpp index c729add..d5ead4a 100644 --- a/Class.hpp +++ b/Class.hpp @@ -24,7 +24,7 @@ class LoxClass : public LoxCallable, public std::enable_shared_from_this superclass, std::unordered_map>&& methods) : superclass{ superclass }, name{ name }, methods{ methods } {} - virtual Value call(Interpreter&, const std::vector>&) override; + virtual Value call(const Interpreter&, const std::vector>&) override; virtual const size_t arity() const override; virtual const std::string toString() const override { return "'; } Value findMethod(const std::string&) const; @@ -68,7 +68,7 @@ inline Value LoxClass::findMethod(const std::string& name) const { } } -inline Value LoxClass::call(Interpreter& interpreter, const std::vector>& arguments) { +inline Value LoxClass::call(const Interpreter& interpreter, const std::vector>& arguments) { auto instance = std::make_shared(shared_from_this()); auto initializer = findMethod("init"); if (static_cast(initializer.index()) == ValueType::Callable) { diff --git a/README.md b/README.md index f0fc283..3ffdbf8 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ nmake /f Makefile.nmake The GNU Makefile can be run wih ``` -make [flexcpp] [bisoncpp] [all] +make [all] [flexcpp] [bisoncpp] [all] ``` For the `flexcpp` and `bisoncpp` targets to work, the `flexc++` and `bisonc++` programs must be installed (these are Linux only and a port to Windows is unlikely). I recommend building from scratch using the source from GitLab: @@ -63,3 +63,5 @@ Don't be fooled by the 1.00+ version number—this is alpha-development qual * *2023/08/27*: **1.00** First upload to GitHub with Windows executable. Many bugs, features and defects: please raise issues and submit pull requests. * *2023/08/30*: **1.01** Second upload to GitHub with Windows executable. Believed to be complete and correct coverage of all of the material in Part II. + +* *2024/06/01*: **1.02** Third upload to GitHub with Windows executable. Fix to `LoxFunction::call()` to handle recursive functions correctly. diff --git a/lexer/Loxerbase.h b/lexer/Loxerbase.h index 7afb9f2..e68a2b5 100644 --- a/lexer/Loxerbase.h +++ b/lexer/Loxerbase.h @@ -1,4 +1,4 @@ -// Generated by Flexc++ V2.14.00 on Wed, 30 Aug 2023 16:28:00 +0100 +// Generated by Flexc++ V2.14.00 on Sat, 06 Jan 2024 15:25:29 +0000 #ifndef LoxerBASE_H_INCLUDED #define LoxerBASE_H_INCLUDED diff --git a/lexer/loxer.cpp b/lexer/loxer.cpp index dbfbfb3..52cfd52 100644 --- a/lexer/loxer.cpp +++ b/lexer/loxer.cpp @@ -1,4 +1,4 @@ -// Generated by Flexc++ V2.14.00 on Wed, 30 Aug 2023 16:28:00 +0100 +// Generated by Flexc++ V2.14.00 on Sat, 06 Jan 2024 15:25:29 +0000 #include #include diff --git a/main.cpp b/main.cpp index afc01ba..05f4a94 100644 --- a/main.cpp +++ b/main.cpp @@ -9,7 +9,7 @@ #include #include -#define VER_STR "1.01 (2023-Aug-30)" +#define VER_STR "1.02 (2024-Jan-06)" #ifdef _MSC_VER #define OPTION_SWITCH '/' diff --git a/parser/Loxgrambase.h b/parser/Loxgrambase.h index 48c3013..1d2fe66 100644 --- a/parser/Loxgrambase.h +++ b/parser/Loxgrambase.h @@ -1,4 +1,4 @@ -// Generated by Bisonc++ V6.05.00 on Wed, 30 Aug 2023 16:28:04 +0100 +// Generated by Bisonc++ V6.05.00 on Sat, 06 Jan 2024 15:25:30 +0000 // hdr/includes #ifndef LoxgramBase_h_included diff --git a/parser/loxgram.cpp b/parser/loxgram.cpp index cf0a5a3..3f8d746 100644 --- a/parser/loxgram.cpp +++ b/parser/loxgram.cpp @@ -1,4 +1,4 @@ -// Generated by Bisonc++ V6.05.00 on Wed, 30 Aug 2023 16:28:04 +0100 +// Generated by Bisonc++ V6.05.00 on Sat, 06 Jan 2024 15:25:30 +0000 // base/comment diff --git a/test/10-super2.lox b/test/10-super2.lox new file mode 100644 index 0000000..acb7dc4 --- /dev/null +++ b/test/10-super2.lox @@ -0,0 +1,19 @@ +class A { + method() { + print "A method"; + } +} + +class B < A { + method() { + print "B method"; + } + + test() { + super.method(); + } +} + +class C < B {} + +C().test(); diff --git a/test/11-fib2.lox b/test/11-fib2.lox new file mode 100644 index 0000000..c0b598d --- /dev/null +++ b/test/11-fib2.lox @@ -0,0 +1,7 @@ +fun fib(n) { + if (n < 2) return n; + else return fib(n-1) + fib(n-2); +} +for (var i = 0; i < 20; i = i + 1) { + print fib(i); +} diff --git a/visitor/Interpreter.hpp b/visitor/Interpreter.hpp index ba6202a..f9f7779 100644 --- a/visitor/Interpreter.hpp +++ b/visitor/Interpreter.hpp @@ -17,11 +17,12 @@ class Interpreter : public ExprVisitor, public StmtVisitor { std::ostream& out; mutable Value recent; mutable std::unordered_map locals; - friend Value LoxFunction::call(Interpreter&, const std::vector>&); + friend Value LoxFunction::call(const Interpreter&, const std::vector>&); public: Interpreter(std::shared_ptr environment, std::ostream& out = std::cout) : globals{ environment }, environment{ environment }, out{ out } {} - + Interpreter(const Interpreter&) = default; + const Value& lastValue() const { return recent; } virtual Value operator()(const ExprAssign& e) const override {