all: remove old sumtype code (#6937)
							parent
							
								
									aa6303f0b2
								
							
						
					
					
						commit
						a042966082
					
				|  | @ -7,7 +7,7 @@ import v.token | |||
| import v.table | ||||
| import v.errors | ||||
| 
 | ||||
| pub __type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl | UnionSumTypeDecl | ||||
| pub __type TypeDecl = AliasTypeDecl | FnTypeDecl | UnionSumTypeDecl | ||||
| 
 | ||||
| pub __type Expr = AnonFn | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral | CTempVar | | ||||
| 	CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | | ||||
|  | @ -529,15 +529,14 @@ pub mut: | |||
| 
 | ||||
| pub struct IfBranch { | ||||
| pub: | ||||
| 	cond         Expr | ||||
| 	pos          token.Position | ||||
| 	body_pos     token.Position | ||||
| 	comments     []Comment | ||||
| 	left_as_name string // `name` in `if cond is SumType as name`
 | ||||
| 	is_mut_name  bool // `if mut name is`
 | ||||
| 	cond        Expr | ||||
| 	pos         token.Position | ||||
| 	body_pos    token.Position | ||||
| 	comments    []Comment | ||||
| 	is_mut_name bool // `if mut name is`
 | ||||
| pub mut: | ||||
| 	stmts        []Stmt | ||||
| 	smartcast    bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
 | ||||
| 	stmts       []Stmt | ||||
| 	smartcast   bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
 | ||||
| } | ||||
| 
 | ||||
| pub struct UnsafeExpr { | ||||
|  | @ -564,8 +563,7 @@ pub: | |||
| 	branches       []MatchBranch | ||||
| 	pos            token.Position | ||||
| 	is_mut         bool // `match mut ast_node {`
 | ||||
| 	var_name       string // `match cond as var_name {`
 | ||||
| 	is_union_match bool // temporary union key after match
 | ||||
| 	is_union_match bool // TODO: remove
 | ||||
| pub mut: | ||||
| 	is_expr        bool // returns a value
 | ||||
| 	return_type    table.Type | ||||
|  | @ -748,15 +746,6 @@ pub: | |||
| 	comments    []Comment | ||||
| } | ||||
| 
 | ||||
| pub struct SumTypeDecl { | ||||
| pub: | ||||
| 	name      string | ||||
| 	is_pub    bool | ||||
| 	sub_types []table.Type | ||||
| 	pos       token.Position | ||||
| 	comments  []Comment | ||||
| } | ||||
| 
 | ||||
| // New implementation of sum types
 | ||||
| pub struct UnionSumTypeDecl { | ||||
| pub: | ||||
|  | @ -1152,7 +1141,7 @@ pub fn (stmt Stmt) position() token.Position { | |||
| 		AssertStmt, AssignStmt, Block, BranchStmt, CompFor, ConstDecl, DeferStmt, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, GotoLabel, GotoStmt, Import, Return, StructDecl, GlobalDecl, HashStmt, InterfaceDecl, Module, SqlStmt { return stmt.pos } | ||||
| 		GoStmt { return stmt.call_expr.position() } | ||||
| 		TypeDecl { match union stmt { | ||||
| 				AliasTypeDecl, FnTypeDecl, SumTypeDecl, UnionSumTypeDecl { return stmt.pos } | ||||
| 				AliasTypeDecl, FnTypeDecl, UnionSumTypeDecl { return stmt.pos } | ||||
| 			} } | ||||
| 		// Please, do NOT use else{} here.
 | ||||
| 		// This match is exhaustive *on purpose*, to help force
 | ||||
|  |  | |||
|  | @ -325,7 +325,7 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte { | |||
| 		} | ||||
| 		if ftyp in [table.string_type, table.bool_type] || | ||||
| 			sym.kind in | ||||
| 			[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type] || ftyp.has_flag(.optional) || | ||||
| 			[.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .union_sum_type] || ftyp.has_flag(.optional) || | ||||
| 			sym.has_method('str') { | ||||
| 			return `s` | ||||
| 		} else { | ||||
|  |  | |||
|  | @ -237,7 +237,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool { | |||
| 					if stmt.is_pub { | ||||
| 						c.warn('type alias `$stmt.name` $no_pub_in_main_warning', stmt.pos) | ||||
| 					} | ||||
| 				} else if stmt is ast.SumTypeDecl { | ||||
| 				} else if stmt is ast.UnionSumTypeDecl { | ||||
| 					if stmt.is_pub { | ||||
| 						c.warn('sum type `$stmt.name` $no_pub_in_main_warning', stmt.pos) | ||||
| 					} | ||||
|  | @ -311,17 +311,6 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) { | |||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ast.SumTypeDecl { | ||||
| 			c.check_valid_pascal_case(node.name, 'sum type', node.pos) | ||||
| 			for typ in node.sub_types { | ||||
| 				typ_sym := c.table.get_type_symbol(typ) | ||||
| 				if typ_sym.kind == .placeholder { | ||||
| 					c.error("type `$typ_sym.source_name` doesn't exist", node.pos) | ||||
| 				} else if typ_sym.kind == .interface_ { | ||||
| 					c.error('sum type cannot hold an interface', node.pos) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ast.UnionSumTypeDecl { | ||||
| 			c.check_valid_pascal_case(node.name, 'sum type', node.pos) | ||||
| 			for typ in node.sub_types { | ||||
|  | @ -456,7 +445,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { | |||
| 		c.error('unknown type', struct_init.pos) | ||||
| 	} | ||||
| 	type_sym := c.table.get_type_symbol(struct_init.typ) | ||||
| 	if type_sym.kind == .sum_type && struct_init.fields.len == 1 { | ||||
| 	if type_sym.kind == .union_sum_type && struct_init.fields.len == 1 { | ||||
| 		sexpr := struct_init.fields[0].expr.str() | ||||
| 		c.error('cast to sum type using `${type_sym.source_name}($sexpr)` not `$type_sym.source_name{$sexpr}`', | ||||
| 			struct_init.pos) | ||||
|  | @ -804,12 +793,11 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { | |||
| 				c.error('$infix_expr.op.str(): type `$typ_sym.source_name` does not exist', | ||||
| 					type_expr.pos) | ||||
| 			} | ||||
| 			if left.kind !in [.interface_, .sum_type, .union_sum_type] { | ||||
| 			if left.kind !in [.interface_, .union_sum_type] { | ||||
| 				c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types', | ||||
| 					infix_expr.pos) | ||||
| 			} else if left.kind == .union_sum_type { | ||||
| 				info := left.info as table.UnionSumType | ||||
| 				if type_expr.typ !in info.variants { | ||||
| 			} else if mut left.info is table.UnionSumType { | ||||
| 				if type_expr.typ !in left.info.variants { | ||||
| 					c.error('`$left.source_name` has no variant `$right.source_name`', | ||||
| 						infix_expr.pos) | ||||
| 				} | ||||
|  | @ -1110,7 +1098,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { | |||
| 		c.error('optional type cannot be called directly', call_expr.left.position()) | ||||
| 		return table.void_type | ||||
| 	} | ||||
| 	if left_type_sym.kind == .sum_type && method_name == 'type_name' { | ||||
| 	if left_type_sym.kind == .union_sum_type && method_name == 'type_name' { | ||||
| 		return table.string_type | ||||
| 	} | ||||
| 	// TODO: remove this for actual methods, use only for compiler magic
 | ||||
|  | @ -2294,7 +2282,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type { | |||
| 		if array_init.has_default { | ||||
| 			c.expr(array_init.default_expr) | ||||
| 		} | ||||
| 		if sym.kind in [.sum_type, .union_sum_type] { | ||||
| 		if sym.kind == .union_sum_type { | ||||
| 			if array_init.has_len && !array_init.has_default { | ||||
| 				c.error('cannot initalize sum type array without default value', array_init.elem_type_pos) | ||||
| 			} | ||||
|  | @ -2799,7 +2787,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { | |||
| 			node.expr_type = c.expr(node.expr) | ||||
| 			expr_type_sym := c.table.get_type_symbol(node.expr_type) | ||||
| 			type_sym := c.table.get_type_symbol(node.typ) | ||||
| 			if expr_type_sym.kind == .sum_type || expr_type_sym.kind == .union_sum_type { | ||||
| 			if expr_type_sym.kind == .union_sum_type { | ||||
| 				if type_sym.kind == .placeholder { | ||||
| 					// Unknown type used in the right part of `as`
 | ||||
| 					c.error('unknown type `$type_sym.source_name`', node.pos) | ||||
|  | @ -2811,7 +2799,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { | |||
| 				} | ||||
| 			} else { | ||||
| 				mut s := 'cannot cast non-sum type `$expr_type_sym.source_name` using `as`' | ||||
| 				if type_sym.kind == .sum_type || expr_type_sym.kind == .union_sum_type { | ||||
| 				if type_sym.kind == .union_sum_type { | ||||
| 					s += ' - use e.g. `${type_sym.source_name}(some_expr)` instead.' | ||||
| 				} | ||||
| 				c.error(s, node.pos) | ||||
|  | @ -3066,7 +3054,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) table.Type { | |||
| 		c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.', | ||||
| 			node.pos) | ||||
| 	} | ||||
| 	if to_type_sym.kind == .sum_type || to_type_sym.kind == .union_sum_type { | ||||
| 	if to_type_sym.kind == .union_sum_type { | ||||
| 		if node.expr_type in [table.any_int_type, table.any_flt_type] { | ||||
| 			node.expr_type = c.promote_num(node.expr_type, if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type }) | ||||
| 		} | ||||
|  | @ -3377,7 +3365,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type { | |||
| 		c.error('compiler bug: match 0 cond type', node.pos) | ||||
| 	} | ||||
| 	cond_type_sym := c.table.get_type_symbol(cond_type) | ||||
| 	if cond_type_sym.kind !in [.sum_type, .interface_, .union_sum_type] { | ||||
| 	if cond_type_sym.kind !in [.interface_, .union_sum_type] { | ||||
| 		node.is_sum_type = false | ||||
| 	} | ||||
| 	c.match_exprs(mut node, cond_type_sym) | ||||
|  | @ -3599,8 +3587,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol | |||
| 						// smartcast either if the value is immutable or if the mut argument is explicitly given
 | ||||
| 						if (!is_mut || node.is_mut) && !is_already_casted { | ||||
| 							sum_type_casts << expr_type | ||||
| 							scope.register(node.var_name, ast.Var{ | ||||
| 								name: node.var_name | ||||
| 							scope.register(node.cond.name, ast.Var{ | ||||
| 								name: node.cond.name | ||||
| 								typ: node.cond_type | ||||
| 								pos: node.cond.pos | ||||
| 								is_used: true | ||||
|  | @ -3621,15 +3609,6 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol | |||
| 	mut is_exhaustive := true | ||||
| 	mut unhandled := []string{} | ||||
| 	match union mut type_sym.info { | ||||
| 		table.SumType { | ||||
| 			for v in type_sym.info.variants { | ||||
| 				v_str := c.table.type_to_str(v) | ||||
| 				if v_str !in branch_exprs { | ||||
| 					is_exhaustive = false | ||||
| 					unhandled << '`$v_str`' | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		table.UnionSumType { | ||||
| 			for v in type_sym.info.variants { | ||||
| 				v_str := c.table.type_to_str(v) | ||||
|  | @ -3833,7 +3812,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { | |||
| 					is_variable := if mut infix.left is ast.Ident { infix.left.kind == .variable } else { true } | ||||
| 					// Register shadow variable or `as` variable with actual type
 | ||||
| 					if is_variable { | ||||
| 						if left_sym.kind in [.sum_type, .interface_, .union_sum_type] { | ||||
| 						if left_sym.kind in [.interface_, .union_sum_type] { | ||||
| 							mut is_mut := false | ||||
| 							mut scope := c.file.scope.innermost(branch.body_pos.pos) | ||||
| 							if mut infix.left is ast.Ident { | ||||
|  | @ -3842,18 +3821,30 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { | |||
| 									is_mut = v.is_mut | ||||
| 									sum_type_casts << v.sum_type_casts | ||||
| 								} | ||||
| 								// smartcast either if the value is immutable or if the mut argument is explicitly given
 | ||||
| 								if (!is_mut || branch.is_mut_name) && | ||||
| 									left_sym.kind == .union_sum_type { | ||||
| 									sum_type_casts << right_expr.typ | ||||
| 									scope.register(branch.left_as_name, ast.Var{ | ||||
| 										name: branch.left_as_name | ||||
| 										typ: infix.left_type | ||||
| 								if left_sym.kind == .union_sum_type { | ||||
| 									// smartcast either if the value is immutable or if the mut argument is explicitly given
 | ||||
| 									if !is_mut || branch.is_mut_name { | ||||
| 										sum_type_casts << right_expr.typ | ||||
| 										scope.register(infix.left.name, ast.Var{ | ||||
| 											name: infix.left.name | ||||
| 											typ: infix.left_type | ||||
| 											sum_type_casts: sum_type_casts | ||||
| 											pos: infix.left.pos | ||||
| 											is_used: true | ||||
| 											is_mut: is_mut | ||||
| 										}) | ||||
| 									} | ||||
| 								} else if left_sym.kind == .interface_ { | ||||
| 									scope.register(infix.left.name, ast.Var{ | ||||
| 										name: infix.left.name | ||||
| 										typ: right_expr.typ.to_ptr() | ||||
| 										sum_type_casts: sum_type_casts | ||||
| 										pos: infix.left.pos | ||||
| 										is_used: true | ||||
| 										is_mut: is_mut | ||||
| 									}) | ||||
| 									// TODO: remove that later @danieldaeschle
 | ||||
| 									node.branches[i].smartcast = true | ||||
| 								} | ||||
| 							} else if mut infix.left is ast.SelectorExpr { | ||||
| 								mut sum_type_casts := []table.Type{} | ||||
|  | @ -3881,16 +3872,6 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { | |||
| 									}) | ||||
| 								} | ||||
| 							} | ||||
| 							if left_sym.kind != .union_sum_type && branch.left_as_name.len > 0 { | ||||
| 								scope.register(branch.left_as_name, ast.Var{ | ||||
| 									name: branch.left_as_name | ||||
| 									typ: right_expr.typ.to_ptr() | ||||
| 									pos: infix.left.position() | ||||
| 									is_used: true | ||||
| 									is_mut: is_mut | ||||
| 								}) | ||||
| 								node.branches[i].smartcast = true | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | @ -4068,7 +4049,7 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool { | |||
| 				return false // TODO
 | ||||
| 			} else if cond.name in valid_comp_if_other { | ||||
| 				// TODO: This should probably be moved
 | ||||
| 				match cond.name as name { | ||||
| 				match cond.name { | ||||
| 					'js' { return c.pref.backend != .js } | ||||
| 					'debug' { return !c.pref.is_debug } | ||||
| 					'test' { return !c.pref.is_test } | ||||
|  | @ -4525,7 +4506,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { | |||
| 		if sym.kind == .interface_ { | ||||
| 			c.error('interfaces cannot be used as method receiver', node.receiver_pos) | ||||
| 		} | ||||
| 		if sym.kind == .sum_type && node.name == 'type_name' { | ||||
| 		if sym.kind == .union_sum_type && node.name == 'type_name' { | ||||
| 			c.error('method overrides built-in sum type method', node.pos) | ||||
| 		} | ||||
| 		// if sym.has_method(node.name) {
 | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| vlib/v/checker/tests/is_type_invalid.vv:14:2: error: cannot use type `byte` as type `IoS` | ||||
| vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte` | ||||
|    12 | | ||||
|    13 | fn main() { | ||||
|    14 |     if IoS(1) is byte { | ||||
|       |     ~~~~~~~~~~~~~~~~~ | ||||
|       |               ~~ | ||||
|    15 |         println('not cool') | ||||
|    16 |     } | ||||
| vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement method `speak` | ||||
|  | @ -11,4 +11,4 @@ vlib/v/checker/tests/is_type_invalid.vv:18:2: error: `Cat` doesn't implement met | |||
|    18 |     if a is Cat { | ||||
|       |     ~~~~~~~~~~~ | ||||
|    19 |         println('not cool either') | ||||
|    20 |     } | ||||
|    20 |     } | ||||
|  | @ -1,4 +1,4 @@ | |||
| vlib/v/checker/tests/match_invalid_type.vv:5:3: error: cannot match `byte` with `IoS` condition | ||||
| vlib/v/checker/tests/match_invalid_type.vv:5:3: error: `IoS` has no variant `byte` | ||||
|     3 | fn sum() { | ||||
|     4 |     match IoS(1) { | ||||
|     5 |         byte { | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| vlib/v/checker/tests/match_sumtype_multiple_types.vv:25:13: error: type `Charlie` has no field or method `char` | ||||
|    23 |     match NATOAlphabet(a) as l { | ||||
|    24 |         Alfa, Charlie { | ||||
|    25 |             assert l.char == `a` | ||||
| vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: type `Charlie` has no field or method `char` | ||||
|    24 |     match l { | ||||
|    25 |         Alfa, Charlie { | ||||
|    26 |             assert l.char == `a` | ||||
|       |                      ~~~~ | ||||
|    26 |             assert l.letter() == 'a' | ||||
|    27 |         } | ||||
| vlib/v/checker/tests/match_sumtype_multiple_types.vv:26:13: error: unknown method: `Charlie.letter` | ||||
|    24 |         Alfa, Charlie { | ||||
|    25 |             assert l.char == `a` | ||||
|    26 |             assert l.letter() == 'a' | ||||
|    27 |             assert l.letter() == 'a' | ||||
|    28 |         } | ||||
| vlib/v/checker/tests/match_sumtype_multiple_types.vv:27:13: error: unknown method: `Charlie.letter` | ||||
|    25 |         Alfa, Charlie { | ||||
|    26 |             assert l.char == `a` | ||||
|    27 |             assert l.letter() == 'a' | ||||
|       |                      ~~~~~~~~~ | ||||
|    27 |         } | ||||
|    28 |         Bravo { | ||||
|    28 |         } | ||||
|    29 |         Bravo { | ||||
|  | @ -20,7 +20,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie | |||
| 
 | ||||
| fn method_not_exists() { | ||||
| 	a := Alfa{} | ||||
| 	match NATOAlphabet(a) as l { | ||||
| 	l := NATOAlphabet(a) | ||||
| 	match l { | ||||
| 		Alfa, Charlie { | ||||
| 			assert l.char == `a` | ||||
| 			assert l.letter() == 'a' | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ pub fn (d Doc) stmt_name(stmt ast.Stmt) string { | |||
| 	match union stmt { | ||||
| 		ast.FnDecl, ast.StructDecl, ast.EnumDecl, ast.InterfaceDecl { return stmt.name } | ||||
| 		ast.TypeDecl { match union stmt { | ||||
| 				ast.SumTypeDecl, ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name } | ||||
| 				ast.FnTypeDecl, ast.AliasTypeDecl, ast.UnionSumTypeDecl { return stmt.name } | ||||
| 			} } | ||||
| 		ast.ConstDecl { return '' } // leave it blank
 | ||||
| 		else { return '' } | ||||
|  |  | |||
|  | @ -454,7 +454,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) { | |||
| 			f.write('sql ') | ||||
| 			f.expr(node.db_expr) | ||||
| 			f.writeln(' {') | ||||
| 			match node.kind as k { | ||||
| 			match node.kind { | ||||
| 				.insert { | ||||
| 					f.writeln('\tinsert $node.object_var_name into ${util.strip_mod_name(node.table_name)}') | ||||
| 				} | ||||
|  | @ -544,26 +544,6 @@ pub fn (mut f Fmt) type_decl(node ast.TypeDecl) { | |||
| 			} | ||||
| 			comments << node.comments | ||||
| 		} | ||||
| 		ast.SumTypeDecl { | ||||
| 			if node.is_pub { | ||||
| 				f.write('pub ') | ||||
| 			} | ||||
| 			f.write('type $node.name = ') | ||||
| 			mut sum_type_names := []string{} | ||||
| 			for t in node.sub_types { | ||||
| 				sum_type_names << f.table.type_to_str(t) | ||||
| 			} | ||||
| 			sum_type_names.sort() | ||||
| 			for i, name in sum_type_names { | ||||
| 				f.write(name) | ||||
| 				if i < sum_type_names.len - 1 { | ||||
| 					f.write(' | ') | ||||
| 				} | ||||
| 				f.wrap_long_line(2, true) | ||||
| 			} | ||||
| 			// f.write(sum_type_names.join(' | '))
 | ||||
| 			comments << node.comments | ||||
| 		} | ||||
| 		ast.UnionSumTypeDecl { | ||||
| 			if node.is_pub { | ||||
| 				f.write('pub ') | ||||
|  | @ -1412,15 +1392,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) { | |||
| 		(it.is_expr || f.is_assign) | ||||
| 	f.single_line_if = single_line | ||||
| 	for i, branch in it.branches { | ||||
| 		// Check `sum is T` smartcast
 | ||||
| 		mut smartcast_as := false | ||||
| 		if branch.cond is ast.InfixExpr { | ||||
| 			if branch.cond.op == .key_is { | ||||
| 				// left_as_name is either empty, branch.cond.left.str() or the `as` name
 | ||||
| 				smartcast_as = branch.left_as_name.len > 0 && | ||||
| 					branch.cond.left.str() != branch.left_as_name | ||||
| 			} | ||||
| 		} | ||||
| 		if i == 0 { | ||||
| 			// first `if`
 | ||||
| 			f.comments(branch.comments, {}) | ||||
|  | @ -1440,9 +1411,6 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) { | |||
| 				f.write('mut ') | ||||
| 			} | ||||
| 			f.expr(branch.cond) | ||||
| 			if smartcast_as { | ||||
| 				f.write(' as $branch.left_as_name') | ||||
| 			} | ||||
| 			f.write(' ') | ||||
| 		} | ||||
| 		f.write('{') | ||||
|  | @ -1560,7 +1528,6 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) { | |||
| 
 | ||||
| pub fn (mut f Fmt) match_expr(it ast.MatchExpr) { | ||||
| 	f.write('match ') | ||||
| 	// TODO: temporary, remove again
 | ||||
| 	if it.is_union_match { | ||||
| 		f.write('union ') | ||||
| 	} | ||||
|  | @ -1570,12 +1537,6 @@ pub fn (mut f Fmt) match_expr(it ast.MatchExpr) { | |||
| 	f.expr(it.cond) | ||||
| 	if it.cond is ast.Ident { | ||||
| 		f.it_name = it.cond.name | ||||
| 	} else if it.cond is ast.SelectorExpr { | ||||
| 		// `x.y as z`
 | ||||
| 		// if ident.name != it.var_name && it.var_name != '' {
 | ||||
| 	} | ||||
| 	if it.var_name != '' && f.it_name != it.var_name { | ||||
| 		f.write(' as $it.var_name') | ||||
| 	} | ||||
| 	f.writeln(' {') | ||||
| 	f.indent++ | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ struct IfExpr { | |||
| struct MatchExpr { | ||||
| } | ||||
| 
 | ||||
| type Expr = IfExpr | MatchExpr | ||||
| __type Expr = IfExpr | MatchExpr | ||||
| 
 | ||||
| fn sum_types(a []Expr) { | ||||
| } | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ fn handle_users(users []User) { | |||
| fn (u &User) foo(u2 &User) { | ||||
| } | ||||
| 
 | ||||
| type Expr = IfExpr | IntegerLiteral | ||||
| __type Expr = IfExpr | IntegerLiteral | ||||
| 
 | ||||
| fn exprs(e []Expr) { | ||||
| 	println(e.len) | ||||
|  |  | |||
|  | @ -6,17 +6,15 @@ mut: | |||
| struct S2 { | ||||
| } | ||||
| 
 | ||||
| type Sum = S1 | S2 | ||||
| __type Sum = S1 | S2 | ||||
| 
 | ||||
| fn f(sum Sum) { | ||||
| 	if mut sum is S1 { | ||||
| 		sum.i++ | ||||
| 	} | ||||
| 	if sum is S1 as s1 { | ||||
| 	if sum is S1 { | ||||
| 	} | ||||
| 	a := [sum] | ||||
| 	if a[0] is S2 { | ||||
| 	} | ||||
| 	if a[0] is S2 as s2 { | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| // Sumtype
 | ||||
| type FooBar = Bar | Foo | ||||
| __type FooBar = Bar | Foo | ||||
| 
 | ||||
| pub type PublicBar = Bar | Foo | FooBar | ||||
| pub __type PublicBar = Bar | Foo | FooBar | ||||
| 
 | ||||
| type Uint = byte | u16 | u32 | u64 // This should stay on the same line
 | ||||
| __type Uint = byte | u16 | u32 | u64 | ||||
| 
 | ||||
| type Float = f32 | f64 | ||||
| __type Float = f32 | f64 | ||||
| 
 | ||||
| // Alias type
 | ||||
| type MyInt = int | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 
 | ||||
| type   Uint =   u16 | u64 | ||||
| 	| u32 | ||||
| 	    | byte // This should stay on the same line
 | ||||
| 	    | byte | ||||
| type | ||||
| Float = | ||||
| 	f32 | | ||||
|  |  | |||
|  | @ -73,9 +73,6 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string { | |||
| 			table.MultiReturn { | ||||
| 				g.gen_str_for_multi_return(sym.info, styp, str_fn_name) | ||||
| 			} | ||||
| 			table.SumType { | ||||
| 				g.gen_str_for_sum_type(sym.info, styp, str_fn_name) | ||||
| 			} | ||||
| 			table.UnionSumType { | ||||
| 				g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name) | ||||
| 			} | ||||
|  | @ -441,7 +438,7 @@ fn struct_auto_str_func(sym table.TypeSymbol, field_type table.Type, fn_name str | |||
| 			return '${fn_name}($obj)' | ||||
| 		} | ||||
| 		return 'indent_${fn_name}($obj, indent_count + 1)' | ||||
| 	} else if sym.kind in [.array, .array_fixed, .map, .sum_type] { | ||||
| 	} else if sym.kind in [.array, .array_fixed, .map, .union_sum_type] { | ||||
| 		if has_custom_str { | ||||
| 			return '${fn_name}(it->${c_name(field_name)})' | ||||
| 		} | ||||
|  | @ -485,50 +482,6 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string | |||
| 	g.auto_str_funcs.writeln('}') | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) gen_str_for_sum_type(info table.SumType, styp string, str_fn_name string) { | ||||
| 	mut gen_fn_names := map[string]string{} | ||||
| 	for typ in info.variants { | ||||
| 		sym := g.table.get_type_symbol(typ) | ||||
| 		if !sym.has_method('str') { | ||||
| 			field_styp := g.typ(typ) | ||||
| 			field_fn_name := g.gen_str_for_type_with_styp(typ, field_styp) | ||||
| 			gen_fn_names[field_styp] = field_fn_name | ||||
| 		} | ||||
| 	} | ||||
| 	// _str() functions should have a single argument, the indenting ones take 2:
 | ||||
| 	g.type_definitions.writeln('string ${str_fn_name}($styp x); // auto') | ||||
| 	g.auto_str_funcs.writeln('string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0); }') | ||||
| 	g.type_definitions.writeln('string indent_${str_fn_name}($styp x, int indent_count); // auto') | ||||
| 	g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp x, int indent_count) {') | ||||
| 	mut clean_sum_type_v_type_name := styp.replace('__', '.') | ||||
| 	if styp.ends_with('*') { | ||||
| 		clean_sum_type_v_type_name = '&' + clean_sum_type_v_type_name.replace('*', '') | ||||
| 	} | ||||
| 	clean_sum_type_v_type_name = util.strip_main_name(clean_sum_type_v_type_name) | ||||
| 	g.auto_str_funcs.writeln('\tswitch(x.typ) {') | ||||
| 	for typ in info.variants { | ||||
| 		mut value_fmt := '%.*s\\000' | ||||
| 		if typ == table.string_type { | ||||
| 			value_fmt = "\'$value_fmt\'" | ||||
| 		} | ||||
| 		typ_str := g.typ(typ) | ||||
| 		mut func_name := if typ_str in gen_fn_names { gen_fn_names[typ_str] } else { g.gen_str_for_type_with_styp(typ, | ||||
| 				typ_str) } | ||||
| 		sym := g.table.get_type_symbol(typ) | ||||
| 		if sym.kind == .struct_ { | ||||
| 			func_name = 'indent_$func_name' | ||||
| 		} | ||||
| 		g.auto_str_funcs.write('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(*($typ_str*)x._object') | ||||
| 		if sym.kind == .struct_ { | ||||
| 			g.auto_str_funcs.write(', indent_count') | ||||
| 		} | ||||
| 		g.auto_str_funcs.writeln('));') | ||||
| 	} | ||||
| 	g.auto_str_funcs.writeln('\t\tdefault: return tos_lit("unknown sum type value");') | ||||
| 	g.auto_str_funcs.writeln('\t}') | ||||
| 	g.auto_str_funcs.writeln('}') | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) gen_str_for_union_sum_type(info table.UnionSumType, styp string, str_fn_name string) { | ||||
| 	mut gen_fn_names := map[string]string{} | ||||
| 	for typ in info.variants { | ||||
|  |  | |||
|  | @ -370,22 +370,6 @@ pub fn (mut g Gen) finish() { | |||
| pub fn (mut g Gen) write_typeof_functions() { | ||||
| 	g.writeln('') | ||||
| 	g.writeln('// >> typeof() support for sum types') | ||||
| 	for typ in g.table.types { | ||||
| 		if typ.kind == .sum_type { | ||||
| 			sum_info := typ.info as table.SumType | ||||
| 			tidx := g.table.find_type_idx(typ.name) | ||||
| 			g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ') | ||||
| 			g.writeln('	switch(sidx) {') | ||||
| 			g.writeln('		case $tidx: return "${util.strip_main_name(typ.name)}";') | ||||
| 			for v in sum_info.variants { | ||||
| 				subtype := g.table.get_type_symbol(v) | ||||
| 				g.writeln('		case $v: return "${util.strip_main_name(subtype.name)}";') | ||||
| 			} | ||||
| 			g.writeln('		default: return "unknown ${util.strip_main_name(typ.name)}";') | ||||
| 			g.writeln('	}') | ||||
| 			g.writeln('}') | ||||
| 		} | ||||
| 	} | ||||
| 	for typ in g.table.types { | ||||
| 		if typ.kind == .union_sum_type { | ||||
| 			sum_info := typ.info as table.UnionSumType | ||||
|  | @ -2293,7 +2277,7 @@ fn (mut g Gen) expr(node ast.Expr) { | |||
| 					g.expr(node.arg) | ||||
| 				} | ||||
| 				g.write(')') | ||||
| 			} else if sym.kind in [.sum_type, .union_sum_type] { | ||||
| 			} else if sym.kind == .union_sum_type { | ||||
| 				g.expr_with_cast(node.expr, node.expr_type, node.typ) | ||||
| 			} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef { | ||||
| 				styp := g.typ(node.typ) | ||||
|  | @ -2649,14 +2633,7 @@ fn (mut g Gen) type_name(type_ table.Type) { | |||
| 
 | ||||
| fn (mut g Gen) typeof_expr(node ast.TypeOf) { | ||||
| 	sym := g.table.get_type_symbol(node.expr_type) | ||||
| 	if sym.kind == .sum_type { | ||||
| 		// When encountering a .sum_type, typeof() should be done at runtime,
 | ||||
| 		// because the subtype of the expression may change:
 | ||||
| 		sum_type_idx := node.expr_type.idx() | ||||
| 		g.write('tos3( /* $sym.name */ v_typeof_sumtype_${sum_type_idx}( (') | ||||
| 		g.expr(node.expr) | ||||
| 		g.write(').typ ))') | ||||
| 	} else if sym.kind == .union_sum_type { | ||||
| 	if sym.kind == .union_sum_type { | ||||
| 		// When encountering a .sum_type, typeof() should be done at runtime,
 | ||||
| 		// because the subtype of the expression may change:
 | ||||
| 		sum_type_idx := node.expr_type.idx() | ||||
|  | @ -3098,7 +3075,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str | |||
| 				} | ||||
| 				g.write(cond_var) | ||||
| 				// branch_sym := g.table.get_type_symbol(branch.typ)
 | ||||
| 				if sym.kind in [.sum_type, .union_sum_type] { | ||||
| 				if sym.kind == .union_sum_type { | ||||
| 					dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' } | ||||
| 					g.write(dot_or_ptr) | ||||
| 					g.write('typ == ') | ||||
|  | @ -3113,25 +3090,6 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str | |||
| 					g.writeln(') {') | ||||
| 				} | ||||
| 			} | ||||
| 			// g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/')
 | ||||
| 			if sym.kind != .union_sum_type && !branch.is_else && !node.is_expr { | ||||
| 				// Use the nodes in the expr to generate `it` variable.
 | ||||
| 				type_expr := branch.exprs[sumtype_index] | ||||
| 				if type_expr !is ast.Type { | ||||
| 					verror('match sum type') | ||||
| 				} | ||||
| 				it_type := g.typ((type_expr as ast.Type).typ) | ||||
| 				// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
 | ||||
| 				g.write('\t$it_type* it = ($it_type*)') | ||||
| 				g.write(cond_var) | ||||
| 				dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' } | ||||
| 				g.write(dot_or_ptr) | ||||
| 				g.writeln('_object; // ST it') | ||||
| 				if node.var_name.len > 0 { | ||||
| 					// for now we just copy it
 | ||||
| 					g.writeln('\t$it_type* $node.var_name = it;') | ||||
| 				} | ||||
| 			} | ||||
| 			g.stmts(branch.stmts) | ||||
| 			if g.inside_ternary == 0 { | ||||
| 				g.write('}') | ||||
|  | @ -3449,13 +3407,6 @@ fn (mut g Gen) match_sumtype_has_no_struct_and_contains(node ast.Ident) bool { | |||
| 		if expr is ast.Ident && node.name == (expr as ast.Ident).name { | ||||
| 			info := g.match_sumtype_syms[i].info | ||||
| 			match union info { | ||||
| 				table.SumType { | ||||
| 					for typ in info.variants { | ||||
| 						if g.table.get_type_symbol(typ).kind == .struct_ { | ||||
| 							return false | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				table.UnionSumType { | ||||
| 					for typ in info.variants { | ||||
| 						if g.table.get_type_symbol(typ).kind == .struct_ { | ||||
|  | @ -3591,18 +3542,20 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { | |||
| 		} | ||||
| 		if branch.smartcast && branch.stmts.len > 0 { | ||||
| 			infix := branch.cond as ast.InfixExpr | ||||
| 			right_type := infix.right as ast.Type | ||||
| 			left_type := infix.left_type | ||||
| 			it_type := g.typ(right_type.typ) | ||||
| 			g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)') | ||||
| 			g.expr(infix.left) | ||||
| 			if left_type.is_ptr() { | ||||
| 				g.write('->') | ||||
| 			} else { | ||||
| 				g.write('.') | ||||
| 			if mut infix.left is ast.Ident { | ||||
| 				right_type := infix.right as ast.Type | ||||
| 				left_type := infix.left_type | ||||
| 				it_type := g.typ(right_type.typ) | ||||
| 				g.write('\t$it_type* _sc_tmp_$branch.pos.pos = ($it_type*)') | ||||
| 				g.expr(infix.left) | ||||
| 				if left_type.is_ptr() { | ||||
| 					g.write('->') | ||||
| 				} else { | ||||
| 					g.write('.') | ||||
| 				} | ||||
| 				g.writeln('_object;') | ||||
| 				g.writeln('\t$it_type* $infix.left.name = _sc_tmp_$branch.pos.pos;') | ||||
| 			} | ||||
| 			g.writeln('_object;') | ||||
| 			g.writeln('\t$it_type* $branch.left_as_name = _sc_tmp_$branch.pos.pos;') | ||||
| 		} | ||||
| 		if needs_tmp_var { | ||||
| 			g.stmts_with_tmp_var(branch.stmts, tmp) | ||||
|  | @ -4640,19 +4593,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) { | |||
| 				g.type_definitions.writeln('};\n') | ||||
| 			} | ||||
| 			table.Alias { | ||||
| 				// table.Alias, table.SumType { TODO
 | ||||
| 			} | ||||
| 			table.SumType { | ||||
| 				g.type_definitions.writeln('') | ||||
| 				g.type_definitions.writeln('// Sum type $name = ') | ||||
| 				for sv in typ.info.variants { | ||||
| 					g.type_definitions.writeln('//          | ${sv:4d} = ${g.typ(sv):-20s}') | ||||
| 				} | ||||
| 				g.type_definitions.writeln('typedef struct {') | ||||
| 				g.type_definitions.writeln('    void* _object;') | ||||
| 				g.type_definitions.writeln('    int typ;') | ||||
| 				g.type_definitions.writeln('} $name;') | ||||
| 				g.type_definitions.writeln('') | ||||
| 				// table.Alias { TODO
 | ||||
| 			} | ||||
| 			table.UnionSumType { | ||||
| 				g.typedefs.writeln('typedef struct $name $name;') | ||||
|  | @ -4781,7 +4722,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool { | |||
| 			g.write('")') | ||||
| 		} | ||||
| 	} else if sym_has_str_method || sym.kind in | ||||
| 		[.array, .array_fixed, .map, .struct_, .multi_return, .sum_type] { | ||||
| 		[.array, .array_fixed, .map, .struct_, .multi_return, .union_sum_type] { | ||||
| 		is_p := typ.is_ptr() | ||||
| 		val_type := if is_p { typ.deref() } else { typ } | ||||
| 		str_fn_name := g.gen_str_for_type(val_type) | ||||
|  | @ -5449,7 +5390,7 @@ fn (mut g Gen) type_default(typ_ table.Type) string { | |||
| 		else {} | ||||
| 	} | ||||
| 	return match sym.kind { | ||||
| 		.interface_, .union_sum_type, .sum_type, .array_fixed, .multi_return { '{0}' } | ||||
| 		.interface_, .union_sum_type, .array_fixed, .multi_return { '{0}' } | ||||
| 		.alias { g.type_default((sym.info as table.Alias).parent_type) } | ||||
| 		else { '0' } | ||||
| 	} | ||||
|  | @ -5604,23 +5545,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) { | |||
| 	// g.insert_before('
 | ||||
| 	styp := g.typ(node.typ) | ||||
| 	expr_type_sym := g.table.get_type_symbol(node.expr_type) | ||||
| 	if expr_type_sym.kind == .sum_type { | ||||
| 		/* | ||||
| 		g.write('*($styp*)') | ||||
| 		g.expr(node.expr) | ||||
| 		g.write('.obj') | ||||
| 		*/ | ||||
| 		dot := if node.expr_type.is_ptr() { '->' } else { '.' } | ||||
| 		g.write('/* as */ ($styp*)__as_cast((') | ||||
| 		g.expr(node.expr) | ||||
| 		g.write(')') | ||||
| 		g.write(dot) | ||||
| 		g.write('_object, (') | ||||
| 		g.expr(node.expr) | ||||
| 		g.write(')') | ||||
| 		g.write(dot) | ||||
| 		g.write('typ, /*expected:*/$node.typ)') | ||||
| 	} else if expr_type_sym.kind == .union_sum_type { | ||||
| 	if expr_type_sym.kind == .union_sum_type { | ||||
| 		dot := if node.expr_type.is_ptr() { '->' } else { '.' } | ||||
| 		g.write('/* as */ *($styp*)__as_cast((') | ||||
| 		g.expr(node.expr) | ||||
|  | @ -5652,7 +5577,7 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) { | |||
| 		sub_sym := g.table.get_type_symbol(sub_type.typ) | ||||
| 		g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index') | ||||
| 		return | ||||
| 	} else if sym.kind in [.sum_type, .union_sum_type] { | ||||
| 	} else if sym.kind == .union_sum_type { | ||||
| 		g.write('typ $eq ') | ||||
| 	} | ||||
| 	g.expr(node.right) | ||||
|  | @ -5719,7 +5644,7 @@ fn (g &Gen) type_to_fmt(typ table.Type) string { | |||
| 		return '%g\\000' // g removes trailing zeros unlike %f
 | ||||
| 	} else if sym.kind == .u64 { | ||||
| 		return '%lld\\000' | ||||
| 	} else if sym.kind == .sum_type { | ||||
| 	} else if sym.kind == .union_sum_type { | ||||
| 		return '%.*s\\000' | ||||
| 	} | ||||
| 	return '%d\\000' | ||||
|  |  | |||
|  | @ -366,8 +366,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) { | |||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
| 	if left_sym.kind == .sum_type && node.name == 'type_name' { | ||||
| 		g.write('tos3( /* $left_sym.name */ v_typeof_sumtype_${node.receiver_type}( (') | ||||
| 	if left_sym.kind == .union_sum_type && node.name == 'type_name' { | ||||
| 		g.write('tos3( /* $left_sym.name */ v_typeof_unionsumtype_${node.receiver_type}( (') | ||||
| 		g.expr(node.left) | ||||
| 		g.write(').typ ))') | ||||
| 		return | ||||
|  | @ -887,7 +887,7 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { | |||
| 			} | ||||
| 			arg_typ_sym := g.table.get_type_symbol(arg.typ) | ||||
| 			expected_deref_type := if expected_type.is_ptr() { expected_type.deref() } else { expected_type } | ||||
| 			is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .sum_type | ||||
| 			is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .union_sum_type | ||||
| 			if !((arg_typ_sym.kind == .function) || is_sum_type) { | ||||
| 				g.write('(voidptr)&/*qq*/') | ||||
| 			} | ||||
|  |  | |||
|  | @ -257,10 +257,6 @@ pub fn (mut g JsGen) typ(t table.Type) string { | |||
| 			joined := types.join(', ') | ||||
| 			styp = '[$joined]' | ||||
| 		} | ||||
| 		.sum_type { | ||||
| 			// TODO: Implement sumtypes
 | ||||
| 			styp = 'sym_type' | ||||
| 		} | ||||
| 		.union_sum_type { | ||||
| 			// TODO: Implement sumtypes
 | ||||
| 			styp = 'union_sym_type' | ||||
|  | @ -1504,7 +1500,7 @@ fn (mut g JsGen) gen_struct_init(it ast.StructInit) { | |||
| 
 | ||||
| fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) { | ||||
| 	sym := g.table.get_type_symbol(it.expr_type) | ||||
| 	if sym.kind == .sum_type { | ||||
| 	if sym.kind == .union_sum_type { | ||||
| 		// TODO: JS sumtypes not implemented yet
 | ||||
| 	} else if sym.kind == .array_fixed { | ||||
| 		fixed_info := sym.info as table.ArrayFixed | ||||
|  |  | |||
|  | @ -567,7 +567,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) { | |||
| 
 | ||||
| fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) { | ||||
| 	sym := p.table.get_type_symbol(typ) | ||||
| 	if sym.kind !in [.array, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() { | ||||
| 	if sym.kind !in [.array, .struct_, .map, .placeholder, .union_sum_type] && !typ.is_ptr() { | ||||
| 		p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' + | ||||
| 			'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`', | ||||
| 			pos) | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ module parser | |||
| import v.ast | ||||
| import v.table | ||||
| import v.token | ||||
| import strings | ||||
| 
 | ||||
| fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { | ||||
| 	was_inside_if_expr := p.inside_if_expr | ||||
|  | @ -121,22 +120,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { | |||
| 			cond = p.expr(0) | ||||
| 		} | ||||
| 		comments << p.eat_comments() | ||||
| 		mut left_as_name := '' | ||||
| 		if mut cond is ast.InfixExpr { | ||||
| 			// if sum is T
 | ||||
| 			is_is_cast := cond.op == .key_is | ||||
| 			is_ident := cond.left is ast.Ident | ||||
| 			left_as_name = if is_comptime { | ||||
| 				'' | ||||
| 			} else if is_is_cast && p.tok.kind == .key_as { | ||||
| 				p.next() | ||||
| 				p.check_name() | ||||
| 			} else if is_ident { | ||||
| 				ident := cond.left as ast.Ident | ||||
| 				ident.name | ||||
| 			} else { | ||||
| 				'' | ||||
| 			} | ||||
| 			if !is_is_cast && is_mut_name { | ||||
| 				p.error_with_pos('remove unnecessary `mut`', mut_pos) | ||||
| 			} | ||||
|  | @ -156,7 +142,6 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { | |||
| 			pos: start_pos.extend(end_pos) | ||||
| 			body_pos: body_pos.extend(p.prev_tok.position()) | ||||
| 			comments: comments | ||||
| 			left_as_name: left_as_name | ||||
| 			is_mut_name: is_mut_name | ||||
| 		} | ||||
| 		comments = p.eat_comments() | ||||
|  | @ -195,14 +180,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr { | |||
| 	if is_mut { | ||||
| 		p.next() | ||||
| 	} | ||||
| 	cond_pos := p.tok.position() | ||||
| 	cond := p.expr(0) | ||||
| 	p.inside_match = false | ||||
| 	mut var_name := '' | ||||
| 	if p.tok.kind == .key_as { | ||||
| 		p.next() | ||||
| 		var_name = p.check_name() | ||||
| 	} | ||||
| 	no_lcbr := p.tok.kind != .lcbr | ||||
| 	if !no_lcbr { | ||||
| 		p.check(.lcbr) | ||||
|  | @ -222,20 +201,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr { | |||
| 		} else if p.tok.kind == .name && !(p.tok.lit == 'C' && | ||||
| 			p.peek_tok.kind == .dot) && (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() || | ||||
| 			(p.peek_tok.kind == .dot && p.peek_tok2.lit[0].is_capital())) { | ||||
| 			if var_name.len == 0 { | ||||
| 				match union cond { | ||||
| 					ast.Ident { | ||||
| 						// shadow match cond variable
 | ||||
| 						var_name = cond.name | ||||
| 					} | ||||
| 					else { | ||||
| 						// ast.SelectorExpr {
 | ||||
| 						// p.error('expecting `as` (eg. `match user.attribute as user_attr`) when matching struct fields')
 | ||||
| 						// }
 | ||||
| 						// p.error('only variables can be used in sum types matches')
 | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			mut types := []table.Type{} | ||||
| 			for { | ||||
| 				// Sum type match
 | ||||
|  | @ -251,52 +216,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr { | |||
| 				} | ||||
| 				p.check(.comma) | ||||
| 			} | ||||
| 			if !is_union_match { | ||||
| 				mut it_typ := table.void_type | ||||
| 				if types.len == 1 { | ||||
| 					it_typ = types[0] | ||||
| 				} else { | ||||
| 					// there is more than one types, so we must create a type aggregate
 | ||||
| 					mut agg_name := strings.new_builder(20) | ||||
| 					agg_name.write('(') | ||||
| 					for i, typ in types { | ||||
| 						if i > 0 { | ||||
| 							agg_name.write(' | ') | ||||
| 						} | ||||
| 						type_str := p.table.type_to_str(typ) | ||||
| 						agg_name.write(p.prepend_mod(type_str)) | ||||
| 					} | ||||
| 					agg_name.write(')') | ||||
| 					name := agg_name.str() | ||||
| 					it_typ = p.table.register_type_symbol(table.TypeSymbol{ | ||||
| 						name: name | ||||
| 						source_name: name | ||||
| 						kind: .aggregate | ||||
| 						mod: p.mod | ||||
| 						info: table.Aggregate{ | ||||
| 							types: types | ||||
| 						} | ||||
| 					}) | ||||
| 				} | ||||
| 				p.scope.register('it', ast.Var{ | ||||
| 					name: 'it' | ||||
| 					typ: it_typ.to_ptr() | ||||
| 					pos: cond_pos | ||||
| 					is_used: true | ||||
| 					is_mut: is_mut | ||||
| 				}) | ||||
| 				if var_name.len > 0 { | ||||
| 					// Register shadow variable or `as` variable with actual type
 | ||||
| 					p.scope.register(var_name, ast.Var{ | ||||
| 						name: var_name | ||||
| 						typ: it_typ.to_ptr() | ||||
| 						pos: cond_pos | ||||
| 						is_used: true | ||||
| 						is_changed: true // TODO mut unchanged warning hack, remove
 | ||||
| 						is_mut: is_mut | ||||
| 					}) | ||||
| 				} | ||||
| 			} | ||||
| 			is_sum_type = true | ||||
| 		} else { | ||||
| 			// Expression match
 | ||||
|  | @ -366,10 +285,9 @@ fn (mut p Parser) match_expr() ast.MatchExpr { | |||
| 		branches: branches | ||||
| 		cond: cond | ||||
| 		is_sum_type: is_sum_type | ||||
| 		is_union_match: is_union_match | ||||
| 		pos: pos | ||||
| 		is_mut: is_mut | ||||
| 		var_name: var_name | ||||
| 		is_union_match: is_union_match | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1999,17 +1999,17 @@ fn (mut p Parser) type_decl() ast.TypeDecl { | |||
| 		} | ||||
| 		prepend_mod_name := p.prepend_mod(name) | ||||
| 		p.table.register_type_symbol(table.TypeSymbol{ | ||||
| 			kind: .sum_type | ||||
| 			kind: .union_sum_type | ||||
| 			name: prepend_mod_name | ||||
| 			source_name: prepend_mod_name | ||||
| 			mod: p.mod | ||||
| 			info: table.SumType{ | ||||
| 			info: table.UnionSumType{ | ||||
| 				variants: sum_variants | ||||
| 			} | ||||
| 			is_public: is_pub | ||||
| 		}) | ||||
| 		comments = p.eat_lineend_comments() | ||||
| 		return ast.SumTypeDecl{ | ||||
| 		return ast.UnionSumTypeDecl{ | ||||
| 			name: name | ||||
| 			is_pub: is_pub | ||||
| 			sub_types: sum_variants | ||||
|  |  | |||
|  | @ -722,17 +722,7 @@ pub fn (mut table Table) register_fn_gen_type(fn_name string, typ Type) { | |||
| // so until fixed at least show v (not C) error `x(variant) =  y(SumType*)`
 | ||||
| pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool { | ||||
| 	parent_sym := table.get_type_symbol(parent) | ||||
| 	if parent_sym.kind == .sum_type { | ||||
| 		parent_info := parent_sym.info as SumType | ||||
| 		for v in parent_info.variants { | ||||
| 			if v.idx() == variant.idx() { | ||||
| 				return true | ||||
| 			} | ||||
| 			if table.sumtype_has_variant(v, variant) { | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 	} else if parent_sym.kind == .union_sum_type { | ||||
| 	if parent_sym.kind == .union_sum_type { | ||||
| 		parent_info := parent_sym.info as UnionSumType | ||||
| 		for v in parent_info.variants { | ||||
| 			if v.idx() == variant.idx() { | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ import strings | |||
| pub type Type = int | ||||
| 
 | ||||
| pub __type TypeInfo = Aggregate | Alias | Array | ArrayFixed | Chan | Enum | FnType | | ||||
| 	GenericStructInst | Interface | Map | MultiReturn | Struct | SumType | UnionSumType | ||||
| 	GenericStructInst | Interface | Map | MultiReturn | Struct | UnionSumType | ||||
| 
 | ||||
| pub enum Language { | ||||
| 	v | ||||
|  | @ -404,7 +404,6 @@ pub enum Kind { | |||
| 	struct_ | ||||
| 	generic_struct_inst | ||||
| 	multi_return | ||||
| 	sum_type | ||||
| 	union_sum_type | ||||
| 	alias | ||||
| 	enum_ | ||||
|  | @ -719,7 +718,6 @@ pub fn (k Kind) str() string { | |||
| 		.map { 'map' } | ||||
| 		.chan { 'chan' } | ||||
| 		.multi_return { 'multi_return' } | ||||
| 		.sum_type { 'sum_type' } | ||||
| 		.union_sum_type { 'union_sum_type' } | ||||
| 		.alias { 'alias' } | ||||
| 		.enum_ { 'enum' } | ||||
|  | @ -843,11 +841,6 @@ pub mut: | |||
| 	value_type Type | ||||
| } | ||||
| 
 | ||||
| pub struct SumType { | ||||
| pub: | ||||
| 	variants []Type | ||||
| } | ||||
| 
 | ||||
| pub struct UnionSumType { | ||||
| pub: | ||||
| 	variants []Type | ||||
|  |  | |||
|  | @ -18,12 +18,12 @@ fn test_if_smartcast() { | |||
| 
 | ||||
| fn test_mutable() { | ||||
| 	mut x := Alphabet(Abc{'original'}) | ||||
| 	if x is Abc { | ||||
| 	if mut x is Abc { | ||||
| 		assert x.val == 'original' | ||||
| 		x.val = 'changed' | ||||
| 		assert x.val == 'changed' | ||||
| 	} | ||||
| 	if x is Abc { | ||||
| 	if mut x is Abc { | ||||
| 		assert x.val == 'changed' | ||||
| 	} | ||||
| } | ||||
|  | @ -38,11 +38,9 @@ fn test_nested_if_smartcast() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn test_as_cast() { | ||||
| 	x := Alphabet(Abc{'test'}) | ||||
| 	if x is Abc as test { | ||||
| 		assert test.val == 'test' | ||||
| 	} | ||||
| struct MutContainer { | ||||
| mut: | ||||
| 	abc Alphabet | ||||
| } | ||||
| 
 | ||||
| struct Container { | ||||
|  | @ -50,29 +48,24 @@ struct Container { | |||
| } | ||||
| 
 | ||||
| fn test_mutable_with_struct() { | ||||
| 	mut c := Container{Abc{'original'}} | ||||
| 	if c.abc is Abc as abc { | ||||
| 		assert abc.val == 'original' | ||||
| 		mut mabc := abc | ||||
| 		// NB: since `abc` is a pointer,
 | ||||
| 		// `mabc` points to the same data:
 | ||||
| 		assert mabc.val == 'original' | ||||
| 		// Modifying `mabc`, modifies the data of abc too.
 | ||||
| 		mabc.val = 'xyz' | ||||
| 		assert abc.val == 'xyz' | ||||
| 	mut c := MutContainer{Abc{'original'}} | ||||
| 	if mut c.abc is Abc { | ||||
| 		assert c.abc.val == 'original' | ||||
| 		c.abc.val = 'xyz' | ||||
| 		assert c.abc.val == 'xyz' | ||||
| 	} | ||||
| 	if c.abc is Abc as another { | ||||
| 	if mut c.abc is Abc { | ||||
| 		// NB: in this second smart cast, `another` is
 | ||||
| 		// the same wrapped value, that was changed in
 | ||||
| 		// the first smart cast:
 | ||||
| 		assert another.val == 'xyz' | ||||
| 		assert c.abc.val == 'xyz' | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn test_as_cast_with_struct() { | ||||
| 	x := Container{Abc{'test'}} | ||||
| 	if x.abc is Abc as test { | ||||
| 		assert test.val == 'test' | ||||
| 	if x.abc is Abc { | ||||
| 		assert x.abc.val == 'test' | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -113,19 +106,19 @@ fn test_mutability() { | |||
| 	} | ||||
| 	mut cell := Cell{} | ||||
| 	cell = cell_str | ||||
| 	if cell is CellStr { | ||||
| 	if mut cell is CellStr { | ||||
| 		println('$cell.str') | ||||
| 	} | ||||
| 	cell = cell_itg | ||||
| 	if cell is CellInt { | ||||
| 	if mut cell is CellInt { | ||||
| 		println('$cell.itg') | ||||
| 	} | ||||
| 	cell = cell_flt | ||||
| 	if cell is CellFloat { | ||||
| 	if mut cell is CellFloat { | ||||
| 		println('$cell.flt') | ||||
| 	} | ||||
| 	cell = cell_u32 | ||||
| 	if cell is CellU32 { | ||||
| 	if mut cell is CellU32 { | ||||
| 		println('$cell.u') | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ const ( | |||
| fn test_shadow() { | ||||
| 	mut animal := Animal{} | ||||
| 	animal = cat | ||||
| 	match animal { | ||||
| 	match mut animal { | ||||
| 		Cat { | ||||
| 			assert animal.name == cat.name | ||||
| 		} | ||||
|  | @ -24,9 +24,9 @@ fn test_shadow() { | |||
| fn test_as() { | ||||
| 	mut animal := Animal{} | ||||
| 	animal = dog | ||||
| 	match animal as animal_kind { | ||||
| 	match mut animal { | ||||
| 		Dog { | ||||
| 			assert animal_kind.name == dog.name | ||||
| 			assert animal.name == dog.name | ||||
| 		} | ||||
| 		else{ | ||||
| 			assert false | ||||
|  |  | |||
|  | @ -205,7 +205,8 @@ type NATOAlphabet = Alfa | Bravo | Charlie | |||
| 
 | ||||
| fn test_match_sumtype_multiple_types() { | ||||
| 	a := Alfa{} | ||||
| 	match NATOAlphabet(a) as l { | ||||
| 	l := NATOAlphabet(a) | ||||
| 	match l { | ||||
| 		Alfa, Bravo { | ||||
| 			assert l.char == `a` | ||||
| 			// TODO make methods work
 | ||||
|  | @ -216,7 +217,7 @@ fn test_match_sumtype_multiple_types() { | |||
| 		} | ||||
| 	} | ||||
| 	// test one branch
 | ||||
| 	match NATOAlphabet(a) as l { | ||||
| 	match l { | ||||
| 		Alfa, Bravo, Charlie { | ||||
| 			assert l.char == `a` | ||||
| 		} | ||||
|  |  | |||
|  | @ -28,8 +28,7 @@ fn handle(e Expr) string { | |||
| 	} | ||||
| 	match e { | ||||
| 		IntegerLiteral { | ||||
| 			assert it.val == '12' | ||||
| 			// assert e.val == '12' // TODO
 | ||||
| 			assert e.val == '12' | ||||
| 			return 'int' | ||||
| 		} | ||||
| 		IfExpr { | ||||
|  | @ -56,10 +55,10 @@ fn test_assignment_and_push() { | |||
| 	arr1 << expr | ||||
| 	match arr1[0] { | ||||
| 		IntegerLiteral { | ||||
| 			arr1 << it | ||||
| 			arr1 << arr1[0] | ||||
| 			// should ref/dereference on assignent be made automatic?
 | ||||
| 			// currently it is done for return stmt and fn args
 | ||||
| 			expr1 = *it | ||||
| 			expr1 = arr1[0] | ||||
| 		} | ||||
| 		else {} | ||||
| 	} | ||||
|  | @ -96,7 +95,7 @@ fn test_converting_down() { | |||
| 	mut res := []Sub2{cap: out.len} | ||||
| 	for d in out { | ||||
| 		match d { | ||||
| 			Sub2 { res << it } | ||||
| 			Sub2 { res << d } | ||||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
|  | @ -107,26 +106,6 @@ fn test_converting_down() { | |||
| } | ||||
| 
 | ||||
| fn test_nested_sumtype() { | ||||
| 	mut a := Node{} | ||||
| 	mut b := Node{} | ||||
| 	a = StructDecl{pos: 1} | ||||
| 	b = IfExpr{pos: 1} | ||||
| 	match a { | ||||
| 		StructDecl { | ||||
| 			assert true | ||||
| 		} | ||||
| 		else { | ||||
| 			assert false | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO: not working
 | ||||
| 	// assert b is IfExpr
 | ||||
| 	if b is IfExpr { | ||||
| 		assert true | ||||
| 	} | ||||
| 	else { | ||||
| 		assert false | ||||
| 	} | ||||
| 	c := Node(Expr(IfExpr{pos:1})) | ||||
| 	if c is Expr { | ||||
| 		if c is IfExpr { | ||||
|  | @ -202,8 +181,8 @@ fn is_gt_nested(val string, dst Number) bool { | |||
| 					return val.int() > dst | ||||
| 				} | ||||
| 				// this branch should never been hit
 | ||||
| 				else {  | ||||
| 					return val.int() < dst  | ||||
| 				else { | ||||
| 					return val.int() < dst | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -213,8 +192,8 @@ fn is_gt_nested(val string, dst Number) bool { | |||
| 					return dst < val.f64() | ||||
| 				} | ||||
| 				// this branch should never been hit
 | ||||
| 				else {  | ||||
| 					return dst > val.f64()  | ||||
| 				else { | ||||
| 					return dst > val.f64() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -255,7 +234,7 @@ fn test_sum_type_match() { | |||
| 	assert is_gt_simple('3', 2) | ||||
| 	assert !is_gt_simple('3', 5) | ||||
| 	assert is_gt_simple('3', 1.2) | ||||
| 	assert !is_gt_simple('3', 3.5)	 | ||||
| 	assert !is_gt_simple('3', 3.5) | ||||
| 	assert is_gt_nested('3', 2) | ||||
| 	assert !is_gt_nested('3', 5) | ||||
| 	assert is_gt_nested('3', 1.2) | ||||
|  |  | |||
|  | @ -51,8 +51,8 @@ type MySumType = int | f32 | FooBar | |||
| 
 | ||||
| pub fn (ms MySumType) str() string { | ||||
| 	match ms { | ||||
| 		int { return it.str() } | ||||
| 		f32 { return it.str() } | ||||
| 		int { return ms.str() } | ||||
| 		f32 { return ms.str() } | ||||
| 		//FooBar { return it.x.str() }
 | ||||
| 		else { return 'unknown: ' + typeof(ms) } | ||||
| 	} | ||||
|  | @ -144,7 +144,7 @@ fn test_generic_type() { | |||
| 	assert type_name([v]) == '[]int' | ||||
| 	assert type_name([[v]]) == '[][]int' | ||||
| 	assert type_name(FooBar{}) == 'FooBar' | ||||
| 	 | ||||
| 
 | ||||
| 	assert array_item_type([v]) == 'int' | ||||
| 	assert array_item_type([[v]]) == '[]int' | ||||
| 	//assert array_item_type([&v]) == '&int'
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue