mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
re-write map.v and update the compiler
This commit is contained in:
parent
9a3baf5609
commit
f7dbbf5810
@ -13,6 +13,7 @@ const (
|
|||||||
struct Fn {
|
struct Fn {
|
||||||
// addr int
|
// addr int
|
||||||
mut:
|
mut:
|
||||||
|
name string
|
||||||
pkg string
|
pkg string
|
||||||
local_vars []Var
|
local_vars []Var
|
||||||
var_idx int
|
var_idx int
|
||||||
@ -22,7 +23,6 @@ mut:
|
|||||||
// idx int
|
// idx int
|
||||||
scope_level int
|
scope_level int
|
||||||
typ string // return type
|
typ string // return type
|
||||||
name string
|
|
||||||
is_c bool
|
is_c bool
|
||||||
receiver_typ string
|
receiver_typ string
|
||||||
is_public bool
|
is_public bool
|
||||||
|
@ -356,8 +356,7 @@ string _STR_TMP(const char *fmt, ...) {
|
|||||||
// Generate `main` which calls every single test function
|
// Generate `main` which calls every single test function
|
||||||
else if v.pref.is_test {
|
else if v.pref.is_test {
|
||||||
cgen.genln('int main() { init_consts();')
|
cgen.genln('int main() { init_consts();')
|
||||||
for entry in v.table.fns.entries {
|
for key, f in v.table.fns {
|
||||||
f := v.table.fns[entry.key]
|
|
||||||
if f.name.starts_with('test_') {
|
if f.name.starts_with('test_') {
|
||||||
cgen.genln('$f.name();')
|
cgen.genln('$f.name();')
|
||||||
}
|
}
|
||||||
@ -680,7 +679,7 @@ fn (v &V) v_files_from_dir(dir string) []string {
|
|||||||
if file.ends_with('_mac.v') && v.os != .mac {
|
if file.ends_with('_mac.v') && v.os != .mac {
|
||||||
lin_file := file.replace('_mac.v', '_lin.v')
|
lin_file := file.replace('_mac.v', '_lin.v')
|
||||||
// println('lin_file="$lin_file"')
|
// println('lin_file="$lin_file"')
|
||||||
// If there are both _mav.v and _lin.v, don't use _mav.v
|
// If there are both _mac.v and _lin.v, don't use _mav.v
|
||||||
if os.file_exists('$dir/$lin_file') {
|
if os.file_exists('$dir/$lin_file') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1035,7 +1034,7 @@ fn run_repl() []string {
|
|||||||
mut temp_line := line
|
mut temp_line := line
|
||||||
mut temp_flag := false
|
mut temp_flag := false
|
||||||
if !(line.contains(' ') || line.contains(':') || line.contains('=') || line.contains(',') ){
|
if !(line.contains(' ') || line.contains(':') || line.contains('=') || line.contains(',') ){
|
||||||
temp_line = 'println('+line+')'
|
temp_line = 'println($line)'
|
||||||
temp_flag = true
|
temp_flag = true
|
||||||
}
|
}
|
||||||
temp_source_code := lines.join('\n') + '\n' + temp_line
|
temp_source_code := lines.join('\n') + '\n' + temp_line
|
||||||
@ -1064,7 +1063,6 @@ fn run_repl() []string {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
// This definitely needs to be better :)
|
|
||||||
const (
|
const (
|
||||||
HelpText = '
|
HelpText = '
|
||||||
Usage: v [options] [file | directory]
|
Usage: v [options] [file | directory]
|
||||||
@ -1077,8 +1075,7 @@ Options:
|
|||||||
-prod Build an optimized executable.
|
-prod Build an optimized executable.
|
||||||
-o <file> Place output into <file>.
|
-o <file> Place output into <file>.
|
||||||
-obf Obfuscate the resulting binary.
|
-obf Obfuscate the resulting binary.
|
||||||
run Build and execute a V program.
|
run Build and execute a V program. You can add arguments after file name.
|
||||||
You can add arguments after file name.
|
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
<file>_test.v Test file.
|
<file>_test.v Test file.
|
||||||
|
@ -1200,7 +1200,7 @@ fn (p mut Parser) var_decl() {
|
|||||||
fn (p mut Parser) bool_expression() string {
|
fn (p mut Parser) bool_expression() string {
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
typ := p.bterm()
|
typ := p.bterm()
|
||||||
for p.tok == .and || p.tok == .ortok {
|
for p.tok == .and || p.tok == .logical_or {
|
||||||
p.gen(' ${p.tok.str()} ')
|
p.gen(' ${p.tok.str()} ')
|
||||||
p.check_space(p.tok)
|
p.check_space(p.tok)
|
||||||
p.check_types(p.bterm(), typ)
|
p.check_types(p.bterm(), typ)
|
||||||
@ -2916,10 +2916,21 @@ fn (p mut Parser) for_st() {
|
|||||||
is_mut: true
|
is_mut: true
|
||||||
}
|
}
|
||||||
p.register_var(i_var)
|
p.register_var(i_var)
|
||||||
|
p.genln('array_string keys_$tmp = map_keys(& $tmp ); ')
|
||||||
|
p.genln('for (int l = 0; l < keys_$tmp .len; l++) {')
|
||||||
|
p.genln(' string $i = ((string*)keys_$tmp .data)[l];')
|
||||||
|
//p.genln(' string $i = *(string*) ( array__get(keys_$tmp, l) );')
|
||||||
|
def := type_default(var_typ)
|
||||||
|
// TODO don't call map_get() for each key, fetch values while traversing
|
||||||
|
// the tree (replace `map_keys()` above with `map_key_vals()`)
|
||||||
|
p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);')
|
||||||
|
|
||||||
|
/*
|
||||||
p.genln('for (int l = 0; l < $tmp . entries.len; l++) {')
|
p.genln('for (int l = 0; l < $tmp . entries.len; l++) {')
|
||||||
p.genln('Entry entry = *((Entry*) (array__get($tmp .entries, l)));')
|
p.genln('Entry entry = *((Entry*) (array__get($tmp .entries, l)));')
|
||||||
p.genln('string $i = entry.key;')
|
p.genln('string $i = entry.key;')
|
||||||
p.genln('$var_typ $val; map_get($tmp, $i, & $val);')
|
p.genln('$var_typ $val; map_get($tmp, $i, & $val);')
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `for val in vals`
|
// `for val in vals`
|
||||||
|
@ -344,7 +344,7 @@ fn (s mut Scanner) scan() ScanRes {
|
|||||||
case `|`:
|
case `|`:
|
||||||
if nextc == `|` {
|
if nextc == `|` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return scan_res(.ortok, '')
|
return scan_res(.logical_or, '')
|
||||||
}
|
}
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
|
@ -565,8 +565,7 @@ fn (t &Table) is_interface(name string) bool {
|
|||||||
|
|
||||||
// Do we have fn main()?
|
// Do we have fn main()?
|
||||||
fn (t &Table) main_exists() bool {
|
fn (t &Table) main_exists() bool {
|
||||||
for entry in t.fns.entries {
|
for _, f in t.fns {
|
||||||
f := t.fns[entry.key]
|
|
||||||
if f.name == 'main' {
|
if f.name == 'main' {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -696,11 +695,11 @@ fn (fit mut FileImportTable) register_import(mod string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
|
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
|
||||||
if !fit.imports.exists(alias) {
|
if fit.imports.exists(alias) {
|
||||||
fit.imports[alias] = mod
|
panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
|
||||||
} else {
|
return
|
||||||
panic('Cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
|
}
|
||||||
}
|
fit.imports[alias] = mod
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (fit &FileImportTable) known_alias(alias string) bool {
|
fn (fit &FileImportTable) known_alias(alias string) bool {
|
||||||
@ -708,10 +707,10 @@ fn (fit &FileImportTable) known_alias(alias string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (fit &FileImportTable) is_aliased(mod string) bool {
|
fn (fit &FileImportTable) is_aliased(mod string) bool {
|
||||||
for i in fit.imports.keys() {
|
for _, val in fit.imports {
|
||||||
if fit.imports[i] == mod {
|
if val == mod {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ enum Token {
|
|||||||
inc
|
inc
|
||||||
dec
|
dec
|
||||||
and
|
and
|
||||||
ortok
|
logical_or
|
||||||
not
|
not
|
||||||
bit_not
|
bit_not
|
||||||
question
|
question
|
||||||
@ -67,51 +67,51 @@ enum Token {
|
|||||||
dotdot
|
dotdot
|
||||||
// keywords
|
// keywords
|
||||||
keyword_beg
|
keyword_beg
|
||||||
key_module
|
key_as
|
||||||
key_struct
|
|
||||||
key_if
|
|
||||||
key_else
|
|
||||||
key_return
|
|
||||||
key_go
|
|
||||||
key_const
|
|
||||||
key_import_const
|
|
||||||
key_mut
|
|
||||||
typ
|
|
||||||
key_enum
|
|
||||||
key_for
|
|
||||||
key_switch
|
|
||||||
MATCH
|
|
||||||
key_case
|
|
||||||
func
|
|
||||||
key_true
|
|
||||||
key_false
|
|
||||||
key_continue
|
|
||||||
key_break
|
|
||||||
key_embed
|
|
||||||
key_import
|
|
||||||
//typeof
|
|
||||||
key_default
|
|
||||||
key_assert
|
key_assert
|
||||||
key_sizeof
|
|
||||||
key_in
|
|
||||||
key_atomic
|
key_atomic
|
||||||
key_interface
|
key_break
|
||||||
key_orelse
|
key_case
|
||||||
|
key_const
|
||||||
|
key_continue
|
||||||
|
key_default
|
||||||
|
key_else
|
||||||
|
key_embed
|
||||||
|
key_enum
|
||||||
|
key_false
|
||||||
|
key_for
|
||||||
|
func
|
||||||
key_global
|
key_global
|
||||||
|
key_go
|
||||||
|
key_goto
|
||||||
|
key_if
|
||||||
|
key_import
|
||||||
|
key_import_const
|
||||||
|
key_in
|
||||||
|
key_interface
|
||||||
|
MATCH
|
||||||
|
key_module
|
||||||
|
key_mut
|
||||||
|
key_return
|
||||||
|
key_sizeof
|
||||||
|
key_struct
|
||||||
|
key_switch
|
||||||
|
key_true
|
||||||
|
typ
|
||||||
|
//typeof
|
||||||
|
key_orelse
|
||||||
key_union
|
key_union
|
||||||
key_pub
|
key_pub
|
||||||
key_goto
|
|
||||||
key_static
|
key_static
|
||||||
key_as
|
|
||||||
keyword_end
|
keyword_end
|
||||||
}
|
}
|
||||||
|
|
||||||
// build_keys genereates a map with keywords' string values:
|
// build_keys genereates a map with keywords' string values:
|
||||||
// Keywords['return'] == .key_return
|
// Keywords['return'] == .key_return
|
||||||
fn build_keys() map_int {
|
fn build_keys() map[string]int {
|
||||||
mut res := map[string]int{}
|
mut res := map[string]int{}
|
||||||
for t := int(Token.keyword_beg) + 1; t < int(Token.keyword_end); t++ {
|
for t := int(Token.keyword_beg) + 1; t < int(Token.keyword_end); t++ {
|
||||||
key := TOKENSTR[t]
|
key := TokenStr[t]
|
||||||
res[key] = int(t)
|
res[key] = int(t)
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
@ -140,7 +140,7 @@ fn build_token_str() []string {
|
|||||||
s[Token.inc] = '++'
|
s[Token.inc] = '++'
|
||||||
s[Token.dec] = '--'
|
s[Token.dec] = '--'
|
||||||
s[Token.and] = '&&'
|
s[Token.and] = '&&'
|
||||||
s[Token.ortok] = '||'
|
s[Token.logical_or] = '||'
|
||||||
s[Token.not] = '!'
|
s[Token.not] = '!'
|
||||||
s[Token.dot] = '.'
|
s[Token.dot] = '.'
|
||||||
s[Token.dotdot] = '..'
|
s[Token.dotdot] = '..'
|
||||||
@ -218,7 +218,7 @@ fn build_token_str() []string {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
NrTokens = 140
|
NrTokens = 140
|
||||||
TOKENSTR = build_token_str()
|
TokenStr = build_token_str()
|
||||||
KEYWORDS = build_keys()
|
KEYWORDS = build_keys()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -232,11 +232,13 @@ fn is_key(key string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (t Token) str() string {
|
fn (t Token) str() string {
|
||||||
return TOKENSTR[int(t)]
|
return TokenStr[int(t)]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t Token) is_decl() bool {
|
fn (t Token) is_decl() bool {
|
||||||
// TODO return t in [.func ,.typ, .key_const, .key_import_.key_const ,AT ,.eof]
|
// TODO i
|
||||||
|
//return t in [.key_enum, .key_interface, .func, .typ, .key_const,
|
||||||
|
//.key_import_const, .key_struct, .key_pub, .eof]
|
||||||
return t == .key_enum || t == .key_interface || t == .func ||
|
return t == .key_enum || t == .key_interface || t == .func ||
|
||||||
t == .key_struct || t == .typ ||
|
t == .key_struct || t == .typ ||
|
||||||
t == .key_const || t == .key_import_const || t == .key_pub || t == .eof
|
t == .key_const || t == .key_import_const || t == .key_pub || t == .eof
|
||||||
|
@ -5,60 +5,116 @@
|
|||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
struct map {
|
struct map {
|
||||||
// cap int
|
|
||||||
// keys []string
|
|
||||||
// table byteptr
|
|
||||||
// keys_table *string
|
|
||||||
// table *Entry
|
|
||||||
element_size int
|
element_size int
|
||||||
// collisions []Entry
|
root *Node
|
||||||
pub:
|
_keys []string // used by `keys()` TODO remove this from map struct,
|
||||||
entries []Entry
|
key_i int // store in a separate var
|
||||||
is_sorted bool
|
pub:
|
||||||
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Entry {
|
struct Node {
|
||||||
pub:
|
left *Node
|
||||||
|
right *Node
|
||||||
key string
|
key string
|
||||||
val voidptr
|
val voidptr
|
||||||
// linked list for collisions
|
|
||||||
// next *Entry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_map(cap, elm_size int) map {
|
fn new_map(cap, elm_size int) map {
|
||||||
res := map {
|
res := map {
|
||||||
// len: len,
|
|
||||||
element_size: elm_size
|
element_size: elm_size
|
||||||
// entries:
|
root: 0
|
||||||
// keys: []string
|
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (m &map) new_entry(key string, val voidptr) Entry {
|
fn new_node(key string, val voidptr, element_size int) *Node {
|
||||||
new_e := Entry {
|
new_e := &Node {
|
||||||
key: key
|
key: key
|
||||||
val: malloc(m.element_size)
|
val: malloc(element_size)
|
||||||
// next: 0
|
left: 0
|
||||||
|
right: 0
|
||||||
}
|
}
|
||||||
C.memcpy(new_e.val, val, m.element_size)
|
C.memcpy(new_e.val, val, element_size)
|
||||||
return new_e
|
return new_e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (m mut map) insert(n mut Node, key string, val voidptr) {
|
||||||
|
if n.key == key {
|
||||||
|
C.memcpy(n.val, val, m.element_size)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n.key > key {
|
||||||
|
if isnil(n.left) {
|
||||||
|
n.left = new_node(key, val, m.element_size)
|
||||||
|
m.size++
|
||||||
|
} else {
|
||||||
|
m.insert(mut n.left, key, val)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isnil(n.right) {
|
||||||
|
n.right = new_node(key, val, m.element_size)
|
||||||
|
m.size++
|
||||||
|
} else {
|
||||||
|
m.insert(mut n.right, key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (n & Node) find(key string, out voidptr, element_size int) bool{
|
||||||
|
if n.key == key {
|
||||||
|
C.memcpy(out, n.val, element_size)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else if n.key > key {
|
||||||
|
if isnil(n.left) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return n.left.find(key, out, element_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if isnil(n.right) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return n.right.find(key, out, element_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// same as `find`, but doesn't return a value. Used by `exists`
|
||||||
|
fn (n & Node) find2(key string, element_size int) bool{
|
||||||
|
if n.key == key {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else if n.key > key {
|
||||||
|
if isnil(n.left) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return n.left.find2(key, element_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if isnil(n.right) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return n.right.find2(key, element_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fn (m mut map) _set(key string, val voidptr) {
|
fn (m mut map) _set(key string, val voidptr) {
|
||||||
e := m.new_entry(key, val)
|
if isnil(m.root) {
|
||||||
for i := 0; i < m.entries.len; i++ {
|
m.root = new_node(key, val, m.element_size)
|
||||||
entry := m.entries[i]
|
m.size++
|
||||||
if entry.key == key {
|
return
|
||||||
// e := Entry2{key: key, val: val}
|
}
|
||||||
m.entries[i] = e
|
m.insert(mut m.root, key, val)
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.entries << e// m.new_entry(key, val)
|
|
||||||
m.is_sorted = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
fn (m map) bs(query string, start, end int, out voidptr) {
|
fn (m map) bs(query string, start, end int, out voidptr) {
|
||||||
// println('bs "$query" $start -> $end')
|
// println('bs "$query" $start -> $end')
|
||||||
mid := start + ((end - start) / 2)
|
mid := start + ((end - start) / 2)
|
||||||
@ -83,63 +139,46 @@ fn (m map) bs(query string, start, end int, out voidptr) {
|
|||||||
}
|
}
|
||||||
m.bs(query, mid, end, out)
|
m.bs(query, mid, end, out)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn compare_map(a, b *Entry) int {
|
fn (m mut map) preorder_keys(node &Node) {
|
||||||
if a.key < b.key {
|
m._keys[m.key_i] = node.key
|
||||||
return -1
|
m.key_i++
|
||||||
}
|
if !isnil(node.left) {
|
||||||
if a.key > b.key {
|
m.preorder_keys(node.left)
|
||||||
return 1
|
}
|
||||||
}
|
if !isnil(node.right) {
|
||||||
return 0
|
m.preorder_keys(node.right)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (m mut map) sort() {
|
pub fn (m mut map) keys() []string {
|
||||||
m.entries.sort_with_compare(compare_map)
|
m._keys = [''; m.size]
|
||||||
m.is_sorted = true
|
m.key_i = 0
|
||||||
}
|
if isnil(m.root) {
|
||||||
|
return m._keys
|
||||||
pub fn (m map) keys() []string {
|
}
|
||||||
mut keys := []string{}
|
m.preorder_keys(m.root)
|
||||||
for i := 0; i < m.entries.len; i++ {
|
return m._keys
|
||||||
entry := m.entries[i]
|
|
||||||
keys << entry.key
|
|
||||||
}
|
|
||||||
return keys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (m map) get(key string, out voidptr) bool {
|
fn (m map) get(key string, out voidptr) bool {
|
||||||
if m.is_sorted {
|
if isnil(m.root) {
|
||||||
// println('\n\nget "$key" sorted')
|
return false
|
||||||
m.bs(key, 0, m.entries.len, out)
|
}
|
||||||
return true
|
return m.root.find(key, out, m.element_size)
|
||||||
}
|
|
||||||
for i := 0; i < m.entries.len; i++ {
|
|
||||||
entry := m.entries[i]
|
|
||||||
if entry.key == key {
|
|
||||||
C.memcpy(out, entry.val, m.element_size)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (m map) exists(key string) bool {
|
pub fn (m map) exists(key string) bool {
|
||||||
for i := 0; i < m.entries.len; i++ {
|
return !isnil(m.root) && m.root.find2(key, m.element_size)
|
||||||
entry := m.entries[i]
|
|
||||||
if entry.key == key {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (m map) print() {
|
pub fn (m map) print() {
|
||||||
println('<<<<<<<<')
|
println('<<<<<<<<')
|
||||||
for i := 0; i < m.entries.len; i++ {
|
//for i := 0; i < m.entries.len; i++ {
|
||||||
// entry := m.entries[i]
|
// entry := m.entries[i]
|
||||||
// println('$entry.key => $entry.val')
|
// println('$entry.key => $entry.val')
|
||||||
}
|
//}
|
||||||
/*
|
/*
|
||||||
for i := 0; i < m.cap * m.element_size; i++ {
|
for i := 0; i < m.cap * m.element_size; i++ {
|
||||||
b := m.table[i]
|
b := m.table[i]
|
||||||
@ -158,15 +197,15 @@ pub fn (m map) free() {
|
|||||||
|
|
||||||
pub fn (m map_string) str() string {
|
pub fn (m map_string) str() string {
|
||||||
// return 'not impl'
|
// return 'not impl'
|
||||||
if m.entries.len == 0 {
|
if m.size == 0 {
|
||||||
return '{}'
|
return '{}'
|
||||||
}
|
}
|
||||||
// TODO use bytes buffer
|
// TODO use bytes buffer
|
||||||
mut s := '{\n'
|
mut s := '{\n'
|
||||||
for entry in m.entries {
|
//for entry in m.entries {
|
||||||
val := m[entry.key]
|
//val := m[entry.key]
|
||||||
s += ' "$entry.key" => "$val"\n'
|
//s += ' "$entry.key" => "$val"\n'
|
||||||
}
|
//}
|
||||||
s += '}'
|
s += '}'
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
@ -13,13 +15,32 @@ fn (a mut A) set(key string, val int) {
|
|||||||
|
|
||||||
fn test_map() {
|
fn test_map() {
|
||||||
mut m := map[string]int{}
|
mut m := map[string]int{}
|
||||||
|
assert m.size == 0
|
||||||
m['hi'] = 80
|
m['hi'] = 80
|
||||||
|
m['hello'] = 101
|
||||||
assert m['hi'] == 80
|
assert m['hi'] == 80
|
||||||
|
assert m['hello'] == 101
|
||||||
|
assert m.size == 2
|
||||||
|
mut sum := 0
|
||||||
|
mut key_sum := ''
|
||||||
|
// Test `for in`
|
||||||
|
for key, val in m {
|
||||||
|
sum += val
|
||||||
|
key_sum += key
|
||||||
|
}
|
||||||
|
assert sum == 80 + 101
|
||||||
|
assert key_sum == 'hihello'
|
||||||
|
// Test `.keys()`
|
||||||
|
keys := m.keys()
|
||||||
|
assert keys.len == 2
|
||||||
|
assert keys[0] == 'hi'
|
||||||
|
assert keys[1] == 'hello'
|
||||||
////
|
////
|
||||||
mut users := map[string]User{}
|
mut users := map[string]User{}
|
||||||
users['1'] = User{'Peter'}
|
users['1'] = User{'Peter'}
|
||||||
peter := users['1']
|
peter := users['1']
|
||||||
assert peter.name == 'Peter'
|
assert peter.name == 'Peter'
|
||||||
|
println(peter.name)
|
||||||
|
|
||||||
mut a := A{
|
mut a := A{
|
||||||
m: map[string]int{}
|
m: map[string]int{}
|
||||||
@ -33,3 +54,22 @@ fn test_map() {
|
|||||||
assert a.m['one'] == 1
|
assert a.m['one'] == 1
|
||||||
assert a.m['two'] == 2
|
assert a.m['two'] == 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_string_map() {
|
||||||
|
//m := map[string]Fn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_large_map() {
|
||||||
|
//ticks := time.ticks()
|
||||||
|
mut nums := map[string]int{}
|
||||||
|
N := 30 * 1000
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
key := i.str()
|
||||||
|
nums[key] = i
|
||||||
|
}
|
||||||
|
assert nums['1'] == 1
|
||||||
|
assert nums['999'] == 999
|
||||||
|
assert nums['1000000'] == 0
|
||||||
|
//println(time.ticks() - ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user