diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 6b250d2778..d07b200168 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -56,6 +56,10 @@ fn (c mut Checker) resolve_expr_types(exprs []ast.Expr) { // update any types chich contain unresolved sub types fn (c &Checker) complete_types() { for idx, t in c.table.types { + // skip builtin types + if idx <= table.map_type_idx { + continue + } // println('Resolve type: $t.name') if t.kind == .array { mut info := t.array_info() @@ -202,29 +206,25 @@ pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef { typ := c.expr(selector_expr.expr) field_name := selector_expr.field - match typ.typ.kind { - .struct_ { - field := c.table.struct_find_field(typ.typ, field_name) or { - c.error('unknown field `${typ.typ.name}.$field_name`', selector_expr.pos) - exit(0) + if field := typ.typ.find_field(field_name) { + return field.typ + } + // types with parent struct (array/maps) handled here + if !isnil(typ.typ.parent) { + if field := typ.typ.parent.find_field(field_name) { + if field.typ.typ.kind == .unresolved { + return c.resolved[field.typ.idx] } return field.typ } - else { - // types with parent struct (array/maps) handled here - if !isnil(typ.typ.parent) && typ.typ.parent.kind == .struct_ { - parent := typ.typ.parent - if field := c.table.struct_find_field(parent, field_name) { - if field.typ.typ.kind == .unresolved { - return c.resolved[field.typ.idx] - } - return field.typ - } - } - c.error('`$typ.typ.name` is not a struct', selector_expr.pos) - } } - return c.table.type_ref(table.void_type_idx) + if typ.typ.kind != .struct_ { + c.error('`$typ.typ.name` is not a struct', selector_expr.pos) + } + else { + c.error('unknown field `${typ.typ.name}.$field_name`', selector_expr.pos) + } + exit(0) } // TODO: non deferred diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 22b591ed86..073d8b6c2c 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -31,16 +31,18 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.TypeRef { } pub fn (p mut Parser) parse_map_type(nr_muls int) table.TypeRef { - if p.tok.kind != .lsbr { - // check notes in table/atypes.v near map_type_idx - return p.table.type_ref(p.table.type_idxs['map']) - } p.next() + if p.tok.kind != .lsbr { + return p.table.type_ref(table.map_type_idx) + } p.check(.lsbr) - key_ti := p.parse_type() + key_type := p.parse_type() + if key_type.typ.kind != .string { + p.error('maps can only have string keys for now') + } p.check(.rsbr) - value_ti := p.parse_type() - idx := p.table.find_or_register_map(key_ti, value_ti) + value_type := p.parse_type() + idx := p.table.find_or_register_map(key_type, value_type) return p.table.type_ref_ptr(idx, nr_muls) } @@ -99,13 +101,14 @@ pub fn (p mut Parser) parse_type() table.TypeRef { return p.parse_multi_return_ti() } else { + // no defer + if name == 'map' { + return p.parse_map_type(nr_muls) + } defer { p.next() } match name { - 'map' { - return p.parse_map_type(nr_muls) - } 'voidptr' { return p.table.type_ref_ptr(table.voidptr_type_idx, nr_muls) } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 60bdc33e24..1a78a364a9 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -458,14 +458,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { p.check(.dot) } if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr { - p.next() - p.check(.lsbr) - key_type := p.check_name() - if key_type != 'string' { - p.error('maps can only have string keys for now') - } - p.check(.rsbr) - p.check_name() + map_type := p.parse_map_type(0) return node,typ } // fn call or type cast diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index b32fb00a61..c8cb1ece04 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -23,6 +23,7 @@ pub: } pub const ( + // primitive types void_type_idx = 1 voidptr_type_idx = 2 charptr_type_idx = 3 @@ -36,15 +37,13 @@ pub const ( u64_type_idx = 11 f32_type_idx = 12 f64_type_idx = 13 - string_type_idx = 14 - char_type_idx = 15 - byte_type_idx = 16 - bool_type_idx = 17 - // currently map is parsed from builtin as a normal struct named `map` - // any maps after that are of type map with parent being the struct named `map` - // same goes for array. this works since builtin is parsed first. - // will probably go back to registering these types manually and add idx here - // map_type_idx = 18 + bool_type_idx = 14 + // advanced / defined from v structs + string_type_idx = 15 + char_type_idx = 16 + byte_type_idx = 17 + array_type_idx = 18 + map_type_idx = 19 ) pub const ( @@ -102,7 +101,7 @@ pub fn(t &Type) array_info() Array { return it } else { - panic('Type.mr_info(): no array info') + panic('Type.array_info(): no array info') } } } @@ -114,7 +113,7 @@ pub fn(t &Type) array_fixed_info() ArrayFixed { return it } else { - panic('Type.mr_info(): no array fixed info') + panic('Type.array_fixed(): no array fixed info') } } } @@ -126,7 +125,7 @@ pub fn(t &Type) map_info() Map { return it } else { - panic('Type.mr_info(): no map info') + panic('Type.map_info(): no map info') } } } @@ -250,6 +249,11 @@ pub fn (t mut Table) register_builtin_types() { kind: .f64 name: 'f64' }) + t.register_type(Type{ + parent: 0 + kind: .bool + name: 'bool' + }) t.register_type(Type{ parent: 0 kind: .string @@ -267,13 +271,13 @@ pub fn (t mut Table) register_builtin_types() { }) t.register_type(Type{ parent: 0 - kind: .bool - name: 'bool' + kind: .array + name: 'array' }) t.register_type(Type{ parent: 0 - kind: .unresolved - name: 'unresolved' + kind: .map + name: 'map' }) } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index dced4c754c..2260101aa5 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -202,6 +202,11 @@ pub fn (t &Table) register_method(typ &Type, new_fn Fn) bool { return true } +pub fn (t mut Table) new_tmp_var() string { + t.tmp_cnt++ + return 'tmp$t.tmp_cnt' +} + pub fn (t &Type) has_method(name string) bool { t.find_method(name) or { return false @@ -218,9 +223,26 @@ pub fn (t &Type) find_method(name string) ?Fn { return none } -pub fn (t mut Table) new_tmp_var() string { - t.tmp_cnt++ - return 'tmp$t.tmp_cnt' + +pub fn (s &Type) has_field(name string) bool { + s.find_field(name) or { + return false + } + return true +} + +pub fn (s &Type) find_field(name string) ?Field { + match s.info { + Struct { + for field in it.fields { + if field.name == name { + return field + } + } + } + else {} + } + return none } pub fn (t &Table) struct_has_field(s &Type, name string) bool { @@ -230,9 +252,6 @@ pub fn (t &Table) struct_has_field(s &Type, name string) bool { else { println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=none') } - // for typ in t.types { - // println('$typ.idx $typ.name') - // } if _ := t.struct_find_field(s, name) { return true } @@ -246,21 +265,13 @@ pub fn (t &Table) struct_find_field(s &Type, name string) ?Field { else { println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=none') } - info := s.info as Struct - for field in info.fields { - if field.name == name { - return field - } + if field := s.find_field(name) { + return field } if !isnil(s.parent) { - if s.parent.kind == .struct_ { - parent_info := s.parent.info as Struct + if field := s.parent.find_field(name) { println('got parent $s.parent.name') - for field in parent_info.fields { - if field.name == name { - return field - } - } + return field } } return none @@ -287,7 +298,10 @@ pub fn (t &Table) find_type(name string) ?Type { pub fn (t mut Table) register_builtin_type(typ Type) int { existing_idx := t.type_idxs[typ.name] if existing_idx > 0 { - t.types[existing_idx] = typ + if existing_idx >= string_type_idx { + existing_type := t.types[existing_idx] + t.types[existing_idx] = { typ | kind: existing_type.kind } + } return existing_idx } return t.register_type(typ) @@ -339,7 +353,7 @@ pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) } // register map_type := Type{ - parent: &t.types[t.type_idxs['map']] + parent: &t.types[map_type_idx] kind: .map name: name info: Map{ @@ -359,7 +373,7 @@ pub fn (t mut Table) find_or_register_array(elem_type TypeRef, nr_dims int) int } // register array_type := Type{ - parent: &t.types[t.type_idxs['array']] + parent: &t.types[array_type_idx] kind: .array name: name info: Array{