COMPILER PLUGINS
Aleksandr Kuzmenko. HaxeUP Linz 2019
COMPILATION
Source
code
Abstract Syntax Tree
Typing
Optimizing
Generating
Parsing
Typed AST
Typed AST
Target code/binary
Macros
AST
MACROS
MACROS
PLUGINS
PLUGINS
PLUGINS
PLUGINS
COMPILATION
Source
code
Abstract Syntax Tree
Typing
Optimizing
Generating
Parsing
Typed AST
Typed AST
Target code/binary
Plugin
AST
Plugin
TAST
Plugin
TAST
PLUGINS, But...
PLUGINS, But...
PLUGINS, But...
No sense to release prebuilt plugin binaries
on haxelib
(but there is hope to figure it out)
BLAZING FAST
Iterate all fields of all classes in compiler’s unit test suite
Macro: 50-60ms
Plugin: 0-1ms
Context.onAfterTyping(types -> {
for(type in types) {
switch type {
case TClassDecl(_.get() => c):
for(field in c.fields.get()) {
fieldName = field.name;
}
for(field in c.statics.get()) {
fieldName = field.name;
}
case _:
}
}
});
let field_name = ref "" in
let handle field = field_name := field.cf_name in
let compiler = (EvalContext.get_ctx()).curapi in
compiler.after_typing (fun haxe_types ->
List.iter
(fun hx_type ->
match hx_type with
| TClassDecl cls ->
List.iter handle cls.cl_ordered_statics;
List.iter handle cls.cl_ordered_fields
| _ -> ()
)
haxe_types
);
USE CASES
USE CASES
AST
Typed AST
Possible optimization by a plugin
matrices
m3 = m1 * m2;
m3.a11 = a11 * b11 + a12 * 0 + a13 * 0 + a14 * 0;
m3.a12 = a11 * 0 + a12 * f + a13 * 0 + a14 * 0;
m3.a13 = a11 * 0 + a12 * 0 + a13 * b33 + a14 * -1;
m3.a14 = a11 * 0 + a12 * 0 + a13 * b34 + a14 * 0;
m3.a21 = a21 * b11 + a22 * 0 + a23 * 0 + a24 * 0;
m3.a22 = a21 * 0 + a22 * f + a23 * 0 + a24 * 0;
m3.a23 = a21 * 0 + a22 * 0 + a23 * b33 + a24 * -1;
m3.a24 = a21 * 0 + a22 * 0 + a23 * b34 + a24 * 0;
m3.a31 = a31 * b11 + a32 * 0 + a33 * 0 + a34 * 0;
<...>
m3.a11 = a11 * b11;
m3.a12 = a12 * f;
m3.a13 = a13 * b33 + a14 * -1;
m3.a14 = a13 * b34;
m3.a21 = a21 * b11;
m3.a22 = a22 * f;
m3.a23 = a23 * b33 + a24 * -1;
m3.a24 = a23 * b34;
m3.a31 = a31 * b11;
<...>
USE CASES
LET’S PLAY
HAXE IS GREAT
Questions?
alex@stablex.ru
twitter @RealyUniqueName