Browse Source

[java/cs] Handle Null<AbstractOfNonNullable> correctly. See #2224

Cauê Waneck 11 years ago
parent
commit
1777dadbdb
3 changed files with 38 additions and 13 deletions
  1. 23 0
      gencommon.ml
  2. 2 1
      gencs.ml
  3. 13 12
      genjava.ml

+ 23 - 0
gencommon.ml

@@ -9565,6 +9565,10 @@ struct
 		(* 	let ret = wrap_val e t b in *)
 		(* 	let ret = wrap_val e t b in *)
 		(* 	{ ret with eexpr = TParenthesis(ret) } *)
 		(* 	{ ret with eexpr = TParenthesis(ret) } *)
 		(* in *)
 		(* in *)
+		let is_string t = match gen.greal_type t with
+			| TInst({ cl_path=([],"String") },_) -> true
+			| _ -> false
+		in
 		let handle_unwrap to_t e =
 		let handle_unwrap to_t e =
 			let e_null_t = get (is_null_t gen e.etype) in
 			let e_null_t = get (is_null_t gen e.etype) in
 			match gen.greal_type to_t with
 			match gen.greal_type to_t with
@@ -9616,6 +9620,9 @@ struct
 					let null_et = is_null_t e.etype in
 					let null_et = is_null_t e.etype in
 					let null_vt = is_null_t v.etype in
 					let null_vt = is_null_t v.etype in
 					(match null_vt, null_et with
 					(match null_vt, null_et with
+						| Some(vt), None when is_string e.etype ->
+							let v = run v in
+							{ e with eexpr = TCast(null_to_dynamic v,None) }
 						| Some(vt), None ->
 						| Some(vt), None ->
 							(match v.eexpr with
 							(match v.eexpr with
 								(* is there an unnecessary cast to Nullable? *)
 								(* is there an unnecessary cast to Nullable? *)
@@ -9720,6 +9727,22 @@ struct
 								| _ ->
 								| _ ->
 									Type.map_expr run e
 									Type.map_expr run e
 							)
 							)
+						| Ast.OpAdd when is_string e1.etype || is_string e2.etype ->
+							let e1 = if is_some e1_t then
+								null_to_dynamic (run e1)
+							else
+								run e1
+							in
+							let e2 = if is_some e2_t then
+								null_to_dynamic (run e2)
+							else
+								run e2
+							in
+							let e_t = is_null_t e.etype in
+							if is_some e_t then
+								wrap_val { eexpr = TBinop(op,e1,e2); etype = get e_t; epos = e.epos } (get e_t) true
+							else
+								{ e with eexpr = TBinop(op,e1,e2) }
 						| _ ->
 						| _ ->
 							let e1 = if is_some e1_t then
 							let e1 = if is_some e1_t then
 								handle_unwrap (get e1_t) (run e1)
 								handle_unwrap (get e1_t) (run e1)

+ 2 - 1
gencs.ml

@@ -779,7 +779,8 @@ let configure gen =
 			| TAbstract ({ a_path = ["cs"],"Out" },_)
 			| TAbstract ({ a_path = ["cs"],"Out" },_)
 			| TType ({ t_path = [],"Single" },[])
 			| TType ({ t_path = [],"Single" },[])
 			| TAbstract ({ a_path = [],"Single" },[]) -> Some t
 			| TAbstract ({ a_path = [],"Single" },[]) -> Some t
-			| TType ({ t_path = [],"Null" },[_]) -> Some t
+			| TType (({ t_path = [],"Null" } as tdef),[t2]) ->
+					Some (TType(tdef,[follow (gen.gfollow#run_f t2)]))
 			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
 					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
 			| TAbstract( { a_path = ([], "EnumValue") }, _	)
 			| TAbstract( { a_path = ([], "EnumValue") }, _	)

+ 13 - 12
genjava.ml

@@ -873,8 +873,10 @@ let configure gen =
 			| TType ({ t_path = ["java"],"Char16" },[])
 			| TType ({ t_path = ["java"],"Char16" },[])
 			| TAbstract ({ a_path = ["java"],"Char16" },[])
 			| TAbstract ({ a_path = ["java"],"Char16" },[])
 			| TType ({ t_path = [],"Single" },[])
 			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[])
-			| TType ({ t_path = [],"Null" },[_]) -> Some t
+			| TAbstract ({ a_path = [],"Single" },[]) ->
+					Some t
+			| TType (({ t_path = [],"Null" } as tdef),[t2]) ->
+					Some (TType(tdef,[gen.gfollow#run_f t2]))
 			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
 					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
 			| TAbstract( { a_path = ([], "EnumValue") }, _ )
 			| TAbstract( { a_path = ([], "EnumValue") }, _ )
@@ -912,7 +914,7 @@ let configure gen =
 			| TInst(c,params) when Meta.has Meta.Enum c.cl_meta ->
 			| TInst(c,params) when Meta.has Meta.Enum c.cl_meta ->
 				TInst(c, List.map (fun _ -> t_dynamic) params)
 				TInst(c, List.map (fun _ -> t_dynamic) params)
 			| TInst _ -> t
 			| TInst _ -> t
-			| TType({ t_path = ([], "Null") }, [t]) when is_java_basic_type t -> t_dynamic
+			| TType({ t_path = ([], "Null") }, [t]) when is_java_basic_type (gen.gfollow#run_f t) -> t_dynamic
 			| TType({ t_path = ([], "Null") }, [t]) ->
 			| TType({ t_path = ([], "Null") }, [t]) ->
 				(match follow t with
 				(match follow t with
 					| TInst( { cl_kind = KTypeParameter _ }, []) ->
 					| TInst( { cl_kind = KTypeParameter _ }, []) ->
@@ -2096,7 +2098,8 @@ let configure gen =
 
 
 	DynamicOperators.configure gen
 	DynamicOperators.configure gen
 		(DynamicOperators.abstract_implementation gen (fun e -> match e.eexpr with
 		(DynamicOperators.abstract_implementation gen (fun e -> match e.eexpr with
-			| TBinop (Ast.OpEq, e1, e2)
+			| TBinop (Ast.OpEq, e1, e2) ->
+				is_dynamic e1.etype || is_dynamic e2.etype || is_type_param e1.etype || is_type_param e2.etype
 			| TBinop (Ast.OpAdd, e1, e2)
 			| TBinop (Ast.OpAdd, e1, e2)
 			| TBinop (Ast.OpNotEq, e1, e2) -> is_dynamic e1.etype || is_dynamic e2.etype || is_type_param e1.etype || is_type_param e2.etype
 			| TBinop (Ast.OpNotEq, e1, e2) -> is_dynamic e1.etype || is_dynamic e2.etype || is_type_param e1.etype || is_type_param e2.etype
 			| TBinop (Ast.OpLt, e1, e2)
 			| TBinop (Ast.OpLt, e1, e2)
@@ -2110,13 +2113,12 @@ let configure gen =
 		(fun e1 e2 ->
 		(fun e1 e2 ->
 			let is_null e = match e.eexpr with | TConst(TNull) | TLocal({ v_name = "__undefined__" }) -> true | _ -> false in
 			let is_null e = match e.eexpr with | TConst(TNull) | TLocal({ v_name = "__undefined__" }) -> true | _ -> false in
 
 
-			if is_null e1 || is_null e2 then
-				match e1.eexpr, e2.eexpr with
-					| TConst c1, TConst c2 ->
-						{ e1 with eexpr = TConst(TBool (c1 = c2)); etype = basic.tbool }
-					| _ ->
-						{ e1 with eexpr = TBinop(Ast.OpEq, e1, e2); etype = basic.tbool }
-			else begin
+			match e1.eexpr, e2.eexpr with
+				| TConst c1, TConst c2 when is_null e1 || is_null e2 ->
+					{ e1 with eexpr = TConst(TBool (c1 = c2)); etype = basic.tbool }
+				| _ when is_null e1 || is_null e2 && not (is_java_basic_type e1.etype || is_java_basic_type e2.etype) ->
+					{ e1 with eexpr = TBinop(Ast.OpEq, e1, e2); etype = basic.tbool }
+				| _ ->
 				let is_ref = match follow e1.etype, follow e2.etype with
 				let is_ref = match follow e1.etype, follow e2.etype with
 					| TDynamic _, _
 					| TDynamic _, _
 					| _, TDynamic _
 					| _, TDynamic _
@@ -2143,7 +2145,6 @@ let configure gen =
 
 
 				let static = mk_static_field_access_infer (runtime_cl) (if is_ref then "refEq" else "eq") e1.epos [] in
 				let static = mk_static_field_access_infer (runtime_cl) (if is_ref then "refEq" else "eq") e1.epos [] in
 				{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tbool; epos=e1.epos }
 				{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tbool; epos=e1.epos }
-			end
 		)
 		)
 		(fun e e1 e2 ->
 		(fun e e1 e2 ->
 			match may_nullable e1.etype, may_nullable e2.etype with
 			match may_nullable e1.etype, may_nullable e2.etype with