Browse Source

[gencommon] cleanup InitFunction a bit

Dan Korostelev 8 years ago
parent
commit
356111e355
1 changed files with 138 additions and 137 deletions
  1. 138 137
      src/generators/gencommon/initFunction.ml

+ 138 - 137
src/generators/gencommon/initFunction.ml

@@ -34,7 +34,8 @@ open Gencommon
 *)
 
 let ensure_simple_expr com e =
-	let rec iter e = match e.eexpr with
+	let rec iter e =
+		match e.eexpr with
 		| TConst _ | TLocal _ | TArray _ | TBinop _
 		| TField _ | TTypeExpr _ | TParenthesis _ | TCast _ | TMeta _
 		| TCall _ | TNew _ | TUnop _ ->
@@ -53,17 +54,14 @@ let handle_override_dynfun acc e this field =
 
 	let rec loop e =
 		match e.eexpr with
-			| TField({ eexpr = TConst(TSuper) }, f) ->
-				let n = field_name f in
-				(if n <> field then assert false);
-				let local = mk_local v e.epos in
-				(match !add_expr with
-					| None ->
-						add_expr := Some { e with eexpr = TVar(v, Some this) }
-					| Some _ -> ());
-				local
-			| TConst TSuper -> assert false
-			| _ -> Type.map_expr loop e
+		| TField ({ eexpr = TConst TSuper }, f) ->
+			let n = field_name f in
+			if n <> field then assert false;
+			if Option.is_none !add_expr then
+				add_expr := Some { e with eexpr = TVar(v, Some this) };
+			mk_local v e.epos
+		| TConst TSuper -> assert false
+		| _ -> Type.map_expr loop e
 	in
 	let e = loop e in
 
@@ -81,154 +79,157 @@ let handle_class com cl =
 			| Var v when Meta.has Meta.ReadOnly cf.cf_meta ->
 					if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then com.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos;
 					(match cf.cf_expr with
-						| None -> com.warning "Uninitialized readonly variable" cf.cf_pos; acc
-						| Some e -> ensure_simple_expr com e; acc)
+					| None -> com.warning "Uninitialized readonly variable" cf.cf_pos
+					| Some e -> ensure_simple_expr com e);
+					acc
 			| Var _
 			| Method MethDynamic when not (Type.is_extern_field cf) ->
 				(match cf.cf_expr with
-					| Some e ->
-						(match cf.cf_params with
-							| [] ->
-								let var = { eexpr = TField(ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf)); etype = cf.cf_type; epos = cf.cf_pos } in
-								let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in
-								cf.cf_expr <- None;
-
-								ret :: acc
-							| _ ->
-								let params = List.map (fun _ -> t_dynamic) cf.cf_params in
-								let fn = apply_params cf.cf_params params in
-								let var = { eexpr = TField(ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf)); etype = fn cf.cf_type; epos = cf.cf_pos } in
-								let rec change_expr e =
-									Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e
-								in
-
-								let ret = ({ eexpr = TBinop(Ast.OpAssign, var, change_expr e); etype = fn cf.cf_type; epos = cf.cf_pos; }) in
-								cf.cf_expr <- None;
-								ret :: acc
-						)
-					| None -> acc)
+				| Some e ->
+					(match cf.cf_params with
+					| [] ->
+						let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in
+						let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
+						cf.cf_expr <- None;
+						ret :: acc
+					| _ ->
+						let params = List.map (fun _ -> t_dynamic) cf.cf_params in
+						let fn = apply_params cf.cf_params params in
+						let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in
+						let rec change_expr e =
+							Type.map_expr_type change_expr fn (fun v -> v.v_type <- fn v.v_type; v) e
+						in
+						let ret = binop Ast.OpAssign var (change_expr e) (fn cf.cf_type) cf.cf_pos in
+						cf.cf_expr <- None;
+						ret :: acc)
+				| None -> acc)
 			| _ -> acc
-	) init cl.cl_ordered_statics
-	in
+	) init cl.cl_ordered_statics in
 	let init = List.rev init in
 	(match init with
-		| [] -> cl.cl_init <- None
-		| _ -> cl.cl_init <- Some { eexpr = TBlock(init); epos = cl.cl_pos; etype = com.basic.tvoid; });
+	| [] -> cl.cl_init <- None
+	| _ -> cl.cl_init <- Some (mk (TBlock init) com.basic.tvoid cl.cl_pos));
 
 	(* FIXME: find a way to tell OverloadingConstructor to execute this code even with empty constructors *)
 	let vars, funs = List.fold_left (fun (acc_vars,acc_funs) cf ->
 		match cf.cf_kind with
-			| Var v when Meta.has Meta.ReadOnly cf.cf_meta ->
-					if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then com.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos;
-					(match cf.cf_expr with
-						| None -> (acc_vars,acc_funs)
-						| Some e -> ensure_simple_expr com e; (acc_vars,acc_funs))
-			| Var _
-			| Method MethDynamic ->
-				let is_var = match cf.cf_kind with | Var _ -> true | _ -> false in
-				(match cf.cf_expr, cf.cf_params with
-					| Some e, [] ->
-						let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
-						let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in
-						cf.cf_expr <- None;
-						let is_override = List.memq cf cl.cl_overrides in
-
-						if is_override then begin
-							cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
-							cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-							acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
-						end else if is_var then
-							ret :: acc_vars, acc_funs
-						else
-							acc_vars, ret :: acc_funs
-					| Some e, _ ->
-						let params = List.map (fun _ -> t_dynamic) cf.cf_params in
-						let fn = apply_params cf.cf_params params in
-						let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in
-						let rec change_expr e =
-							Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e
-						in
+		| Var v when Meta.has Meta.ReadOnly cf.cf_meta ->
+				if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then com.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos;
+				Option.may (ensure_simple_expr com) cf.cf_expr;
+				(acc_vars,acc_funs)
+		| Var _
+		| Method MethDynamic ->
+			let is_var = match cf.cf_kind with Var _ -> true | _ -> false in
+			(match cf.cf_expr, cf.cf_params with
+			| Some e, [] ->
+				let var = mk (TField ((mk (TConst TThis) (TInst (cl, List.map snd cl.cl_params)) cf.cf_pos), FInstance(cl, List.map snd cl.cl_params, cf))) cf.cf_type cf.cf_pos in
+				let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
+				cf.cf_expr <- None;
+				let is_override = List.memq cf cl.cl_overrides in
+
+				if is_override then begin
+					cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
+					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
+					acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
+				end else if is_var then
+					ret :: acc_vars, acc_funs
+				else
+					acc_vars, ret :: acc_funs
+			| Some e, _ ->
+				let params = List.map (fun _ -> t_dynamic) cf.cf_params in
+				let fn = apply_params cf.cf_params params in
+				let var = mk (TField ((mk (TConst TThis) (TInst (cl, List.map snd cl.cl_params)) cf.cf_pos), FInstance(cl, List.map snd cl.cl_params, cf))) cf.cf_type cf.cf_pos in
+				let rec change_expr e =
+					Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e
+				in
 
-						let ret = ({ eexpr = TBinop(Ast.OpAssign, var, change_expr e); etype = fn cf.cf_type; epos = cf.cf_pos; }) in
-						cf.cf_expr <- None;
-						let is_override = List.memq cf cl.cl_overrides in
-
-						if is_override then begin
-							cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
-							cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-							acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
-						end else if is_var then
-							ret :: acc_vars, acc_funs
-						else
-							acc_vars, ret :: acc_funs
-					| None, _ -> acc_vars,acc_funs)
-			| _ -> acc_vars,acc_funs
+				let ret = binop Ast.OpAssign var (change_expr e) (fn cf.cf_type) cf.cf_pos in
+				cf.cf_expr <- None;
+				let is_override = List.memq cf cl.cl_overrides in
+
+				if is_override then begin
+					cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
+					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
+					acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
+				end else if is_var then
+					ret :: acc_vars, acc_funs
+				else
+					acc_vars, ret :: acc_funs
+			| None, _ -> acc_vars,acc_funs)
+		| _ -> acc_vars,acc_funs
 	) ([],[]) cl.cl_ordered_fields
 	in
 	(* let vars = List.rev vars in *)
 	(* let funs = List.rev funs in *)
 	(* see if there is any *)
 	(match vars, funs with
-		| [], [] -> ()
-		| _ ->
-			(* if there is, we need to find the constructor *)
-			let ctors = match cl.cl_constructor with
-			| Some ctor -> ctor
-			| None -> try
-				let sctor, sup, stl = OverloadingConstructor.prev_ctor cl (List.map snd cl.cl_params) in
-				let ctor = OverloadingConstructor.clone_ctors com sctor sup stl cl in
-				cl.cl_constructor <- Some ctor;
+	| [], [] -> ()
+	| _ ->
+		(* if there is, we need to find the constructor *)
+		let ctors =
+			match cl.cl_constructor with
+			| Some ctor ->
 				ctor
-			with | Not_found ->
-				let ctor = mk_class_field "new" (TFun([], com.basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in
-				ctor.cf_expr <- Some
-				{
-					eexpr = TFunction {
-						tf_args = [];
-						tf_type = com.basic.tvoid;
-						tf_expr = { eexpr = TBlock[]; etype = com.basic.tvoid; epos = cl.cl_pos };
+			| None ->
+				try
+					let sctor, sup, stl = OverloadingConstructor.prev_ctor cl (List.map snd cl.cl_params) in
+					let ctor = OverloadingConstructor.clone_ctors com sctor sup stl cl in
+					cl.cl_constructor <- Some ctor;
+					ctor
+				with Not_found ->
+					let ctor = mk_class_field "new" (TFun([], com.basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in
+					ctor.cf_expr <- Some
+					{
+						eexpr = TFunction {
+							tf_args = [];
+							tf_type = com.basic.tvoid;
+							tf_expr = { eexpr = TBlock[]; etype = com.basic.tvoid; epos = cl.cl_pos };
+						};
+						etype = ctor.cf_type;
+						epos = ctor.cf_pos;
 					};
-					etype = ctor.cf_type;
-					epos = ctor.cf_pos;
-				};
-				cl.cl_constructor <- Some ctor;
-				ctor
-			in
-
-			let process ctor =
-				let func = match ctor.cf_expr with
-					| Some({eexpr = TFunction(tf)} as e) ->
-						let rec add_fn e = match e.eexpr with
-							| TBlock(hd :: tl) -> (match hd.eexpr with
-								| TCall({ eexpr = TConst TSuper }, _) ->
-									if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then
-										{ e with eexpr = TBlock(vars @ (hd :: (funs @ tl))) }
-									else
-										{ e with eexpr = TBlock(hd :: (vars @ funs @ tl)) }
-								| TBlock(_) ->
-									{ e with eexpr = TBlock( (add_fn hd) :: tl ) }
-								| _ ->
-									{ e with eexpr = TBlock( vars @ funs @ (hd :: tl) ) })
-							| _ -> Type.concat { e with eexpr = TBlock(vars @ funs) } e
-						in
-						let tf_expr = add_fn (mk_block tf.tf_expr) in
-						{ e with eexpr = TFunction({ tf with tf_expr = tf_expr }) }
-					| _ -> assert false
-				in
-				ctor.cf_expr <- Some(func)
+					cl.cl_constructor <- Some ctor;
+					ctor
+		in
+		let process ctor =
+			let func =
+				match ctor.cf_expr with
+				| Some ({ eexpr = TFunction tf } as e) ->
+					let rec add_fn e =
+						match e.eexpr with
+						| TBlock(hd :: tl) ->
+							(match hd.eexpr with
+							| TCall ({ eexpr = TConst TSuper }, _) ->
+								if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then
+									{ e with eexpr = TBlock (vars @ (hd :: (funs @ tl))) }
+								else
+									{ e with eexpr = TBlock (hd :: (vars @ funs @ tl)) }
+							| TBlock _ ->
+								{ e with eexpr = TBlock ((add_fn hd) :: tl) }
+							| _ ->
+								{ e with eexpr = TBlock (vars @ funs @ (hd :: tl)) })
+						| _ ->
+							Type.concat { e with eexpr = TBlock (vars @ funs) } e
+					in
+					let tf_expr = add_fn (mk_block tf.tf_expr) in
+					{ e with eexpr = TFunction { tf with tf_expr = tf_expr } }
+				| _ ->
+					assert false
 			in
-			List.iter process (ctors :: ctors.cf_overloads)
+			ctor.cf_expr <- Some func
+		in
+		List.iter process (ctors :: ctors.cf_overloads)
 	)
 
+let mod_filter com md =
+	match md with
+	| TClassDecl cl when not cl.cl_extern ->
+		handle_class com cl
+	| _ -> ()
+
 let name = "init_funcs"
 let priority = solve_deps name [DBefore OverloadingConstructor.priority]
 
 let configure gen =
-	let mod_filter md =
-		(match md with
-		| TClassDecl cl when not cl.cl_extern ->
-			handle_class gen.gcon cl
-		| _ -> ());
-		md
-	in
-	gen.gmodule_filters#add name (PCustom priority) mod_filter
+	let run = (fun md -> mod_filter gen.gcon md; md) in
+	gen.gmodule_filters#add name (PCustom priority) run