compiler: make optionals work with multi return
parent
f0efb42a30
commit
554d1dd7c6
|
@ -1052,26 +1052,6 @@ fn (p mut Parser) get_type() string {
|
||||||
mut mul := false
|
mut mul := false
|
||||||
mut nr_muls := 0
|
mut nr_muls := 0
|
||||||
mut typ := ''
|
mut typ := ''
|
||||||
// multiple returns
|
|
||||||
if p.tok == .lpar {
|
|
||||||
// p.warn('`()` are no longer necessary in multiple returns' +
|
|
||||||
// '\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
|
||||||
// if p.inside_tuple {p.error('unexpected (')}
|
|
||||||
// p.inside_tuple = true
|
|
||||||
p.check(.lpar)
|
|
||||||
mut types := []string
|
|
||||||
for {
|
|
||||||
types << p.get_type()
|
|
||||||
if p.tok != .comma {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.check(.comma)
|
|
||||||
}
|
|
||||||
p.check(.rpar)
|
|
||||||
// p.inside_tuple = false
|
|
||||||
typ = p.register_multi_return_stuct(types)
|
|
||||||
return typ
|
|
||||||
}
|
|
||||||
// fn type
|
// fn type
|
||||||
if p.tok == .key_fn {
|
if p.tok == .key_fn {
|
||||||
mut f := Fn{
|
mut f := Fn{
|
||||||
|
@ -1104,12 +1084,39 @@ fn (p mut Parser) get_type() string {
|
||||||
p.table.register_type(fn_typ)
|
p.table.register_type(fn_typ)
|
||||||
return f.typ_str()
|
return f.typ_str()
|
||||||
}
|
}
|
||||||
// arrays ([]int)
|
|
||||||
mut arr_level := 0
|
|
||||||
is_question := p.tok == .question
|
is_question := p.tok == .question
|
||||||
if is_question {
|
if is_question {
|
||||||
p.check(.question)
|
p.check(.question)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multiple returns
|
||||||
|
if p.tok == .lpar {
|
||||||
|
// p.warn('`()` are no longer necessary in multiple returns' +
|
||||||
|
// '\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
||||||
|
// if p.inside_tuple {p.error('unexpected (')}
|
||||||
|
// p.inside_tuple = true
|
||||||
|
p.check(.lpar)
|
||||||
|
mut types := []string
|
||||||
|
for {
|
||||||
|
types << p.get_type()
|
||||||
|
if p.tok != .comma {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.check(.comma)
|
||||||
|
}
|
||||||
|
p.check(.rpar)
|
||||||
|
// p.inside_tuple = false
|
||||||
|
typ = p.register_multi_return_stuct(types)
|
||||||
|
if is_question {
|
||||||
|
typ = stringify_pointer(typ)
|
||||||
|
typ = 'Option_$typ'
|
||||||
|
p.table.register_type_with_parent(typ, 'Option')
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrays ([]int)
|
||||||
|
mut arr_level := 0
|
||||||
for p.tok == .lsbr {
|
for p.tok == .lsbr {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
// [10]int
|
// [10]int
|
||||||
|
@ -2854,6 +2861,7 @@ fn (p mut Parser) return_st() {
|
||||||
is_none := p.tok == .key_none
|
is_none := p.tok == .key_none
|
||||||
p.expected_type = p.cur_fn.typ
|
p.expected_type = p.cur_fn.typ
|
||||||
mut expr_type := p.bool_expression()
|
mut expr_type := p.bool_expression()
|
||||||
|
mut expr_type_chk := expr_type
|
||||||
// println('$p.cur_fn.name returns type $expr_type, should be $p.cur_fn.typ')
|
// println('$p.cur_fn.name returns type $expr_type, should be $p.cur_fn.typ')
|
||||||
mut types := []string
|
mut types := []string
|
||||||
mut mr_values := [p.cgen.cur_line[ph..].trim_space()]
|
mut mr_values := [p.cgen.cur_line[ph..].trim_space()]
|
||||||
|
@ -2867,7 +2875,13 @@ fn (p mut Parser) return_st() {
|
||||||
mut cur_fn_typ_chk := p.cur_fn.typ
|
mut cur_fn_typ_chk := p.cur_fn.typ
|
||||||
// multiple returns
|
// multiple returns
|
||||||
if types.len > 1 {
|
if types.len > 1 {
|
||||||
expr_type = types.join(',')
|
mr_type := if p.cur_fn.typ.starts_with('Option_') {
|
||||||
|
p.cur_fn.typ[7..]
|
||||||
|
} else {
|
||||||
|
p.cur_fn.typ
|
||||||
|
}
|
||||||
|
expr_type = mr_type
|
||||||
|
expr_type_chk = types.join(',')
|
||||||
cur_fn_typ_chk = cur_fn_typ_chk.replace('_V_MulRet_', '').replace('_PTR_', '*').replace('_V_', ',')
|
cur_fn_typ_chk = cur_fn_typ_chk.replace('_V_MulRet_', '').replace('_PTR_', '*').replace('_V_', ',')
|
||||||
mut ret_fields := ''
|
mut ret_fields := ''
|
||||||
for ret_val_idx, ret_val in mr_values {
|
for ret_val_idx, ret_val in mr_values {
|
||||||
|
@ -2876,7 +2890,7 @@ fn (p mut Parser) return_st() {
|
||||||
}
|
}
|
||||||
ret_fields += '.var_$ret_val_idx=${ret_val}'
|
ret_fields += '.var_$ret_val_idx=${ret_val}'
|
||||||
}
|
}
|
||||||
p.cgen.resetln('($p.cur_fn.typ){$ret_fields}')
|
p.cgen.resetln('($mr_type){$ret_fields}')
|
||||||
}
|
}
|
||||||
p.inside_return_expr = false
|
p.inside_return_expr = false
|
||||||
// Automatically wrap an object inside an option if the function
|
// Automatically wrap an object inside an option if the function
|
||||||
|
@ -2908,7 +2922,7 @@ fn (p mut Parser) return_st() {
|
||||||
p.genln('return $tmp;')
|
p.genln('return $tmp;')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check_types(expr_type, cur_fn_typ_chk)
|
p.check_types(expr_type_chk, cur_fn_typ_chk)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Don't allow `return val` in functions that don't return anything
|
// Don't allow `return val` in functions that don't return anything
|
||||||
|
|
|
@ -12,31 +12,6 @@ fn (p mut Parser) get_type2() Type {
|
||||||
mut nr_muls := 0
|
mut nr_muls := 0
|
||||||
mut typ := ''
|
mut typ := ''
|
||||||
cat := TypeCategory.struct_
|
cat := TypeCategory.struct_
|
||||||
// multiple returns
|
|
||||||
if p.tok == .lpar {
|
|
||||||
// p.warn('`()` are no longer necessary in multiple returns' +
|
|
||||||
// '\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
|
||||||
// if p.inside_tuple {p.error('unexpected (')}
|
|
||||||
// p.inside_tuple = true
|
|
||||||
p.check(.lpar)
|
|
||||||
mut types := []string
|
|
||||||
for {
|
|
||||||
types << p.get_type()
|
|
||||||
if p.tok != .comma {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.check(.comma)
|
|
||||||
p.fspace()
|
|
||||||
}
|
|
||||||
p.check(.rpar)
|
|
||||||
// p.inside_tuple = false
|
|
||||||
typ = p.register_multi_return_stuct(types)
|
|
||||||
return Type{
|
|
||||||
name: typ
|
|
||||||
mod: p.mod
|
|
||||||
cat: cat
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fn type
|
// fn type
|
||||||
if p.tok == .key_fn {
|
if p.tok == .key_fn {
|
||||||
mut f := Fn{
|
mut f := Fn{
|
||||||
|
@ -70,12 +45,44 @@ fn (p mut Parser) get_type2() Type {
|
||||||
p.table.register_type(fn_typ)
|
p.table.register_type(fn_typ)
|
||||||
return fn_typ
|
return fn_typ
|
||||||
}
|
}
|
||||||
// arrays ([]int)
|
|
||||||
mut arr_level := 0
|
|
||||||
is_question := p.tok == .question
|
is_question := p.tok == .question
|
||||||
if is_question {
|
if is_question {
|
||||||
p.check(.question)
|
p.check(.question)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multiple returns
|
||||||
|
if p.tok == .lpar {
|
||||||
|
// p.warn('`()` are no longer necessary in multiple returns' +
|
||||||
|
// '\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
||||||
|
// if p.inside_tuple {p.error('unexpected (')}
|
||||||
|
// p.inside_tuple = true
|
||||||
|
p.check(.lpar)
|
||||||
|
mut types := []string
|
||||||
|
for {
|
||||||
|
types << p.get_type()
|
||||||
|
if p.tok != .comma {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.check(.comma)
|
||||||
|
p.fspace()
|
||||||
|
}
|
||||||
|
p.check(.rpar)
|
||||||
|
// p.inside_tuple = false
|
||||||
|
typ = p.register_multi_return_stuct(types)
|
||||||
|
if is_question {
|
||||||
|
typ = stringify_pointer(typ)
|
||||||
|
typ = 'Option_$typ'
|
||||||
|
p.table.register_type_with_parent(typ, 'Option')
|
||||||
|
}
|
||||||
|
return Type{
|
||||||
|
name: typ
|
||||||
|
mod: p.mod
|
||||||
|
cat: cat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrays ([]int)
|
||||||
|
mut arr_level := 0
|
||||||
for p.tok == .lsbr {
|
for p.tok == .lsbr {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
// [10]int
|
// [10]int
|
||||||
|
|
|
@ -144,3 +144,21 @@ fn test_opt_ptr() {
|
||||||
println('`$r2` should be none')
|
println('`$r2` should be none')
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn multi_return_opt(err bool) ?(string, string) {
|
||||||
|
if err {
|
||||||
|
return error('oops')
|
||||||
|
}
|
||||||
|
return 'hello', 'v'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_multi_return_opt() {
|
||||||
|
a, b := multi_return_opt(false) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
assert a == 'hello' && b == 'v'
|
||||||
|
_, _ := multi_return_opt(true) or {
|
||||||
|
assert err == 'oops'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue