Implement "when" form
This commit is contained in:
parent
52eae6b3e3
commit
4945a86c2e
2 changed files with 47 additions and 0 deletions
|
@ -433,6 +433,49 @@ Result<Expression> Compiler::compile_if(Context& context, Symbol& op,
|
|||
return std::move(ex);
|
||||
}
|
||||
|
||||
Result<Expression> Compiler::compile_when(Context& context, Symbol& op,
|
||||
const Value& expr) {
|
||||
Value rest = TRY(expr.rest());
|
||||
Expression ex = TRY(Expression::create());
|
||||
|
||||
auto num_params = TRY(rest.size());
|
||||
if (num_params < 2) {
|
||||
return syntax_error(TRY(expr.first()),
|
||||
"\"when\" form must have at least 2 arguments");
|
||||
}
|
||||
|
||||
auto condition = TRY(rest.first());
|
||||
auto body = TRY(rest.rest());
|
||||
|
||||
auto condition_comp = TRY(compile_expr(context, condition));
|
||||
|
||||
ex.add_code(condition_comp.code);
|
||||
uint64_t firstreg = condition_comp.reg;
|
||||
uint64_t reg = firstreg;
|
||||
|
||||
auto body_comp = TRY(compile_body(context, body));
|
||||
uint64_t body_reg = body_comp.reg;
|
||||
|
||||
context.maxreg = firstreg + 1;
|
||||
|
||||
int64_t true_const = TRY(context.add_const(TRY(Bool::create(true))));
|
||||
int64_t nil_const = TRY(context.add_const(TRY(Nil::create())));
|
||||
|
||||
TRY(ex.add_opcode(Oc::Equal, {0, (int64_t)firstreg}, {1, (int64_t)true_const},
|
||||
{0, (int64_t)1}));
|
||||
|
||||
TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)3}));
|
||||
TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)firstreg}, {1, (int64_t)nil_const}));
|
||||
TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)TRY(body_comp.code.size()) + 2}));
|
||||
|
||||
ex.add_code(body_comp.code);
|
||||
|
||||
TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)firstreg}, {0, (int64_t)body_reg}));
|
||||
|
||||
context.maxreg = firstreg + 1;
|
||||
ex.reg = firstreg;
|
||||
return std::move(ex);
|
||||
}
|
||||
Result<Expression> Compiler::compile_and(Context& context, Symbol& op,
|
||||
const Value& expr) {
|
||||
Value param = TRY(expr.rest());
|
||||
|
@ -918,6 +961,8 @@ Result<Expression> Compiler::compile_list(Context& context, const Value& 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("when")) == 0) {
|
||||
return compile_when(context, sym, expr);
|
||||
} else if (TRY(sym.cmp("and")) == 0) {
|
||||
return compile_and(context, sym, expr);
|
||||
} else if (TRY(sym.cmp("or")) == 0) {
|
||||
|
|
|
@ -42,6 +42,8 @@ class Compiler {
|
|||
Result<Expression> compile_symbol(Context& context, const Value& value);
|
||||
Result<Expression> compile_if(Context& context, Symbol& op,
|
||||
const Value& expr);
|
||||
Result<Expression> compile_when(Context& context, Symbol& op,
|
||||
const Value& expr);
|
||||
Result<Expression> compile_and(Context& context, Symbol& op,
|
||||
const Value& expr);
|
||||
Result<Expression> compile_or(Context& context, Symbol& op,
|
||||
|
|
Loading…
Reference in a new issue