Meta Programming
Together with support for first-class type values, and the ability to execute almost any code at compile time, the language facilities described in the following sections enable powerful meta programming schemes, including simple generics, code generation, defining custom checked annotations, and implementing domain specific languages.
Meta Parameters
⚠️ TODO
Generic Aggregate Types
Any of the aggregate types can have an optional list of parameters. These parameters are constant and compile-time and can be used to customize the definitions inside of the aggregate type. Furthermore, the parameters are accessible as properties of the type from the outside.
Generic types are not proper types. In order to use them as an actual type, the type name must be followed by a matching list of arguments to turn them into a concrete type definition.
Example
struct Vector(Scalar: type, dim: size_t) {
var elements : Scalar[dim];
meta if (dim >= 1) var x { get => elements[0]; }
meta if (dim >= 2) var y { get => elements[1]; }
meta if (dim >= 3) var z { get => elements[2]; }
}
alias Vec3f = Vector(float, 3);
metaAssert (Vec3f.Scalar = float && Vec3f.dim == 3);
Introspection
❌ Not Implemented
Meta Control Flow
⚠️ TODO
meta if: ⚠️ TODOmeta for: ⚠️ TODOmeta switch: ❌ Not Implemented
Mixins
Mixins are a means to insert declarations or statements directly within an
existing scope. The content of the mixin is copied into the place of the
instantiation, as if the statements were written there directly, with the
exception that block level attributes (e.g. private:) will not be inherited.
Example
void registerFunctionCallTime(func: string, dur: Duration);
mixin benchmark {
let _benchmark_startTime = MonoTime.currTime;
scope (exit) {
let dur = MonoTime.currTime - _benchmark_StartTime;
registerFunctionCallTime(meta(function).name, dur);
}
}
function updateGraph()
{
// insert the benchmark code here
mixin! benchmark;
// perform some computations here...
}
Parameters
A mixin has an optional list of compiletime parameters that can be used to customize the generated code:
mixin generateFactoryFunction(S: type) {
function #("create" ~ meta(S).name)()
{
S ret;
// ...
return ret;
}
}
struct Button { /*...*/ }
mixin! generateFactoryFunction(Button);
var btn = createButton();