1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
open EvalValue
open Type
class plugin =
object (self)
(**
Prints greeting to stdout.
Takes no arguments, returns Void.
*)
method hello () : value =
print_endline "Hello from plugin";
(*
Plugin architecture requires to return something even for methods typed Void on Haxe side.
Return `null`
*)
vnull
(**
Takes `haxe.macro.Position` and returns a string of that position in the same format used for
compiler errors
*)
method stringify_position (pos:value) : value =
let pos = EvalDecode.decode_pos pos in
let str = Lexer.get_error_pos (Printf.sprintf "%s:%d:") pos in
EvalEncode.encode_string str
(**
Change all static methods named "test" to throw "Hello from plugin".
This is an example how to modify typed syntax tree.
*)
method hijack_static_test () : value =
let compiler = (EvalContext.get_ctx()).curapi in
(**
Add a callback like `haxe.macro.Context.onAfterTyping`
*)
compiler.after_typing (fun haxe_types ->
List.iter
(fun hx_type ->
match hx_type with
| TClassDecl cls ->
List.iter
(fun field ->
match field.cf_name, field.cf_expr with
| "test", Some e ->
let hello = {
eexpr = TConst (TString "Hello from plugin");
etype = (compiler.get_com()).basic.tstring;
epos = Globals.null_pos;
} in
field.cf_expr <- Some { e with eexpr = TThrow hello }
| _ -> ()
)
cls.cl_ordered_statics
| _ -> ()
)
haxe_types
);
vnull
end
;;
let api = new plugin in
(**
Register our plugin API.
This code is executed upon `eval.vm.Context.loadPlugin` call.
*)
EvalStdLib.StdContext.register [
("hello", EvalEncode.vfun0 api#hello);
("stringifyPosition", EvalEncode.vfun1 api#stringify_position);
("hijackStaticTest", EvalEncode.vfun0 api#hijack_static_test);
]
|