First working implementation of closures
This commit is contained in:
parent
6fcd231694
commit
5948bfa973
6 changed files with 51 additions and 4 deletions
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)); }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
16
src/vm.cpp
16
src/vm.cpp
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue