rune icon indicating copy to clipboard operation
rune copied to clipboard

Support const evaluation

Open udoprog opened this issue 4 years ago • 1 comments

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 fns (which will always be constant evaled if used in a non-const context).
  • [ ] const blocks const { <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);
}

udoprog avatar Sep 21 '20 00:09 udoprog

FTR, this is what I'm currently working on.

udoprog avatar Sep 21 '20 00:09 udoprog