Allow redefining local variables with "fn"

This commit is contained in:
Konstantin Nazarov 2024-10-10 20:12:23 +01:00
parent 58af636293
commit 353102f8cd
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
2 changed files with 46 additions and 9 deletions

View file

@ -820,16 +820,42 @@ Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
Oc::MakeClosure, {0, (int64_t)reg},
{0, (int64_t)reg + (int64_t)TRY(ctx.closures.size()) + 1}));
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},
{0, (int64_t)reg}));
if (!name.is<Nil>()) {
if (context.toplevel) {
int64_t gname = TRY(context.add_const(name));
TRY(ex_res.add_opcode(Oc::GlobalStore, {1, (int64_t)gname},
{0, (int64_t)reg}));
context.maxreg = reg + 1;
ex_res.reg = reg;
return ex_res;
} else {
auto maybe_binding = context.get_var(name);
if (maybe_binding.has_value()) {
auto breg = maybe_binding.value();
TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)breg}, {0, (int64_t)reg}));
ex_res.reg = reg;
context.maxreg = reg + 1;
return std::move(ex_res);
} else {
context.maxreg = reg + 1;
auto breg = TRY(context.add_var(name));
TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)breg}, {0, (int64_t)reg}));
ex_res.reg = breg;
context.maxreg = breg + 1;
return std::move(ex_res);
}
}
} else {
context.maxreg = reg + 1;
ex_res.reg = reg;
return ex_res;
}
context.maxreg = reg + 1;
ex_res.reg = reg;
return ex_res;
}
Result<Expression> Compiler::compile_let(Context& context, Symbol& op,
@ -924,6 +950,7 @@ Result<Expression> Compiler::compile_body(Context& context, const Value& expr) {
if (cur.is<Nil>()) {
ex_res.reg = expr.reg;
} else {
// TODO: commenting this out means we waste registers
// context.maxreg = maxreg;
}
}

View file

@ -65,3 +65,13 @@
(+ x y))
(assert (= (def-redef) 6))
;; allow redefenition of variables with "fn"
(fn def-redef-fn ()
(def x 2)
(fn x (y) (+ x y))
(x 3)
)
(assert (= (def-redef-fn) 5))