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(', ')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if call_return_is_optional {
 | 
			
		||||
		g.write('))')
 | 
			
		||||
	} else {
 | 
			
		||||
	// end method call
 | 
			
		||||
	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' {
 | 
			
		||||
	}
 | 
			
		||||
	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