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