Skip to content

Commit c6242b4

Browse files
committed
support argument names in function type (closes #4799)
1 parent abd38ff commit c6242b4

File tree

9 files changed

+89
-42
lines changed

9 files changed

+89
-42
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: 48 additions & 33 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
@@ -933,49 +934,63 @@ and parse_complex_type_inner = parser
933934
| [< >] -> serror())
934935
| [< '(Question,p1); t,p2 = parse_complex_type_inner >] ->
935936
CTOptional (t,p2),punion p1 p2
937+
| [< n = dollar_ident; s >] ->
938+
(match s with parser
939+
| [< '(DblDot,_); t = parse_complex_type_inner >] ->
940+
let p1 = snd n in
941+
let p2 = snd t in
942+
CTNamed (n,t),punion p1 p2
943+
| [< s >] ->
944+
let n,p = n in
945+
let t,p = parse_type_path2 None [] n p s in
946+
CTPath t,p
947+
)
936948
| [< t,p = parse_type_path >] ->
937949
CTPath t,p
938950

939951
and parse_type_path s = parse_type_path1 None [] s
940952

941953
and parse_type_path1 p0 pack = parser
942954
| [< 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
955+
parse_type_path2 p0 pack name p1 s
976956
| [< '(Binop OpOr,_) when do_resume() >] ->
977957
raise (TypePath (List.rev pack,None,false))
978958

959+
and parse_type_path2 p0 pack name p1 s =
960+
if is_lower_ident name then
961+
(match s with parser
962+
| [< '(Dot,p) >] ->
963+
if is_resuming p then
964+
raise (TypePath (List.rev (name :: pack),None,false))
965+
else
966+
parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s
967+
| [< '(Semicolon,_) >] ->
968+
error (Custom "Type name should start with an uppercase letter") p1
969+
| [< >] -> serror())
970+
else
971+
let sub,p2 = (match s with parser
972+
| [< '(Dot,p); s >] ->
973+
(if is_resuming p then
974+
raise (TypePath (List.rev pack,Some (name,false),false))
975+
else match s with parser
976+
| [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2
977+
| [< '(Binop OpOr,_) when do_resume() >] ->
978+
set_resume p;
979+
raise (TypePath (List.rev pack,Some (name,false),false))
980+
| [< >] -> serror())
981+
| [< >] -> None,p1
982+
) in
983+
let params,p2 = (match s with parser
984+
| [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,p2) >] -> l,p2
985+
| [< >] -> [],p2
986+
) in
987+
{
988+
tpackage = List.rev pack;
989+
tname = name;
990+
tparams = params;
991+
tsub = sub;
992+
},punion (match p0 with None -> p1 | Some p -> p) p2
993+
979994
and type_name = parser
980995
| [< '(Const (Ident name),p) >] ->
981996
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, n = (match fst t with CTNamed (n,t) -> t,fst n | _ -> t,"") in
692+
n,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
/**

std/haxe/macro/Printer.hx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class Printer {
119119
case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}";
120120
case TParent(ct): "(" + printComplexType(ct) + ")";
121121
case TOptional(ct): "?" + printComplexType(ct);
122+
case TNamed(n,ct): n + ":" + printComplexType(ct);
122123
case TExtend(tpl, fields): '{> ${tpl.map(printTypePath).join(" >, ")}, ${fields.map(printField).join(", ")} }';
123124
}
124125

tests/unit/src/unit/HelperMacros.hx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ class HelperMacros {
77
return macro $v { Std.string(Date.now()) };
88
}
99

10+
static public macro function typeString(e) {
11+
var typed = haxe.macro.Context.typeExpr(e);
12+
var s = haxe.macro.TypeTools.toString(typed.t);
13+
return macro $v{s};
14+
}
15+
1016
static public macro function typedAs(actual:haxe.macro.Expr, expected:haxe.macro.Expr) {
1117
var tExpected = haxe.macro.Context.typeof(expected);
1218
var tActual = haxe.macro.Context.typeof(actual);
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package unit.issues;
22

3+
import unit.HelperMacros.typeString;
4+
35
private typedef Asset<@:const T> = String;
46

57
class Issue2958 extends Test {
@@ -9,11 +11,4 @@ class Issue2958 extends Test {
911
"unit.issues._Issue2958.Asset<[\"test\", 1]>"
1012
);
1113
}
12-
13-
static macro function typeString(e)
14-
{
15-
var typed = haxe.macro.Context.typeExpr(e);
16-
var s = haxe.macro.TypeTools.toString(typed.t);
17-
return macro $v{s};
18-
}
1914
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package unit.issues;
2+
3+
import unit.HelperMacros.typeErrorText;
4+
import unit.HelperMacros.typeString;
5+
6+
class Issue4799 extends Test {
7+
function test() {
8+
var f : arg1:Int->?arg2:String->Float->Void;
9+
eq(typeString(f), "arg1 : Int -> ?arg2 : String -> Float -> Void");
10+
11+
eq(typeErrorText((null : arg:Int)), "Named type not allowed here");
12+
13+
// TODO: maybe we could actually allow this?
14+
eq(typeErrorText((null : Int->returnValue:Int)), "Named type not allowed here");
15+
}
16+
}

0 commit comments

Comments
 (0)