alan
alan copied to clipboard
Conditionals
This one will be the most fun :) /s
Work on implementing the 2-opcode conditional design originally implemented in #430. The biggest difference between the 2 should be the name of the condfn
opcode, since that opcode name is already taken by the current front-end compiler's conditionals implementation, and we need to maintain backwards compatibility at least until the lnn compiler replaces the current front-end compiler.
Status
- This is currently blocked on #535
Design
Ideally, the desugaring would happen while constructing the AST. This requires closures for each of the branches that can be executed, as well as a way of signalling from class Expr
to class Stmt
(and from there to class Fn
) that it needs the rest of the statements in the syntactic function.
#430 has most of the design for the new way conditionals will work. Effectively, it would desugar Alan code that looks like this:
let x = 4;
if somethingIsTrue() {
x = 5;
} else if somethingElseIsTrue() {
x = 6;
} else {
x = 7;
}
return x;
into Alan code that looks like this:
let x = 4;
let condTable = condtable(); // note: condtable is an opcode that returns the opaque type CondTable<T>
// note: condfn is an opcode with the signature `fn(CondTable<T>, boolean, fn(): Maybe<T>): void`
condfn(condTable, somethingIsTrue(), fn() {
x = 5;
return none();
});
condfn(condTable, somethingElseIsTrue(), fn() {
x = 6;
return none();
});
condfn(condTable, true, fn() {
x = 7;
return none();
});
// note: evalcond is an opcode with the signature `fn(CondTable<T>, fn(): Maybe<T>): Maybe<T>`
return evalcond(condTable, fn() = some(x)).getOrExit();
The desugaring will have to take care when inlining nested conditionals though, to ensure that only one getOrExit
call is inserted.