Skip to content

Commit ef5eead

Browse files
cristianoczth
authored andcommitted
Skeleton adapt untagged variants to several instanceof cases.
1 parent 6390057 commit ef5eead

File tree

3 files changed

+37
-18
lines changed

3 files changed

+37
-18
lines changed

jscomp/core/js_exp_make.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ let tag_type = function
807807
| Untagged FloatType -> str "number"
808808
| Untagged FunctionType -> str "function"
809809
| Untagged StringType -> str "string"
810-
| Untagged ArrayType -> str "Array" ~delim:DNoQuotes
810+
| Untagged (InstanceType i) -> str (Ast_untagged_variants.Instance.to_string i) ~delim:DNoQuotes
811811
| Untagged ObjectType -> str "object"
812812
| Untagged UnknownType ->
813813
(* TODO: this should not happen *)
@@ -824,7 +824,10 @@ let rec emit_check (check : t Ast_untagged_variants.DynamicChecks.t) = match che
824824
in
825825
bin op (emit_check x) (emit_check y)
826826
| TypeOf x -> typeof (emit_check x)
827-
| IsArray x -> is_array (emit_check x)
827+
| IsInstanceOf (Array, x) -> is_array (emit_check x)
828+
| IsInstanceOf (instance, x) ->
829+
let instance_name = Ast_untagged_variants.Instance.to_string instance in
830+
instanceof (emit_check x) (str instance_name ~delim:DNoQuotes)
828831
| Not x -> not (emit_check x)
829832
| Expr x -> x
830833

jscomp/core/lam_compile.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ and compile_untagged_cases ~cxt ~switch_exp ~default ~block_cases cases =
762762
in
763763
E.emit_check check
764764
in
765-
let is_array (l, _) = l = Ast_untagged_variants.Untagged ArrayType in
765+
let is_array (l, _) = l = Ast_untagged_variants.Untagged (InstanceType Array) in
766766
let switch ?default ?declaration e clauses =
767767
let array_clauses = Ext_list.filter clauses is_array in
768768
match array_clauses with

jscomp/ml/ast_untagged_variants.ml

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
module Instance = struct
2+
type t = Array | Promise
3+
let to_string = function Array -> "Array" | Promise -> "Promise"
4+
end
5+
16
type untaggedError =
27
| OnlyOneUnknown of string
38
| AtMostOneObject
4-
| AtMostOneArray
9+
| AtMostOneInstance of Instance.t
510
| AtMostOneFunction
611
| AtMostOneString
712
| AtMostOneNumber
@@ -29,7 +34,7 @@ let report_error ppf =
2934
(match untaggedVariant with
3035
| OnlyOneUnknown name -> "Case " ^ name ^ " has a payload that is not of one of the recognized shapes (object, array, etc). Then it must be the only case with payloads."
3136
| AtMostOneObject -> "At most one case can be an object type."
32-
| AtMostOneArray -> "At most one case can be an array type."
37+
| AtMostOneInstance i -> "At most one case can be a " ^ (Instance.to_string i) ^ " type."
3338
| AtMostOneFunction -> "At most one case can be a function type."
3439
| AtMostOneString -> "At most one case can be a string type."
3540
| AtMostOneNumber ->
@@ -42,7 +47,7 @@ type block_type =
4247
| IntType
4348
| StringType
4449
| FloatType
45-
| ArrayType
50+
| InstanceType of Instance.t
4651
| FunctionType
4752
| ObjectType
4853
| UnknownType
@@ -139,7 +144,10 @@ let get_block_type ~env (cstr : Types.constructor_declaration) :
139144
Some FloatType
140145
| true, Cstr_tuple [{desc = Tconstr (path, _, _)}]
141146
when Path.same path Predef.path_array ->
142-
Some ArrayType
147+
Some (InstanceType Array)
148+
| true, Cstr_tuple [{desc = Tconstr (path, _, _)}]
149+
when Path.same path Predef.path_promise ->
150+
Some (InstanceType Promise)
143151
| true, Cstr_tuple [({desc = Tconstr _} as t)]
144152
when Ast_uncurried_utils.typeIsUncurriedFun t ->
145153
Some FunctionType
@@ -192,7 +200,7 @@ let checkInvariant ~isUntaggedDef ~(consts : (Location.t * tag) list)
192200
let module StringSet = Set.Make (String) in
193201
let string_literals = ref StringSet.empty in
194202
let nonstring_literals = ref StringSet.empty in
195-
let arrayTypes = ref 0 in
203+
let instanceTypes = Hashtbl.create 1 in
196204
let functionTypes = ref 0 in
197205
let objectTypes = ref 0 in
198206
let stringTypes = ref 0 in
@@ -213,8 +221,10 @@ let checkInvariant ~isUntaggedDef ~(consts : (Location.t * tag) list)
213221
raise (Error (loc, InvalidUntaggedVariantDefinition (OnlyOneUnknown name)));
214222
if !objectTypes > 1 then
215223
raise (Error (loc, InvalidUntaggedVariantDefinition AtMostOneObject));
216-
if !arrayTypes > 1 then
217-
raise (Error (loc, InvalidUntaggedVariantDefinition AtMostOneArray));
224+
Hashtbl.iter (fun i count ->
225+
if count > 1 then
226+
raise (Error (loc, InvalidUntaggedVariantDefinition (AtMostOneInstance i))))
227+
instanceTypes;
218228
if !functionTypes > 1 then
219229
raise (Error (loc, InvalidUntaggedVariantDefinition AtMostOneFunction));
220230
if !stringTypes > 1 then
@@ -244,8 +254,9 @@ let checkInvariant ~isUntaggedDef ~(consts : (Location.t * tag) list)
244254
| Some ObjectType ->
245255
incr objectTypes;
246256
invariant loc name
247-
| Some ArrayType ->
248-
incr arrayTypes;
257+
| Some (InstanceType i) ->
258+
let count = Hashtbl.find_opt instanceTypes i |> Option.value ~default:0 in
259+
Hashtbl.replace instanceTypes i (count + 1);
249260
invariant loc name
250261
| Some FunctionType ->
251262
incr functionTypes;
@@ -298,15 +309,15 @@ module DynamicChecks = struct
298309
| BinOp of op * 'a t * 'a t
299310
| TagType of tag_type
300311
| TypeOf of 'a t
301-
| IsArray of 'a t
312+
| IsInstanceOf of Instance.t * 'a t
302313
| Not of 'a t
303314
| Expr of 'a
304315

305316
let bin op x y = BinOp (op, x, y)
306317
let tag_type t = TagType t
307318
let typeof x = TypeOf x
308319
let str s = String s |> tag_type
309-
let is_array x = IsArray x
320+
let is_instance i x = IsInstanceOf (i, x)
310321
let not x = Not x
311322
let nil = Null |> tag_type
312323
let undefined = Undefined |> tag_type
@@ -348,7 +359,7 @@ module DynamicChecks = struct
348359
typeof e != number
349360
| FloatType when literals_overlaps_with_number () = false ->
350361
typeof e != number
351-
| ArrayType -> not (is_array e)
362+
| InstanceType i -> not (is_instance i e)
352363
| FunctionType -> typeof e != function_
353364
| ObjectType when literals_overlaps_with_object () = false ->
354365
typeof e != object_
@@ -394,13 +405,18 @@ module DynamicChecks = struct
394405
typeof e != object_
395406

396407
let add_runtime_type_check ~tag_type ~(block_cases : block_type list) x y =
397-
let has_array () = Ext_list.exists block_cases (fun t -> t = ArrayType) in
408+
let instances = Ext_list.filter_map block_cases (function InstanceType i -> Some i | _ -> None) in
398409
match tag_type with
399410
| Untagged (IntType | StringType | FloatType | FunctionType) ->
400411
typeof y == x
401412
| Untagged ObjectType ->
402-
if has_array () then typeof y == x &&& not (is_array y) else typeof y == x
403-
| Untagged ArrayType -> is_array y
413+
if instances <> [] then
414+
let not_one_of_the_instances =
415+
Ext_list.fold_right instances (typeof y == x) (fun i x -> x &&& not (is_instance i y)) in
416+
not_one_of_the_instances
417+
else
418+
typeof y == x
419+
| Untagged (InstanceType i) -> is_instance i y
404420
| Untagged UnknownType ->
405421
(* This should not happen because unknown must be the only non-literal case *)
406422
assert false

0 commit comments

Comments
 (0)