compiler: support default values in optional blocks

pull/4245/head
Delyan Angelov 2020-04-05 11:37:14 +03:00
parent 05fbe5ab7a
commit 5e76d53fcd
2 changed files with 137 additions and 3 deletions

View File

@ -2524,14 +2524,71 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
// to access its fields (`.ok`, `.error` etc)
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }`
fn (g mut Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
mr_styp := g.typ(return_type)
mr_styp2 := mr_styp[7..] // remove Option_
g.writeln(';') // or')
g.writeln('if (!${var_name}.ok) {')
g.writeln('string err = ${var_name}.v_error;')
g.writeln('int errcode = ${var_name}.ecode;')
g.writeln('\tstring err = ${var_name}.v_error;')
g.writeln('\tint errcode = ${var_name}.ecode;')
last_type, type_of_last_expression := g.type_of_last_statement( stmts )
if last_type == 'v.ast.ExprStmt' && type_of_last_expression != 'void' {
g.indent++
for i, stmt in stmts {
if i == stmts.len-1 {
g.indent--
g.write('\t*(${mr_styp2}*) ${var_name}.data = ')
}
g.stmt(stmt)
}
} else {
g.stmts(stmts)
}
g.write('}')
}
fn (g mut Gen) type_of_last_statement(stmts []ast.Stmt) (string,string) {
mut last_type := ''
mut last_expr_result_type := ''
if stmts.len > 0 {
last_stmt := stmts[stmts.len-1]
last_type = typeof(last_stmt)
if last_type == 'v.ast.ExprStmt' {
match last_stmt {
ast.ExprStmt {
it_expr_type := typeof(it.expr)
if it_expr_type == 'v.ast.CallExpr' {
g.writeln('\t // typeof it_expr_type: $it_expr_type')
last_expr_result_type = g.type_of_call_expr(it.expr)
}else{
last_expr_result_type = it_expr_type
}
}
else {
last_expr_result_type = last_type
}
}
}
}
g.writeln('\t// last_type: $last_type')
g.writeln('\t// last_expr_result_type: $last_expr_result_type')
return last_type, last_expr_result_type
}
fn (g mut Gen) type_of_call_expr(node ast.Expr) string {
match node {
ast.CallExpr {
return g.typ(it.return_type)
}
else {
return typeof(node)
}
}
return ''
}
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
is_str := right.elem_type == table.string_type

View File

@ -0,0 +1,77 @@
struct Abc {
x int
}
fn i_0(x int) ?int {
if x == 0 {
return error('my error 1')
}
return x
}
fn struct_0(x int) ?Abc {
if x == 0 {
return error('my error 2')
}
return Abc{x}
}
fn string_0(x int) ?string {
if x == 0 {
return error('my error 3')
}
return '$x'
}
fn return_a_string() string {
return 'abcdef'
}
//
fn test_optional_int() {
a := i_0(0) or {
4999
}
assert a == 4999
b := i_0(4123) or {
4999
}
assert b == 4123
}
fn test_optional_struct() {
sa := struct_0(0) or {
Abc{7999}
}
assert sa.x == 7999
sb := struct_0(3456) or {
Abc{7999}
}
assert sb.x == 3456
}
fn test_optional_with_statements_before_last_expression() {
s := struct_0(0) or {
eprintln('hello')
Abc{12345}
}
assert s.x == 12345
}
fn test_optional_with_fn_call_as_last_expression() {
s := string_0(0) or {
return_a_string()
}
assert s == 'abcdef'
}
fn test_optional_with_fn_call_last_expr_and_preceding_statements() {
s := string_0(0) or {
eprintln('hello')
println('world')
return_a_string()
}
assert s == 'abcdef'
}