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, Context(Value&& env, Array&& constants, Dict&& constants_dict,
Dict&& variables_dict, Array&& closures, Dict&& closures_dict, Dict&& variables_dict, Array&& closures, Dict&& closures_dict,
Context* parent) Context* parent, bool toplevel)
: env(std::move(env)), : env(std::move(env)),
constants(std::move(constants)), constants(std::move(constants)),
constants_dict(std::move(constants_dict)), constants_dict(std::move(constants_dict)),
@ -27,7 +27,7 @@ struct Context {
return Context(std::move(env), std::move(constants), return Context(std::move(env), 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), 0); std::move(closures), std::move(closures_dict), 0, true);
} }
static Result<Context> create(Context& parent) { static Result<Context> create(Context& parent) {
@ -40,7 +40,8 @@ struct Context {
return Context(std::move(env), std::move(constants), return Context(std::move(env), 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), &parent); std::move(closures), std::move(closures_dict), &parent,
false);
} }
uint64_t alloc_reg() { uint64_t alloc_reg() {
@ -119,6 +120,7 @@ struct Context {
Dict closures_dict; Dict closures_dict;
uint64_t maxreg; uint64_t maxreg;
Context* parent; Context* parent;
bool toplevel;
}; };
Result<void> Expression::add_opcode(Oc opcode, OpArg arg1, OpArg arg2, 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); return std::move(ex);
} }
Result<Expression> Compiler::compile_lambda(Context& context, Symbol& op, Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
Pair& expr) { Pair& expr) {
Context ctx = TRY(Context::create(context)); Context ctx = TRY(Context::create(context));
ctx.maxreg = 1; // Reserve the slot for function itself 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>(); 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()); auto param = TRY(first_pair.first());
uint64_t arity = 0; 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::Mov, {0, (int64_t)0}, {0, (int64_t)ex.reg}));
TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)0})); 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, auto fun = TRY(Function::create(name, arity, ctx.constants, ex.code,
TRY(Array::create()))); TRY(Array::create())));
@ -557,8 +574,8 @@ Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
return compile_comparison(context, sym, expr); return compile_comparison(context, sym, expr);
} else if (TRY(sym.cmp("if")) == 0) { } else if (TRY(sym.cmp("if")) == 0) {
return compile_if(context, sym, expr); return compile_if(context, sym, expr);
} else if (TRY(sym.cmp("lambda")) == 0) { } else if (TRY(sym.cmp("fn")) == 0) {
return compile_lambda(context, sym, expr); return compile_fn(context, sym, expr);
} else { } else {
return compile_function_call(context, expr); 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_symbol(Context& context, Symbol& value);
Result<Expression> compile_bool(Context& context, Bool& value); Result<Expression> compile_bool(Context& context, Bool& value);
Result<Expression> compile_if(Context& context, Symbol& op, Pair& expr); 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_body(Context& context, Pair& expr);
Result<Expression> compile_function_call(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>")); return TRY(String::create("#<function>"));
} }
if (!name.is<String>()) return ERROR(TypeMismatch); if (!name.is<Symbol>()) return ERROR(TypeMismatch);
String& name_str = *name.to<String>(); String name_str = TRY(write_symbol(*name.to<Symbol>()));
String res = TRY(String::create("#<function ")); String res = TRY(String::create("#<function "));
res = TRY(res.concat(name_str)); res = TRY(res.concat(name_str));