parser: get_type2() for the upcoming type system refactoring
							parent
							
								
									718041194f
								
							
						
					
					
						commit
						0db1eaa55a
					
				|  | @ -429,14 +429,19 @@ fn (p mut Parser) type_decl() { | |||
| 	if p.tok == .key_struct { | ||||
| 		p.error('use `struct $name {` instead of `type $name struct {`') | ||||
| 	} | ||||
| 	parent := p.get_type() | ||||
| 	nt_pair := p.table.cgen_name_type_pair(name, parent) | ||||
| 	parent := p.get_type2() | ||||
| 	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.contains('[') && !parent.starts_with('fn ') && !p.table.known_type(parent){'struct'} else { ''} | ||||
| 	p.gen_typedef('typedef $_struct $nt_pair; // type alias name="$name" parent="$parent"') | ||||
| 	p.register_type_with_parent(name, parent) | ||||
| 	_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.register_type_with_parent(name, parent.name) | ||||
| } | ||||
| 
 | ||||
| fn (p mut Parser) interface_method(field_name, receiver string) &Fn { | ||||
|  | @ -743,7 +748,7 @@ if p.scanner.line_comment != '' { | |||
| } | ||||
| 
 | ||||
| fn (p mut Parser) warn(s string) { | ||||
| 	println('$p.scanner.file_path:${p.scanner.line_nr+1}: $s') | ||||
| 	println('warning: $p.scanner.file_path:${p.scanner.line_nr+1}: $s') | ||||
| } | ||||
| 
 | ||||
| fn (p mut Parser) error(s string) { | ||||
|  | @ -782,24 +787,17 @@ fn (p &Parser) first_pass() bool { | |||
| 
 | ||||
| // TODO return Type instead of string?
 | ||||
| fn (p mut Parser) get_type() string { | ||||
| 	debug := p.fileis('fn_test') && false | ||||
| 	mut mul := false | ||||
| 	mut nr_muls := 0 | ||||
| 	mut typ := '' | ||||
| 	// fn type
 | ||||
| 	if p.tok == .func { | ||||
| 		if debug { | ||||
| 			println('\nget_type() .key_goT FN TYP line=$p.scanner.line_nr') | ||||
| 		} | ||||
| 		mut f := Fn{name: '_', mod: p.mod} | ||||
| 		p.next() | ||||
| 		line_nr := p.scanner.line_nr | ||||
| 		p.fn_args(mut f) | ||||
| 		// Same line, it's a return type
 | ||||
| 		if p.scanner.line_nr == line_nr { | ||||
| 			if debug { | ||||
| 				println('same line getting type') | ||||
| 			} | ||||
| 			if p.tok == .name { | ||||
| 				f.typ = p.get_type() | ||||
| 			} | ||||
|  |  | |||
|  | @ -0,0 +1,173 @@ | |||
| module main | ||||
| 
 | ||||
| import strings | ||||
| 
 | ||||
| fn (p mut Parser) get_type2() Type { | ||||
| 	mut mul := false | ||||
| 	mut nr_muls := 0 | ||||
| 	mut typ := '' | ||||
| 	mut cat := TypeCategory.struct_ | ||||
| 	// fn type
 | ||||
| 	if p.tok == .func { | ||||
| 		mut f := Fn{name: '_', mod: p.mod} | ||||
| 		p.next() | ||||
| 		line_nr := p.scanner.line_nr | ||||
| 		p.fn_args(mut f) | ||||
| 		// Same line, it's a return type
 | ||||
| 		if p.scanner.line_nr == line_nr { | ||||
| 			if p.tok == .name { | ||||
| 				f.typ = p.get_type() | ||||
| 			} | ||||
| 			else { | ||||
| 				f.typ = 'void' | ||||
| 			} | ||||
| 			// println('fn return typ=$f.typ')
 | ||||
| 		} | ||||
| 		else { | ||||
| 			f.typ = 'void' | ||||
| 		} | ||||
| 		// Register anon fn type
 | ||||
| 		fn_typ := Type { | ||||
| 			name: f.typ_str()// 'fn (int, int) string'
 | ||||
| 			mod: p.mod | ||||
| 			func: f | ||||
| 			cat: TypeCategory.func | ||||
| 		} | ||||
| 		p.table.register_type2(fn_typ) | ||||
| 		return fn_typ | ||||
| 	} | ||||
| 	// arrays ([]int)
 | ||||
| 	mut is_arr := false | ||||
| 	mut is_arr2 := false// [][]int TODO remove this and allow unlimited levels of arrays
 | ||||
| 	is_question := p.tok == .question | ||||
| 	if is_question { | ||||
| 		p.check(.question) | ||||
| 	} | ||||
| 	if p.tok == .lsbr { | ||||
| 		p.check(.lsbr) | ||||
| 		// [10]int
 | ||||
| 		if p.tok == .number { | ||||
| 			typ = '[$p.lit]' | ||||
| 			p.next() | ||||
| 		} | ||||
| 		else { | ||||
| 			is_arr = true | ||||
| 		} | ||||
| 		p.check(.rsbr) | ||||
| 		// [10][3]int
 | ||||
| 		if p.tok == .lsbr { | ||||
| 			p.next() | ||||
| 			if p.tok == .number { | ||||
| 				typ += '[$p.lit]' | ||||
| 				p.check(.number) | ||||
| 			} | ||||
| 			else { | ||||
| 				is_arr2 = true | ||||
| 			} | ||||
| 			p.check(.rsbr) | ||||
| 		} | ||||
| 		cat = .array | ||||
| 	} | ||||
| 	// map[string]int
 | ||||
| 	if !p.builtin_mod && p.tok == .name && p.lit == 'map' { | ||||
| 		p.next() | ||||
| 		p.check(.lsbr) | ||||
| 		key_type := p.check_name() | ||||
| 		if key_type != 'string' { | ||||
| 			p.error('maps only support string keys for now') | ||||
| 		} | ||||
| 		p.check(.rsbr) | ||||
| 		val_type := p.get_type()// p.check_name()
 | ||||
| 		typ = 'map_$val_type' | ||||
| 		p.register_map(typ) | ||||
| 		return Type{name: typ} | ||||
| 	} | ||||
| 	//
 | ||||
| 	for p.tok == .mul { | ||||
| 		if p.first_pass() { | ||||
| 			p.warn('use `&Foo` instead of `*Foo`') | ||||
| 		} | ||||
| 		mul = true | ||||
| 		nr_muls++ | ||||
| 		p.check(.mul) | ||||
| 	} | ||||
| 	if p.tok == .amp { | ||||
| 		mul = true | ||||
| 		nr_muls++ | ||||
| 		p.check(.amp) | ||||
| 	} | ||||
| 	typ += p.lit | ||||
| 	if !p.is_struct_init { | ||||
| 		// Otherwise we get `foo := FooFoo{` because `Foo` was already
 | ||||
| 		// generated in name_expr()
 | ||||
| 		p.fgen(p.lit) | ||||
| 	} | ||||
| 	// C.Struct import
 | ||||
| 	if p.lit == 'C' && p.peek() == .dot { | ||||
| 		p.next() | ||||
| 		p.check(.dot) | ||||
| 		typ = p.lit | ||||
| 	} | ||||
| 	else { | ||||
| 		// Module specified? (e.g. gx.Image)
 | ||||
| 		if p.peek() == .dot { | ||||
| 			// try resolve full submodule
 | ||||
| 			if !p.builtin_mod && p.import_table.known_alias(typ) { | ||||
| 				mod := p.import_table.resolve_alias(typ) | ||||
| 				if mod.contains('.') { | ||||
| 					typ = mod.replace('.', '_dot_') | ||||
| 				} | ||||
| 			} | ||||
| 			p.next() | ||||
| 			p.check(.dot) | ||||
| 			typ += '__$p.lit' | ||||
| 		} | ||||
| 		mut t := p.table.find_type(typ) | ||||
| 		// "typ" not found? try "mod__typ"
 | ||||
| 		if t.name == '' && !p.builtin_mod { | ||||
| 			// && !p.first_pass() {
 | ||||
| 			if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') && | ||||
| 				!typ.starts_with('[') { | ||||
| 				typ = p.prepend_mod(typ) | ||||
| 			} | ||||
| 			t = p.table.find_type(typ) | ||||
| 			if t.name == '' && !p.pref.translated && !p.first_pass() && !typ.starts_with('[') { | ||||
| 				println('get_type() bad type') | ||||
| 				// println('all registered types:')
 | ||||
| 				// for q in p.table.types {
 | ||||
| 				// println(q.name)
 | ||||
| 				// }
 | ||||
| 				p.error('unknown type `$typ`') | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if typ == 'void' { | ||||
| 		p.error('unknown type `$typ`') | ||||
| 	} | ||||
| 	if mul { | ||||
| 		typ += strings.repeat(`*`, nr_muls) | ||||
| 	} | ||||
| 	// Register an []array type
 | ||||
| 	if is_arr2 { | ||||
| 		typ = 'array_array_$typ' | ||||
| 		p.register_array(typ) | ||||
| 	} | ||||
| 	else if is_arr { | ||||
| 		typ = 'array_$typ' | ||||
| 		// p.log('ARR TYPE="$typ" run=$p.pass')
 | ||||
| 		// We come across "[]User" etc ?
 | ||||
| 		p.register_array(typ) | ||||
| 	} | ||||
| 	p.next() | ||||
| 	if p.tok == .question || is_question { | ||||
| 		typ = 'Option_$typ' | ||||
| 		p.table.register_type_with_parent(typ, 'Option') | ||||
| 		if p.tok == .question { | ||||
| 			p.next() | ||||
| 		} | ||||
| 	} | ||||
| 	if typ.last_index('__') > typ.index('__') { | ||||
| 		p.error('2 __ in gettype(): typ="$typ"') | ||||
| 	} | ||||
| 	return Type{name: typ, cat: cat} | ||||
| } | ||||
|  | @ -53,6 +53,7 @@ enum TypeCategory { | |||
| 	union_ // 5
 | ||||
| 	c_struct | ||||
| 	c_typedef | ||||
| 	array | ||||
| } | ||||
| 
 | ||||
| struct Var { | ||||
|  | @ -96,6 +97,7 @@ mut: | |||
| 	// This information is needed in the first pass.
 | ||||
| 	is_placeholder bool | ||||
| 	gen_str	       bool  // needs `.str()` method generation
 | ||||
| 	 | ||||
| } | ||||
| 
 | ||||
| struct TypeNode { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue