Skip to content

Commit

Permalink
make the difference between "parse" and "parseInlineString" (substrin…
Browse files Browse the repository at this point in the history
…g error reporting + completion support)
  • Loading branch information
ncannasse committed Mar 11, 2012
1 parent f3254fd commit 0c71f57
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 17 deletions.
64 changes: 64 additions & 0 deletions ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,67 @@ let unescape s =
in
loop false 0;
Buffer.contents b


let map_expr loop (e,p) =
let opt f o =
match o with None -> None | Some v -> Some (f v)
in
let rec tparam = function
| TPType t -> TPType (ctype t)
| TPExpr e -> TPExpr (loop e)
and cfield f =
{ f with cff_kind = (match f.cff_kind with
| FVar (t,e) -> FVar (opt ctype t, opt loop e)
| FFun f -> FFun (func f)
| FProp (get,set,t,e) -> FProp (get,set,ctype t,opt loop e))
}
and ctype = function
| CTPath t -> CTPath (tpath t)
| CTFunction (cl,c) -> CTFunction (List.map ctype cl, ctype c)
| CTAnonymous fl -> CTAnonymous (List.map cfield fl)
| CTParent t -> CTParent (ctype t)
| CTExtend (t,fl) -> CTExtend (tpath t, List.map cfield fl)
| CTOptional t -> CTOptional (ctype t)
and func f =
{
f_params = List.map (fun (n,tl) -> n,List.map ctype tl) f.f_params;
f_args = List.map (fun (n,o,t,e) -> n,o,opt ctype t,opt loop e) f.f_args;
f_type = opt ctype f.f_type;
f_expr = opt loop f.f_expr;
}
and tpath t = { t with tparams = List.map tparam t.tparams }
in
let e = (match e with
| EConst _ -> e
| EArray (e1,e2) -> EArray (loop e1, loop e2)
| EBinop (op,e1,e2) -> EBinop (op,loop e1, loop e2)
| EField (e,f) -> EField (loop e, f)
| EType (e,f) -> EType (loop e, f)
| EParenthesis e -> EParenthesis (loop e)
| EObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> f,loop e) fl)
| EArrayDecl el -> EArrayDecl (List.map loop el)
| ECall (e,el) -> ECall (loop e, List.map loop el)
| ENew (t,el) -> ENew (tpath t,List.map loop el)
| EUnop (op,f,e) -> EUnop (op,f,loop e)
| EVars vl -> EVars (List.map (fun (n,t,eo) -> n,opt ctype t,opt loop eo) vl)
| EFunction (n,f) -> EFunction (n,func f)
| EBlock el -> EBlock (List.map loop el)
| EFor (e1,e2) -> EFor (loop e1, loop e2)
| EIn (e1,e2) -> EIn (loop e1, loop e2)
| EIf (e,e1,e2) -> EIf (loop e, loop e1, opt loop e2)
| EWhile (econd,e,f) -> EWhile (loop econd, loop e, f)
| ESwitch (e,cases,def) -> ESwitch (loop e, List.map (fun (el,e) -> List.map loop el, loop e) cases, opt loop def)
| ETry (e, catches) -> ETry (loop e, List.map (fun (n,t,e) -> n,ctype t,loop e) catches)
| EReturn e -> EReturn (opt loop e)
| EBreak -> EBreak
| EContinue -> EContinue
| EUntyped e -> EUntyped (loop e)
| EThrow e -> EThrow (loop e)
| ECast (e,t) -> ECast (loop e,opt ctype t)
| EDisplay (e,f) -> EDisplay (loop e,f)
| EDisplayNew t -> EDisplayNew (tpath t)
| ETernary (e1,e2,e3) -> ETernary (loop e1,loop e2,loop e3)
| ECheckType (e,t) -> ECheckType (loop e, ctype t)
) in
(e,p)
8 changes: 4 additions & 4 deletions interp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ type extern_api = {
get_type : string -> Type.t option;
get_module : string -> Type.t list;
on_generate : (Type.t list -> unit) -> unit;
parse_string : string -> Ast.pos -> Ast.expr;
parse_string : string -> Ast.pos -> bool -> Ast.expr;
typeof : Ast.expr -> Type.t;
type_patch : string -> string -> bool -> string option -> unit;
meta_patch : string -> string -> string option -> bool -> unit;
Expand Down Expand Up @@ -1752,9 +1752,9 @@ let macro_lib =
VNull
| _ -> error()
);
"parse", Fun2 (fun s p ->
match s, p with
| VString s, VAbstract (APos p) -> encode_expr ((get_ctx()).curapi.parse_string s p)
"parse", Fun3 (fun s p b ->
match s, p, b with
| VString s, VAbstract (APos p), VBool b -> encode_expr ((get_ctx()).curapi.parse_string s p b)
| _ -> error()
);
"make_expr", Fun2 (fun v p ->
Expand Down
11 changes: 9 additions & 2 deletions std/haxe/macro/Context.hx
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,17 @@ class Context {
}

/**
Parse an expression.
Parse a constructed string into the corresponding expression.
**/
public static function parse( expr : String, pos : Position ) : Expr {
return load("parse", 2)(untyped expr.__s, pos);
return load("parse", 3)(untyped expr.__s, pos, false);
}

/**
Parse a string contained into source code into the corresponding expression. Errors positions are reported within this string
**/
public static function parseInlineString( expr : String, pos : Position ) : Expr {
return load("parse", 3)(untyped expr.__s, pos, true);
}

/**
Expand Down
26 changes: 15 additions & 11 deletions typer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2188,24 +2188,27 @@ let get_type_patch ctx t sub =
Hashtbl.add h k tp;
tp

let parse_string ctx s p =
let parse_string ctx s p inlined =
let old = Lexer.save() in
let old_file = (try Some (Hashtbl.find Lexer.all_files p.pfile) with Not_found -> None) in
let old_display = !Parser.resume_display in
let restore() =
(match old_file with
| None -> ()
| Some f -> Hashtbl.replace Lexer.all_files p.pfile f);
if not inlined then Parser.resume_display := old_display;
Lexer.restore old;
in
Lexer.init p.pfile;
if not inlined then Parser.resume_display := null_pos;
let _, decls = try
Parser.parse ctx.com (Lexing.from_string s)
with Parser.Error (e,p) ->
with Parser.Error (e,pe) ->
restore();
error (Parser.error_msg e) p
| Lexer.Error (e,p) ->
error (Parser.error_msg e) (if inlined then pe else p)
| Lexer.Error (e,pe) ->
restore();
error (Lexer.error_msg e) p
error (Lexer.error_msg e) (if inlined then pe else p)
in
restore();
match decls with
Expand Down Expand Up @@ -2268,12 +2271,13 @@ let make_macro_api ctx p =
t()
)
);
Interp.parse_string = (fun s p ->
Interp.parse_string = (fun s p inl ->
typing_timer ctx (fun() ->
let head = "class X{static function main() " in
let head = (if p.pmin > String.length head then head ^ String.make (p.pmin - String.length head) ' ' else head) in
match parse_string ctx (head ^ s ^ "}") p with
| EClass { d_data = [{ cff_name = "main"; cff_kind = FFun { f_expr = Some e } }]} -> e
let rec loop e = let e = Ast.map_expr loop e in (fst e,p) in
match parse_string ctx (head ^ s ^ "}") p inl with
| EClass { d_data = [{ cff_name = "main"; cff_kind = FFun { f_expr = Some e } }]} -> if inl then e else loop e
| _ -> assert false
)
);
Expand All @@ -2283,7 +2287,7 @@ let make_macro_api ctx p =
Interp.type_patch = (fun t f s v ->
typing_timer ctx (fun() ->
let v = (match v with None -> None | Some s ->
match parse_string ctx ("typedef T = " ^ s) null_pos with
match parse_string ctx ("typedef T = " ^ s) null_pos false with
| ETypedef { d_data = ct } -> Some ct
| _ -> assert false
) in
Expand All @@ -2294,7 +2298,7 @@ let make_macro_api ctx p =
);
);
Interp.meta_patch = (fun m t f s ->
let m = (match parse_string ctx (m ^ " typedef T = T") null_pos with
let m = (match parse_string ctx (m ^ " typedef T = T") null_pos false with
| ETypedef t -> t.d_meta
| _ -> assert false
) in
Expand Down Expand Up @@ -2603,7 +2607,7 @@ let call_macro ctx path meth args p =
let call_init_macro ctx e =
let p = { pfile = "--macro"; pmin = 0; pmax = 0 } in
let api = make_macro_api ctx p in
let e = api.Interp.parse_string e p in
let e = api.Interp.parse_string e p false in
match fst e with
| ECall (e,args) ->
let rec loop e =
Expand Down

0 comments on commit 0c71f57

Please sign in to comment.