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(', ')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// 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('})()')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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