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()
// V up hint
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('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 ')

View File

@ -183,7 +183,7 @@ fn (p mut Parser) fn_decl() {
}
// Don't allow modifying types from a different module
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('p.mod=$p.mod')
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 {
mod_name := p.mod.replace('_dot_', '.')
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(
'v_panic (',
'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 {
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
}
}
@ -636,11 +636,6 @@ fn (v mut V) add_v_files_to_compile() {
// Parse user imports
for file in v.get_user_files() {
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)
//if p.pref.autofree { p.scanner.text.free() free(p.scanner) }
v.add_parser(p)
@ -681,7 +676,7 @@ fn (v mut V) add_v_files_to_compile() {
// add remaining main files last
for _, fit in v.table.file_imports {
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
for {
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 {
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))
break
}
vfiles := v.v_files_from_dir(import_path)
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))
}
// Add all imports referenced by these libs
@ -763,11 +758,11 @@ fn (v mut V) parse_lib_imports() {
done_imports << file
p_mod := v.parsers[pid].import_table.module_name
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}
}

View File

@ -72,18 +72,31 @@ fn v_type_str(typ_ string) string {
typ_
}
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') {
words := typ.replace('_V_MulRet_', '').split('_V_')
words := typ.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_')
typ = '('
for i in 0 .. words.len {
typ += words[i]
typ += v_type_str(words[i])
if i != words.len - 1 {
typ += ','
}
}
typ += ')'
return typ
}
}
//println('"$typ"')
if typ == '*void' {
return 'voidptr'
@ -130,7 +143,7 @@ fn (v &V) generate_vh() {
if c.mod != v.mod {
continue
}
println('$i $c.name')
// println('$i $c.name')
//if !c.name.contains('__') {
//continue
//}
@ -158,7 +171,7 @@ fn (v &V) generate_vh() {
for _, typ in v.table.typesmap {
//println(typ.name)
if typ.mod != v.mod && typ.mod != ''{ // int, string etc mod == ''
//println('skipping type "$typ.name"')
// println('skipping type "$typ.name"')
continue
}
if typ.name.contains('_V_MulRet') {
@ -229,7 +242,7 @@ fn (v &V) generate_vh() {
file.writeln('\n// Methods //////////////////')
for _, typ in v.table.typesmap {
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
}
for method in typ.methods {

View File

@ -61,10 +61,10 @@ fn (v &V) find_module_path(mod string) ?string {
return import_path
}
fn mod_gen_name(mod string) string {
[inline] fn mod_gen_name(mod string) string {
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_', '.')
}

View File

@ -18,8 +18,7 @@ struct Token {
}
struct Parser {
id string // unique id. if parsing file will be same as file_path
file_path string // "/home/user/hello.v"
file_path_id string // unique id. if parsing file will be path eg, "/home/user/hello.v"
file_name string // "hello.v"
file_platform string // ".v", "_win.v", "_nix.v", "_mac.v", "_lin.v" ...
// When p.file_pcguard != '', it contains a
@ -49,7 +48,6 @@ mut:
assigned_type string // non-empty if we are in an assignment expression
expected_type string
tmp_cnt int
is_script bool
builtin_mod bool
inside_if_expr 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)
p = { p|
file_path: path,
file_name: path.all_after(os.path_separator),
file_platform: path_platform,
file_pcguard: path_pcguard,
is_script: (v.pref.is_script && os.realpath(path) == os.realpath(path)),
is_vh: path.ends_with('.vh')
}
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 {
v.reset_cgen_file_line_parameters()
mut p := Parser {
id: id
file_path_id: id
scanner: scanner
v: v
table: v.table
cur_fn: EmptyFn
cgen: v.cgen
is_script: false
pref: v.pref
os: v.os
vroot: v.vroot
@ -215,7 +210,6 @@ fn (p & Parser) peek() TokenKind {
[inline] fn (p &Parser) prev_token() Token {
return p.tokens[p.token_idx - 2]
}
[inline] fn (p &Parser) cur_tok() Token {
return p.tokens[p.token_idx - 1]
}
@ -237,22 +231,19 @@ fn (p &Parser) log(s string) {
fn (p mut Parser) parse(pass Pass) {
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.token_idx = 0
p.next()
//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
if p.is_script || p.pref.is_test {
if p.pref.is_script || p.pref.is_test {
// User may still specify `module main`
if p.tok == .key_module {
p.next()
p.fgen('module ')
mod := p.check_name()
if p.mod == '' {
p.mod = mod
}
p.mod = p.check_name()
} else {
p.mod = 'main'
}
@ -260,11 +251,7 @@ fn (p mut Parser) parse(pass Pass) {
else {
p.check(.key_module)
p.fspace()
// setting mod manually for mod init parsers
mod := p.check_name()
if p.mod == '' {
p.mod = mod
}
p.mod = p.check_name()
}
//
@ -278,12 +265,17 @@ fn (p mut Parser) parse(pass Pass) {
p.builtin_mod = p.mod == 'builtin'
p.can_chash = p.mod=='ui' || p.mod == 'darwin'// TODO tmp remove
// 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
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.table.register_module(fq_mod)
// replace "." with "_dot_" in module name for C variable names
p.mod = mod_gen_name(fq_mod)
p.mod = fq_mod
if p.pass == .imports {
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')
}
// 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
}
// 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()')
// TODO: check why this was added? everything seems to work
// 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.check_unused_variables()
// }
@ -400,7 +392,7 @@ fn (p mut Parser) parse(pass Pass) {
return
default:
// 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
// we need to set it to save and find variables
if p.cur_fn.name == '' {
@ -848,7 +840,7 @@ fn (p mut Parser) enum_decl(_enum_name string) {
field := p.check_name()
fields << field
p.fgenln('')
name := '${p.mod}__${enum_name}_$field'
name := '${mod_gen_name(p.mod)}__${enum_name}_$field'
if p.pass == .main {
p.cgen.consts << '#define $name $val'
}
@ -856,7 +848,9 @@ fn (p mut Parser) enum_decl(_enum_name string) {
p.next()
}
// !!!! 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++
}
p.table.register_type2(Type {
@ -1748,7 +1742,7 @@ fn (p mut Parser) name_expr() string {
if !T.has_enum_val(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
}
@ -1800,15 +1794,13 @@ fn (p mut Parser) name_expr() string {
// must be aliased module
if name != p.mod && p.import_table.known_alias(name) {
p.import_table.register_used_import(name)
// we replaced "." with "_dot_" in p.mod for C variable names,
// do same here.
mod = mod_gen_name(p.import_table.resolve_alias(name))
mod = p.import_table.resolve_alias(name)
}
p.next()
p.check(.dot)
name = p.lit
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
// TODO perf
@ -1890,7 +1882,7 @@ fn (p mut Parser) name_expr() string {
p.check(.dot)
val := p.lit
// 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()
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 p.table.known_mod(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`')
}
else {
@ -3073,7 +3065,7 @@ fn (p mut Parser) array_init() string {
//p.gen('{0}')
p.is_alloc = false
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'
} else {
@ -3864,7 +3856,7 @@ fn (p mut Parser) assert_statement() {
p.gen('bool $tmp = ')
p.check_types(p.bool_expression(), 'bool')
// TODO print "expected: got" for failed tests
filename := cescaped_path(p.file_path)
filename := cescaped_path(p.file_path_id)
p.genln(';
\n
@ -3988,7 +3980,7 @@ fn prepend_mod(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() {
@ -4152,7 +4144,7 @@ fn (p mut Parser) check_and_register_used_imported_type(typ_name string) {
fn (p mut Parser) check_unused_imports() {
// Don't run in the generated V file with `.str()`
if p.id == 'vgen' {
if p.file_path_id == 'vgen' {
return
}
mut output := ''

View File

@ -53,7 +53,7 @@ mut:
struct FileImportTable {
mut:
module_name string
file_path string
file_path_id string // file path or id
imports map[string]string // alias => module
used_imports []string // alias
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
}
fn (table &Table) get_file_import_table(id string) FileImportTable {
if id in table.file_imports {
return table.file_imports[id]
fn (table &Table) get_file_import_table(file_path_id string) FileImportTable {
if file_path_id in table.file_imports {
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{
file_path: file_path
file_path_id: file_path_id
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
// 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.') {
mod_parts := mod.split('.')
@ -971,7 +971,7 @@ fn (p &Parser) identify_typo(name string, fit &FileImportTable) string {
// dont check if so short
if name.len < 2 { return '' }
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 := ''
// check functions
mut n := p.table.find_misspelled_fn(name, fit, min_match)