Skip to content

Commit 4cee735

Browse files
committed
quick and dirty POC implementation for HaxeFoundation/haxe-evolution#23
1 parent 824a603 commit 4cee735

File tree

5 files changed

+78
-37
lines changed

5 files changed

+78
-37
lines changed

src/macro/macroApi.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ and encode_ctype t =
425425
4, [encode_array (List.map encode_path tl); encode_array (List.map encode_field fields)]
426426
| CTOptional t ->
427427
5, [encode_ctype t]
428+
| CTNamed (n,t) ->
429+
6, [encode_placed_name n; encode_ctype t]
428430
in
429431
encode_enum ~pos:(Some (pos t)) ICType tag pl
430432

@@ -723,6 +725,8 @@ and decode_ctype t =
723725
CTExtend (List.map decode_path (decode_array tl), List.map decode_field (decode_array fl))
724726
| 5, [t] ->
725727
CTOptional (decode_ctype t)
728+
| 6, [n;t] ->
729+
CTNamed ((decode_string n,p), decode_ctype t)
726730
| _ ->
727731
raise Invalid_expr),p
728732

src/syntax/ast.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ and complex_type =
155155
| CTParent of type_hint
156156
| CTExtend of placed_type_path list * class_field list
157157
| CTOptional of type_hint
158+
| CTNamed of placed_name * type_hint
158159

159160
and type_hint = complex_type * pos
160161

@@ -550,7 +551,8 @@ let map_expr loop (e,p) =
550551
let tl = List.map tpath tl in
551552
let fl = List.map cfield fl in
552553
CTExtend (tl,fl)
553-
| CTOptional t -> CTOptional (type_hint t)),p
554+
| CTOptional t -> CTOptional (type_hint t)
555+
| CTNamed (n,t) -> CTNamed (n,type_hint t)),p
554556
and tparamdecl t =
555557
let constraints = List.map type_hint t.tp_constraints in
556558
let params = List.map tparamdecl t.tp_params in
@@ -749,6 +751,7 @@ let s_expr e =
749751
| CTAnonymous fl -> "{ " ^ String.concat "; " (List.map (s_class_field tabs) fl) ^ "}";
750752
| CTParent(t,_) -> "(" ^ s_complex_type tabs t ^ ")"
751753
| CTOptional(t,_) -> "?" ^ s_complex_type tabs t
754+
| CTNamed((n,_),(t,_)) -> n ^ ":" ^ s_complex_type tabs t
752755
| CTExtend (tl, fl) -> "{> " ^ String.concat " >, " (List.map (s_complex_type_path tabs) tl) ^ ", " ^ String.concat ", " (List.map (s_class_field tabs) fl) ^ " }"
753756
and s_class_field tabs f =
754757
match f.cff_doc with

src/syntax/parser.mly

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ let reify in_macro =
281281
| CTParent t -> ct "TParent" [to_type_hint t p]
282282
| CTExtend (tl,fields) -> ct "TExtend" [to_array to_tpath tl p; to_array to_cfield fields p]
283283
| CTOptional t -> ct "TOptional" [to_type_hint t p]
284+
| CTNamed (n,t) -> ct "TNamed" [to_placed_name n; to_type_hint t p]
284285
and to_type_hint (t,p) _ =
285286
(* to_obj ["type",to_ctype t p;"pos",to_pos p] p *)
286287
to_ctype (t,p) p
@@ -911,7 +912,7 @@ and parse_type_opt = parser
911912
| [< t = parse_type_hint >] -> Some t
912913
| [< >] -> None
913914

914-
and parse_complex_type s =
915+
and parse_complex_type ?(allow_named=false) s =
915916
let t = parse_complex_type_inner s in
916917
parse_complex_type_next t s
917918

@@ -920,7 +921,16 @@ and parse_structural_extension = parser
920921
t
921922

922923
and parse_complex_type_inner = parser
923-
| [< '(POpen,p1); t = parse_complex_type; '(PClose,p2) >] -> CTParent t,punion p1 p2
924+
| [< '(POpen,p1); tl = psep Comma (parse_complex_type ~allow_named:true); '(PClose,p2); s >] ->
925+
let arg_error p = error (Custom "Unnamed function arguments are not supported") p in
926+
(match tl with
927+
| [] as rest | ((CTOptional (CTNamed _,_) | CTNamed _), _) :: rest ->
928+
List.iter (fun (t,p) -> match t with (CTNamed _ | CTOptional (CTNamed _,_)) -> () | _ -> arg_error p) rest;
929+
let t = parse_ctfunction_rest p1 tl s in
930+
CTParent t,pos t (* wrap in parens to prevent CTFunction merging *)
931+
| [t] ->
932+
CTParent t,punion p1 p2
933+
| _ -> arg_error (punion p1 p2))
924934
| [< '(BrOpen,p1); s >] ->
925935
(match s with parser
926936
| [< l,p2 = parse_type_anonymous false >] -> CTAnonymous l,punion p1 p2
@@ -933,49 +943,66 @@ and parse_complex_type_inner = parser
933943
| [< >] -> serror())
934944
| [< '(Question,p1); t,p2 = parse_complex_type_inner >] ->
935945
CTOptional (t,p2),punion p1 p2
946+
| [< n = dollar_ident; s >] ->
947+
(match s with parser
948+
| [< '(DblDot,_); t = parse_complex_type >] ->
949+
let p1 = snd n in
950+
let p2 = snd t in
951+
CTNamed (n,t),punion p1 p2
952+
| [< s >] ->
953+
let n,p = n in
954+
let t,p = parse_type_path2 None [] n p s in
955+
CTPath t,p)
936956
| [< t,p = parse_type_path >] ->
937957
CTPath t,p
938958

959+
and parse_ctfunction_rest p1 args = parser
960+
| [< '(Arrow,_); ret = parse_complex_type >] ->
961+
CTFunction (args,ret),punion p1 (snd ret)
962+
939963
and parse_type_path s = parse_type_path1 None [] s
940964

941965
and parse_type_path1 p0 pack = parser
942966
| [< name, p1 = dollar_ident_macro pack; s >] ->
943-
if is_lower_ident name then
944-
(match s with parser
945-
| [< '(Dot,p) >] ->
946-
if is_resuming p then
947-
raise (TypePath (List.rev (name :: pack),None,false))
948-
else
949-
parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s
950-
| [< '(Semicolon,_) >] ->
951-
error (Custom "Type name should start with an uppercase letter") p1
952-
| [< >] -> serror())
953-
else
954-
let sub,p2 = (match s with parser
955-
| [< '(Dot,p); s >] ->
956-
(if is_resuming p then
957-
raise (TypePath (List.rev pack,Some (name,false),false))
958-
else match s with parser
959-
| [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2
960-
| [< '(Binop OpOr,_) when do_resume() >] ->
961-
set_resume p;
962-
raise (TypePath (List.rev pack,Some (name,false),false))
963-
| [< >] -> serror())
964-
| [< >] -> None,p1
965-
) in
966-
let params,p2 = (match s with parser
967-
| [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,p2) >] -> l,p2
968-
| [< >] -> [],p2
969-
) in
970-
{
971-
tpackage = List.rev pack;
972-
tname = name;
973-
tparams = params;
974-
tsub = sub;
975-
},punion (match p0 with None -> p1 | Some p -> p) p2
967+
parse_type_path2 p0 pack name p1 s
976968
| [< '(Binop OpOr,_) when do_resume() >] ->
977969
raise (TypePath (List.rev pack,None,false))
978970

971+
and parse_type_path2 p0 pack name p1 s =
972+
if is_lower_ident name then
973+
(match s with parser
974+
| [< '(Dot,p) >] ->
975+
if is_resuming p then
976+
raise (TypePath (List.rev (name :: pack),None,false))
977+
else
978+
parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s
979+
| [< '(Semicolon,_) >] ->
980+
error (Custom "Type name should start with an uppercase letter") p1
981+
| [< >] -> serror())
982+
else
983+
let sub,p2 = (match s with parser
984+
| [< '(Dot,p); s >] ->
985+
(if is_resuming p then
986+
raise (TypePath (List.rev pack,Some (name,false),false))
987+
else match s with parser
988+
| [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2
989+
| [< '(Binop OpOr,_) when do_resume() >] ->
990+
set_resume p;
991+
raise (TypePath (List.rev pack,Some (name,false),false))
992+
| [< >] -> serror())
993+
| [< >] -> None,p1
994+
) in
995+
let params,p2 = (match s with parser
996+
| [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,p2) >] -> l,p2
997+
| [< >] -> [],p2
998+
) in
999+
{
1000+
tpackage = List.rev pack;
1001+
tname = name;
1002+
tparams = params;
1003+
tsub = sub;
1004+
},punion (match p0 with None -> p1 | Some p -> p) p2
1005+
9791006
and type_name = parser
9801007
| [< '(Const (Ident name),p) >] ->
9811008
if is_lower_ident name then

src/typing/typeload.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ and load_complex_type ctx allow_display p (t,pn) =
547547
| CTParent t -> load_complex_type ctx allow_display p t
548548
| CTPath t -> load_instance ~allow_display ctx (t,pn) false p
549549
| CTOptional _ -> error "Optional type not allowed here" p
550+
| CTNamed _ -> error "Named type not allowed here" p
550551
| CTExtend (tl,l) ->
551552
(match load_complex_type ctx allow_display p (CTAnonymous l,p) with
552553
| TAnon a as ta ->
@@ -687,7 +688,8 @@ and load_complex_type ctx allow_display p (t,pn) =
687688
| _ ->
688689
TFun (List.map (fun t ->
689690
let t, opt = (match fst t with CTOptional t -> t, true | _ -> t,false) in
690-
"",opt,load_complex_type ctx allow_display p t
691+
let t, name = (match fst t with CTNamed ((n,_),t) -> t, n | _ -> t,"") in
692+
name,opt,load_complex_type ctx allow_display p t
691693
) args,load_complex_type ctx allow_display p r)
692694

693695
and init_meta_overloads ctx co cf =

std/haxe/macro/Expr.hx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ enum ComplexType {
535535
Represents an optional type.
536536
**/
537537
TOptional( t : ComplexType );
538+
539+
/**
540+
Represents a named type.
541+
**/
542+
TNamed( n:String, t : ComplexType );
538543
}
539544

540545
/**

0 commit comments

Comments
 (0)