jsgen: optional "or blocks" (#6938)

pull/6939/head
Leah Lundqvist 2020-11-24 22:52:23 +01:00 committed by GitHub
parent 23c9563600
commit 96b73acad7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 8 deletions

View File

@ -0,0 +1,6 @@
module builtin
// used to generate JS throw statements.
pub fn js_throw(s any) {
#throw (s instanceof Error ? s : new Error(s))
}

View File

@ -35,13 +35,13 @@ pub fn eprint(s any) {
// a 'real' way to exit in the browser. // a 'real' way to exit in the browser.
pub fn exit(c int) { pub fn exit(c int) {
JS.process.exit(c) JS.process.exit(c)
js_throw('exit($c)')
} }
pub fn unwrap(opt any) any { pub fn unwrap(opt any) any {
o := &Option(opt) o := &Option(opt)
if o.not_ok { if o.not_ok {
panic(o.error) js_throw(o.error)
return o.error
} }
return opt return opt
} }

View File

@ -15,7 +15,7 @@ const (
'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void',
'while', 'with', 'yield'] 'while', 'with', 'yield']
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t', tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
'\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t'
] ]
) )
@ -1011,6 +1011,10 @@ fn (mut g JsGen) gen_go_stmt(node ast.GoStmt) {
receiver_sym := g.table.get_type_symbol(node.call_expr.receiver_type) receiver_sym := g.table.get_type_symbol(node.call_expr.receiver_type)
name = receiver_sym.name + '.' + name name = receiver_sym.name + '.' + name
} }
// todo: please add a name feild without the mod name for ast.CallExpr
if name.starts_with('$node.call_expr.mod\.') {
name = name[node.call_expr.mod.len+1..]
}
g.writeln('await new Promise(function(resolve){') g.writeln('await new Promise(function(resolve){')
g.inc_indent() g.inc_indent()
g.write('${name}(') g.write('${name}(')
@ -1048,7 +1052,7 @@ fn (mut g JsGen) gen_interface_decl(it ast.InterfaceDecl) {
fn (mut g JsGen) gen_return_stmt(it ast.Return) { fn (mut g JsGen) gen_return_stmt(it ast.Return) {
if it.exprs.len == 0 { if it.exprs.len == 0 {
// Returns nothing // Returns nothing
g.write('return;') g.writeln('return;')
return return
} }
g.write('return ') g.write('return ')
@ -1173,7 +1177,11 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
} }
call_return_is_optional := it.return_type.has_flag(.optional) call_return_is_optional := it.return_type.has_flag(.optional)
if call_return_is_optional { if call_return_is_optional {
g.write('builtin.unwrap(') g.writeln('(function(){')
g.inc_indent()
g.writeln('try {')
g.inc_indent()
g.write('return builtin.unwrap(')
} }
g.expr(it.left) g.expr(it.left)
if it.is_method { // foo.bar.baz() if it.is_method { // foo.bar.baz()
@ -1224,10 +1232,40 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
g.write(', ') g.write(', ')
} }
} }
// end method call
g.write(')')
if call_return_is_optional { if call_return_is_optional {
g.write('))') // end unwrap
} else { g.writeln(')')
g.write(')') g.dec_indent()
// begin catch block
g.writeln('} catch(err) {')
g.inc_indent()
// gen or block contents
match it.or_block.kind {
.block {
if it.or_block.stmts.len > 1 {
g.stmts(it.or_block.stmts[..it.or_block.stmts.len-1])
}
g.write('return ')
g.stmt(it.or_block.stmts.last())
}
.propagate {
panicstr := '`optional not set (\${err})`'
if g.file.mod.name == 'main' && g.fn_decl.name == 'main.main' {
g.writeln('return builtin.panic($panicstr)')
} else {
g.writeln('builtin.js_throw(err)')
}
}
else {}
}
// end catch
g.dec_indent()
g.writeln('}')
// end anon fn
g.dec_indent()
g.write('})()')
} }
} }

View File

@ -59,8 +59,12 @@ fn main() {
} }
for i, x in 'hello' { for i, x in 'hello' {
} }
mut evens := []int{}
for x in 1 .. 10 { for x in 1 .. 10 {
y := error_if_even(x) or { x + 1 }
evens << y
} }
println(evens)
arr := [1, 2, 3, 4, 5] arr := [1, 2, 3, 4, 5]
for i in arr { for i in arr {
} }
@ -81,6 +85,7 @@ fn main() {
println(message) println(message)
}) })
hl.raw_js_log() hl.raw_js_log()
propagation() or { println(err) }
} }
fn anon_consumer(greeting string, anon fn (message string)) { fn anon_consumer(greeting string, anon fn (message string)) {
@ -120,3 +125,13 @@ fn (it Companies) method() int {
} }
return 0 return 0
} }
fn error_if_even(num int) ?int {
if num % 2 == 0 { return error('number is even') }
return num
}
fn propagation() ? {
println('Propagation test:')
return error('"Task failed successfully" - Windows XP')
}

View File

@ -0,0 +1,31 @@
module main
fn main() {
try_propagation() or { println("captured: $err") }
}
fn try_propagation() ? {
try_numbers()?
}
fn try_numbers() ? {
for x in 1 .. 10 {
y := error_if_even(x) or { x + 1 }
println("$x rounded to $y")
error_if_prime(y)?
}
}
fn error_if_even(num int) ?int {
if num % 2 == 0 { return error('number is even') }
return num
}
fn error_if_prime(num int) ?int {
for i in 2..num {
if num % i == 0 {
return error('$num is prime')
}
}
return num
}