Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[js] optimize Std.is for common types #2543

Merged
merged 1 commit into from
Jan 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[js] optimize Std.is for common types
  • Loading branch information
nadako committed Jan 18, 2014
commit dd8c8be1c4f9abd428cb7b77759bc86ea0f393cf
18 changes: 18 additions & 0 deletions genjs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,24 @@ let rec gen_call ctx e el in_value =
print ctx " instanceof ";
gen_value ctx t;
spr ctx ")";
| TLocal { v_name = "__typeof__" }, [o] ->
spr ctx "typeof(";
gen_value ctx o;
spr ctx ")";
| TLocal { v_name = "__strict_eq__" } , [x;y] ->
(* add extra parenthesis here because of operator precedence *)
spr ctx "((";
gen_value ctx x;
spr ctx ") === ";
gen_value ctx y;
spr ctx ")";
| TLocal { v_name = "__strict_neq__" } , [x;y] ->
(* add extra parenthesis here because of operator precedence *)
spr ctx "((";
gen_value ctx x;
spr ctx ") !== ";
gen_value ctx y;
spr ctx ")";
| TLocal ({v_name = "__define_feature__"}), [_;e] ->
gen_expr ctx e
| TLocal { v_name = "__feature__" }, { eexpr = TConst (TString f) } :: eif :: eelse ->
Expand Down
39 changes: 39 additions & 0 deletions optimizer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,45 @@ let api_inline ctx c field params p =
Some stringv
| _ ->
None)
| ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js ->
let mk_local ctx n t pos = mk (TLocal (try PMap.find n ctx.locals with _ -> add_local ctx n t)) t pos in

let tstring = ctx.com.basic.tstring in
let tbool = ctx.com.basic.tbool in
let tint = ctx.com.basic.tint in

let is_trivial e =
match e.eexpr with
| TConst _ | TLocal _ -> true
| _ -> false
in

let typeof t =
let tof = mk_local ctx "__typeof__" (tfun [o.etype] tstring) p in
let tof = mk (TCall (tof, [o])) tstring p in
mk (TBinop (Ast.OpEq, tof, (mk (TConst (TString t)) tstring p))) tbool p
in

(match t.eexpr with
(* generate simple typeof checks for basic types *)
| TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> Some (typeof "string")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number")
| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o ->
(* generate (o|0) === o check *)
let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in
let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in
Some (mk (TCall (teq, [lhs; o])) tbool p)
| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
(* generate (o instanceof Array) && o.__enum__ == null check *)
let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in
let iof = mk (TCall (iof, [o; t])) tbool p in
let enum = mk (TField (o, FDynamic "__enum__")) (mk_mono()) p in
let null = mk (TConst TNull) (mk_mono()) p in
let not_enum = mk (TBinop (Ast.OpEq, enum, null)) tbool p in
Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p)
| _ ->
None)
| ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] ->
let f = float_of_string f in
(match classify_float f with
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/unitstd/Std.unit.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Std.is(unknown, String) == false;
Std.is(null, String) == false;
Std.is("foo", null) == false;

Std.is("", String) == true;
Std.is(false, Bool) == true;
Std.is(1, Int) == true;
Std.is(1.5, Int) == false;
Std.is(1.5, Float) == true;
Std.is([], Array) == true;
Std.is(unit.MyEnum.A, Array) == false;

// instance
#if !js
Std.instance("", String) == "";
Expand Down