1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

map: cleanup (#7621)

This commit is contained in:
ka-weihe 2020-12-27 18:31:50 +01:00 committed by GitHub
parent df61cf246b
commit b9df7aae4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 28 deletions

View File

@ -308,11 +308,29 @@ fn map_free_string(pkey voidptr) {
fn map_free_nop(_ voidptr) { fn map_free_nop(_ voidptr) {
} }
// bootstrap fn new_map_2(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map {
fn new_map_1(value_bytes int) map { metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc))
return new_map(int(sizeof(string)), value_bytes) // for now assume anything bigger than a pointer is a string
has_string_keys := key_bytes > sizeof(voidptr)
return map{
key_bytes: key_bytes
value_bytes: value_bytes
even_index: init_even_index
cached_hashbits: max_cached_hashbits
shift: init_log_capicity
key_values: new_dense_array(key_bytes, value_bytes)
metas: &u32(vcalloc(metasize))
extra_metas: extra_metas_inc
len: 0
has_string_keys: has_string_keys
hash_fn: hash_fn
key_eq_fn: key_eq_fn
clone_fn: clone_fn
free_fn: free_fn
}
} }
// delete this
fn new_map(key_bytes int, value_bytes int) map { fn new_map(key_bytes int, value_bytes int) map {
metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc)) metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc))
// for now assume anything bigger than a pointer is a string // for now assume anything bigger than a pointer is a string
@ -372,10 +390,22 @@ fn new_map(key_bytes int, value_bytes int) map {
} }
} }
fn new_map_init(n int, value_bytes int, keys &string, values voidptr) map { fn new_map_init_2(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map {
return new_map_init_1(n, int(sizeof(string)), value_bytes, keys, values) mut out := new_map_2(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, free_fn)
// TODO pre-allocate n slots
mut pkey := byteptr(keys)
mut pval := byteptr(values)
for _ in 0 .. n {
unsafe {
out.set_1(pkey, pval)
pkey += key_bytes
pval += value_bytes
}
}
return out
} }
// delete this
fn new_map_init_1(n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map { fn new_map_init_1(n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map {
mut out := new_map(key_bytes, value_bytes) mut out := new_map(key_bytes, value_bytes)
// TODO pre-allocate n slots // TODO pre-allocate n slots
@ -454,11 +484,6 @@ fn (mut m map) ensure_extra_metas(probe_count u32) {
} }
} }
// bootstrap
fn (mut m map) set(key string, value voidptr) {
m.set_1(&key, value)
}
// Insert new element to the map. The element is inserted if its key is // Insert new element to the map. The element is inserted if its key is
// not equivalent to the key of any other element already in the container. // not equivalent to the key of any other element already in the container.
// If the key already exists, its value is changed to the value of the new element. // If the key already exists, its value is changed to the value of the new element.
@ -554,10 +579,6 @@ fn (mut m map) cached_rehash(old_cap u32) {
unsafe { free(old_metas) } unsafe { free(old_metas) }
} }
fn (mut m map) get_and_set(key string, zero voidptr) voidptr {
return m.get_and_set_1(&key, zero)
}
// This method is used for assignment operators. If the argument-key // This method is used for assignment operators. If the argument-key
// does not exist in the map, it's added to the map along with the zero/default value. // does not exist in the map, it's added to the map along with the zero/default value.
// If the key exists, its respective value is returned. // If the key exists, its respective value is returned.
@ -585,10 +606,6 @@ fn (mut m map) get_and_set_1(key voidptr, zero voidptr) voidptr {
return voidptr(0) return voidptr(0)
} }
fn (m map) get(key string, zero voidptr) voidptr {
return m.get_1(&key, zero)
}
// If `key` matches the key of an element in the container, // If `key` matches the key of an element in the container,
// the method returns a reference to its mapped value. // the method returns a reference to its mapped value.
// If not, a zero/default value is returned. // If not, a zero/default value is returned.
@ -611,6 +628,7 @@ fn (m &map) get_1(key voidptr, zero voidptr) voidptr {
return zero return zero
} }
// delete this
fn (m map) exists(key string) bool { fn (m map) exists(key string) bool {
return m.exists_1(&key) return m.exists_1(&key)
} }
@ -646,6 +664,7 @@ fn (mut d DenseArray) delete(i int) {
} }
} }
// delete this
pub fn (mut m map) delete(key string) { pub fn (mut m map) delete(key string) {
m.delete_1(&key) m.delete_1(&key)
} }
@ -690,6 +709,7 @@ pub fn (mut m map) delete_1(key voidptr) {
} }
// bootstrap // bootstrap
// delete this
pub fn (m &map) keys() []string { pub fn (m &map) keys() []string {
mut keys := []string{len: m.len} mut keys := []string{len: m.len}
mut item := unsafe { byteptr(keys.data) } mut item := unsafe { byteptr(keys.data) }

View File

@ -130,9 +130,9 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
fn_builder.writeln('\t\t$value_typ v = (*($value_typ*)map_get_1(&a, &k, &($value_typ[]){ 0 }));') fn_builder.writeln('\t\t$value_typ v = (*($value_typ*)map_get_1(&a, &k, &($value_typ[]){ 0 }));')
} }
match value_sym.kind { match value_sym.kind {
.string { fn_builder.writeln('\t\tif (!map_exists(b, k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') } .string { fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') }
.function { fn_builder.writeln('\t\tif (!map_exists(b, k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') } .function { fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') }
else { fn_builder.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get_1(&b, &k, &($value_typ[]){ 0 })) != v) {') } else { fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*($value_typ*)map_get_1(&b, &k, &($value_typ[]){ 0 })) != v) {') }
} }
fn_builder.writeln('\t\t\treturn false;') fn_builder.writeln('\t\t\treturn false;')
fn_builder.writeln('\t\t}') fn_builder.writeln('\t\t}')

View File

@ -2325,6 +2325,45 @@ fn (mut g Gen) gen_anon_fn_decl(it ast.AnonFn) {
g.definitions.write(fn_body) g.definitions.write(fn_body)
} }
fn (mut g Gen) map_fn_ptrs(key_typ table.TypeSymbol) (string, string, string, string) {
mut hash_fn := ''
mut key_eq_fn := ''
mut clone_fn := ''
mut free_fn := '&map_free_nop'
match key_typ.kind {
.byte, .bool, .i8, .char {
hash_fn = '&map_hash_int_2'
key_eq_fn = '&map_eq_int_2'
clone_fn = '&map_clone_int_2'
}
.i16, .u16 {
hash_fn = '&map_hash_int_2'
key_eq_fn = '&map_eq_int_2'
clone_fn = '&map_clone_int_2'
}
.int, .u32 {
hash_fn = '&map_hash_int_4'
key_eq_fn = '&map_eq_int_4'
clone_fn = '&map_clone_int_4'
}
.byteptr, .charptr, .voidptr, .u64, .i64 {
hash_fn = '&map_hash_int_8'
key_eq_fn = '&map_eq_int_8'
clone_fn = '&map_clone_int_8'
}
.string {
hash_fn = '&map_hash_string'
key_eq_fn = '&map_eq_string'
clone_fn = '&map_clone_string'
free_fn = '&map_free_string'
}
else {
verror('map key type not supported')
}
}
return hash_fn, key_eq_fn, clone_fn, free_fn
}
fn (mut g Gen) expr(node ast.Expr) { fn (mut g Gen) expr(node ast.Expr) {
// println('cgen expr() line_nr=$node.pos.line_nr') // println('cgen expr() line_nr=$node.pos.line_nr')
// NB: please keep the type names in the match here in alphabetical order: // NB: please keep the type names in the match here in alphabetical order:
@ -2513,6 +2552,8 @@ fn (mut g Gen) expr(node ast.Expr) {
key_typ_str := g.typ(node.key_type) key_typ_str := g.typ(node.key_type)
value_typ_str := g.typ(node.value_type) value_typ_str := g.typ(node.value_type)
value_typ := g.table.get_type_symbol(node.value_type) value_typ := g.table.get_type_symbol(node.value_type)
key_typ := g.table.get_type_symbol(node.key_type)
hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_typ)
size := node.vals.len size := node.vals.len
mut shared_styp := '' // only needed for shared &[]{...} mut shared_styp := '' // only needed for shared &[]{...}
mut styp := '' mut styp := ''
@ -2535,9 +2576,9 @@ fn (mut g Gen) expr(node ast.Expr) {
} }
if size > 0 { if size > 0 {
if value_typ.kind == .function { if value_typ.kind == .function {
g.write('new_map_init_1($size, sizeof($key_typ_str), sizeof(voidptr), _MOV(($key_typ_str[$size]){') g.write('new_map_init_2($hash_fn, $key_eq_fn, $clone_fn, $free_fn, $size, sizeof($key_typ_str), sizeof(voidptr), _MOV(($key_typ_str[$size]){')
} else { } else {
g.write('new_map_init_1($size, sizeof($key_typ_str), sizeof($value_typ_str), _MOV(($key_typ_str[$size]){') g.write('new_map_init_2($hash_fn, $key_eq_fn, $clone_fn, $free_fn, $size, sizeof($key_typ_str), sizeof($value_typ_str), _MOV(($key_typ_str[$size]){')
} }
for expr in node.keys { for expr in node.keys {
g.expr(expr) g.expr(expr)
@ -2554,7 +2595,7 @@ fn (mut g Gen) expr(node ast.Expr) {
} }
g.write('}))') g.write('}))')
} else { } else {
g.write('new_map(sizeof($key_typ_str), sizeof($value_typ_str))') g.write('new_map_2(sizeof($key_typ_str), sizeof($value_typ_str), $hash_fn, $key_eq_fn, $clone_fn, $free_fn)')
} }
if g.is_shared { if g.is_shared {
g.write(', .mtx = sync__new_rwmutex()}') g.write(', .mtx = sync__new_rwmutex()}')
@ -5130,9 +5171,9 @@ fn (mut g Gen) type_default(typ_ table.Type) string {
} }
if sym.kind == .map { if sym.kind == .map {
info := sym.map_info() info := sym.map_info()
key_type_str := g.typ(info.key_type) key_typ := g.table.get_type_symbol(info.key_type)
value_type_str := g.typ(info.value_type) hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_typ)
return 'new_map(sizeof($key_type_str), sizeof($value_type_str))' return 'new_map_2(sizeof(${g.typ(info.key_type)}), sizeof(${g.typ(info.value_type)}), $hash_fn, $key_eq_fn, $clone_fn, $free_fn)'
} }
// User struct defined in another module. // User struct defined in another module.
// if typ.contains('__') { // if typ.contains('__') {

View File

@ -272,7 +272,7 @@ static void* g_live_info = NULL;
// take the address of an rvalue // take the address of an rvalue
#define ADDR(type, expr) (&((type[]){expr}[0])) #define ADDR(type, expr) (&((type[]){expr}[0]))
#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push_many(arr, tmp.data, tmp.len);} #define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push_many(arr, tmp.data, tmp.len);}
#define _IN_MAP(val, m) map_exists(m, val) #define _IN_MAP(val, m) map_exists_1(&m, &val)
// unsigned/signed comparisons // unsigned/signed comparisons
static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; } static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; }