jsgen: optional "or blocks" (#6938)
parent
23c9563600
commit
96b73acad7
|
@ -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))
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if call_return_is_optional {
|
// end method call
|
||||||
g.write('))')
|
|
||||||
} else {
|
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
if call_return_is_optional {
|
||||||
|
// end unwrap
|
||||||
|
g.writeln(')')
|
||||||
|
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('})()')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue