Initial support for compiling named functions
This commit is contained in:
parent
ecbdc17f2b
commit
7a36787bd8
3 changed files with 28 additions and 11 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in a new issue