rune
rune copied to clipboard
Support const evaluation
Support constant expressions, like these:x
const VALUE = #{hello: "World"};
They can reference other constant expressions, but will fail to compile if there are cycles:
const VALUE = #{hello: OTHER};
const OTHER = "World";
Fail:
const VALUE = #{hello: OTHER};
const OTHER = #{hello: VALUE};
Plumbing is being built in #93. As it stands, constant value resolving is hooked into the query phase through a component called the ConstCompiler
. Which will probably be renamed to something involving the world eval, since that is really all it does. Essentially it's an eval function which does AST walking.
When CompileMeta::Const
is resolved for a query, it includes the calculated ConstValue
. All const resolving is memoized.
Checklist
- [ ] constant
fn
s (which will always be constant evaled if used in a non-const context). - [ ]
const
blocksconst { <block> }
.- This will need yet another re-implementation of scopes. This time simpler, since we don't need to keep track of Vm state.
- [ ]
if
expressions (started in #93). - [ ]
while
expressions (started in #93). - [ ] String operations.
- [ ] Template strings (started in #93).
- [ ] integer operations (started in #93).
- [ ] float operations (started in #93).
- [ ] Literals (started in #93, #94).
Current state
The current state of the constant compiler is a very naive ast walker. With the existing design it's not possible to implement break
or returns
, because each expression is evaluated recursively and that would require returning early everywhere in a manner which would be very cumbersome.
Instead, the constant compiler should be redesigned to execute a stack, where returning simply pops the execution context of each scope until it's reached the thing it should break out of or return from. The root of the execution simply executed the AST that is at the top of the stack until it receives instructions to behave differently.
But the current constant compiler is fully capable of understanding cycles, and can do string templating, like this:
const LIMIT = 10;
const URL = `https://api.example.com/query?limit={LIMIT}`;
fn main() {
let _ = http::get(URL);
}
FTR, this is what I'm currently working on.