js: fix break and continue in or blocks (#13165)

pull/13178/head
playX 2022-01-14 19:43:18 +03:00 committed by GitHub
parent 9329b6c8c8
commit 104e0c5692
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 1 deletions

View File

@ -97,6 +97,11 @@ fn (mut g JsGen) js_call(node ast.CallExpr) {
} }
if call_return_is_optional { if call_return_is_optional {
g.write(';\n') g.write(';\n')
prev_inside_or := g.inside_or
g.inside_or = true
defer {
g.inside_or = prev_inside_or
}
g.writeln('if (tmp === null) throw "none";') g.writeln('if (tmp === null) throw "none";')
g.writeln('return tmp;') g.writeln('return tmp;')
g.writeln('} catch(err) {') g.writeln('} catch(err) {')
@ -151,6 +156,11 @@ fn (mut g JsGen) js_method_call(node ast.CallExpr) {
// end method call // end method call
g.write(')') g.write(')')
if call_return_is_optional { if call_return_is_optional {
prev_inside_or := g.inside_or
g.inside_or = true
defer {
g.inside_or = prev_inside_or
}
g.write(';\n') g.write(';\n')
g.writeln('if (tmp === null) throw "none";') g.writeln('if (tmp === null) throw "none";')
g.writeln('return tmp;') g.writeln('return tmp;')
@ -339,6 +349,11 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
// end unwrap // end unwrap
g.writeln(')') g.writeln(')')
g.dec_indent() g.dec_indent()
prev_inside_or := g.inside_or
g.inside_or = true
defer {
g.inside_or = prev_inside_or
}
// begin catch block // begin catch block
g.writeln('} catch(err) {') g.writeln('} catch(err) {')
g.inc_indent() g.inc_indent()
@ -432,6 +447,11 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
g.write(')') g.write(')')
if call_return_is_optional { if call_return_is_optional {
// end unwrap // end unwrap
prev_inside_or := g.inside_or
g.inside_or = true
defer {
g.inside_or = prev_inside_or
}
g.writeln(')') g.writeln(')')
g.dec_indent() g.dec_indent()
// begin catch block // begin catch block

View File

@ -54,6 +54,7 @@ mut:
file &ast.File file &ast.File
tmp_count int tmp_count int
inside_ternary bool inside_ternary bool
inside_or bool
inside_loop bool inside_loop bool
inside_map_set bool // map.set(key, value) inside_map_set bool // map.set(key, value)
inside_builtin bool inside_builtin bool
@ -478,6 +479,9 @@ pub fn (mut g JsGen) init() {
g.definitions.writeln('function checkDefine(key) {') g.definitions.writeln('function checkDefine(key) {')
g.definitions.writeln('\tif (globalThis.hasOwnProperty(key)) { return !!globalThis[key]; } return false;') g.definitions.writeln('\tif (globalThis.hasOwnProperty(key)) { return !!globalThis[key]; } return false;')
g.definitions.writeln('}') g.definitions.writeln('}')
g.definitions.writeln('function BreakException() {}')
g.definitions.writeln('function ContinueException() {}')
} }
pub fn (g JsGen) hashes() string { pub fn (g JsGen) hashes() string {
@ -1500,6 +1504,20 @@ fn (mut g JsGen) gen_block(it ast.Block) {
fn (mut g JsGen) gen_branch_stmt(it ast.BranchStmt) { fn (mut g JsGen) gen_branch_stmt(it ast.BranchStmt) {
// continue or break // continue or break
if g.inside_or {
match it.kind {
.key_break {
g.writeln('throw new BreakException();')
}
.key_continue {
g.writeln('throw new ContinueException();')
}
else {
verror('unexpected branch stmt: $it.kind')
}
}
return
}
g.write(it.kind.str()) g.write(it.kind.str())
g.writeln(';') g.writeln(';')
} }
@ -1606,7 +1624,12 @@ fn (mut g JsGen) gen_for_c_stmt(it ast.ForCStmt) {
g.stmt_no_semi(it.inc) g.stmt_no_semi(it.inc)
} }
g.writeln(') {') g.writeln(') {')
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } }')
g.writeln('}') g.writeln('}')
g.inside_loop = false g.inside_loop = false
} }
@ -1625,7 +1648,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
g.expr(it.high) g.expr(it.high)
g.writeln('; $i = new int($i + 1)) {') g.writeln('; $i = new int($i + 1)) {')
g.inside_loop = false g.inside_loop = false
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } }')
g.writeln('}') g.writeln('}')
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) { } else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
// `for num in nums {` // `for num in nums {`
@ -1670,7 +1698,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
} }
} }
g.writeln(') {') g.writeln(') {')
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } }')
g.writeln('}') g.writeln('}')
} else if it.kind == .map { } else if it.kind == .map {
// `for key, val in map[string]int {` // `for key, val in map[string]int {`
@ -1695,7 +1728,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
g.writeln('\tlet $key = $tmp[$tmp3];') g.writeln('\tlet $key = $tmp[$tmp3];')
g.writeln('\tlet $val = ${tmp2}.map[$tmp[$tmp3]];') g.writeln('\tlet $val = ${tmp2}.map[$tmp[$tmp3]];')
g.inc_indent() g.inc_indent()
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } }')
g.dec_indent() g.dec_indent()
g.writeln('}') g.writeln('}')
} else { } else {
@ -1710,7 +1748,12 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
g.inc_indent() g.inc_indent()
g.writeln('let $val = ${tmp}.map[$tmp2];') g.writeln('let $val = ${tmp}.map[$tmp2];')
g.writeln('let $key = $tmp2;') g.writeln('let $key = $tmp2;')
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } } ')
g.dec_indent() g.dec_indent()
g.writeln('}') g.writeln('}')
} }
@ -1726,7 +1769,12 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) {
g.expr(it.cond) g.expr(it.cond)
} }
g.writeln(') {') g.writeln(') {')
g.writeln('try { ')
g.stmts(it.stmts) g.stmts(it.stmts)
g.writeln('} catch (e) {')
g.writeln(' if (e instanceof BreakException) { break; }')
g.writeln(' else if (e instanceof ContinueException) { continue; }')
g.writeln(' else { throw e; } }')
g.writeln('}') g.writeln('}')
} }

View File

@ -31,7 +31,7 @@ fn main() {
println('Hello from V.js!') println('Hello from V.js!')
println(JS.Math.atan2(1, 0)) println(JS.Math.atan2(1, 0))
non := JS.eval("console.log('Hello!')".str) non := JS.eval("console.log('Hello!')".str)
if isnil (non) { if isnil(non) {
println('non=nil') println('non=nil')
} }
ren := int(JS.eval('3'.str)) ren := int(JS.eval('3'.str))