浏览代码

inline next/hasNext methods in for/in if hasNext is inline (fixed issue #114)

Nicolas Cannasse 13 年之前
父节点
当前提交
0dd97dcc0a
共有 1 个文件被更改,包括 20 次插入2 次删除
  1. 20 2
      typer.ml

+ 20 - 2
typer.ml

@@ -1977,14 +1977,32 @@ and type_expr ctx ?(need_val=true) (e,p) =
 						match follow acc.etype with
 						| TFun ([],it) ->
 							unify ctx it t e1.epos;
-							make_call ctx acc [] t e1.epos
+							make_call ctx acc [] it e1.epos
 						| _ ->
 							display_error ctx "The field iterator is not a method" e1.epos;
 							mk (TConst TNull) t_dynamic p
 					)
 				) in
 				let e2 = type_expr ~need_val:false ctx e2 in
-				mk (TFor (i,e1,e2)) ctx.t.tvoid p
+				(* can we inline hasNext() ? *)
+				(try
+					let c,pl = (match follow e1.etype with TInst (c,pl) -> c,pl | _ -> raise Exit) in
+					let ft, fhasnext = (try class_field ctx c pl "hasNext" p with Not_found -> raise Exit) in
+					if fhasnext.cf_kind <> Method MethInline then raise Exit;
+					let tmp = gen_local ctx e1.etype in
+					let eit = mk (TLocal tmp) e1.etype p in
+					let ehasnext = make_call ctx (mk (TField (eit,"hasNext")) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in
+					let enext = mk (TVars [i,Some (make_call ctx (mk (TField (eit,"next")) (TFun ([],pt)) p) [] pt p)]) ctx.t.tvoid p in
+					let eblock = (match e2.eexpr with
+						| TBlock el -> { e2 with eexpr = TBlock (enext :: el) }
+						| _ -> mk (TBlock [enext;e2]) ctx.t.tvoid p
+					) in
+					mk (TBlock [
+						mk (TVars [tmp,Some e1]) ctx.t.tvoid p;
+						mk (TWhile (ehasnext,eblock,NormalWhile)) ctx.t.tvoid p
+					]) ctx.t.tvoid p
+				with Exit ->
+					mk (TFor (i,e1,e2)) ctx.t.tvoid p)
 		) in
 		ctx.in_loop <- old_loop;
 		old_locals();