Skip to content

Commit

Permalink
[macro] Expose Context.loadLexerLines(file,content) instead
Browse files Browse the repository at this point in the history
  • Loading branch information
kLabz committed Jan 16, 2025
1 parent 09f3d1a commit 699d243
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/macro/macroApi.ml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type 'value compiler_api = {
after_generate : (unit -> unit) -> unit;
on_type_not_found : (string -> 'value) -> unit;
parse_string : string -> Globals.pos -> bool -> Ast.expr;
load_lexer_lines : string -> string -> unit;
parse : 'a . ((Ast.token * Globals.pos) Stream.t -> 'a) -> string -> 'a;
type_expr : Ast.expr -> Type.texpr;
resolve_type : Ast.complex_type -> Globals.pos -> t;
Expand Down Expand Up @@ -1908,6 +1909,12 @@ let macro_api ccom get_api =
if s = "" then (get_api()).exc_string "Invalid expression";
encode_expr ((get_api()).parse_string s (decode_pos p) (decode_bool b))
);
"load_lexer_lines", vfun2 (fun f c ->
let f = decode_string f in
let content = decode_string c in
(get_api()).load_lexer_lines f content;
vnull
);
"make_expr", vfun2 (fun v p ->
encode_expr (value_to_expr v (decode_pos p))
);
Expand Down
45 changes: 32 additions & 13 deletions src/syntax/lexer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -210,27 +210,19 @@ let find_line p f =
loop 0 (Array.length f.lalines)

(* resolve a position within a non-haxe file by counting newlines *)
let resolve_pos file =
let ch = open_in_bin file in
let f = make_file file in
let resolve_pos f next skip =
let rec loop p =
let inc i () =
f.lline <- f.lline + 1;
f.llines <- (p + i,f.lline) :: f.llines;
i
in
let i = match input_char ch with
let i = match next() with
| '\n' -> inc 1
| '\r' ->
ignore(input_char ch);
skip 1;
inc 2
| c -> (fun () ->
let rec skip n =
if n > 0 then begin
ignore(input_char ch);
skip (n - 1)
end
in
let code = int_of_char c in
if code < 0xC0 then ()
else if code < 0xE0 then skip 1
Expand All @@ -241,8 +233,35 @@ let resolve_pos file =
in
loop (p + i())
in
loop 0

let resolve_file_content_pos file content =
let f = make_file file in
let i = ref 0 in
let next () =
try
let ret = String.get content !i in
incr i;
ret
with Invalid_argument _ -> raise End_of_file
in
let skip n =
i := !i + n
in
try resolve_pos f next skip with End_of_file -> f

let resolve_file_pos file =
let ch = open_in_bin file in
let f = make_file file in
let next () = input_char ch in
let rec skip n =
if n > 0 then begin
ignore(next ());
skip (n - 1)
end
in
try
loop 0
resolve_pos f next skip
with End_of_file ->
close_in ch;
f
Expand All @@ -252,7 +271,7 @@ let find_file file =
Hashtbl.find all_files file
with Not_found ->
try
let f = resolve_pos file in
let f = resolve_file_pos file in
Hashtbl.add all_files file f;
f
with Sys_error _ ->
Expand Down
4 changes: 4 additions & 0 deletions src/typing/macroContext.ml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ let make_macro_com_api com mcom p =
| ParseSuccess(r,_,_) -> r
| ParseError(_,(msg,p),_) -> Parser.error msg p
);
load_lexer_lines = (fun file content ->
let f = Lexer.resolve_file_content_pos file content in
Hashtbl.add Lexer.all_files file f;
);
type_expr = (fun e ->
Interp.exc_string "unsupported"
);
Expand Down
9 changes: 9 additions & 0 deletions std/haxe/macro/Context.hx
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,15 @@ class Context {
return load("do_parse", 3)(expr, pos, true);
}

/**
Parse file content for newlines, allowing positions to be resolved
properly inside that file later on (using `Context.parseInlineString`
for example). Works with both real and virtual files.
**/
public static function loadLexerLines(file:String, content:String):Void {
load("load_lexer_lines", 2)(file, content);
}

/**
Builds an expression from `v`.
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/src/unit/issues/Issue3387.hx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class Issue3387 extends unit.Test {
}

static macro function getPos(source:String, file:String) {
haxe.macro.Context.loadLexerLines(file, source);
var e = haxe.macro.Context.parseInlineString(source, haxe.macro.Context.makePosition({min: 0, max: 0, file: file}));
return macro $v{Std.string(e.pos)};
}
}
}

0 comments on commit 699d243

Please sign in to comment.