1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser: cleanup & reuse

This commit is contained in:
joe-conigliaro
2019-10-26 00:34:12 +11:00
committed by Alexander Medvednikov
parent 784847cf18
commit 7d418e9105
6 changed files with 187 additions and 200 deletions

View File

@ -67,8 +67,9 @@ pub mut:
out_name string // "program.exe"
vroot string
mod string // module being built with -lib
parsers []Parser
parsers []Parser // file parsers
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
file_parser_idx map[string]int // map absolute file path to v.parsers index
cached_mods []string
}
@ -137,15 +138,17 @@ pub fn (v mut V) finalize_compilation(){
}
}
pub fn (v mut V) add_parser(parser Parser) {
pub fn (v mut V) add_parser(parser Parser) int {
v.parsers << parser
pidx := v.parsers.len-1
v.file_parser_idx[os.realpath(parser.file_path)] = pidx
return pidx
}
pub fn (v &V) get_file_parser_index(file string) ?int {
for i, p in v.parsers {
if os.realpath(p.file_path_id) == os.realpath(file) {
return i
}
file_path := os.realpath(file)
if file_path in v.file_parser_idx {
return v.file_parser_idx[file_path]
}
return error('parser for "$file" not found')
}
@ -157,9 +160,9 @@ pub fn (v mut V) parse(file string, pass Pass) int {
mut p := v.new_parser_from_file(file)
p.parse(pass)
//if p.pref.autofree { p.scanner.text.free() free(p.scanner) }
v.add_parser(p)
return v.parsers.len-1
return v.add_parser(p)
}
// println('matched ' + v.parsers[pidx].file_path + ' with $file')
v.parsers[pidx].parse(pass)
//if v.parsers[i].pref.autofree { v.parsers[i].scanner.text.free() free(v.parsers[i].scanner) }
return pidx
@ -274,8 +277,9 @@ pub fn (v mut V) compile() {
}
// parse generated V code (str() methods etc)
mut vgen_parser := v.new_parser_from_string(v.vgen_buf.str(), 'vgen')
mut vgen_parser := v.new_parser_from_string(v.vgen_buf.str())
// free the string builder which held the generated methods
vgen_parser.is_vgen = true
v.vgen_buf.free()
vgen_parser.parse(.main)
// v.parsers.add(vgen_parser)
@ -582,8 +586,7 @@ pub fn (v mut V) add_v_files_to_compile() {
v.log('imports0:')
println(v.table.imports)
println(v.files)
p.import_table.register_import('os', 0)
v.table.file_imports[p.file_path_id] = p.import_table
p.register_import('os', 0)
p.table.imports << 'os'
p.table.register_module('os')
}
@ -622,9 +625,9 @@ pub 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_id
for p in v.parsers {
if p.mod != 'main' { continue }
v.files << p.file_path
}
}
@ -684,9 +687,9 @@ pub fn (v &V) get_user_files() []string {
// get module files from already parsed imports
fn (v &V) get_imported_module_files(mod string) []string {
mut files := []string
for _, fit in v.table.file_imports {
if fit.module_name == mod {
files << fit.file_path_id
for p in v.parsers {
if p.mod == mod {
files << p.file_path
}
}
return files
@ -694,48 +697,34 @@ fn (v &V) get_imported_module_files(mod string) []string {
// parse deps from already parsed builtin/user files
pub fn (v mut V) parse_lib_imports() {
mut done_fits := []string
mut done_imports := []string
for {
for _, fit in v.table.file_imports {
if fit.file_path_id in done_fits { continue }
for _, mod in fit.imports {
for i in 0..v.parsers.len {
for _, mod in v.parsers[i].import_table.imports {
if mod in done_imports { continue }
import_path := v.find_module_path(mod) or {
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[i].error_with_token_index(
'cannot import module "$mod" (not found)',
v.parsers[i].import_table.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_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[i].error_with_token_index(
'cannot import module "$mod" (no .v files in "$import_path")',
v.parsers[i].import_table.get_import_tok_idx(mod))
}
// Add all imports referenced by these libs
for file in vfiles {
pid := v.parse(file, .imports)
p_mod := v.parsers[pid].import_table.module_name
pidx := v.parse(file, .imports)
p_mod := v.parsers[pidx].mod
if p_mod != mod {
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)
v.parsers[pidx].error_with_token_index(
'bad module definition: ${v.parsers[pidx].file_path} imports module "$mod" but $file is defined as module `$p_mod`', 1)
}
}
done_imports << mod
}
done_fits << fit.file_path_id
}
if v.table.file_imports.size == done_fits.len { break}
}
}
// return resolved dep graph (order deps)
pub fn (v &V) resolve_deps() &DepGraph {
mut dep_graph := new_dep_graph()
dep_graph.from_import_tables(v.table.file_imports)
deps_resolved := dep_graph.resolve()
if !deps_resolved.acyclic {
verror('import cycle detected between the following modules: \n' + deps_resolved.display_cycles())
}
return deps_resolved
}
pub fn get_arg(joined_args, arg, def string) string {