From d078aa360bdeb1f410f37b2f4d06ed613eacf2b2 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 1 Sep 2019 14:31:43 +0300 Subject: [PATCH] parser: use map[string]Type instead of []Type --- compiler/cgen.v | 24 +++++++-- compiler/parser.v | 3 ++ compiler/table.v | 135 +++++++++------------------------------------- 3 files changed, 49 insertions(+), 113 deletions(-) diff --git a/compiler/cgen.v b/compiler/cgen.v index c41cfd7579..54d156b549 100644 --- a/compiler/cgen.v +++ b/compiler/cgen.v @@ -184,6 +184,7 @@ fn (c mut V) prof_counters() string { //res << 'double ${c.table.cgen_name(f)}_time;' //} // Methods + /* for typ in c.table.types { // println('') for f in typ.methods { @@ -192,6 +193,7 @@ fn (c mut V) prof_counters() string { // println(f.cgen_name()) } } + */ return res.join(';\n') } @@ -203,6 +205,7 @@ fn (p mut Parser) print_prof_counters() string { //res << 'if ($counter) printf("%%f : $f.name \\n", $counter);' //} // Methods + /* for typ in p.table.types { // println('') for f in typ.methods { @@ -214,6 +217,7 @@ fn (p mut Parser) print_prof_counters() string { // println(f.cgen_name()) } } + */ return res.join(';\n') } @@ -293,14 +297,24 @@ fn platform_postfix_to_ifdefguard(name string) string { fn (v mut V) c_type_definitions() string { mut types := []Type // structs that need to be sorted mut top_types := []Type // builtin types and types that only have primitive fields - for t in v.table.types { + mut builtin_types := []Type + // builtin types need to be on top + builtins := ['string', 'array', 'map', 'Option'] + for builtin in builtins { + typ := v.table.typesmap[builtin] + builtin_types << typ + v.table.typesmap.delete(builtin) + } + // split all types + for _, t in v.table.typesmap { if !t.name[0].is_capital() { top_types << t continue } mut only_builtin_fields := true for field in t.fields { - if field.typ[0].is_capital() { + // user types start with a capital or contain __ (defined in another module) + if field.typ[0].is_capital() || field.typ.contains('__') { only_builtin_fields = false break } @@ -311,10 +325,12 @@ fn (v mut V) c_type_definitions() string { } types << t } + sort_structs(mut top_types) sort_structs(mut types) // Generate C code - return types_to_c(top_types, v.table) + '\n/*----*/\n' + - types_to_c(types, v.table) + return types_to_c(builtin_types,v.table) + '\n//----\n' + + types_to_c(top_types, v.table) + '\n/*----*/\n' + + types_to_c(types, v.table) } fn types_to_c(types []Type, table &Table) string { diff --git a/compiler/parser.v b/compiler/parser.v index 15f9d6d602..39f0bb53cd 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -899,6 +899,9 @@ fn (p mut Parser) get_type() string { typ += '__$p.lit' } mut t := p.table.find_type(typ) + if typ == 'V' { + //println('QQ V res=$t.name') + } // "typ" not found? try "mod__typ" if t.name == '' && !p.builtin_mod { // && !p.first_pass() { diff --git a/compiler/table.v b/compiler/table.v index 6f20417a76..61510f6d9e 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -9,7 +9,7 @@ import strings struct Table { mut: - types []Type + typesmap map[string]Type consts []Var fns map[string]Fn generic_fns []GenTable //map[string]GenTable // generic_fns['listen_and_serve'] == ['Blog', 'Forum'] @@ -22,9 +22,6 @@ mut: obfuscate bool } - - - struct GenTable { fn_name string mut: @@ -216,12 +213,7 @@ fn is_primitive_type(typ string) bool { fn new_table(obfuscate bool) *Table { mut t := &Table { - obf_ids: map[string]int - fns: map[string]Fn - //generic_fns: map[string]GenTable{} - generic_fns: []GenTable obfuscate: obfuscate - file_imports: []FileImportTable } t.register_type('int') t.register_type('size_t') @@ -327,12 +319,8 @@ fn (table &Table) known_type(typ_ string) bool { if typ.ends_with('*') && !typ.contains(' ') { typ = typ.left(typ.len - 1) } - for t in table.types { - if t.name == typ && !t.is_placeholder { - return true - } - } - return false + t := table.typesmap[typ] + return t.name.len > 0 && !t.is_placeholder } fn (t &Table) find_fn(name string) Fn { @@ -358,17 +346,10 @@ fn (t mut Table) register_type(typ string) { if typ.len == 0 { return } - for typ2 in t.types { - if typ2.name == typ { - return + if typ in t.typesmap { + return } - } - // if t.types.filter( _.name == typ.name).len > 0 { - // return - // } - t.types << Type { - name: typ - } + t.typesmap[typ] = Type{name:typ} } fn (p mut Parser) register_type_with_parent(strtyp, parent string) { @@ -384,19 +365,7 @@ fn (t mut Table) register_type_with_parent(typ, parent string) { if typ.len == 0 { return } - // if t.types.filter(_.name == typ) > 0 - for typ2 in t.types { - if typ2.name == typ { - return - } - } - /* -mut mod := '' -if parent == 'array' { -mod = 'builtin' -} -*/ - t.types << Type { + t.typesmap[typ] = Type { name: typ parent: parent //mod: mod @@ -407,24 +376,14 @@ fn (t mut Table) register_type2(typ Type) { if typ.name.len == 0 { return } - for typ2 in t.types { - if typ2.name == typ.name { - return - } - } - t.types << typ + t.typesmap[typ.name] = typ } fn (t mut Table) rewrite_type(typ Type) { if typ.name.len == 0 { return } - for i, typ2 in t.types { - if typ2.name == typ.name { - t.types[i] = typ - return - } - } + t.typesmap[typ.name] = typ } fn (table mut Table) add_field(type_name, field_name, field_type string, is_mut bool, attr string, access_mod AccessMod) { @@ -432,39 +391,17 @@ fn (table mut Table) add_field(type_name, field_name, field_type string, is_mut print_backtrace() cerror('add_field: empty type') } - for i, typ in table.types { - if typ.name == type_name { - table.types[i].fields << Var { - name: field_name - typ: field_type - is_mut: is_mut - attr: attr - parent_fn: type_name // Name of the parent type - access_mod: access_mod - } - return - } - } - print_backtrace() - cerror('failed to add_field `$field_name` to type `$type_name`') -} - -/* -fn adf(name, typ string, is_mut bool, attr string, access_mod AccessMod) { - // if t.name == 'Parser' { - // println('adding field $name') - // } - v := Var { - name: name - typ: typ + mut t := table.typesmap[type_name] + t.fields << Var { + name: field_name + typ: field_type is_mut: is_mut attr: attr - parent_fn: t.name // Name of the parent type + parent_fn: type_name // Name of the parent type access_mod: access_mod } - t.fields << v + table.typesmap[type_name] = t } -*/ fn (t &Type) has_field(name string) bool { field := t.find_field(name) @@ -503,14 +440,9 @@ fn (table mut Table) add_method(type_name string, f Fn) { print_backtrace() cerror('add_method: empty type') } - for i, typ in table.types { - if typ.name == type_name { - table.types[i].methods << f - return - } - } - print_backtrace() - cerror('failed to add_method `$f.name` to type `$type_name`') + mut t := table.typesmap[type_name] + t.methods << f + table.typesmap[type_name] = t } fn (t &Type) has_method(name string) bool { @@ -568,26 +500,13 @@ fn (p &Parser) find_type(name string) Type { fn (t &Table) find_type(name_ string) Type { mut name := name_ - debug := name.starts_with('V') && name.len < 3 - if debug { - //println('find_type("$name)"') - } if name.ends_with('*') && !name.contains(' ') { name = name.left(name.len - 1) } - // TODO PERF use map - for i, typ in t.types { - if debug { - //println('^^ "$typ.name"') - } - if typ.name == name { - return t.types[i] - } + if !(name in t.typesmap) { + return Type{} } - if debug { - //println('NOT FOUND') - } - return Type{} + return t.typesmap[name] } fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool { @@ -748,14 +667,12 @@ fn type_default(typ string) string { return '{0}' } -// TODO PERF O(n) -fn (t &Table) is_interface(name string) bool { - for typ in t.types { - if typ.cat == .interface_ && typ.name == name { - return true - } +fn (table &Table) is_interface(name string) bool { + if !(name in table.typesmap) { + return false } - return false + t := table.typesmap[name] + return t.cat == .interface_ } // Do we have fn main()?