compiler: clean up multiple returns and verify number of returned values
							parent
							
								
									a44a03f9a5
								
							
						
					
					
						commit
						3317d7fd7c
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue