v2: start impl multi assign
							parent
							
								
									65744207fc
								
							
						
					
					
						commit
						67a13fc916
					
				|  | @ -14,7 +14,7 @@ AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | |||
| 
 | ||||
| pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | 	 | ||||
| ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | 	 | ||||
| HashStmt | ||||
| HashStmt | AssignStmt | ||||
| // | IncDecStmt k
 | ||||
| // Stand-alone expression in a statement list.
 | ||||
| pub struct ExprStmt { | ||||
|  | @ -195,7 +195,8 @@ pub: | |||
| 
 | ||||
| pub struct IdentVar { | ||||
| pub mut: | ||||
| 	typ  table.TypeRef | ||||
| 	typ    table.TypeRef | ||||
| 	is_mut bool | ||||
| 	//name string
 | ||||
| } | ||||
| 
 | ||||
|  | @ -205,6 +206,7 @@ pub enum IdentKind { | |||
| 	blank_ident | ||||
| 	variable | ||||
| 	constant | ||||
| 	func | ||||
| } | ||||
| 
 | ||||
| // A single identifier
 | ||||
|  | @ -219,6 +221,18 @@ mut: | |||
| 	info     IdentInfo | ||||
| } | ||||
| 
 | ||||
| pub fn(i &Ident) var_info() IdentVar { | ||||
| 	match i.info { | ||||
| 		IdentVar { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			// return IdentVar{}
 | ||||
| 			panic('Ident.var_info(): info is not IdentVar variant') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub struct InfixExpr { | ||||
| pub: | ||||
| // op    BinaryOp
 | ||||
|  | @ -326,14 +340,14 @@ pub: | |||
| 	name string | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| 
 | ||||
| pub struct AssignStmt { | ||||
| pub: | ||||
| 	left  Expr | ||||
| 	right Expr | ||||
| 	left  []Ident | ||||
| 	right []Expr | ||||
| 	op    token.Kind | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| // e.g. `[unsafe_fn]`
 | ||||
| pub struct Attr { | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ fn (c mut Checker) resolve_types() { | |||
| 	// update any types with unresolved sub types
 | ||||
| 	for idx, t in c.table.types { | ||||
| 		if t.kind == .array { | ||||
| 			mut info := t.info as table.Array | ||||
| 			mut info := t.array_info() | ||||
| 			if info.elem_type.typ.kind == .unresolved { | ||||
| 				info.elem_type = c.resolved[info.elem_type.idx] | ||||
| 				mut t1 := &c.table.types[idx] | ||||
|  | @ -55,7 +55,7 @@ fn (c mut Checker) resolve_types() { | |||
| 			} | ||||
| 		} | ||||
| 		else if t.kind == .map { | ||||
| 			mut info := t.info as table.Map | ||||
| 			mut info := t.map_info() | ||||
| 			mut updated := false | ||||
| 			if info.key_type.typ.kind == .unresolved { | ||||
| 				info.key_type = c.resolved[info.key_type.idx] | ||||
|  | @ -71,6 +71,22 @@ fn (c mut Checker) resolve_types() { | |||
| 				t1.info = info | ||||
| 			} | ||||
| 		} | ||||
| 		else if t.kind == .multi_return { | ||||
| 			mut info := t.mr_info() | ||||
| 			mut types := info.types | ||||
| 			mut updated := false | ||||
| 			for i, ut in types { | ||||
| 				if ut.typ.kind == .unresolved { | ||||
| 					types[i] = c.resolved[ut.idx] | ||||
| 					updated = true | ||||
| 				} | ||||
| 			} | ||||
| 			if updated { | ||||
| 				mut t1 := &c.table.types[idx] | ||||
| 				info.types = types | ||||
| 				t1.info = info | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -197,6 +213,8 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {} | ||||
| 
 | ||||
| pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef { | ||||
| 	mut elem_type := c.table.type_ref(table.void_type_idx) | ||||
| 	for i, expr in array_init.exprs { | ||||
|  | @ -224,6 +242,9 @@ fn (c &Checker) stmt(node ast.Stmt) { | |||
| 		ast.Return { | ||||
| 			c.return_stmt(it) | ||||
| 		} | ||||
| 		ast.AssignStmt { | ||||
| 			c.assign_stmt(it) | ||||
| 		} | ||||
| 		ast.VarDecl { | ||||
| 			typ := c.expr(it.expr) | ||||
| 			// println('checker: var decl $typ.name  it.typ=$it.typ.name $it.pos.line_nr')
 | ||||
|  |  | |||
|  | @ -106,6 +106,23 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 			} | ||||
| 			g.writeln(';') | ||||
| 		} | ||||
| 		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(';')
 | ||||
| 			// }
 | ||||
| 		} | ||||
| 		ast.VarDecl { | ||||
| 			g.write('$it.typ.typ.name $it.name = ') | ||||
| 			g.expr(it.expr) | ||||
|  |  | |||
|  | @ -55,6 +55,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) { | |||
| 			} | ||||
| 			g.writeln(';') | ||||
| 		} | ||||
| 		ast.AssignStmt {} | ||||
| 		ast.VarDecl { | ||||
| 			g.write('var /* $it.typ.typ.name */ $it.name = ') | ||||
| 			g.expr(it.expr) | ||||
|  |  | |||
|  | @ -1,9 +1,11 @@ | |||
| multi_return_int_string mr_test(); | ||||
| int testa(); | ||||
| string testb(int a); | ||||
| int testc(int a); | ||||
| int testa(); | ||||
| int testb(); | ||||
| int testa(); | ||||
| 
 | ||||
| int main() { | ||||
|     Bar b = (Bar){ | ||||
|         .a = 122, | ||||
|  | @ -29,7 +31,11 @@ int main() { | |||
|     array_string g = new_array_from_c_array(2, 2, sizeof(array_string), { | ||||
|         testb(1), tos3("hello"), | ||||
|     }); | ||||
| 	return 0; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| multi_return_int_string mr_test() { | ||||
|     return (multi_return_int_string){.arg0=1,.arg1=tos3("v")}; | ||||
| } | ||||
| 
 | ||||
| int testa() { | ||||
|  |  | |||
|  | @ -30,8 +30,13 @@ fn main() { | |||
| 
 | ||||
| 	mut f := [testa(),2,3,4] | ||||
| 	mut g := [testb(1),'hello'] | ||||
| 
 | ||||
| 	m1, m2 := mr_test() | ||||
| } | ||||
| 
 | ||||
| fn mr_test() (int, string) { | ||||
| 	return 1,'v' | ||||
| } | ||||
| 
 | ||||
| fn testa() int { | ||||
| 	return testc(1) | ||||
|  |  | |||
|  | @ -326,6 +326,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { | |||
| 			g.ret() | ||||
| 		} | ||||
| 		ast.Return {} | ||||
| 		ast.AssignStmt {} | ||||
| 		ast.VarDecl {} | ||||
| 		ast.ForStmt {} | ||||
| 		ast.StructDecl {} | ||||
|  |  | |||
|  | @ -242,9 +242,13 @@ pub fn (p mut Parser) stmt() ast.Stmt { | |||
| 		} | ||||
| 		else { | ||||
| 			// `x := ...`
 | ||||
| 			if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] { | ||||
| 			// if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
 | ||||
| 			if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign] { | ||||
| 				return p.var_decl() | ||||
| 			} | ||||
| 			if p.tok.kind == .name && p.peek_tok.kind in [.comma] { | ||||
| 				return p.assign_stmt() | ||||
| 			} | ||||
| 			expr,typ := p.expr(0) | ||||
| 			return ast.ExprStmt{ | ||||
| 				expr: expr | ||||
|  | @ -370,6 +374,60 @@ pub fn (p &Parser) warn(s string) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) { | ||||
| 	mut node := ast.Ident{} | ||||
| 	mut typ := p.table.type_ref(table.void_type_idx) | ||||
| 	// p.warn('name ')
 | ||||
| 	// left := p.parse_ident()
 | ||||
| 	name := p.check_name() | ||||
| 	mut ident := ast.Ident{ | ||||
| 		name: name | ||||
| 	} | ||||
| 	mut known_var := false | ||||
| 	if var := p.table.find_var(name) { | ||||
| 		known_var = true | ||||
| 		typ = var.typ | ||||
| 	}  | ||||
| 	// variable
 | ||||
| 	if known_var || p.tok.kind in [.comma, .decl_assign, .assign] { | ||||
| 		// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
 | ||||
| 		ident.kind = .variable | ||||
| 		ident.info = ast.IdentVar{ | ||||
| 			typ: typ | ||||
| 			// name: ident.name
 | ||||
| 			// expr: p.expr(0)// var.expr
 | ||||
| 		} | ||||
| 		return ident, typ | ||||
| 	}else{ | ||||
| 		if is_c { | ||||
| 			typ = p.table.type_ref(table.int_type_idx) | ||||
| 			ident.info = ast.IdentVar{ | ||||
| 				typ: typ | ||||
| 				// name: ident.name
 | ||||
| 			} | ||||
| 			return ident,typ | ||||
| 		} | ||||
| 		// const
 | ||||
| 		if c := p.table.find_const(name) { | ||||
| 			typ = c.typ | ||||
| 			ident.kind = .constant | ||||
| 			ident.info = ast.IdentVar{ | ||||
| 				typ: typ | ||||
| 				// name: ident.name
 | ||||
| 			} | ||||
| 			node = ident | ||||
| 		}else{ | ||||
| 			// Function object (not a call), e.g. `onclick(my_click)`
 | ||||
| 			p.table.find_fn(name) or { | ||||
| 				p.error('parse_ident: unknown identifier `$name`') | ||||
| 				exit(0) | ||||
| 			} | ||||
| 			// p.next()
 | ||||
| 		} | ||||
| 	} | ||||
| 	return node, typ | ||||
| } | ||||
| 
 | ||||
| pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { | ||||
| 	mut node := ast.Expr{} | ||||
| 	mut typ := p.table.type_ref(table.void_type_idx) | ||||
|  | @ -425,54 +483,9 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { | |||
| 		p.check(.rcbr) | ||||
| 	} | ||||
| 	else { | ||||
| 		// p.warn('name ')
 | ||||
| 		// left := p.parse_ident()
 | ||||
| 		mut ident := ast.Ident{ | ||||
| 			name: p.tok.lit | ||||
| 		} | ||||
| 		// variable
 | ||||
| 		if var := p.table.find_var(p.tok.lit) { | ||||
| 			// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
 | ||||
| 			typ = var.typ | ||||
| 			ident.kind = .variable | ||||
| 			ident.info = ast.IdentVar{ | ||||
| 				typ: typ | ||||
| 				// name: ident.name
 | ||||
| 				// expr: p.expr(0)// var.expr
 | ||||
| 			} | ||||
| 			// ident.ti = ti
 | ||||
| 			node = ident | ||||
| 			p.next() | ||||
| 		}else{ | ||||
| 			if is_c { | ||||
| 				typ = p.table.type_ref(table.int_type_idx) | ||||
| 				ident.info = ast.IdentVar{ | ||||
| 					typ: typ | ||||
| 					// name: ident.name
 | ||||
| 				} | ||||
| 				node = ident | ||||
| 				p.next() | ||||
| 				return node,typ | ||||
| 			} | ||||
| 			// const
 | ||||
| 			if c := p.table.find_const(p.tok.lit) { | ||||
| 				typ = c.typ | ||||
| 				ident.kind = .constant | ||||
| 				ident.info = ast.IdentVar{ | ||||
| 					typ: typ | ||||
| 					// name: ident.name
 | ||||
| 				} | ||||
| 				node = ident | ||||
| 				p.next() | ||||
| 			}else{ | ||||
| 				// Function object (not a call), e.g. `onclick(my_click)`
 | ||||
| 				p.table.find_fn(p.tok.lit) or { | ||||
| 					p.error('name expr unknown identifier `$p.tok.lit`') | ||||
| 					exit(0) | ||||
| 				} | ||||
| 				p.next() | ||||
| 			} | ||||
| 		} | ||||
| 		mut ident := ast.Ident{} | ||||
| 		ident, typ = p.parse_ident(is_c) | ||||
| 		node = ident | ||||
| 	} | ||||
| 	return node,typ | ||||
| } | ||||
|  | @ -1047,7 +1060,6 @@ fn (p mut Parser) return_stmt() ast.Return { | |||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO: consider non deferred
 | ||||
| 	stmt := ast.Return{ | ||||
| 		expected_type: p.return_type | ||||
| 		exprs: exprs | ||||
|  | @ -1056,6 +1068,26 @@ fn (p mut Parser) return_stmt() ast.Return { | |||
| 	return stmt | ||||
| } | ||||
| 
 | ||||
| pub fn (p mut Parser) assign_stmt() ast.AssignStmt { | ||||
| 	// TODO: multiple return & multiple assign
 | ||||
| 	mut idents := []ast.Ident | ||||
| 	for { | ||||
| 		ident, _ := p.parse_ident(false) | ||||
| 		idents << ident | ||||
| 		if p.tok.kind == .comma { | ||||
| 			p.check(.comma) | ||||
| 		} else { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	p.next() // :=, =
 | ||||
| 	expr, _ := p.expr(0) | ||||
| 	return ast.AssignStmt{ | ||||
| 		left: idents | ||||
| 		right: [expr] | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (p mut Parser) var_decl() ast.VarDecl { | ||||
| 	is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for
 | ||||
| 	// is_static := p.tok.kind == .key_static
 | ||||
|  | @ -1076,8 +1108,6 @@ fn (p mut Parser) var_decl() ast.VarDecl { | |||
| 	p.table.register_var(table.Var{ | ||||
| 		name: name | ||||
| 		is_mut: is_mut | ||||
| 		// expr: expr
 | ||||
| 		 | ||||
| 		typ: typ | ||||
| 	}) | ||||
| 	p.warn('var decl name=$name typ=$typ.typ.name') | ||||
|  | @ -1170,7 +1200,7 @@ fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.TypeRef { | |||
| 		typ: &table.Type{ | ||||
| 			parent: 0 | ||||
| 			kind: .unresolved | ||||
| 			name: 'unresolved $p.unresolved.len' | ||||
| 			name: 'unresolved $idx' | ||||
| 		} | ||||
| 	} | ||||
| 	return t | ||||
|  |  | |||
|  | @ -77,6 +77,54 @@ pub enum Kind { | |||
| 	unresolved | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn(t &Type) mr_info() MultiReturn { | ||||
| 	match t.info { | ||||
| 		MultiReturn { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('Type.mr_info(): no multi return info') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn(t &Type) array_info() Array { | ||||
| 	match t.info { | ||||
| 		Array { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('Type.mr_info(): no array info') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn(t &Type) array_fixed_info() ArrayFixed { | ||||
| 	match t.info { | ||||
| 		ArrayFixed { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('Type.mr_info(): no array fixed info') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn(t &Type) map_info() Map { | ||||
| 	match t.info { | ||||
| 		Map { | ||||
| 			return it | ||||
| 		} | ||||
| 		else { | ||||
| 			panic('Type.mr_info(): no map info') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn (t Type) str() string { | ||||
| 	return t.name | ||||
|  | @ -395,6 +443,7 @@ pub mut: | |||
| pub struct MultiReturn { | ||||
| pub: | ||||
| 	name  string | ||||
| mut: | ||||
| 	types []TypeRef | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue