sum type `type Foo = Bar | Baz`
							parent
							
								
									9dd05474b0
								
							
						
					
					
						commit
						803ded3dec
					
				|  | @ -4,6 +4,8 @@ | |||
| module compiler | ||||
| 
 | ||||
| fn (p mut Parser) bool_expression() string { | ||||
| 	start_ph := p.cgen.add_placeholder() | ||||
| 	expected := p.expected_type | ||||
| 	tok := p.tok | ||||
| 	typ := p.bterm() | ||||
| 	mut got_and := false // to catch `a && b || c` in one expression without ()
 | ||||
|  | @ -44,6 +46,11 @@ fn (p mut Parser) bool_expression() string { | |||
| 		println(tok.str()) | ||||
| 		p.error('expr() returns empty type') | ||||
| 	} | ||||
| 	if expected != typ && expected in p.table.sum_types { // TODO perf
 | ||||
| 		p.cgen.set_placeholder(start_ph, '/*KUK*/($expected) { .obj = ($typ[]) { ') | ||||
| 		p.gen('}, .typ = 1}')//${val}_type }')
 | ||||
| 
 | ||||
| 	} | ||||
| 	return typ | ||||
| } | ||||
| 
 | ||||
|  | @ -362,7 +369,7 @@ fn (p mut Parser) name_expr() string { | |||
| 				//println(q)
 | ||||
| 				//println(q[idx])
 | ||||
| 				arg_type := q[idx] | ||||
| 				p.gen('($enum_type.name) { .obj = ($arg_type[]) { ') | ||||
| 	p.gen('($enum_type.name) { .obj = ($arg_type[]) { ') | ||||
| 				p.bool_expression() | ||||
| 				p.check(.rpar) | ||||
| 				p.gen('}, .typ = ${val}_type }') | ||||
|  |  | |||
|  | @ -160,7 +160,7 @@ fn (v mut V) new_parser_from_file(path string) Parser { | |||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 
 | ||||
| 	if v.compile_defines.len > 0 { | ||||
| 		for cdefine in v.compile_defines { | ||||
| 			custom_path_ending := '_d_${cdefine}.v' | ||||
|  | @ -171,7 +171,7 @@ fn (v mut V) new_parser_from_file(path string) Parser { | |||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 
 | ||||
| 	mut p := v.new_parser(new_scanner_file(path)) | ||||
| 	p = { | ||||
| 		p | | ||||
|  | @ -793,20 +793,79 @@ fn (p mut Parser) type_decl() { | |||
| 	if p.tok == .key_struct { | ||||
| 		p.error('use `struct $name {` instead of `type $name struct {`') | ||||
| 	} | ||||
| 	if p.tok == .assign { | ||||
| 		p.next() | ||||
| 
 | ||||
| 	} | ||||
| 	parent := p.get_type2() | ||||
| 	// Sum type
 | ||||
| 	is_sum := p.tok == .pipe | ||||
| 	if is_sum { | ||||
| 		// Register the first child  (name we already parsed)
 | ||||
| 		/* | ||||
| 		p.table.register_type(Type{ | ||||
| 			parent: name | ||||
| 			name: parent.name // yeah it's not a parent here
 | ||||
| 			mod: p.mod | ||||
| 			is_public: is_pub | ||||
| 		}) | ||||
| 		*/ | ||||
| 		// Register the rest of them
 | ||||
| 		for p.tok == .pipe { | ||||
| 			p.next() | ||||
| 			child := p.check_name() | ||||
| 			if p.pass == .main { | ||||
| 				// Update the type's parent
 | ||||
| 				println('child=$child parent=$name') | ||||
| 				mut t := p.table.find_type(child) | ||||
| 				if t.name == '' { | ||||
| 					p.error('unknown type `$child`') | ||||
| 				} | ||||
| 				t.parent = name | ||||
| 				p.table.rewrite_type(t) | ||||
| 				/* | ||||
| 				p.table.register_type(Type{ | ||||
| 					parent: name | ||||
| 					name: child | ||||
| 					mod: p.mod | ||||
| 					is_public: is_pub | ||||
| 				}) | ||||
| 				*/ | ||||
| 			} | ||||
| 		} | ||||
| 		if p.pass == .decl { | ||||
| 			p.table.sum_types << name | ||||
| 			println(p.table.sum_types) | ||||
| 		} | ||||
| 		// Register the actual sum type
 | ||||
| 		println('reging sum $name') | ||||
| 		p.table.register_type(Type{ | ||||
| 			name: name | ||||
| 			mod: p.mod | ||||
| 			cat: .alias | ||||
| 			is_public: is_pub | ||||
| 		}) | ||||
| 		p.gen_typedef('typedef struct { | ||||
| void* obj; | ||||
| int typ; | ||||
| } $name; | ||||
| ') | ||||
| 	} | ||||
| 	nt_pair := p.table.cgen_name_type_pair(name, parent.name) | ||||
| 	// TODO dirty C typedef hacks for DOOM
 | ||||
| 	// Unknown type probably means it's a struct, and it's used before the struct is defined,
 | ||||
| 	// so specify "struct"
 | ||||
| 	_struct := if parent.cat != .array && parent.cat != .func && !p.table.known_type(parent.name) { 'struct' } else { '' } | ||||
| 	p.gen_typedef('typedef $_struct $nt_pair; //type alias name="$name" parent=`$parent.name`') | ||||
| 	p.table.register_type(Type{ | ||||
| 		name: name | ||||
| 		parent: parent.name | ||||
| 		mod: p.mod | ||||
| 		cat: .alias | ||||
| 		is_public: is_pub | ||||
| 	}) | ||||
| 	if !is_sum { | ||||
| 		p.gen_typedef('typedef $_struct $nt_pair; //type alias name="$name" parent=`$parent.name`') | ||||
| 		p.table.register_type(Type{ | ||||
| 			name: name | ||||
| 			parent: parent.name | ||||
| 			mod: p.mod | ||||
| 			cat: .alias | ||||
| 			is_public: is_pub | ||||
| 		}) | ||||
| 	} | ||||
| 	if p.tok != .key_type { | ||||
| 		p.fspace() | ||||
| 	} | ||||
|  |  | |||
|  | @ -21,7 +21,8 @@ pub mut: | |||
| 	// names        []Name
 | ||||
| 	max_field_len         map[string]int // for vfmt: max_field_len['Parser'] == 12
 | ||||
| 	generic_struct_params map[string][]string | ||||
| 	tuple_variants map[string][]string | ||||
| 	tuple_variants map[string][]string // enum( Bool(BoolExpr) )
 | ||||
| 	sum_types []string | ||||
| } | ||||
| 
 | ||||
| struct VargAccess { | ||||
|  | @ -593,6 +594,9 @@ fn (t &Table) find_type(name_ string) Type { | |||
| } | ||||
| 
 | ||||
| fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool { | ||||
| 	if p.fileis('type_test') { | ||||
| 		println('got=$got_ exp=$expected_') | ||||
| 	} | ||||
| 	mut got := got_ | ||||
| 	mut expected := expected_ | ||||
| 	// p.log('check types got="$got" exp="$expected"  ')
 | ||||
|  | @ -725,6 +729,16 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool { | |||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 		// Sum type
 | ||||
| 		println(expected) | ||||
| 		if expected in p.table.sum_types { | ||||
| 			println('checking sum') | ||||
| 			child := p.table.find_type(got) | ||||
| 			if child.parent == expected { | ||||
| 				println('yep $expected') | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 		if !throw { | ||||
| 			return false | ||||
| 		} | ||||
|  |  | |||
|  | @ -17,3 +17,48 @@ fn test_person_str() { | |||
| 	println(p) | ||||
| 	assert p.str() == 'Person: Bilbo' | ||||
| } | ||||
| 
 | ||||
| struct Foo {} | ||||
| 
 | ||||
| struct WTF { | ||||
| 	wtf int | ||||
| } | ||||
| 
 | ||||
| struct BoolExpr { | ||||
| 	foo int | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| struct BinExpr { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| struct UnaryExpr { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| type Expr = Foo | BoolExpr |  BinExpr | UnaryExpr | ||||
| 
 | ||||
| fn handle_expr(e Expr) { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| fn parse_bool() BoolExpr { | ||||
| 	return BoolExpr{} | ||||
| } | ||||
| 
 | ||||
| fn test_sum() { | ||||
| 	b := parse_bool() | ||||
| 	handle_expr(b) | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| #define ExprType_BoolExpr 0 | ||||
| #define ExprType_BinExpr 1 | ||||
| #define ExprType_UnaryExpr 2 | ||||
| 
 | ||||
| struct Expr { | ||||
| 	int   typ; | ||||
| 	void* obj; | ||||
| } | ||||
| */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue