Implement access to previously defined functions in REPL

This commit is contained in:
Konstantin Nazarov 2024-09-01 14:31:25 +01:00
parent 5279b44441
commit 7d160da5d0
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
10 changed files with 50 additions and 40 deletions

View file

@ -224,7 +224,6 @@ Result<PodObject*> Arena::gc_module(PodModule* obj) {
auto nobj = TRY(alloc<PodModule>()); auto nobj = TRY(alloc<PodModule>());
nobj->header.tag = Tag::Module; nobj->header.tag = Tag::Module;
nobj->name = TRY(gc_pod(obj->name.get())); nobj->name = TRY(gc_pod(obj->name.get()));
nobj->globals = TRY(gc_pod(obj->globals.get()));
nobj->fun = TRY(gc_pod(obj->fun.get())); nobj->fun = TRY(gc_pod(obj->fun.get()));
return nobj; return nobj;

View file

@ -195,11 +195,6 @@ Result<short> Module::cmp(const Module& rhs) const {
auto lhs_fun = TRY(fun()); auto lhs_fun = TRY(fun());
auto rhs_fun = TRY(rhs.fun()); auto rhs_fun = TRY(rhs.fun());
res = TRY(lhs_fun.cmp(rhs_fun)); res = TRY(lhs_fun.cmp(rhs_fun));
if (res != 0) return res;
auto lhs_globals = TRY(globals());
auto rhs_globals = TRY(rhs.globals());
res = TRY(lhs_globals.cmp(rhs_globals));
return res; return res;
} }
@ -347,13 +342,11 @@ StdlibFunctionId StdlibFunction::fun_id() const {
return StdlibFunctionId(_value->fun_id); return StdlibFunctionId(_value->fun_id);
} }
Result<Module> Module::create(const Value& name, const Function& fun, Result<Module> Module::create(const Value& name, const Function& fun) {
const Dict& globals) {
auto pod = TRY(arena_alloc<PodModule>()); auto pod = TRY(arena_alloc<PodModule>());
pod->header.tag = Tag::Module; pod->header.tag = Tag::Module;
pod->name = name.pod(); pod->name = name.pod();
pod->fun = fun.pod(); pod->fun = fun.pod();
pod->globals = globals.pod();
return Module(TRY(MkGcRoot(pod))); return Module(TRY(MkGcRoot(pod)));
} }
@ -364,10 +357,6 @@ Result<Function> Module::fun() const {
return Function::create((PodFunction*)_value->fun.get()); return Function::create((PodFunction*)_value->fun.get());
} }
Result<Dict> Module::globals() const {
return Dict::create((PodDict*)_value->globals.get());
}
Result<Value> reverse(Value& val) { Result<Value> reverse(Value& val) {
if (val.is<Nil>()) return Value(TRY(Nil::create())); if (val.is<Nil>()) return Value(TRY(Nil::create()));
if (!val.is<Pair>()) return ERROR(TypeMismatch); if (!val.is<Pair>()) return ERROR(TypeMismatch);

View file

@ -994,12 +994,10 @@ class Module : public Object {
return Module(TRY(MkGcRoot(obj))); return Module(TRY(MkGcRoot(obj)));
} }
static Result<Module> create(const Value& name, const Function& fun, static Result<Module> create(const Value& name, const Function& fun);
const Dict& globals);
Result<Value> name() const; Result<Value> name() const;
Result<Function> fun() const; Result<Function> fun() const;
Result<Dict> globals() const;
virtual Result<Value> copy_value() const final; virtual Result<Value> copy_value() const final;
Result<Module> copy() const; Result<Module> copy() const;

View file

@ -8,14 +8,13 @@ struct Context {
Context(Value&& fname, Array&& constants, Dict&& constants_dict, Context(Value&& fname, Array&& constants, Dict&& constants_dict,
Dict&& variables_dict, Array&& closures, Dict&& closures_dict, Dict&& variables_dict, Array&& closures, Dict&& closures_dict,
Dict&& globals_dict, Context* parent, bool toplevel) Context* parent, bool toplevel)
: fname(std::move(fname)), : fname(std::move(fname)),
constants(std::move(constants)), constants(std::move(constants)),
constants_dict(std::move(constants_dict)), constants_dict(std::move(constants_dict)),
variables_dict(std::move(variables_dict)), variables_dict(std::move(variables_dict)),
closures(std::move(closures)), closures(std::move(closures)),
closures_dict(std::move(closures_dict)), closures_dict(std::move(closures_dict)),
globals_dict(std::move(globals_dict)),
maxreg(0), maxreg(0),
parent(parent), parent(parent),
toplevel(toplevel) {} toplevel(toplevel) {}
@ -27,12 +26,10 @@ struct Context {
auto variables_dict = TRY(Dict::create()); auto variables_dict = TRY(Dict::create());
auto closures = TRY(Array::create()); auto closures = TRY(Array::create());
auto closures_dict = TRY(Dict::create()); auto closures_dict = TRY(Dict::create());
auto globals_dict = TRY(Dict::create());
return Context(std::move(fname), std::move(constants), return Context(std::move(fname), std::move(constants),
std::move(constants_dict), std::move(variables_dict), std::move(constants_dict), std::move(variables_dict),
std::move(closures), std::move(closures_dict), std::move(closures), std::move(closures_dict), 0, true);
std::move(globals_dict), 0, true);
} }
static Result<Context> create(Context& parent) { static Result<Context> create(Context& parent) {
@ -42,12 +39,11 @@ struct Context {
auto variables_dict = TRY(Dict::create()); auto variables_dict = TRY(Dict::create());
auto closures = TRY(Array::create()); auto closures = TRY(Array::create());
auto closures_dict = TRY(Dict::create()); auto closures_dict = TRY(Dict::create());
auto globals_dict = TRY(Dict::create());
return Context(std::move(fname), std::move(constants), return Context(std::move(fname), std::move(constants),
std::move(constants_dict), std::move(variables_dict), std::move(constants_dict), std::move(variables_dict),
std::move(closures), std::move(closures_dict), std::move(closures), std::move(closures_dict), &parent,
std::move(globals_dict), &parent, false); false);
} }
uint64_t alloc_reg() { uint64_t alloc_reg() {
@ -143,18 +139,12 @@ struct Context {
return i; return i;
} }
Result<void> add_global(const Value& name, const Value& value) {
globals_dict = TRY(globals_dict.insert(name, value));
return Result<void>();
}
Value fname; Value fname;
Array constants; Array constants;
Dict constants_dict; Dict constants_dict;
Dict variables_dict; Dict variables_dict;
Array closures; Array closures;
Dict closures_dict; Dict closures_dict;
Dict globals_dict;
uint64_t maxreg; uint64_t maxreg;
Context* parent; Context* parent;
bool toplevel; bool toplevel;
@ -196,7 +186,7 @@ Result<Value> Compiler::compile(Value& expr) {
auto fun = TRY(Function::create(name, 0, context.constants, ex.code, auto fun = TRY(Function::create(name, 0, context.constants, ex.code,
TRY(Array::create()))); TRY(Array::create())));
auto mod = TRY(Module::create(name, fun, context.globals_dict)); auto mod = TRY(Module::create(name, fun));
return Value(std::move(mod)); return Value(std::move(mod));
} }
@ -216,7 +206,7 @@ Result<Value> Compiler::compile(Value& expr) {
auto fun = TRY(Function::create(name, 0, context.constants, ex.code, auto fun = TRY(Function::create(name, 0, context.constants, ex.code,
TRY(Array::create()))); TRY(Array::create())));
auto mod = TRY(Module::create(name, fun, context.globals_dict)); auto mod = TRY(Module::create(name, fun));
return Value(std::move(mod)); return Value(std::move(mod));
} }
@ -634,12 +624,14 @@ Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
Expression ex_res = TRY(Expression::create()); Expression ex_res = TRY(Expression::create());
if (ctx.closures.size() == 0) { if (ctx.closures.size() == 0) {
if (context.toplevel && !name.is<Nil>()) {
context.add_global(name, TRY(fun.copy()));
}
int64_t c = TRY(context.add_const(TRY(fun.copy()))); int64_t c = TRY(context.add_const(TRY(fun.copy())));
if (context.toplevel && !name.is<Nil>()) {
int64_t gname = TRY(context.add_const(name));
TRY(ex_res.add_opcode(Oc::GlobalStore, {1, (int64_t)gname},
{1, (int64_t)c}));
}
uint64_t reg = context.alloc_reg(); uint64_t reg = context.alloc_reg();
TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)reg}, {1, (int64_t)c})); TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)reg}, {1, (int64_t)c}));

View file

@ -80,6 +80,8 @@ op_t get_op(Oc op) {
return op_t{"setglobal", OpcodeType::Reg2}; return op_t{"setglobal", OpcodeType::Reg2};
case Oc::GlobalLoad: case Oc::GlobalLoad:
return op_t{"global-load", OpcodeType::Reg2}; return op_t{"global-load", OpcodeType::Reg2};
case Oc::GlobalStore:
return op_t{"global-store", OpcodeType::Reg2};
case Oc::MakeClosure: case Oc::MakeClosure:
return op_t{"make-closure", OpcodeType::Reg2}; return op_t{"make-closure", OpcodeType::Reg2};
case Oc::ClosureLoad: case Oc::ClosureLoad:

View file

@ -61,6 +61,7 @@ enum class Oc : uint8_t {
SetJump, SetJump,
// Globals // Globals
GlobalLoad, GlobalLoad,
GlobalStore,
// Closures // Closures
MakeClosure, MakeClosure,
ClosureLoad, ClosureLoad,

View file

@ -183,7 +183,6 @@ class PodModule final : public PodObject {
OffPtr<PodObject> name; OffPtr<PodObject> name;
OffPtr<PodObject> fun; OffPtr<PodObject> fun;
OffPtr<PodObject> globals;
}; };
class PodStack final : public PodObject { class PodStack final : public PodObject {

View file

@ -28,9 +28,17 @@ Result<Value> run_string(const String& src) {
} }
Result<void> run_repl() { Result<void> run_repl() {
Dict globals = TRY(Dict::create());
while (true) { while (true) {
auto src = TRY(read_line("vli> ")); auto src = TRY(read_line("vli> "));
auto res = TRY(run_string(src)); auto parsed = TRY(read_multiple(src));
auto compiled = TRY(compile(parsed));
Module& mod = *compiled.to<Module>();
auto vm = TRY(VM::create());
auto res = TRY(vm.run(mod, globals));
globals = TRY(vm.globals());
if (!res.is<Nil>()) { if (!res.is<Nil>()) {
debug_print(res); debug_print(res);
} }

View file

@ -249,6 +249,15 @@ Result<void> VM::vm_global_load(Opcode& oc) {
return Result<void>(); return Result<void>();
} }
Result<void> VM::vm_global_store(Opcode& oc) {
Value sym = TRY(get(oc.arg1().is_const, (uint64_t)oc.arg1().arg));
Value val = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
_globals = TRY(_globals.insert(sym, val));
_pc++;
return Result<void>();
}
Result<void> VM::step() { Result<void> VM::step() {
auto opcode = TRY(_code.get(_pc)); auto opcode = TRY(_code.get(_pc));
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch); if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
@ -302,6 +311,9 @@ Result<void> VM::step() {
case Oc::GlobalLoad: case Oc::GlobalLoad:
TRY(vm_global_load(oc)); TRY(vm_global_load(oc));
break; break;
case Oc::GlobalStore:
TRY(vm_global_store(oc));
break;
default: default:
return ERROR(NotImplemented); return ERROR(NotImplemented);
} }
@ -311,14 +323,14 @@ Result<void> VM::step() {
// Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy()))); // Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy())));
// } // }
Result<Value> VM::run(const Module& mod) { Result<Value> VM::run(const Module& mod, const Dict& globals) {
_fun = TRY(mod.fun()); _fun = TRY(mod.fun());
_pc = 0; _pc = 0;
_base = 0; _base = 0;
_code = TRY(_fun.code()); _code = TRY(_fun.code());
_constants = TRY(_fun.constants()); _constants = TRY(_fun.constants());
_closure = TRY(_fun.closure()); _closure = TRY(_fun.closure());
_globals = TRY(mod.globals()); _globals = TRY(globals.copy());
while (true) { while (true) {
auto rc = step(); auto rc = step();
@ -331,3 +343,7 @@ Result<Value> VM::run(const Module& mod) {
} }
return ERROR(NotImplemented); return ERROR(NotImplemented);
} }
Result<Value> VM::run(const Module& mod) {
return run(mod, TRY(Dict::create()));
}

View file

@ -18,6 +18,7 @@ class VM {
} }
Result<Value> run(const Module& mod); Result<Value> run(const Module& mod);
Result<Value> run(const Module& mod, const Dict& globals);
Result<void> step(); Result<void> step();
Result<void> vm_mov(Opcode& oc); Result<void> vm_mov(Opcode& oc);
@ -40,12 +41,17 @@ class VM {
Result<void> vm_closure_load(Opcode& oc); Result<void> vm_closure_load(Opcode& oc);
Result<void> vm_global_load(Opcode& oc); Result<void> vm_global_load(Opcode& oc);
Result<void> vm_global_store(Opcode& oc);
Result<Value> get(bool is_const, uint64_t idx); Result<Value> get(bool is_const, uint64_t idx);
Result<Value> getconst(uint64_t idx); Result<Value> getconst(uint64_t idx);
Result<Value> getreg(uint64_t idx); Result<Value> getreg(uint64_t idx);
Result<void> setreg(uint64_t idx, const Value& value); Result<void> setreg(uint64_t idx, const Value& value);
Result<Dict> globals() {
return _globals.copy();
}
private: private:
Stack _stack; Stack _stack;
Stack _callstack; Stack _callstack;