mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: support default values in optional blocks
This commit is contained in:
parent
05fbe5ab7a
commit
5e76d53fcd
@ -2524,14 +2524,71 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
|||||||
// to access its fields (`.ok`, `.error` etc)
|
// to access its fields (`.ok`, `.error` etc)
|
||||||
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }`
|
// `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) {
|
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(';') // or')
|
||||||
g.writeln('if (!${var_name}.ok) {')
|
g.writeln('if (!${var_name}.ok) {')
|
||||||
g.writeln('string err = ${var_name}.v_error;')
|
g.writeln('\tstring err = ${var_name}.v_error;')
|
||||||
g.writeln('int errcode = ${var_name}.ecode;')
|
g.writeln('\tint errcode = ${var_name}.ecode;')
|
||||||
g.stmts(stmts)
|
|
||||||
|
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('}')
|
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`
|
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
|
||||||
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
||||||
is_str := right.elem_type == table.string_type
|
is_str := right.elem_type == table.string_type
|
||||||
|
77
vlib/v/tests/option_default_values_test.v
Normal file
77
vlib/v/tests/option_default_values_test.v
Normal 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'
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user