v2: map / string / builtin type fixes

pull/3695/head
joe-conigliaro 2020-02-09 02:59:57 +11:00 committed by GitHub
parent c2f22a4bf3
commit a2d2586331
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 74 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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'
})
}

View File

@ -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{