浏览代码

fixed while...switch...break bug.

Nicolas Cannasse 19 年之前
父节点
当前提交
c8340c286c
共有 1 个文件被更改,包括 37 次插入3 次删除
  1. 37 3
      genjs.ml

+ 37 - 3
genjs.ml

@@ -26,6 +26,7 @@ type ctx = {
 	mutable inits : texpr list;
 	mutable tabs : string;
 	mutable in_value : bool;
+	mutable handle_break : bool;
 }
 
 let s_path = function
@@ -48,7 +49,7 @@ let field s = if Hashtbl.mem kwds s then "[\"" ^ s ^ "\"]" else "." ^ s
 let ident s = if Hashtbl.mem kwds s then "$" ^ s else s
 
 let spr ctx s = Buffer.add_string ctx.buf s
-let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
+let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)			
 
 let unsupported p = 
 	raise (Typer.Error (Typer.Custom "This expression cannot be compiled to Javascript",p))
@@ -81,6 +82,32 @@ let open_block ctx =
 	ctx.tabs <- "\t" ^ ctx.tabs;
 	(fun() -> ctx.tabs <- oldt)
 
+let rec iter_switch_break in_switch e =	
+	match e.eexpr with
+	| TFunction _ | TWhile _ | TFor _ -> ()
+	| TSwitch _ | TMatch _ when not in_switch -> iter_switch_break true e
+	| TBreak when in_switch -> raise Exit
+	| _ -> iter (iter_switch_break in_switch) e
+
+let handle_break ctx e =
+	let old_handle = ctx.handle_break in
+	try
+		iter_switch_break false e;
+		ctx.handle_break <- false;
+		(fun() -> ctx.handle_break <- old_handle)
+	with
+		Exit ->
+			spr ctx "try {";
+			let b = open_block ctx in
+			newline ctx;
+			ctx.handle_break <- true;
+			(fun() ->
+				b();
+				ctx.handle_break <- old_handle;
+				newline ctx;
+				spr ctx "} catch( e ) { if( e != \"__break__\" ) throw e; }";
+			)
+
 let this ctx = if ctx.in_value then "$this" else "this"
 
 let gen_constant ctx = function
@@ -181,7 +208,7 @@ and gen_expr ctx e =
 			gen_value ctx e);
 	| TBreak ->
 		if ctx.in_value then unsupported e.epos;
-		spr ctx "break"
+		if ctx.handle_break then spr ctx "throw \"__break__\"" else spr ctx "break"
 	| TContinue ->
 		if ctx.in_value then unsupported e.epos;
 		spr ctx "continue"
@@ -240,20 +267,25 @@ and gen_expr ctx e =
 		gen_value ctx e;
 		spr ctx (Ast.s_unop op)
 	| TWhile (cond,e,Ast.NormalWhile) ->
+		let handle_break = handle_break ctx e in
 		spr ctx "while";
 		gen_value ctx (parent cond);
 		spr ctx " ";
 		gen_expr ctx e;
+		handle_break();
 	| TWhile (cond,e,Ast.DoWhile) ->
+		let handle_break = handle_break ctx e in
 		spr ctx "do ";
 		gen_expr ctx e;
 		spr ctx " while";
 		gen_value ctx (parent cond);		
+		handle_break();
 	| TObjectDecl fields ->
 		spr ctx "{ ";
 		concat ctx ", " (fun (f,e) -> print ctx "%s : " f; gen_value ctx e) fields;
 		spr ctx "}"
 	| TFor (v,it,e) ->
+		let handle_break = handle_break ctx e in
 		spr ctx "var $it = ";
 		gen_value ctx it;
 		newline ctx;
@@ -261,7 +293,8 @@ and gen_expr ctx e =
 		newline ctx;
 		gen_expr ctx e;
 		newline ctx;
-		spr ctx "}"
+		spr ctx "}";
+		handle_break();
 	| TTry (e,catchs) ->
 		spr ctx "try ";
 		gen_expr ctx e;
@@ -596,6 +629,7 @@ let generate file types hres =
 		current = null_class;
 		tabs = "";
 		in_value = false;
+		handle_break = false;
 	} in
 	print ctx "$class_str = function() { return this.__name__.join(\".\"); }";
 	newline ctx;