parser: p.mod clean up

pull/2319/head
joe-conigliaro 2019-10-13 11:05:11 +11:00 committed by Alexander Medvednikov
parent ae2af4c36d
commit efe03a39cc
7 changed files with 70 additions and 70 deletions

View File

@ -154,7 +154,7 @@ fn (p mut Parser) print_error_context(){
p.cgen.save() p.cgen.save()
// V up hint // V up hint
cur_path := os.getwd() cur_path := os.getwd()
if !p.pref.is_repl && !p.pref.is_test && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){ if !p.pref.is_repl && !p.pref.is_test && ( p.file_path_id.contains('v/compiler') || cur_path.contains('v/compiler') ){
println('\n=========================') println('\n=========================')
println('It looks like you are building V. It is being frequently updated every day.') println('It looks like you are building V. It is being frequently updated every day.')
println('If you didn\'t modify V\'s code, most likely there was a change that ') println('If you didn\'t modify V\'s code, most likely there was a change that ')

View File

@ -183,7 +183,7 @@ fn (p mut Parser) fn_decl() {
} }
// Don't allow modifying types from a different module // Don't allow modifying types from a different module
if !p.first_pass() && !p.builtin_mod && T.mod != p.mod && if !p.first_pass() && !p.builtin_mod && T.mod != p.mod &&
p.id != 'vgen' { // allow .str() on builtin arrays p.file_path_id != 'vgen' { // allow .str() on builtin arrays
println('T.mod=$T.mod') println('T.mod=$T.mod')
println('p.mod=$p.mod') println('p.mod=$p.mod')
p.error('cannot define new methods on non-local type `$receiver_typ`') p.error('cannot define new methods on non-local type `$receiver_typ`')
@ -814,7 +814,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
if p.v.pref.is_debug && f.name == 'panic' && !p.is_js { if p.v.pref.is_debug && f.name == 'panic' && !p.is_js {
mod_name := p.mod.replace('_dot_', '.') mod_name := p.mod.replace('_dot_', '.')
fn_name := p.cur_fn.name.replace('${p.mod}__', '') fn_name := p.cur_fn.name.replace('${p.mod}__', '')
file_path := cescaped_path(p.file_path) file_path := cescaped_path(p.file_path_id)
p.cgen.resetln(p.cgen.cur_line.replace( p.cgen.resetln(p.cgen.cur_line.replace(
'v_panic (', 'v_panic (',
'panic_debug ($p.scanner.line_nr, tos3("$file_path"), tos3("$mod_name"), tos2((byte *)"$fn_name"), ' 'panic_debug ($p.scanner.line_nr, tos3("$file_path"), tos3("$mod_name"), tos2((byte *)"$fn_name"), '

View File

@ -221,7 +221,7 @@ fn (v mut V) add_parser(parser Parser) {
fn (v &V) get_file_parser_index(file string) ?int { fn (v &V) get_file_parser_index(file string) ?int {
for i, p in v.parsers { for i, p in v.parsers {
if os.realpath(p.file_path) == os.realpath(file) { if os.realpath(p.file_path_id) == os.realpath(file) {
return i return i
} }
} }
@ -636,11 +636,6 @@ fn (v mut V) add_v_files_to_compile() {
// Parse user imports // Parse user imports
for file in v.get_user_files() { for file in v.get_user_files() {
mut p := v.new_parser_from_file(file) mut p := v.new_parser_from_file(file)
// set mod so we dont have to resolve submodule
if v.pref.build_mode == .build_module &&
file.contains(v.mod.replace('.', os.path_separator)) {
p.mod = v.mod
}
p.parse(.imports) p.parse(.imports)
//if p.pref.autofree { p.scanner.text.free() free(p.scanner) } //if p.pref.autofree { p.scanner.text.free() free(p.scanner) }
v.add_parser(p) v.add_parser(p)
@ -681,7 +676,7 @@ fn (v mut V) add_v_files_to_compile() {
// add remaining main files last // add remaining main files last
for _, fit in v.table.file_imports { for _, fit in v.table.file_imports {
if fit.module_name != 'main' { continue } if fit.module_name != 'main' { continue }
v.files << fit.file_path v.files << fit.file_path_id
} }
} }
@ -744,16 +739,16 @@ fn (v mut V) parse_lib_imports() {
mut done_imports := []string mut done_imports := []string
for { for {
for _, fit in v.table.file_imports { for _, fit in v.table.file_imports {
if fit.file_path in done_fits { continue } if fit.file_path_id in done_fits { continue }
for _, mod in fit.imports { for _, mod in fit.imports {
import_path := v.find_module_path(mod) or { import_path := v.find_module_path(mod) or {
pidx := v.get_file_parser_index(fit.file_path) or { verror(err) break } pidx := v.get_file_parser_index(fit.file_path_id) or { verror(err) break }
v.parsers[pidx].error_with_token_index('cannot import module "$mod" (not found)', fit.get_import_tok_idx(mod)) v.parsers[pidx].error_with_token_index('cannot import module "$mod" (not found)', fit.get_import_tok_idx(mod))
break break
} }
vfiles := v.v_files_from_dir(import_path) vfiles := v.v_files_from_dir(import_path)
if vfiles.len == 0 { if vfiles.len == 0 {
pidx := v.get_file_parser_index(fit.file_path) or { verror(err) break } pidx := v.get_file_parser_index(fit.file_path_id) or { verror(err) break }
v.parsers[pidx].error_with_token_index('cannot import module "$mod" (no .v files in "$import_path")', fit.get_import_tok_idx(mod)) v.parsers[pidx].error_with_token_index('cannot import module "$mod" (no .v files in "$import_path")', fit.get_import_tok_idx(mod))
} }
// Add all imports referenced by these libs // Add all imports referenced by these libs
@ -763,11 +758,11 @@ fn (v mut V) parse_lib_imports() {
done_imports << file done_imports << file
p_mod := v.parsers[pid].import_table.module_name p_mod := v.parsers[pid].import_table.module_name
if p_mod != mod { if p_mod != mod {
v.parsers[pid].error_with_token_index('bad module definition: $fit.file_path imports module "$mod" but $file is defined as module `$p_mod`', 1) v.parsers[pid].error_with_token_index('bad module definition: $fit.file_path_id imports module "$mod" but $file is defined as module `$p_mod`', 1)
} }
} }
} }
done_fits << fit.file_path done_fits << fit.file_path_id
} }
if v.table.file_imports.size == done_fits.len { break} if v.table.file_imports.size == done_fits.len { break}
} }

View File

@ -72,18 +72,31 @@ fn v_type_str(typ_ string) string {
typ_ typ_
} }
typ = typ.replace('Option_', '?') typ = typ.replace('Option_', '?')
// fn parent/alias?
if typ.starts_with('fn ') {
mut types := []string
fi_lpar := typ.index_byte(`(`)
li_rpar := typ.last_index_byte(`)`)
ret_type := typ.right(li_rpar+1)
for t in typ.substr(fi_lpar+1, li_rpar).split(',') {
types << v_type_str(t)
}
return 'fn (' + types.join(', ') + ')$ret_type'
}
typ = typ.replace('Option_', '?')
// multiple return
if typ.contains('_V_MulRet') { if typ.contains('_V_MulRet') {
words := typ.replace('_V_MulRet_', '').split('_V_') words := typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_')
typ = '(' typ = '('
for i in 0 .. words.len { for i in 0 .. words.len {
typ += words[i] typ += v_type_str(words[i])
if i != words.len - 1 { if i != words.len - 1 {
typ += ',' typ += ','
} }
} }
typ += ')' typ += ')'
return typ return typ
} }
//println('"$typ"') //println('"$typ"')
if typ == '*void' { if typ == '*void' {
return 'voidptr' return 'voidptr'
@ -130,7 +143,7 @@ fn (v &V) generate_vh() {
if c.mod != v.mod { if c.mod != v.mod {
continue continue
} }
println('$i $c.name') // println('$i $c.name')
//if !c.name.contains('__') { //if !c.name.contains('__') {
//continue //continue
//} //}
@ -158,7 +171,7 @@ fn (v &V) generate_vh() {
for _, typ in v.table.typesmap { for _, typ in v.table.typesmap {
//println(typ.name) //println(typ.name)
if typ.mod != v.mod && typ.mod != ''{ // int, string etc mod == '' if typ.mod != v.mod && typ.mod != ''{ // int, string etc mod == ''
//println('skipping type "$typ.name"') // println('skipping type "$typ.name"')
continue continue
} }
if typ.name.contains('_V_MulRet') { if typ.name.contains('_V_MulRet') {
@ -229,7 +242,7 @@ fn (v &V) generate_vh() {
file.writeln('\n// Methods //////////////////') file.writeln('\n// Methods //////////////////')
for _, typ in v.table.typesmap { for _, typ in v.table.typesmap {
if typ.mod != v.mod && !(v.mod == 'builtin' && typ.mod == '') { if typ.mod != v.mod && !(v.mod == 'builtin' && typ.mod == '') {
//println('skipping method typ $typ.name mod=$typ.mod') // println('skipping method typ $typ.name mod=$typ.mod')
continue continue
} }
for method in typ.methods { for method in typ.methods {

View File

@ -61,10 +61,10 @@ fn (v &V) find_module_path(mod string) ?string {
return import_path return import_path
} }
fn mod_gen_name(mod string) string { [inline] fn mod_gen_name(mod string) string {
return mod.replace('.', '_dot_') return mod.replace('.', '_dot_')
} }
fn mod_gen_name_rev(mod string) string { [inline] fn mod_gen_name_rev(mod string) string {
return mod.replace('_dot_', '.') return mod.replace('_dot_', '.')
} }

View File

@ -18,8 +18,7 @@ struct Token {
} }
struct Parser { struct Parser {
id string // unique id. if parsing file will be same as file_path file_path_id string // unique id. if parsing file will be path eg, "/home/user/hello.v"
file_path string // "/home/user/hello.v"
file_name string // "hello.v" file_name string // "hello.v"
file_platform string // ".v", "_win.v", "_nix.v", "_mac.v", "_lin.v" ... file_platform string // ".v", "_win.v", "_nix.v", "_mac.v", "_lin.v" ...
// When p.file_pcguard != '', it contains a // When p.file_pcguard != '', it contains a
@ -49,7 +48,6 @@ mut:
assigned_type string // non-empty if we are in an assignment expression assigned_type string // non-empty if we are in an assignment expression
expected_type string expected_type string
tmp_cnt int tmp_cnt int
is_script bool
builtin_mod bool builtin_mod bool
inside_if_expr bool inside_if_expr bool
inside_unwrapping_match_statement bool inside_unwrapping_match_statement bool
@ -121,11 +119,9 @@ fn (v mut V) new_parser_from_file(path string) Parser {
mut p := v.new_parser(new_scanner_file(path), path) mut p := v.new_parser(new_scanner_file(path), path)
p = { p| p = { p|
file_path: path,
file_name: path.all_after(os.path_separator), file_name: path.all_after(os.path_separator),
file_platform: path_platform, file_platform: path_platform,
file_pcguard: path_pcguard, file_pcguard: path_pcguard,
is_script: (v.pref.is_script && os.realpath(path) == os.realpath(path)),
is_vh: path.ends_with('.vh') is_vh: path.ends_with('.vh')
} }
if p.pref.building_v { if p.pref.building_v {
@ -141,13 +137,12 @@ fn (v mut V) new_parser_from_file(path string) Parser {
fn (v mut V) new_parser(scanner &Scanner, id string) Parser { fn (v mut V) new_parser(scanner &Scanner, id string) Parser {
v.reset_cgen_file_line_parameters() v.reset_cgen_file_line_parameters()
mut p := Parser { mut p := Parser {
id: id file_path_id: id
scanner: scanner scanner: scanner
v: v v: v
table: v.table table: v.table
cur_fn: EmptyFn cur_fn: EmptyFn
cgen: v.cgen cgen: v.cgen
is_script: false
pref: v.pref pref: v.pref
os: v.os os: v.os
vroot: v.vroot vroot: v.vroot
@ -215,7 +210,6 @@ fn (p & Parser) peek() TokenKind {
[inline] fn (p &Parser) prev_token() Token { [inline] fn (p &Parser) prev_token() Token {
return p.tokens[p.token_idx - 2] return p.tokens[p.token_idx - 2]
} }
[inline] fn (p &Parser) cur_tok() Token { [inline] fn (p &Parser) cur_tok() Token {
return p.tokens[p.token_idx - 1] return p.tokens[p.token_idx - 1]
} }
@ -237,22 +231,19 @@ fn (p &Parser) log(s string) {
fn (p mut Parser) parse(pass Pass) { fn (p mut Parser) parse(pass Pass) {
p.cgen.line = 0 p.cgen.line = 0
p.cgen.file = cescaped_path(os.realpath(p.file_path)) p.cgen.file = cescaped_path(os.realpath(p.file_path_id))
///////////////////////////////////// /////////////////////////////////////
p.pass = pass p.pass = pass
p.token_idx = 0 p.token_idx = 0
p.next() p.next()
//p.log('\nparse() run=$p.pass file=$p.file_name tok=${p.strtok()}')// , "script_file=", script_file) //p.log('\nparse() run=$p.pass file=$p.file_name tok=${p.strtok()}')// , "script_file=", script_file)
// `module main` is not required if it's a single file program // `module main` is not required if it's a single file program
if p.is_script || p.pref.is_test { if p.pref.is_script || p.pref.is_test {
// User may still specify `module main` // User may still specify `module main`
if p.tok == .key_module { if p.tok == .key_module {
p.next() p.next()
p.fgen('module ') p.fgen('module ')
mod := p.check_name() p.mod = p.check_name()
if p.mod == '' {
p.mod = mod
}
} else { } else {
p.mod = 'main' p.mod = 'main'
} }
@ -260,11 +251,7 @@ fn (p mut Parser) parse(pass Pass) {
else { else {
p.check(.key_module) p.check(.key_module)
p.fspace() p.fspace()
// setting mod manually for mod init parsers p.mod = p.check_name()
mod := p.check_name()
if p.mod == '' {
p.mod = mod
}
} }
// //
@ -278,12 +265,17 @@ fn (p mut Parser) parse(pass Pass) {
p.builtin_mod = p.mod == 'builtin' p.builtin_mod = p.mod == 'builtin'
p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove
// Import pass - the first and the smallest pass that only analyzes imports // Import pass - the first and the smallest pass that only analyzes imports
// if we are a building module get the full module name from v.mod
fq_mod := if p.pref.build_mode == .build_module && p.v.mod.ends_with(p.mod) {
p.v.mod
}
// fully qualify the module name, eg base64 to encoding.base64 // fully qualify the module name, eg base64 to encoding.base64
fq_mod := p.table.qualify_module(p.mod, p.file_path) else {
p.table.qualify_module(p.mod, p.file_path_id)
}
p.import_table.module_name = fq_mod p.import_table.module_name = fq_mod
p.table.register_module(fq_mod) p.table.register_module(fq_mod)
// replace "." with "_dot_" in module name for C variable names p.mod = fq_mod
p.mod = mod_gen_name(fq_mod)
if p.pass == .imports { if p.pass == .imports {
for p.tok == .key_import && p.peek() != .key_const { for p.tok == .key_import && p.peek() != .key_const {
@ -293,7 +285,7 @@ fn (p mut Parser) parse(pass Pass) {
p.error('module `builtin` cannot be imported') p.error('module `builtin` cannot be imported')
} }
// save file import table // save file import table
p.table.file_imports[p.id] = p.import_table p.table.file_imports[p.file_path_id] = p.import_table
return return
} }
// Go through every top level token or throw a compilation error if a non-top level token is met // Go through every top level token or throw a compilation error if a non-top level token is met
@ -382,7 +374,7 @@ fn (p mut Parser) parse(pass Pass) {
//p.log('end of parse()') //p.log('end of parse()')
// TODO: check why this was added? everything seems to work // TODO: check why this was added? everything seems to work
// without it, and it's already happening in fn_decl // without it, and it's already happening in fn_decl
// if p.is_script && !p.pref.is_test { // if p.pref.is_script && !p.pref.is_test {
// p.set_current_fn( MainFn ) // p.set_current_fn( MainFn )
// p.check_unused_variables() // p.check_unused_variables()
// } // }
@ -400,7 +392,7 @@ fn (p mut Parser) parse(pass Pass) {
return return
default: default:
// no `fn main`, add this "global" statement to cgen.fn_main // no `fn main`, add this "global" statement to cgen.fn_main
if p.is_script && !p.pref.is_test { if p.pref.is_script && !p.pref.is_test {
// cur_fn is empty since there was no fn main declared // cur_fn is empty since there was no fn main declared
// we need to set it to save and find variables // we need to set it to save and find variables
if p.cur_fn.name == '' { if p.cur_fn.name == '' {
@ -848,7 +840,7 @@ fn (p mut Parser) enum_decl(_enum_name string) {
field := p.check_name() field := p.check_name()
fields << field fields << field
p.fgenln('') p.fgenln('')
name := '${p.mod}__${enum_name}_$field' name := '${mod_gen_name(p.mod)}__${enum_name}_$field'
if p.pass == .main { if p.pass == .main {
p.cgen.consts << '#define $name $val' p.cgen.consts << '#define $name $val'
} }
@ -856,7 +848,9 @@ fn (p mut Parser) enum_decl(_enum_name string) {
p.next() p.next()
} }
// !!!! NAME free // !!!! NAME free
p.table.register_const(name, enum_name, p.mod) if p.first_pass() {
p.table.register_const(name, enum_name, p.mod)
}
val++ val++
} }
p.table.register_type2(Type { p.table.register_type2(Type {
@ -1748,7 +1742,7 @@ fn (p mut Parser) name_expr() string {
if !T.has_enum_val(val) { if !T.has_enum_val(val) {
p.error('enum `$T.name` does not have value `$val`') p.error('enum `$T.name` does not have value `$val`')
} }
p.gen(T.mod + '__' + p.expected_type + '_' + val) p.gen(mod_gen_name(T.mod) + '__' + p.expected_type + '_' + val)
} }
return p.expected_type return p.expected_type
} }
@ -1800,15 +1794,13 @@ fn (p mut Parser) name_expr() string {
// must be aliased module // must be aliased module
if name != p.mod && p.import_table.known_alias(name) { if name != p.mod && p.import_table.known_alias(name) {
p.import_table.register_used_import(name) p.import_table.register_used_import(name)
// we replaced "." with "_dot_" in p.mod for C variable names, mod = p.import_table.resolve_alias(name)
// do same here.
mod = mod_gen_name(p.import_table.resolve_alias(name))
} }
p.next() p.next()
p.check(.dot) p.check(.dot)
name = p.lit name = p.lit
p.fgen(name) p.fgen(name)
name = prepend_mod(mod, name) name = prepend_mod(mod_gen_name(mod), name)
} }
// Unknown name, try prepending the module name to it // Unknown name, try prepending the module name to it
// TODO perf // TODO perf
@ -1890,7 +1882,7 @@ fn (p mut Parser) name_expr() string {
p.check(.dot) p.check(.dot)
val := p.lit val := p.lit
// println('enum val $val') // println('enum val $val')
p.gen(enum_type.mod + '__' + enum_type.name + '_' + val)// `color = main__Color_green` p.gen(mod_gen_name(enum_type.mod) + '__' + enum_type.name + '_' + val)// `color = main__Color_green`
p.next() p.next()
return enum_type.name return enum_type.name
} }
@ -1967,7 +1959,7 @@ fn (p mut Parser) name_expr() string {
// If orig_name is a mod, then printing undefined: `mod` tells us nothing // If orig_name is a mod, then printing undefined: `mod` tells us nothing
// if p.table.known_mod(orig_name) { // if p.table.known_mod(orig_name) {
if p.table.known_mod(orig_name) || p.import_table.known_alias(orig_name) { if p.table.known_mod(orig_name) || p.import_table.known_alias(orig_name) {
name = mod_gen_name_rev(name.replace('__', '.')) name = name.replace('__', '.')
p.error('undefined: `$name`') p.error('undefined: `$name`')
} }
else { else {
@ -3073,7 +3065,7 @@ fn (p mut Parser) array_init() string {
//p.gen('{0}') //p.gen('{0}')
p.is_alloc = false p.is_alloc = false
if is_const_len { if is_const_len {
return '[${p.mod}__$lit]$array_elem_typ' return '[${mod_gen_name(p.mod)}__$lit]$array_elem_typ'
} }
return '[$lit]$array_elem_typ' return '[$lit]$array_elem_typ'
} else { } else {
@ -3864,7 +3856,7 @@ fn (p mut Parser) assert_statement() {
p.gen('bool $tmp = ') p.gen('bool $tmp = ')
p.check_types(p.bool_expression(), 'bool') p.check_types(p.bool_expression(), 'bool')
// TODO print "expected: got" for failed tests // TODO print "expected: got" for failed tests
filename := cescaped_path(p.file_path) filename := cescaped_path(p.file_path_id)
p.genln('; p.genln(';
\n \n
@ -3988,7 +3980,7 @@ fn prepend_mod(mod, name string) string {
} }
fn (p &Parser) prepend_mod(name string) string { fn (p &Parser) prepend_mod(name string) string {
return prepend_mod(p.mod, name) return prepend_mod(mod_gen_name(p.mod), name)
} }
fn (p mut Parser) go_statement() { fn (p mut Parser) go_statement() {
@ -4152,7 +4144,7 @@ fn (p mut Parser) check_and_register_used_imported_type(typ_name string) {
fn (p mut Parser) check_unused_imports() { fn (p mut Parser) check_unused_imports() {
// Don't run in the generated V file with `.str()` // Don't run in the generated V file with `.str()`
if p.id == 'vgen' { if p.file_path_id == 'vgen' {
return return
} }
mut output := '' mut output := ''

View File

@ -53,7 +53,7 @@ mut:
struct FileImportTable { struct FileImportTable {
mut: mut:
module_name string module_name string
file_path string file_path_id string // file path or id
imports map[string]string // alias => module imports map[string]string // alias => module
used_imports []string // alias used_imports []string // alias
import_tok_idx map[string]int // module => idx import_tok_idx map[string]int // module => idx
@ -879,16 +879,16 @@ fn (table &Table) qualify_module(mod string, file_path string) string {
return mod return mod
} }
fn (table &Table) get_file_import_table(id string) FileImportTable { fn (table &Table) get_file_import_table(file_path_id string) FileImportTable {
if id in table.file_imports { if file_path_id in table.file_imports {
return table.file_imports[id] return table.file_imports[file_path_id]
} }
return new_file_import_table(id) return new_file_import_table(file_path_id)
} }
fn new_file_import_table(file_path string) FileImportTable { fn new_file_import_table(file_path_id string) FileImportTable {
return FileImportTable{ return FileImportTable{
file_path: file_path file_path_id: file_path_id
imports: map[string]string imports: map[string]string
} }
} }
@ -905,7 +905,7 @@ fn (fit mut FileImportTable) register_alias(alias string, mod string, tok_idx in
// NOTE: come back here // NOTE: come back here
// if alias in fit.imports && fit.imports[alias] == mod {} // if alias in fit.imports && fit.imports[alias] == mod {}
if alias in fit.imports && fit.imports[alias] != mod { if alias in fit.imports && fit.imports[alias] != mod {
verror('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}"') verror('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path_id}"')
} }
if mod.contains('.internal.') { if mod.contains('.internal.') {
mod_parts := mod.split('.') mod_parts := mod.split('.')
@ -971,7 +971,7 @@ fn (p &Parser) identify_typo(name string, fit &FileImportTable) string {
// dont check if so short // dont check if so short
if name.len < 2 { return '' } if name.len < 2 { return '' }
min_match := 0.50 // for dice coefficient between 0.0 - 1.0 min_match := 0.50 // for dice coefficient between 0.0 - 1.0
name_orig := name.replace('__', '.').replace('_dot_', '.') name_orig := mod_gen_name_rev(name.replace('__', '.'))
mut output := '' mut output := ''
// check functions // check functions
mut n := p.table.find_misspelled_fn(name, fit, min_match) mut n := p.table.find_misspelled_fn(name, fit, min_match)