diff --git a/compiler/fn.v b/compiler/fn.v index 82c2bc045d..8971716acf 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -275,18 +275,16 @@ fn (p mut Parser) fn_decl() { typ = p.get_type() } // multiple returns - if typ.starts_with('MultiReturn_') { - if !p.first_pass() && !p.table.known_type(typ) { - p.table.register_type2(Type{ - cat: TypeCategory.struct_, - name: typ, - mod: p.mod - }) - for i, t in typ.replace('MultiReturn_', '').replace('_ZptrZ_', '*').split('_Z_') { - p.table.add_field(typ, 'var_$i', t, false, '', .public) - } - p.cgen.typedefs << 'typedef struct $typ $typ;' + if typ.starts_with('_V_MulRet_') && p.first_pass() && !p.table.known_type(typ) { + p.table.register_type2(Type{ + cat: TypeCategory.struct_, + name: typ, + mod: p.mod + }) + for i, t in typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') { + p.table.add_field(typ, 'var_$i', t, false, '', .public) } + p.cgen.typedefs << 'typedef struct $typ $typ;' } // Translated C code can have empty functions (just definitions) is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr diff --git a/compiler/parser.v b/compiler/parser.v index dd57615d40..f2fbceb8d8 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -276,6 +276,8 @@ fn (p mut Parser) parse(pass Pass) { p.cgen.consts << g case Token.eof: //p.log('end of parse()') + // TODO: check why this was added? everything seems to work + // without it, and it's already happening in fn_decl // if p.is_script && !p.pref.is_test { // p.set_current_fn( MainFn ) // p.check_unused_variables() @@ -863,7 +865,7 @@ fn (p mut Parser) get_type() string { } p.check(.rpar) // p.inside_tuple = false - return 'MultiReturn_' + types.join('_Z_').replace('*', '_ZptrZ_') + return '_V_MulRet_' + types.join('_V_').replace('*', '_PTR_') } // fn type if p.tok == .func { @@ -1366,16 +1368,19 @@ fn (p mut Parser) var_decl() { // t := p.bool_expression() p.var_decl_name = mr_var_name t := p.gen_var_decl(mr_var_name, is_static) - mut types := [t] // multiple returns if names.len > 1 { // should we register __ret var? - types = t.replace('MultiReturn_', '').replace('_ZptrZ_', '*').split('_Z_') + types = t.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_') } for i, name in names { typ := types[i] if names.len > 1 { + if names.len != types.len { + mr_fn := p.cgen.cur_line.find_between('=', '(').trim_space() + p.error('assignment mismatch: ${names.len} variables but `$mr_fn` returns $types.len values.') + } p.gen(';\n') p.gen('$typ $name = ${mr_var_name}.var_$i') } @@ -3563,9 +3568,11 @@ fn (p mut Parser) return_st() { p.check(.comma) types << p.bool_expression() } + mut cur_fn_typ_chk := p.cur_fn.typ // multiple returns if types.len > 1 { - expr_type = 'MultiReturn_' + types.join('_Z_').replace('*', '_ZptrZ_') + expr_type = types.join(',') + cur_fn_typ_chk = cur_fn_typ_chk.replace('_V_MulRet_', '').replace('_PTR_', '*').replace('_V_', ',') ret_vals := p.cgen.cur_line.right(ph) mut ret_fields := '' for ret_val_idx, ret_val in ret_vals.split(' ') { @@ -3574,7 +3581,7 @@ fn (p mut Parser) return_st() { } ret_fields += '.var_$ret_val_idx=$ret_val' } - p.cgen.resetln('($expr_type){$ret_fields}') + p.cgen.resetln('($p.cur_fn.typ){$ret_fields}') } p.inside_return_expr = false // Automatically wrap an object inside an option if the function @@ -3618,7 +3625,7 @@ fn (p mut Parser) return_st() { p.genln('return $tmp;') } } - p.check_types(expr_type, p.cur_fn.typ) + p.check_types(expr_type, cur_fn_typ_chk) } } else {