Initial support for compiling named functions

This commit is contained in:
Konstantin Nazarov 2024-08-23 22:08:02 +01:00
parent ecbdc17f2b
commit 7a36787bd8
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
3 changed files with 28 additions and 11 deletions

View file

@ -7,7 +7,7 @@ struct Context {
Context(Value&& env, Array&& constants, Dict&& constants_dict,
Dict&& variables_dict, Array&& closures, Dict&& closures_dict,
Context* parent)
Context* parent, bool toplevel)
: env(std::move(env)),
constants(std::move(constants)),
constants_dict(std::move(constants_dict)),
@ -27,7 +27,7 @@ struct Context {
return Context(std::move(env), std::move(constants),
std::move(constants_dict), std::move(variables_dict),
std::move(closures), std::move(closures_dict), 0);
std::move(closures), std::move(closures_dict), 0, true);
}
static Result<Context> create(Context& parent) {
@ -40,7 +40,8 @@ struct Context {
return Context(std::move(env), std::move(constants),
std::move(constants_dict), std::move(variables_dict),
std::move(closures), std::move(closures_dict), &parent);
std::move(closures), std::move(closures_dict), &parent,
false);
}
uint64_t alloc_reg() {
@ -119,6 +120,7 @@ struct Context {
Dict closures_dict;
uint64_t maxreg;
Context* parent;
bool toplevel;
};
Result<void> Expression::add_opcode(Oc opcode, OpArg arg1, OpArg arg2,
@ -392,7 +394,7 @@ Result<Expression> Compiler::compile_if(Context& context, Symbol& op,
return std::move(ex);
}
Result<Expression> Compiler::compile_lambda(Context& context, Symbol& op,
Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
Pair& expr) {
Context ctx = TRY(Context::create(context));
ctx.maxreg = 1; // Reserve the slot for function itself
@ -405,6 +407,22 @@ Result<Expression> Compiler::compile_lambda(Context& context, Symbol& op,
Pair& first_pair = *first.to<Pair>();
Value name = TRY(Nil::create());
auto maybe_name = TRY(first_pair.first());
if (maybe_name.is<Symbol>()) {
name = TRY(maybe_name.to<Symbol>()->copy_value());
first = TRY(first_pair.rest());
if (first.is<Nil>() || !first.is<Pair>()) {
return ERROR(CompilationError);
}
Pair& first_pair = *first.to<Pair>();
}
auto param = TRY(first_pair.first());
uint64_t arity = 0;
@ -439,7 +457,6 @@ Result<Expression> Compiler::compile_lambda(Context& context, Symbol& op,
TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)0}, {0, (int64_t)ex.reg}));
TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)0}));
Value name = TRY(Nil::create());
auto fun = TRY(Function::create(name, arity, ctx.constants, ex.code,
TRY(Array::create())));
@ -557,8 +574,8 @@ Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
return compile_comparison(context, sym, expr);
} else if (TRY(sym.cmp("if")) == 0) {
return compile_if(context, sym, expr);
} else if (TRY(sym.cmp("lambda")) == 0) {
return compile_lambda(context, sym, expr);
} else if (TRY(sym.cmp("fn")) == 0) {
return compile_fn(context, sym, expr);
} else {
return compile_function_call(context, expr);
}

View file

@ -38,7 +38,7 @@ class Compiler {
Result<Expression> compile_symbol(Context& context, Symbol& value);
Result<Expression> compile_bool(Context& context, Bool& value);
Result<Expression> compile_if(Context& context, Symbol& op, Pair& expr);
Result<Expression> compile_lambda(Context& context, Symbol& op, Pair& expr);
Result<Expression> compile_fn(Context& context, Symbol& op, Pair& expr);
Result<Expression> compile_body(Context& context, Pair& expr);
Result<Expression> compile_function_call(Context& context, Pair& expr);
};

View file

@ -309,8 +309,8 @@ Result<String> Writer::write_function(const Function& val) {
return TRY(String::create("#<function>"));
}
if (!name.is<String>()) return ERROR(TypeMismatch);
String& name_str = *name.to<String>();
if (!name.is<Symbol>()) return ERROR(TypeMismatch);
String name_str = TRY(write_symbol(*name.to<Symbol>()));
String res = TRY(String::create("#<function "));
res = TRY(res.concat(name_str));