From 5948bfa973954ff5af4ded3fc39aee86d4979ada Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Thu, 22 Aug 2024 17:21:05 +0100 Subject: [PATCH] First working implementation of closures --- example.vli | 8 +++++++- src/common.cpp | 21 +++++++++++++++++++++ src/common.hpp | 4 ++-- src/compiler.cpp | 4 +++- src/vm.cpp | 16 ++++++++++++++++ src/vm.hpp | 2 ++ 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/example.vli b/example.vli index 84dc672..ca94781 100644 --- a/example.vli +++ b/example.vli @@ -1,3 +1,9 @@ ;; Check that lambdas can be passed as arguments -((lambda (f y) (f y)) (lambda (x) (* x x)) 2) +((lambda (f y) (f y)) + (lambda (x) (* x x)) + 2) + +(((lambda (x) + (lambda () (* x x 2))) + 2)) diff --git a/src/common.cpp b/src/common.cpp index f64b55d..bc23705 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -448,6 +448,27 @@ Result Dict::cmp(const Dict& rhs) const { return 0; } +Result Array::cmp(const Array& rhs) const { + auto lsize = size(); + auto rsize = rhs.size(); + uint64_t i = 0; + uint64_t j = 0; + while (1) { + if (i == lsize && j == lsize) return 0; + + short cmp = short(i == lsize) - short(j == rsize); + if (cmp != 0) return cmp; + + Value lc = TRY(Value::create(_value->data[i].get())); + Value rc = TRY(Value::create(rhs._value->data[j].get())); + cmp = TRY(lc.cmp(rc)); + if (cmp != 0) return cmp; + i++; + j++; + } + return 0; +} + Result Object::get(const Value& key) const { return ERROR(TypeMismatch); } diff --git a/src/common.hpp b/src/common.hpp index a8710b7..b19ba0b 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -75,7 +75,7 @@ class Object { return cmp_tag(tag(), Tag::Opcode); } virtual Result cmp(const Function& rhs) const { - return cmp_tag(tag(), Tag::Opcode); + return cmp_tag(tag(), Tag::Function); } virtual Result cmp(const char* rhs) const { return ERROR(NotImplemented); @@ -150,7 +150,7 @@ class Array : public Object { virtual Result cmp(const Object& rhs) const final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(const Array& rhs) const final { return 0; } + virtual Result cmp(const Array& rhs) const final; virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 757bc5a..58c28ca 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -373,6 +373,7 @@ Result Compiler::compile_lambda(Context& context, Symbol& op, uint64_t reg = context.alloc_reg(); TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)reg}, {1, (int64_t)c})); + context.maxreg = reg + 1; ex_res.reg = reg; return ex_res; @@ -393,7 +394,7 @@ Result Compiler::compile_lambda(Context& context, Symbol& op, TRY(ex_res.add_opcode(Oc::MakeClosure, {0, (int64_t)reg}, {0, (int64_t)reg + (int64_t)ctx.closures.size() + 1})); - context.maxreg = reg; + context.maxreg = reg + 1; ex_res.reg = reg; return ex_res; @@ -459,6 +460,7 @@ Result Compiler::compile_function_call(Context& context, {0, (int64_t)context.maxreg})); ex.reg = fun_ex.reg; + context.maxreg = maxreg; return ex; } diff --git a/src/vm.cpp b/src/vm.cpp index 6a9b38f..09166a4 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -96,6 +96,7 @@ Result VM::vm_call(Opcode& oc) { _code = TRY(fun.code()); _constants = TRY(fun.constants()); + _closure = TRY(fun.closure()); _fun = std::move(fun); _pc = 0; _base = reg_start; @@ -123,6 +124,7 @@ Result VM::vm_ret(Opcode& oc) { _code = TRY(fun.code()); _constants = TRY(fun.constants()); + _closure = TRY(fun.closure()); _fun = std::move(fun); _pc = pc + 1; _base = oldbase; @@ -155,11 +157,21 @@ Result VM::vm_make_closure(Opcode& oc) { return Result(); } +Result VM::vm_closure_load(Opcode& oc) { + uint64_t acc = (uint64_t)oc.arg1().arg; + Value val = TRY(_closure.get((uint64_t)oc.arg2().arg)); + setreg(acc, val); + _pc++; + return Result(); +} + Result VM::step() { auto opcode = TRY(_code.get(_pc)); if (!opcode.is()) return ERROR(TypeMismatch); Opcode& oc = *opcode.to(); + // TRY(debug_print(TRY(oc.copy_value()))); + switch (oc.opcode()) { case Oc::Mov: TRY(vm_mov(oc)); @@ -191,6 +203,9 @@ Result VM::step() { case Oc::MakeClosure: TRY(vm_make_closure(oc)); break; + case Oc::ClosureLoad: + TRY(vm_closure_load(oc)); + break; default: return ERROR(NotImplemented); } @@ -206,6 +221,7 @@ Result VM::run(const Function& fun) { _base = 0; _code = TRY(fun.code()); _constants = TRY(fun.constants()); + _closure = TRY(fun.closure()); while (true) { auto rc = step(); diff --git a/src/vm.hpp b/src/vm.hpp index 6d78b8e..1cd82f4 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -32,6 +32,7 @@ class VM { Result vm_jump(Opcode& oc); Result vm_make_closure(Opcode& oc); + Result vm_closure_load(Opcode& oc); Result get(bool is_const, uint64_t idx); Result getconst(uint64_t idx); @@ -44,6 +45,7 @@ class VM { Function _fun; Array _code; Array _constants; + Array _closure; uint64_t _pc; uint64_t _base; Value _res;