Browse Source

[cs] fixes for Std.is check for Float, Int and UInt (closes #2114)

Dan Korostelev 11 years ago
parent
commit
9ed383efe9
2 changed files with 93 additions and 24 deletions
  1. 69 24
      gencs.ml
  2. 24 0
      std/cs/internal/Runtime.hx

+ 69 - 24
gencs.ml

@@ -169,6 +169,11 @@ struct
       | TInst(cl,_) -> cl
       | _ -> assert false
 
+  let get_ab_from_t t =
+    match follow t with
+      | TAbstract(ab,_) -> ab
+      | _ -> assert false
+
   let traverse gen runtime_cl =
     let basic = gen.gcon.basic in
     let uint = match get_type gen ([], "UInt") with | TTypeDecl t -> TType(t, []) | TAbstractDecl a -> TAbstract(a, []) | _ -> assert false in
@@ -193,40 +198,80 @@ struct
               { eexpr = TTypeExpr md; etype = t_dynamic (* this is after all a syntax filter *); epos = e.epos }
             ] ) }
           in
+
+          let mk_or a b =
+            {
+              eexpr = TBinop(Ast.OpBoolOr, a, b);
+              etype = basic.tbool;
+              epos = e.epos
+            }
+          in
+
+          let wrap_if_needed obj f =
+            (* introduce temp variable for complex expressions *)
+            match obj.eexpr with
+              | TLocal(v) -> f obj
+              | _ ->
+                let var = mk_temp gen "is" obj.etype in
+                let added = { obj with eexpr = TVars([var, Some(obj)]); etype = basic.tvoid } in
+                let local = mk_local var obj.epos in
+                {
+                  eexpr = TBlock([ added; f local ]);
+                  etype = basic.tbool;
+                  epos = e.epos
+                }
+          in
+
           let obj = run obj in
           (match follow_module follow md with
-            | TClassDecl{ cl_path = ([], "Float") } ->
+            | TAbstractDecl{ a_path = ([], "Float") } ->
               (* on the special case of seeing if it is a Float, we need to test if both it is a float and if it is an Int *)
               let mk_is local =
-                mk_paren {
-                  eexpr = TBinop(Ast.OpBoolOr, mk_is local md, mk_is local (TClassDecl (get_cl_from_t basic.tint)));
+                (* we check if it float or int or uint *)
+                let eisint = mk_is local (TAbstractDecl (get_ab_from_t basic.tint)) in
+                let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
+                let eisfloat = mk_is local md in
+                mk_paren (mk_or eisfloat (mk_or eisint eisuint))
+              in
+              wrap_if_needed obj mk_is
+
+            | TAbstractDecl{ a_path = ([], "Int") } ->
+              (* int can be stored in double variable because of anonymous functions, check that case *)
+              let mk_isint_call local =
+                {
+                  eexpr = TCall(
+                    mk_static_field_access_infer runtime_cl "isInt" e.epos [],
+                    [ local ]
+                  );
                   etype = basic.tbool;
                   epos = e.epos
                 }
               in
+              let mk_is local =
+                let eisint = mk_is local (TAbstractDecl (get_ab_from_t basic.tint)) in
+                let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
+                mk_paren (mk_or (mk_or eisint eisuint) (mk_isint_call local))
+              in
+              wrap_if_needed obj mk_is
 
-              let ret = match obj.eexpr with
-                | TLocal(v) -> mk_is obj
-                | _ ->
-                  let var = mk_temp gen "is" obj.etype in
-                  let added = { obj with eexpr = TVars([var, Some(obj)]); etype = basic.tvoid } in
-                  let local = mk_local var obj.epos in
-                  {
-                    eexpr = TBlock([ added; mk_is local ]);
-                    etype = basic.tbool;
-                    epos = e.epos
-                  }
+            | TAbstractDecl{ a_path = ([], "UInt") } ->
+              (* uint can be stored in double variable because of anonymous functions, check that case *)
+              let mk_isuint_call local =
+                {
+                  eexpr = TCall(
+                    mk_static_field_access_infer runtime_cl "isUInt" e.epos [],
+                    [ local ]
+                  );
+                  etype = basic.tbool;
+                  epos = e.epos
+                }
               in
-              ret
-            | TClassDecl{ cl_path = ([], "Int") } ->
-              {
-                eexpr = TCall(
-                  mk_static_field_access_infer runtime_cl "isInt" e.epos [],
-                  [ obj ]
-                );
-                etype = basic.tbool;
-                epos = e.epos
-              }
+              let mk_is local =
+                let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
+                mk_paren (mk_or eisuint (mk_isuint_call local))
+              in
+              wrap_if_needed obj mk_is
+
             | _ ->
               mk_is obj md
           )

+ 24 - 0
std/cs/internal/Runtime.hx

@@ -181,6 +181,30 @@ import cs.system.Type;
 		return false;
 	}
 
+	@:functionCode('
+			System.IConvertible cv1 = obj as System.IConvertible;
+			if (cv1 != null)
+			{
+                switch (cv1.GetTypeCode())
+                {
+                    case System.TypeCode.Double:
+                        double d = (double)obj;
+
+				        return d >= uint.MinValue && d <= uint.MaxValue && d == ( (uint)d );
+                    case System.TypeCode.UInt32:
+                        return true;
+                    default:
+                        return false;
+                }
+
+			}
+			return false;
+	')
+	public static function isUInt(obj:Dynamic):Bool
+	{
+		return false;
+	}
+
 	@:functionCode('
 			if (v1 == v2) return 0;
 			if (v1 == null) return -1;