parser: p.mod clean up
parent
ae2af4c36d
commit
efe03a39cc
|
@ -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 ')
|
||||
|
|
|
@ -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"), '
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_', '.')
|
||||
}
|
||||
|
|
|
@ -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 := ''
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue