v: fix/gen multi return/assign + merge VarDecl & AssignStmt
							parent
							
								
									876b73f92c
								
							
						
					
					
						commit
						f7a93a69f6
					
				|  | @ -16,7 +16,7 @@ AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | | |||
| CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | 	 | ||||
| ConcatExpr | Type | AsCast | ||||
| 
 | ||||
| pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | 	 | ||||
| pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | 	 | ||||
| ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | 	 | ||||
| HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | 	 | ||||
| LineComment | MultiLineComment | AssertStmt | UnsafeStmt | ||||
|  | @ -164,6 +164,7 @@ mut: | |||
| 	is_c     bool | ||||
| 	muts     []bool | ||||
| 	or_block OrExpr | ||||
| 	typ      table.Type | ||||
| } | ||||
| 
 | ||||
| pub struct MethodCallExpr { | ||||
|  | @ -201,10 +202,9 @@ pub struct Stmt { | |||
| */ | ||||
| 
 | ||||
| 
 | ||||
| pub struct VarDecl { | ||||
| pub struct Var { | ||||
| pub: | ||||
| 	name   string | ||||
| 	name2  string // TODO
 | ||||
| 	expr   Expr | ||||
| 	is_mut bool | ||||
| mut: | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ mut: | |||
| 	start_pos int | ||||
| 	end_pos   int | ||||
| 	// vars      map[string]table.Var
 | ||||
| 	vars      map[string]VarDecl | ||||
| 	vars      map[string]Var | ||||
| } | ||||
| 
 | ||||
| pub fn new_scope(parent &Scope, start_pos int) &Scope { | ||||
|  | @ -20,7 +20,7 @@ pub fn new_scope(parent &Scope, start_pos int) &Scope { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (s &Scope) find_scope_and_var(name string) ?(&Scope,VarDecl) { | ||||
| pub fn (s &Scope) find_scope_and_var(name string) ?(&Scope,Var) { | ||||
| 	if name in s.vars { | ||||
| 		return s,s.vars[name] | ||||
| 	} | ||||
|  | @ -32,7 +32,7 @@ pub fn (s &Scope) find_scope_and_var(name string) ?(&Scope,VarDecl) { | |||
| 	return none | ||||
| } | ||||
| 
 | ||||
| pub fn (s &Scope) find_var(name string) ?VarDecl { | ||||
| pub fn (s &Scope) find_var(name string) ?Var { | ||||
| 	if name in s.vars { | ||||
| 		return s.vars[name] | ||||
| 	} | ||||
|  | @ -51,7 +51,7 @@ pub fn (s &Scope) known_var(name string) bool { | |||
| 	return false | ||||
| } | ||||
| 
 | ||||
| pub fn (s mut Scope) register_var(var VarDecl) { | ||||
| pub fn (s mut Scope) register_var(var Var) { | ||||
| 	if x := s.find_var(var.name) { | ||||
| 		// println('existing var: $var.name')
 | ||||
| 		return | ||||
|  | @ -59,7 +59,7 @@ pub fn (s mut Scope) register_var(var VarDecl) { | |||
| 	s.vars[var.name] = var | ||||
| } | ||||
| 
 | ||||
| pub fn (s mut Scope) override_var(var VarDecl) { | ||||
| pub fn (s mut Scope) override_var(var Var) { | ||||
| 	s.vars[var.name] = var | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -78,8 +78,26 @@ pub fn (x Expr) str() string { | |||
| 
 | ||||
| pub fn (node Stmt) str() string { | ||||
| 	match node { | ||||
| 		VarDecl { | ||||
| 			return it.name + ' = ' + it.expr.str() | ||||
| 		AssignStmt { | ||||
| 			mut out := '' | ||||
| 			for i,ident in it.left { | ||||
| 				var_info := ident.var_info() | ||||
| 				if var_info.is_mut { | ||||
| 					out += 'mut ' | ||||
| 				} | ||||
| 				out += ident.name | ||||
| 				if i < it.left.len-1 { | ||||
| 					out += ',' | ||||
| 				} | ||||
| 			} | ||||
| 			out += ' $it.op.str() ' | ||||
| 			for i,val in it.right { | ||||
| 				out += val.str() | ||||
| 				if i < it.right.len-1 { | ||||
| 					out += ',' | ||||
| 				} | ||||
| 			} | ||||
| 			return out | ||||
| 		} | ||||
| 		ExprStmt { | ||||
| 			return it.expr.str() | ||||
|  |  | |||
|  | @ -206,6 +206,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { | |||
| 	if !found { | ||||
| 		c.error('unknown fn: $fn_name', call_expr.pos) | ||||
| 	} | ||||
| 	call_expr.typ = f.return_type | ||||
| 	if f.is_c || call_expr.is_c { | ||||
| 		for expr in call_expr.args { | ||||
| 			c.expr(expr) | ||||
|  | @ -259,12 +260,13 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) | |||
| 			mut scope := c.file.scope.innermost(method_call_expr.pos.pos) or { | ||||
| 				c.file.scope | ||||
| 			} | ||||
| 			scope.override_var(ast.VarDecl{ | ||||
| 			scope.override_var(ast.Var{ | ||||
| 				name: 'it' | ||||
| 				typ: array_info.elem_type | ||||
| 			}) | ||||
| 		} | ||||
| 		if method := typ_sym.find_method(name) { | ||||
| 			method_call_expr.typ = method.return_type | ||||
| 			for i, arg_expr in method_call_expr.args { | ||||
| 				c.expected_type = method.args[i].typ | ||||
| 				c.expr(arg_expr) | ||||
|  | @ -370,27 +372,70 @@ pub fn (c mut Checker) return_stmt(return_stmt ast.Return) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (c mut Checker) assign_stmt(assign_stmt ast.AssignStmt) { | ||||
| pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) { | ||||
| 	// multi return
 | ||||
| 	if assign_stmt.left.len > assign_stmt.right.len { | ||||
| 		right := c.expr(assign_stmt.right[0]) | ||||
| 		right_sym := c.table.get_type_symbol(right) | ||||
| 		info := right_sym.mr_info() | ||||
| 		mr_info := right_sym.mr_info() | ||||
| 		if right_sym.kind != .multi_return { | ||||
| 			c.error('wrong number of vars', assign_stmt.pos) | ||||
| 		} | ||||
| 		mut scope := c.file.scope.innermost(assign_stmt.pos.pos) or { | ||||
| 			c.file.scope | ||||
| 		} | ||||
| 		for i, ident in assign_stmt.left { | ||||
| 			// TODO: check types
 | ||||
| 			scope.override_var(ast.VarDecl{ | ||||
| 		for i, _ in assign_stmt.left { | ||||
| 			mut ident := assign_stmt.left[i] | ||||
| 			mut var_info := ident.var_info() | ||||
| 			val_type :=  mr_info.types[i] | ||||
| 			var_info.typ = val_type | ||||
| 			ident.info = var_info | ||||
| 			assign_stmt.left[i] = ident | ||||
| 			if assign_stmt.op == .assign { | ||||
| 				if !c.table.check(val_type, var_info.typ) { | ||||
| 					val_type_sym := c.table.get_type_symbol(val_type) | ||||
| 					var_type_sym := c.table.get_type_symbol(var_info.typ) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos) | ||||
| 				} | ||||
| 			} | ||||
| 			scope.override_var(ast.Var{ | ||||
| 				name: ident.name | ||||
| 				typ: info.types[i] | ||||
| 				typ: mr_info.types[i] | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	// `a := 1` | `a,b := 1,2`
 | ||||
| 	else { | ||||
| 		if assign_stmt.left.len != assign_stmt.right.len  { | ||||
| 			c.error('wrong number of vars', assign_stmt.pos) | ||||
| 		} | ||||
| 		for i, _ in assign_stmt.left { | ||||
| 			mut ident := assign_stmt.left[i] | ||||
| 			val := assign_stmt.right[i] | ||||
| 			val_type := c.expr(val) | ||||
| 			if assign_stmt.op == .assign { | ||||
| 				var_info := ident.var_info() | ||||
| 				if !c.table.check(val_type, var_info.typ) { | ||||
| 					val_type_sym := c.table.get_type_symbol(val_type) | ||||
| 					var_type_sym := c.table.get_type_symbol(var_info.typ) | ||||
| 					c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos) | ||||
| 				} | ||||
| 			} | ||||
| 			else if assign_stmt.op == .decl_assign { | ||||
| 				mut var_info := ident.var_info() | ||||
| 				var_info.typ = val_type | ||||
| 				ident.info = var_info | ||||
| 				assign_stmt.left[i] = ident | ||||
| 			} | ||||
| 			mut scope := c.file.scope.innermost(assign_stmt.pos.pos) or { | ||||
| 				c.file.scope | ||||
| 			} | ||||
| 			scope.override_var(ast.Var{ | ||||
| 				name: ident.name | ||||
| 				typ: val_type | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO: multiple assign
 | ||||
| } | ||||
| 
 | ||||
| pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { | ||||
|  | @ -448,7 +493,7 @@ fn (c mut Checker) stmt(node ast.Stmt) { | |||
| 	// c.expected_type = table.void_type
 | ||||
| 	match mut node { | ||||
| 		ast.AssignStmt { | ||||
| 			c.assign_stmt(it) | ||||
| 			c.assign_stmt(mut it) | ||||
| 		} | ||||
| 		// ast.Attr {}
 | ||||
| 		// ast.CompIf {}
 | ||||
|  | @ -507,10 +552,6 @@ fn (c mut Checker) stmt(node ast.Stmt) { | |||
| 				c.stmt(stmt) | ||||
| 			} | ||||
| 		} | ||||
| 		ast.VarDecl { | ||||
| 			typ := c.expr(it.expr) | ||||
| 			it.typ = typ | ||||
| 		} | ||||
| 		else {} | ||||
| 		// println('checker.stmt(): unhandled node')
 | ||||
| 		// println('checker.stmt(): unhandled node (${typeof(node)})')
 | ||||
|  | @ -646,7 +687,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { | |||
| 		} | ||||
| 		mut found := true | ||||
| 		mut var_scope := &ast.Scope(0) | ||||
| 		mut var := ast.VarDecl{} | ||||
| 		mut var := ast.Var{} | ||||
| 		var_scope,var = start_scope.find_scope_and_var(ident.name) or { | ||||
| 			found = false | ||||
| 			c.error('not found: $ident.name - POS: $ident.pos.pos', ident.pos) | ||||
|  |  | |||
|  | @ -66,11 +66,14 @@ fn (e mut Eval) stmt(node ast.Stmt) string { | |||
| 		// ast.StructDecl {
 | ||||
| 		// println('s decl')
 | ||||
| 		// }
 | ||||
| 		ast.VarDecl { | ||||
| 			e.vars[it.name] = Var{ | ||||
| 				value: e.expr(it.expr) | ||||
| 			} | ||||
| 		ast.AssignStmt { | ||||
| 			// TODO; replaced VarDecl
 | ||||
| 		} | ||||
| 		// ast.VarDecl {
 | ||||
| 		// 	e.vars[it.name] = Var{
 | ||||
| 		// 		value: e.expr(it.expr)
 | ||||
| 		// 	}
 | ||||
| 		// }
 | ||||
| 		else {} | ||||
| 	} | ||||
| 	return '>>' | ||||
|  |  | |||
|  | @ -100,18 +100,22 @@ fn (f mut Fmt) stmts(stmts []ast.Stmt) { | |||
| fn (f mut Fmt) stmt(node ast.Stmt) { | ||||
| 	match node { | ||||
| 		ast.AssignStmt { | ||||
| 			for i, left in it.left { | ||||
| 				if left.var_info().is_mut { | ||||
| 			for i,ident in it.left { | ||||
| 				var_info := ident.var_info() | ||||
| 				if var_info.is_mut { | ||||
| 					f.write('mut ') | ||||
| 				} | ||||
| 				f.expr(left) | ||||
| 				if i < it.left.len - 1 { | ||||
| 				f.write(ident.name) | ||||
| 				if i < it.left.len-1 { | ||||
| 					f.write(', ') | ||||
| 				} | ||||
| 			} | ||||
| 			f.write(' $it.op.str() ') | ||||
| 			for right in it.right { | ||||
| 				f.expr(right) | ||||
| 			for i,val in it.right { | ||||
| 				f.expr(val) | ||||
| 				if i < it.right.len-1 { | ||||
| 					f.write(', ') | ||||
| 				} | ||||
| 			} | ||||
| 			f.writeln('') | ||||
| 		} | ||||
|  | @ -231,20 +235,6 @@ fn (f mut Fmt) stmt(node ast.Stmt) { | |||
| 			f.stmts(it.stmts) | ||||
| 			f.writeln('}') | ||||
| 		} | ||||
| 		ast.VarDecl { | ||||
| 			// type_sym := f.table.get_type_symbol(it.typ)
 | ||||
| 			if it.is_mut { | ||||
| 				f.write('mut ') | ||||
| 			} | ||||
| 			if it.name2 == '' { | ||||
| 				f.write('$it.name := ') | ||||
| 			} | ||||
| 			else { | ||||
| 				f.write('/*2*/$it.name, $it.name2 := ') | ||||
| 			} | ||||
| 			f.expr(it.expr) | ||||
| 			f.writeln('') | ||||
| 		} | ||||
| 		ast.Import { | ||||
| 			// already handled in f.imports
 | ||||
| 		} | ||||
|  |  | |||
|  | @ -135,22 +135,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 	// g.writeln('//// stmt start')
 | ||||
| 	match node { | ||||
| 		ast.AssignStmt { | ||||
| 			// ident0 := it.left[0]
 | ||||
| 			// info0 := ident0.var_info()
 | ||||
| 			// for i, ident in it.left {
 | ||||
| 			// info := ident.var_info()
 | ||||
| 			// if info0.typ.typ.kind == .multi_return {
 | ||||
| 			// if i == 0 {
 | ||||
| 			// g.write('$info.typ.typ.name $ident.name = ')
 | ||||
| 			// g.expr(it.right[0])
 | ||||
| 			// } else {
 | ||||
| 			// arg_no := i-1
 | ||||
| 			// g.write('$info.typ.typ.name $ident.name = $ident0.name->arg[$arg_no]')
 | ||||
| 			// }
 | ||||
| 			// }
 | ||||
| 			// g.writeln(';')
 | ||||
| 			// }
 | ||||
| 			g.write('') // /*assign*/')
 | ||||
| 			g.gen_assign_stmt(it) | ||||
| 		} | ||||
| 		ast.AssertStmt { | ||||
| 			g.write('// assert') | ||||
|  | @ -283,18 +268,51 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 		ast.UnsafeStmt { | ||||
| 			g.stmts(it.stmts) | ||||
| 		} | ||||
| 		ast.VarDecl { | ||||
| 			styp := g.typ(it.typ) | ||||
| 			g.write('$styp $it.name = ') | ||||
| 			g.expr(it.expr) | ||||
| 			g.writeln(';') | ||||
| 		} | ||||
| 		else { | ||||
| 			verror('cgen.stmt(): unhandled node ' + typeof(node)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { | ||||
| 	// multi return
 | ||||
| 	if assign_stmt.left.len > assign_stmt.right.len { | ||||
| 		mut return_type := table.void_type | ||||
| 		match assign_stmt.right[0] { | ||||
| 			ast.CallExpr { | ||||
| 				return_type = it.typ | ||||
| 			} | ||||
| 			ast.MethodCallExpr { | ||||
| 				return_type = it.typ | ||||
| 			} | ||||
| 			else { | ||||
| 				panic('expected call') | ||||
| 			} | ||||
| 		} | ||||
| 		mr_typ_sym := g.table.get_type_symbol(return_type) | ||||
| 		mr_var_name := 'mr_$assign_stmt.pos.pos' | ||||
| 		g.write('$mr_typ_sym.name $mr_var_name = ') | ||||
| 		g.expr(assign_stmt.right[0]) | ||||
| 		g.writeln(';') | ||||
| 		for i, ident in assign_stmt.left { | ||||
| 			ident_var_info := ident.var_info() | ||||
| 			var_type_sym := g.table.get_type_symbol(ident_var_info.typ) | ||||
| 			g.writeln('$var_type_sym.name $ident.name = $mr_var_name->arg[$i];') | ||||
| 		} | ||||
| 	} | ||||
| 	// `a := 1` | `a,b := 1,2`
 | ||||
| 	else { | ||||
| 		for i, ident in assign_stmt.left { | ||||
| 			val := assign_stmt.right[i] | ||||
| 			ident_var_info := ident.var_info() | ||||
| 			var_type_sym := g.table.get_type_symbol(ident_var_info.typ) | ||||
| 			g.write('$var_type_sym.name $ident.name = ') | ||||
| 			g.expr(val) | ||||
| 			g.writeln(';') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { | ||||
| 	if it.is_c || it.name == 'malloc' || it.no_body { | ||||
| 		return | ||||
|  |  | |||
|  | @ -57,12 +57,20 @@ fn (g mut JsGen) stmt(node ast.Stmt) { | |||
| 			} | ||||
| 			g.writeln(';') | ||||
| 		} | ||||
| 		ast.AssignStmt {} | ||||
| 		ast.VarDecl { | ||||
| 			type_sym := g.table.get_type_symbol(it.typ) | ||||
| 			g.write('var /* $type_sym.name */ $it.name = ') | ||||
| 			g.expr(it.expr) | ||||
| 			g.writeln(';') | ||||
| 		ast.AssignStmt { | ||||
| 			if it.left.len > it.right.len { | ||||
| 				// TODO: multi return
 | ||||
| 			} | ||||
| 			else { | ||||
| 				for i,ident in it.left { | ||||
| 					var_info := ident.var_info() | ||||
| 					var_type_sym := g.table.get_type_symbol(var_info.typ) | ||||
| 					val := it.right[i] | ||||
| 					g.write('var /* $var_type_sym.name */ $ident.name = ') | ||||
| 					g.expr(val) | ||||
| 					g.writeln(';') | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ast.ForStmt { | ||||
| 			g.write('while (') | ||||
|  |  | |||
|  | @ -54,7 +54,10 @@ int main() { | |||
| 	string foo_a = af_idx_el.a; | ||||
|     map_string_string m1 = new_map(1, sizeof(string)); | ||||
|     map_string_int m2 = new_map_init(2, sizeof(int), (string[2]){tos3("v"), tos3("lang"), }, (int[2]){1, 2, }); | ||||
| 	return 0; | ||||
|     multi_return_int_string mr_548 = mr_test(); | ||||
|     int mr1 = mr_548->arg[0]; | ||||
|     string mr2 = mr_548->arg[1]; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| multi_return_int_string mr_test() { | ||||
|  |  | |||
|  | @ -31,8 +31,6 @@ fn main() { | |||
| 	mut f := [testa(),2,3,4] | ||||
| 	mut g := [testb(1),'hello'] | ||||
| 
 | ||||
| 	mr1, mr2 := mr_test() | ||||
| 
 | ||||
| 	//mut arr_foo := []Foo
 | ||||
| 	arr_foo := [a] | ||||
| 	//arr_foo << a // TODO
 | ||||
|  | @ -41,6 +39,8 @@ fn main() { | |||
| 
 | ||||
| 	mut m1 := map[string]string | ||||
| 	mut m2 := {'v': 1, 'lang': 2} | ||||
| 
 | ||||
| 	mr1, mr2 := mr_test() | ||||
| } | ||||
| 
 | ||||
| fn mr_test() (int, string) { | ||||
|  |  | |||
|  | @ -332,7 +332,6 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 		} | ||||
| 		ast.Return {} | ||||
| 		ast.AssignStmt {} | ||||
| 		ast.VarDecl {} | ||||
| 		ast.ForStmt {} | ||||
| 		ast.StructDecl {} | ||||
| 		ast.ExprStmt { | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | |||
| 		// name: rec_name
 | ||||
| 		// typ: rec_type
 | ||||
| 		// })
 | ||||
| 		p.scope.register_var(ast.VarDecl{ | ||||
| 		p.scope.register_var(ast.Var{ | ||||
| 			name: rec_name | ||||
| 			typ: rec_type | ||||
| 		}) | ||||
|  | @ -115,7 +115,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { | |||
| 			typ: ast_arg.typ | ||||
| 		} | ||||
| 		args << var | ||||
| 		p.scope.register_var(ast.VarDecl{ | ||||
| 		p.scope.register_var(ast.Var{ | ||||
| 			name: ast_arg.name | ||||
| 			typ: ast_arg.typ | ||||
| 		}) | ||||
|  |  | |||
|  | @ -296,7 +296,7 @@ pub fn (p mut Parser) stmt() ast.Stmt { | |||
| 			} | ||||
| 		} | ||||
| 		.key_mut { | ||||
| 			return p.var_decl_and_assign_stmt() | ||||
| 			return p.assign_stmt() | ||||
| 		} | ||||
| 		.key_for { | ||||
| 			return p.for_statement() | ||||
|  | @ -341,7 +341,7 @@ pub fn (p mut Parser) stmt() ast.Stmt { | |||
| 		else { | ||||
| 			// `x := ...`
 | ||||
| 			if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] { | ||||
| 				return p.var_decl_and_assign_stmt() | ||||
| 				return p.assign_stmt() | ||||
| 			} | ||||
| 			// `label:`
 | ||||
| 			else if p.tok.kind == .name && p.peek_tok.kind == .colon { | ||||
|  | @ -870,7 +870,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.IndexExpr { | |||
| } | ||||
| 
 | ||||
| fn (p mut Parser) filter() { | ||||
| 	p.scope.register_var(ast.VarDecl{ | ||||
| 	p.scope.register_var(ast.Var{ | ||||
| 		name: 'it' | ||||
| 	}) | ||||
| } | ||||
|  | @ -990,7 +990,7 @@ fn (p mut Parser) for_statement() ast.Stmt { | |||
| 		// mut inc := ast.Stmt{}
 | ||||
| 		mut inc := ast.Expr{} | ||||
| 		if p.peek_tok.kind in [.assign, .decl_assign] { | ||||
| 			init = p.var_decl_and_assign_stmt() | ||||
| 			init = p.assign_stmt() | ||||
| 		} | ||||
| 		else if p.tok.kind != .semicolon {} | ||||
| 		// allow `for ;; i++ {`
 | ||||
|  | @ -1029,7 +1029,7 @@ fn (p mut Parser) for_statement() ast.Stmt { | |||
| 		if p.tok.kind == .comma { | ||||
| 			p.check(.comma) | ||||
| 			val_name = p.check_name() | ||||
| 			p.scope.register_var(ast.VarDecl{ | ||||
| 			p.scope.register_var(ast.Var{ | ||||
| 				name: val_name | ||||
| 				typ: table.int_type | ||||
| 			}) | ||||
|  | @ -1048,7 +1048,7 @@ fn (p mut Parser) for_statement() ast.Stmt { | |||
| 			high_expr = p.expr(0) | ||||
| 		} | ||||
| 		// TODO: update var type in checker
 | ||||
| 		p.scope.register_var(ast.VarDecl{ | ||||
| 		p.scope.register_var(ast.Var{ | ||||
| 			name: var_name | ||||
| 			// expr: cond
 | ||||
| 
 | ||||
|  | @ -1093,7 +1093,7 @@ fn (p mut Parser) if_expr() ast.Expr { | |||
| 		var_name := p.check_name() | ||||
| 		p.check(.decl_assign) | ||||
| 		expr := p.expr(0) | ||||
| 		p.scope.register_var(ast.VarDecl{ | ||||
| 		p.scope.register_var(ast.Var{ | ||||
| 			name: var_name | ||||
| 			expr: expr | ||||
| 		}) | ||||
|  | @ -1508,50 +1508,22 @@ fn (p mut Parser) parse_assign_rhs() []ast.Expr { | |||
| 	return exprs | ||||
| } | ||||
| 
 | ||||
| fn (p mut Parser) var_decl_and_assign_stmt() ast.Stmt { | ||||
| fn (p mut Parser) assign_stmt() ast.Stmt { | ||||
| 	idents := p.parse_assign_lhs() | ||||
| 	op := p.tok.kind | ||||
| 	p.next() // :=, =
 | ||||
| 	exprs := p.parse_assign_rhs() | ||||
| 	is_decl := op == .decl_assign | ||||
| 	// VarDecl
 | ||||
| 	if idents.len == 1 { | ||||
| 		ident := idents[0] | ||||
| 		expr := exprs[0] | ||||
| 		info0 := ident.var_info() | ||||
| 	for ident in idents { | ||||
| 		known_var := p.scope.known_var(ident.name) | ||||
| 		if !is_decl && !known_var { | ||||
| 			p.error('unknown variable `$ident.name`') | ||||
| 		} | ||||
| 		if is_decl && ident.kind != .blank_ident { | ||||
| 			if known_var { | ||||
| 				p.error('redefinition of `$ident.name`') | ||||
| 			} | ||||
| 			p.scope.register_var(ast.VarDecl{ | ||||
| 				name: ident.name | ||||
| 				expr: expr | ||||
| 			}) | ||||
| 		} | ||||
| 		return ast.VarDecl{ | ||||
| 			name: ident.name | ||||
| 			// name2: name2
 | ||||
| 
 | ||||
| 			expr: expr // p.expr(token.lowest_prec)
 | ||||
| 
 | ||||
| 			is_mut: info0.is_mut | ||||
| 			// typ: typ
 | ||||
| 
 | ||||
| 			pos: p.tok.position() | ||||
| 		} | ||||
| 		// return p.var_decl(ident[0], exprs[0])
 | ||||
| 	} | ||||
| 	// AssignStmt
 | ||||
| 	for ident in idents { | ||||
| 		if is_decl && ident.kind != .blank_ident { | ||||
| 			if p.scope.known_var(ident.name) { | ||||
| 				p.error('redefinition of `$ident.name`') | ||||
| 			} | ||||
| 			p.scope.register_var(ast.VarDecl{ | ||||
| 			p.scope.register_var(ast.Var{ | ||||
| 				name: ident.name | ||||
| 			}) | ||||
| 		} | ||||
|  | @ -1564,8 +1536,6 @@ fn (p mut Parser) var_decl_and_assign_stmt() ast.Stmt { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // pub fn (p mut Parser) assign_stmt() ast.AssignStmt {}
 | ||||
| // fn (p mut Parser) var_decl() ast.VarDecl {}
 | ||||
| fn (p mut Parser) hash() ast.HashStmt { | ||||
| 	val := p.tok.lit | ||||
| 	p.next() | ||||
|  | @ -1633,7 +1603,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr { | |||
| 			exprs << ast.Type{ | ||||
| 				typ: typ | ||||
| 			} | ||||
| 			p.scope.register_var(ast.VarDecl{ | ||||
| 			p.scope.register_var(ast.Var{ | ||||
| 				name: 'it' | ||||
| 				typ: typ | ||||
| 			}) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue