mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: map / string / builtin type fixes
This commit is contained in:
parent
c2f22a4bf3
commit
a2d2586331
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
Loading…
Reference in New Issue
Block a user