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.
 | ||||
| pub fn exit(c int) { | ||||
| 	JS.process.exit(c) | ||||
| 	js_throw('exit($c)') | ||||
| } | ||||
| 
 | ||||
| pub fn unwrap(opt any) any { | ||||
| 	o := &Option(opt) | ||||
| 	if o.not_ok { | ||||
| 		panic(o.error) | ||||
| 		return o.error | ||||
| 		js_throw(o.error) | ||||
| 	} | ||||
| 	return opt | ||||
| } | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ const ( | |||
| 		'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', | ||||
| 		'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', | ||||
| 		'\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) | ||||
| 				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.inc_indent() | ||||
| 			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) { | ||||
| 	if it.exprs.len == 0 { | ||||
| 		// Returns nothing
 | ||||
| 		g.write('return;') | ||||
| 		g.writeln('return;') | ||||
| 		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) | ||||
| 	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) | ||||
| 	if it.is_method { // foo.bar.baz()
 | ||||
|  | @ -1224,10 +1232,40 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { | |||
| 			g.write(', ') | ||||
| 		} | ||||
| 	} | ||||
| 	// end method call
 | ||||
| 	g.write(')') | ||||
| 	if call_return_is_optional { | ||||
| 		g.write('))') | ||||
| 	} else { | ||||
| 		g.write(')') | ||||
| 		// 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' { | ||||
| 	} | ||||
| 	mut evens := []int{} | ||||
| 	for x in 1 .. 10 { | ||||
| 		y := error_if_even(x) or { x + 1 } | ||||
| 		evens << y | ||||
| 	} | ||||
| 	println(evens) | ||||
| 	arr := [1, 2, 3, 4, 5] | ||||
| 	for i in arr { | ||||
| 	} | ||||
|  | @ -81,6 +85,7 @@ fn main() { | |||
| 		println(message) | ||||
| 	}) | ||||
| 	hl.raw_js_log() | ||||
| 	propagation() or { println(err) } | ||||
| } | ||||
| 
 | ||||
| fn anon_consumer(greeting string, anon fn (message string)) { | ||||
|  | @ -120,3 +125,13 @@ fn (it Companies) method() int { | |||
| 	} | ||||
| 	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