Browse Source

deal with EDisplay nodes in EFor

Simon Krajewski 9 years ago
parent
commit
2cbb904acd
1 changed files with 39 additions and 34 deletions
  1. 39 34
      src/typing/typer.ml

+ 39 - 34
src/typing/typer.ml

@@ -3503,50 +3503,55 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EVars vl ->
 		type_vars ctx vl p
 	| EFor (it,e2) ->
-		let i, pi, e1 = (match it with
-			| (EIn ((EConst (Ident i),pi),e),_) -> i, pi, e
+		let rec loop_ident display e1 = match e1 with
+			| EConst(Ident i),p -> i,p,display
+			| EDisplay(e1,_),_ -> loop_ident true e1
+			| _ -> error "Identifier expected" (pos e1)
+		in
+		let rec loop display e1 = match fst e1 with
+			| EIn(e1,e2) -> loop_ident display e1,e2
+			| EDisplay(e1,_) -> loop true e1
 			| _ -> error "For expression should be 'v in expr'" (snd it)
-		) in
+		in
+		let (i, pi, display), e1 = loop false it in
 		let e1 = type_expr ctx e1 Value in
 		let old_loop = ctx.in_loop in
 		let old_locals = save_locals ctx in
 		ctx.in_loop <- true;
 		let e2 = Expr.ensure_block e2 in
-		let e = if ctx.com.display <> DMNone then begin
-			(* Don't be fancy in display mode because there's no point. *)
+		let default() =
 			let t, pt = Typeload.t_iterator ctx in
 			let i = add_local ctx i pt pi in
-			unify ctx e1.etype t e1.epos;
+			let e1 = (match follow e1.etype with
+			| TMono _
+			| TDynamic _ ->
+				display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e1.epos;
+				e1
+			| TLazy _ ->
+				assert false
+			| _ ->
+				(try
+					Codegen.AbstractCast.cast_or_unify_raise ctx t e1 p
+				with Error (Unify _,_) ->
+					let acc = build_call ctx (type_field ctx e1 "iterator" e1.epos MCall) [] Value e1.epos in
+					try
+						unify_raise ctx acc.etype t acc.epos;
+						acc
+					with Error (Unify(l),p) ->
+						display_error ctx "Field iterator has an invalid type" acc.epos;
+						display_error ctx (error_msg (Unify l)) p;
+						mk (TConst TNull) t_dynamic p
+				)
+			) in
+			if display then ignore(handle_display ctx (EConst(Ident i.v_name),i.v_pos) false (WithType i.v_type) i.v_pos);
 			let e2 = type_expr ctx e2 NoValue in
-			mk (TFor (i,e1,e2)) ctx.t.tvoid p
-		end else (match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with
+			(try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p)
+		in
+		let e = if ctx.com.display <> DMNone then
+			default()
+		else (match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with
 			| Some e -> e
-			| None ->
-				let t, pt = Typeload.t_iterator ctx in
-				let i = add_local ctx i pt pi in
-				let e1 = (match follow e1.etype with
-				| TMono _
-				| TDynamic _ ->
-					display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e1.epos;
-					e1
-				| TLazy _ ->
-					assert false
-				| _ ->
-					(try
-						Codegen.AbstractCast.cast_or_unify_raise ctx t e1 p
-					with Error (Unify _,_) ->
-						let acc = build_call ctx (type_field ctx e1 "iterator" e1.epos MCall) [] Value e1.epos in
-						try
-							unify_raise ctx acc.etype t acc.epos;
-							acc
-						with Error (Unify(l),p) ->
-							display_error ctx "Field iterator has an invalid type" acc.epos;
-							display_error ctx (error_msg (Unify l)) p;
-							mk (TConst TNull) t_dynamic p
-					)
-				) in
-				let e2 = type_expr ctx e2 NoValue in
-				(try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p)
+			| None -> default()
 		) in
 		ctx.in_loop <- old_loop;
 		old_locals();