소스 검색

rework some stuff

Dan Korostelev 4 년 전
부모
커밋
38b4b8a404
1개의 변경된 파일56개의 추가작업 그리고 53개의 파일을 삭제
  1. 56 53
      src/optimization/analyzerTexprTransformer.ml

+ 56 - 53
src/optimization/analyzerTexprTransformer.ml

@@ -795,11 +795,13 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 		mk (TCall (econtinuation, [make_null t_dynamic p; eerror])) com.basic.tvoid p
 	in
 
-	let exc_cases = ref [] in
+	let states = ref [] in
+
+	let exc_states = ref [] in
 
 	(* TODO: maybe merge this into block_to_texpr somehow, and only introduce new states when there is a suspension point *)
 	print_endline "---";
-	let rec loop ?(exc_state=None) bb state_id back_state_id statecases current_el while_loop =
+	let rec loop ?(exc_state=None) bb state_id back_state_id current_el while_loop =
 		let p = bb.bb_pos in
 		(* TODO: only do this in the end, avoid unnecessary List.rev *)
 		let el = DynArray.to_list bb.bb_el in
@@ -811,14 +813,16 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 
 		let ereturn = mk (TReturn None) com.basic.tvoid p in
 
-		let mk_case el = [make_int com.basic state_id p], mk (TBlock el) com.basic.tvoid p in
+		let add_state el =
+			states := (state_id,mk (TBlock el) com.basic.tvoid null_pos) :: !states
+		in
 		let get_cond_branch () = match bb.bb_terminator with TermCondBranch e -> e | _ -> die "" __LOC__ in
 
 		match bb.bb_syntax_edge with
 		| SESuspend (call, bb_next) ->
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "suspend cur:%d,next:%d,back:%d" state_id next_state_id back_state_id);
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
+			loop bb_next next_state_id back_state_id [] while_loop;
 			let args = call.args @ [ estatemachine ] in
 
 			(* lose Coroutine<T> type for the called function not to confuse further filters and generators *)
@@ -834,7 +838,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 			let ecreatecoroutine = mk (TCall (efun, args)) tcoroutine call.pos in
 			let ecallcoroutine = mk (TCall (ecreatecoroutine, [make_null t_dynamic p])) com.basic.tvoid call.pos in
 			let esetstate = set_state next_state_id in
-			mk_case (current_el @ el @ [esetstate; ecallcoroutine; ereturn]) :: statecases
+			add_state (current_el @ el @ [esetstate; ecallcoroutine; ereturn])
 
 		| SENone ->
 			print_endline (Printf.sprintf "none cur:%d,back:%d" state_id back_state_id);
@@ -842,11 +846,11 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 			| TermBreak _ -> (* todo use pos *)
 				let _,next_state_id = Option.get while_loop in
 				let esetstate = set_state next_state_id in
-				mk_case (current_el @ el @ [esetstate]) :: statecases
+				add_state (current_el @ el @ [esetstate])
 			| TermContinue _ -> (* todo use pos *)
 				let body_state_id,_ = Option.get while_loop in
 				let esetstate = set_state body_state_id in
-				mk_case (current_el @ el @ [esetstate]) :: statecases
+				add_state (current_el @ el @ [esetstate])
 			| TermReturn _ | TermReturnValue _ -> (* todo use pos *)
 				let esetstate = set_state (-1) in
 				let eresult = match bb.bb_terminator with
@@ -854,40 +858,40 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 					| _ -> make_null t_dynamic p
 				in
 				let ecallcontinuation = mk_continuation_call eresult p in
-				mk_case (current_el @ el @ [esetstate; ecallcontinuation; ereturn]) :: statecases
+				add_state (current_el @ el @ [esetstate; ecallcontinuation; ereturn])
 			| TermNone when back_state_id = -1 ->
 				let esetstate = set_state (-1) in
 				let ecallcontinuation = mk_continuation_call (make_null t_dynamic p) p in
-				mk_case (current_el @ el @ [esetstate; ecallcontinuation; ereturn]) :: statecases
+				add_state (current_el @ el @ [esetstate; ecallcontinuation; ereturn])
 			| TermNone ->
-				mk_case (current_el @ el @ [set_state back_state_id]) :: statecases
+				add_state (current_el @ el @ [set_state back_state_id])
 			| TermThrow (e,p) ->
 				let ethrow = mk (TThrow e) t_dynamic p in
-				mk_case (current_el @ el @ [ethrow]) :: statecases
+				add_state (current_el @ el @ [ethrow])
 			| TermCondBranch _ ->
 				die "unexpected TermCondBranch" __LOC__)
 
 		| SEMerge bb_next ->
 			print_endline (Printf.sprintf "merge cur:%d,back:%d" state_id back_state_id);
-			loop bb_next state_id back_state_id statecases (current_el @ el) while_loop
+			loop bb_next state_id back_state_id (current_el @ el) while_loop
 
 		| SESubBlock (bb_sub,bb_next) ->
 			let sub_state_id = get_next_state_id () in
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "sub cur:%d,sub:%d,next:%d,back:%d" state_id sub_state_id next_state_id back_state_id);
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
-			let statecases = loop bb_sub sub_state_id next_state_id statecases [] while_loop in
-			mk_case (current_el @ el @ [set_state sub_state_id]) :: statecases
+			loop bb_next next_state_id back_state_id [] while_loop;
+			loop bb_sub sub_state_id next_state_id [] while_loop;
+			add_state (current_el @ el @ [set_state sub_state_id])
 
 		| SEIfThen (bb_then,bb_next,p) ->
 			let econd = get_cond_branch () in
 			let then_state_id = get_next_state_id () in
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "if-then cur:%d,then:%d,next:%d,back:%d" state_id then_state_id next_state_id back_state_id);
-			let statecases = loop bb_then then_state_id next_state_id statecases [] while_loop in
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
+			loop bb_then then_state_id next_state_id [] while_loop;
+			loop bb_next next_state_id back_state_id [] while_loop;
 			let eif = mk (TIf (econd, set_state then_state_id, Some (set_state next_state_id))) com.basic.tint p in
-			mk_case (current_el @ el @ [eif]) :: statecases
+			add_state (current_el @ el @ [eif])
 
 		| SEIfThenElse (bb_then,bb_else,bb_next,t,p) ->
 			let econd = get_cond_branch () in
@@ -895,36 +899,35 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 			let else_state_id = get_next_state_id () in
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "if-then-else cur:%d,then:%d,else:%d,next:%d,back:%d" state_id then_state_id else_state_id next_state_id back_state_id);
-			let statecases = loop bb_then then_state_id next_state_id statecases [] while_loop in
-			let statecases = loop bb_else else_state_id next_state_id statecases [] while_loop in
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
+			loop bb_then then_state_id next_state_id [] while_loop;
+			loop bb_else else_state_id next_state_id [] while_loop;
+			loop bb_next next_state_id back_state_id [] while_loop;
 			let eif = mk (TIf (econd, set_state then_state_id, Some (set_state else_state_id))) com.basic.tint p in
-			mk_case (current_el @ el @ [eif]) :: statecases
+			add_state (current_el @ el @ [eif])
 
 		| SESwitch (cases,bb_default,bb_next,p) ->
 			let esubj = get_cond_branch () in
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "switch cur:%d,next:%d,back:%d" state_id next_state_id back_state_id);
-			let statecases = ref statecases in
 			let ecases = List.map (fun (patterns,bb) ->
 				(* TODO: variable capture and other fancy things O_o *)
 				let case_state_id = get_next_state_id () in
 				print_endline (Printf.sprintf "  case %d" case_state_id);
-				statecases := loop bb case_state_id next_state_id !statecases [] while_loop;
+				loop bb case_state_id next_state_id [] while_loop;
 				patterns, set_state case_state_id
 			) cases in
 			let default_state_id = match bb_default with
 				| Some bb ->
 					let default_state_id = get_next_state_id () in
-					statecases := loop bb default_state_id next_state_id !statecases [] while_loop;
+					loop bb default_state_id next_state_id [] while_loop;
 					default_state_id
 				| None ->
 					next_state_id
 			in
 			print_endline (Printf.sprintf "  default %d" default_state_id);
 			let eswitch = mk (TSwitch (esubj,ecases,Some (set_state default_state_id))) com.basic.tvoid p in
-			let statecases = loop bb_next next_state_id back_state_id !statecases [] while_loop in
-			mk_case (current_el @ el @ [eswitch]) :: statecases
+			loop bb_next next_state_id back_state_id [] while_loop;
+			add_state (current_el @ el @ [eswitch])
 
 		| SEWhile (bb_body, bb_next, p) ->
 			let body_state_id = get_next_state_id () in
@@ -932,16 +935,16 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 			print_endline (Printf.sprintf "while cur:%d,body:%d,next:%d,back:%d" state_id body_state_id next_state_id back_state_id);
 			let new_while_loop = Some (body_state_id,next_state_id) in
 			(* TODO: next is empty? *)
-			let statecases = loop bb_body body_state_id body_state_id statecases [] new_while_loop in
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
-			mk_case (current_el @ el @ [set_state body_state_id]) :: statecases
+			loop bb_body body_state_id body_state_id [] new_while_loop;
+			loop bb_next next_state_id back_state_id [] while_loop;
+			add_state (current_el @ el @ [set_state body_state_id]);
 
 		| SETry (bb_try,_,catches,bb_next,p) ->
 			let try_state_id = get_next_state_id () in
 			let new_exc_state_id = get_next_state_id () in
 			let next_state_id = get_next_state_id () in
 			print_endline (Printf.sprintf "try cur:%d,try:%d,catch:%d,next:%d,back:%d" state_id try_state_id new_exc_state_id next_state_id back_state_id);
-			let statecases = loop bb_try try_state_id next_state_id statecases [] while_loop ~exc_state:(Some new_exc_state_id) in
+			loop bb_try try_state_id next_state_id [] while_loop ~exc_state:(Some new_exc_state_id);
 			let catch_case =
 				let erethrow = mk (TThrow eerror) t_dynamic null_pos in
 (* 				let eif = List.fold_left (fun acc (v,bb) ->
@@ -950,18 +953,22 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 				let eif = erethrow in
 				(new_exc_state_id, eif)
 			in
-			exc_cases := catch_case :: !exc_cases;
-			let statecases = loop bb_next next_state_id back_state_id statecases [] while_loop in
-			mk_case (current_el @ el @ [set_state try_state_id]) :: statecases
+			exc_states := catch_case :: !exc_states;
+			loop bb_next next_state_id back_state_id [] while_loop;
+			add_state (current_el @ el @ [set_state try_state_id])
 	in
-	let statecases = loop bb (get_next_state_id ()) (-1) [] [] None in
+	loop bb (get_next_state_id ()) (-1) [] None;
 
 	let rethrow_state_id = get_next_state_id () in
-	let statecases = statecases @ List.map (fun (id, e) ->
-		let epattern = mk_int id in
-		let ebody = mk (TBlock [set_excstate rethrow_state_id; e]) com.basic.tvoid null_pos in
-		([epattern],ebody)
-	) !exc_cases in
+
+	(* prepend setting exceptionState to the rethrow one *)
+	let exc_states =
+		List.map (fun (id, e) ->
+			id, mk (TBlock [set_excstate rethrow_state_id; e]) com.basic.tvoid null_pos
+		) !exc_states
+	in
+
+	let states = !states @ exc_states in
 
 	(* TODO: this (and the coroutine transform in general) should probably be run before captured vars handling *)
 	(* very ugly, but seems to work: extract locals that are used across states *)
@@ -977,11 +984,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 			in
 			Hashtbl.replace m state_id true
 		in
-		List.iter (fun (patterns, expr) ->
-			let state_id = match patterns with
-				| [{eexpr = TConst (TInt state_id)}] -> state_id
-				| _ -> die "" __LOC__ (* TODO: use proper data structure :) *)
-			in
+		List.iter (fun (state_id, expr) ->
 			let rec loop e =
 				match e.eexpr with
 				| TVar (v, eo) ->
@@ -993,16 +996,16 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 					Type.iter loop e
 			in
 			loop expr
-		) statecases;
+		) states;
 	end;
-	let statecases, decls = begin
+	let states, decls = begin
 		let is_used_across_states v_id =
 			let m = Hashtbl.find var_usages v_id in
 			(Hashtbl.length m) > 1
 		in
 		let rec loop cases cases_acc decls =
 			match cases with
-			| (patterns,expr) :: rest ->
+			| (id,expr) :: rest ->
 				let decls = ref decls in
 				let expr = begin
 					let rec loop e =
@@ -1018,11 +1021,11 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 					in
 					loop expr
 				end in
-				loop rest ((patterns,expr) :: cases_acc) !decls
+				loop rest ((id,expr) :: cases_acc) !decls
 			| [] ->
 				List.rev cases_acc, decls
 		in
-		loop statecases [] []
+		loop states [] []
 	end in
 
 	(* TODO:
@@ -1030,8 +1033,8 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 		 - if there's only one state (no suspensions) - don't wrap into while/switch, don't introduce state var
 	*)
 
-	let rethrow_case = ([mk_int rethrow_state_id], mk (TThrow eerror) com.basic.tvoid null_pos) in
-	let statecases = statecases @ [rethrow_case] in
+	let rethrow_state = (rethrow_state_id, mk (TThrow eerror) com.basic.tvoid null_pos) in
+	let states = states @ [rethrow_state] in
 
 	let ethrow = mk (TBlock [
 		set_state rethrow_state_id;
@@ -1039,7 +1042,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
 	]) com.basic.tvoid null_pos
 	in
 
-	let eswitch = mk (TSwitch (estate, statecases, Some ethrow)) com.basic.tvoid p in
+	let eswitch = mk (TSwitch (estate, List.map (fun (id,e) -> [mk_int id], e) states, Some ethrow)) com.basic.tvoid p in
 
 	let etry = mk (TTry (
 		eswitch,