First working implementation of closures

This commit is contained in:
Konstantin Nazarov 2024-08-22 17:21:05 +01:00
parent 6fcd231694
commit 5948bfa973
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
6 changed files with 51 additions and 4 deletions

View file

@ -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))

View file

@ -448,6 +448,27 @@ Result<short> Dict::cmp(const Dict& rhs) const {
return 0;
}
Result<short> 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<Value> Object::get(const Value& key) const {
return ERROR(TypeMismatch);
}

View file

@ -75,7 +75,7 @@ class Object {
return cmp_tag(tag(), Tag::Opcode);
}
virtual Result<short> cmp(const Function& rhs) const {
return cmp_tag(tag(), Tag::Opcode);
return cmp_tag(tag(), Tag::Function);
}
virtual Result<short> cmp(const char* rhs) const {
return ERROR(NotImplemented);
@ -150,7 +150,7 @@ class Array : public Object {
virtual Result<short> cmp(const Object& rhs) const final {
return -TRY(rhs.cmp(*this));
}
virtual Result<short> cmp(const Array& rhs) const final { return 0; }
virtual Result<short> cmp(const Array& rhs) const final;
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }

View file

@ -373,6 +373,7 @@ Result<Expression> 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<Expression> 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<Expression> Compiler::compile_function_call(Context& context,
{0, (int64_t)context.maxreg}));
ex.reg = fun_ex.reg;
context.maxreg = maxreg;
return ex;
}

View file

@ -96,6 +96,7 @@ Result<void> 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<void> 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<void> VM::vm_make_closure(Opcode& oc) {
return Result<void>();
}
Result<void> 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<void>();
}
Result<void> VM::step() {
auto opcode = TRY(_code.get(_pc));
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
Opcode& oc = *opcode.to<Opcode>();
// TRY(debug_print(TRY(oc.copy_value())));
switch (oc.opcode()) {
case Oc::Mov:
TRY(vm_mov(oc));
@ -191,6 +203,9 @@ Result<void> 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<Value> VM::run(const Function& fun) {
_base = 0;
_code = TRY(fun.code());
_constants = TRY(fun.constants());
_closure = TRY(fun.closure());
while (true) {
auto rc = step();

View file

@ -32,6 +32,7 @@ class VM {
Result<void> vm_jump(Opcode& oc);
Result<void> vm_make_closure(Opcode& oc);
Result<void> vm_closure_load(Opcode& oc);
Result<Value> get(bool is_const, uint64_t idx);
Result<Value> 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;