From 24136ab88b79ccc04050a5e753bb504df2d2dbf8 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Sat, 5 Oct 2019 14:10:28 +1000 Subject: [PATCH] compiler: get existing parser using path --- compiler/cc.v | 2 +- compiler/main.v | 100 ++++++++++++++++++++------------------- compiler/module_header.v | 2 +- compiler/modules.v | 12 ++--- compiler/parser.v | 4 +- compiler/scanner.v | 2 +- compiler/table.v | 3 +- 7 files changed, 65 insertions(+), 60 deletions(-) diff --git a/compiler/cc.v b/compiler/cc.v index 9166c9840b..9ba1082d18 100644 --- a/compiler/cc.v +++ b/compiler/cc.v @@ -64,7 +64,7 @@ fn (v mut V) cc() { } if v.pref.build_mode == .build_module { // Create the modules & out directory if it's not there. - out_dir := v_modules_path + v.dir + out_dir := '$v_modules_path${os.PathSeparator}$v.dir' if !os.dir_exists(out_dir) { os.mkdir(out_dir) } diff --git a/compiler/main.v b/compiler/main.v index 2487e2f6a2..024d3720bb 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -65,6 +65,7 @@ mut: out_name_c string // name of the temporary C file files []string // all V files that need to be parsed and compiled dir string // directory (or file) being compiled (TODO rename to path?) + rdir string // abs dir table &Table // table with types, vars, functions etc cgen &CGen // C code generator pref &Preferences // all the preferences and settings extracted to a struct for reusability @@ -218,11 +219,13 @@ fn (v mut V) add_parser(parser Parser) { fn (v mut V) parse(file string, pass Pass) { //println('parse($file, $pass)') for i, p in v.parsers { - if p.file_path == file { + if os.realpath(p.file_path) == os.realpath(file) { v.parsers[i].parse(pass) return } - } + } + mut p := v.new_parser_from_file(file) + p.parse(pass) } @@ -566,7 +569,7 @@ fn (v &V) v_files_from_dir(dir string) []string { if file.ends_with('_c.v') && v.os == .js { continue } - res << '$dir/$file' + res << '$dir${os.PathSeparator}$file' } return res } @@ -596,15 +599,16 @@ fn (v mut V) add_v_files_to_compile() { // resolve deps & add imports in correct order for mod in v.resolve_deps().imports() { // if mod == v.mod { continue } // Building this module? Skip. TODO it's a hack. - if mod == 'main' { continue } // main files will get added last + if mod == 'builtin' { continue } // builtin already added + if mod == 'main' { continue } // main files will get added last // use cached built module if exists - vh_path := '$v_modules_path/${mod}.vh' - if os.file_exists(vh_path) { - println('using cached module `$mod`: $vh_path') - v.files << vh_path - continue - } + // vh_path := '$v_modules_path/${mod}.vh' + // if os.file_exists(vh_path) { + // println('using cached module `$mod`: $vh_path') + // v.files << vh_path + // continue + // } // standard module vfiles := v.v_files_from_dir(v.find_module_path(mod)) for file in vfiles { @@ -621,14 +625,14 @@ fn (v mut V) add_v_files_to_compile() { // get builtin files fn (v &V) get_builtin_files() []string { $if js { - return v.v_files_from_dir('$v.vroot/vlib/builtin/js/') + return v.v_files_from_dir('$v.vroot${os.PathSeparator}vlib${os.PathSeparator}builtin${os.PathSeparator}js') } - return v.v_files_from_dir('$v.vroot/vlib/builtin/') + return v.v_files_from_dir('$v.vroot${os.PathSeparator}vlib${os.PathSeparator}builtin') } // get user files fn (v &V) get_user_files() []string { - mut dir := v.dir + mut dir := v.rdir v.log('get_v_files($dir)') // Need to store user files separately, because they have to be added after libs, but we dont know // which libs need to be added yet @@ -636,16 +640,16 @@ fn (v &V) get_user_files() []string { // v volt/slack_test.v: compile all .v files to get the environment // I need to implement user packages! TODO is_test_with_imports := dir.ends_with('_test.v') && - (dir.contains('/volt') || dir.contains('/c2volt'))// TODO + (dir.contains('${os.PathSeparator}volt') || dir.contains('${os.PathSeparator}c2volt'))// TODO if is_test_with_imports { user_files << dir - pos := dir.last_index('/') - dir = dir.left(pos) + '/'// TODO WHY IS THIS .neEDED? + pos := dir.last_index(os.PathSeparator) + dir = dir.left(pos) + os.PathSeparator// TODO WHY IS THIS .neEDED? } if dir.ends_with('.v') { // Just compile one file and get parent dir user_files << dir - dir = dir.all_before('/') + dir = dir.all_before('${os.PathSeparator}') } else { // Add .v files from the directory being compiled @@ -668,33 +672,30 @@ fn (v &V) get_user_files() []string { // parse deps from already parsed builtin/user files 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 in done_fits { continue } - v.parse_file_imports(fit) - done_fits << fit.file_path - } - if v.table.file_imports.size == done_fits.len { break} - } -} - -// parse imports from file import table -fn (v mut V) parse_file_imports(fit &FileImportTable) { - for _, mod in fit.imports { - import_path := v.find_module_path(mod) - vfiles := v.v_files_from_dir(import_path) - if vfiles.len == 0 { - verror('cannot import module $mod (no .v files in "$import_path")') - } - // Add all imports referenced by these libs - for file in vfiles { - mut p := v.new_parser_from_file(file) - p.parse(.imports) - if p.import_table.module_name != mod { - verror('bad module name: $file was imported as `$mod` but it is defined as module `$p.import_table.module_name`') + for _, fit in v.table.file_imports { + if fit.file_path in done_fits { continue } + for _, mod in fit.imports { + import_path := v.find_module_path(mod) + vfiles := v.v_files_from_dir(import_path) + if vfiles.len == 0 { + verror('cannot import module $mod (no .v files in "$import_path")') + } + // Add all imports referenced by these libs + for file in vfiles { + if file in done_imports { continue } + v.parse(file, .imports) + done_imports << file + // if p.import_table.module_name != mod { + // verror('bad module name: $file was imported as `$mod` but it is defined as module `$p.import_table.module_name`') + // } + //if p.pref.autofree { p.scanner.text.free() free(p.scanner) } } - //if p.pref.autofree { p.scanner.text.free() free(p.scanner) } } + done_fits << fit.file_path + } + if v.table.file_imports.size == done_fits.len { break} } } @@ -744,7 +745,7 @@ fn new_v(args[]string) &V { joined_args := args.join(' ') target_os := get_arg(joined_args, 'os', '') mut out_name := get_arg(joined_args, 'o', 'a.out') - + mut dir := args.last() if 'run' in args { dir = get_all_after(joined_args, 'run', '') @@ -752,9 +753,11 @@ fn new_v(args[]string) &V { if dir.ends_with(os.PathSeparator) { dir = dir.all_before_last(os.PathSeparator) } + adir := os.realpath(dir) if args.len < 2 { dir = '' } + // println('new compiler "$dir"') // build mode mut build_mode := BuildMode.default_mode @@ -763,15 +766,15 @@ fn new_v(args[]string) &V { if joined_args.contains('build module ') { build_mode = .build_module // v build module ~/v/os => os.o - //mod = os.dir(dir) - mod = if dir.contains(os.PathSeparator) { - dir.all_after(os.PathSeparator) + mod = if adir.contains(os.PathSeparator) { + adir.all_after(os.PathSeparator) } else { - dir + adir } println('Building module "${mod}" (dir="$dir")...') //out_name = '$TmpPath/vlib/${base}.o' out_name = mod + '.o' + println('$out_name') // Cross compiling? Use separate dirs for each os /* if target_os != os.user_os() { @@ -864,7 +867,7 @@ fn new_v(args[]string) &V { //exit(1) } //println('out_name:$out_name') - mut out_name_c := os.realpath( out_name ) + '.tmp.c' + mut out_name_c := os.realpath('${out_name}.tmp.c') cflags := get_cmdline_cflags(args) @@ -906,6 +909,7 @@ fn new_v(args[]string) &V { return &V{ os: _os out_name: out_name + rdir: rdir dir: dir lang_dir: vroot table: new_table(obfuscate) @@ -927,7 +931,7 @@ fn env_vflags_and_os_args() []string { if os.args.len > 1 { args << os.args.right(1) } - }else{ + } else{ args << os.args } return args diff --git a/compiler/module_header.v b/compiler/module_header.v index cefb3bc905..f661118f3f 100644 --- a/compiler/module_header.v +++ b/compiler/module_header.v @@ -85,7 +85,7 @@ fn v_type_str(typ_ string) string { fn (v &V) generate_vh() { println('Generating a V header file for module `$v.mod`') - dir := v_modules_path + v.mod + dir := '$v_modules_path${os.PathSeparator}$v.mod' path := dir + '.vh' if !os.dir_exists(dir) { os.mkdir(dir) diff --git a/compiler/modules.v b/compiler/modules.v index 0e4c594097..7fd5e251a5 100644 --- a/compiler/modules.v +++ b/compiler/modules.v @@ -7,7 +7,7 @@ module main import os const ( - v_modules_path = os.home_dir() + '/.vmodules/' + v_modules_path = os.home_dir() + '.vmodules' ) // add a module and its deps (module speficic dag method) @@ -33,8 +33,8 @@ pub fn(graph &DepGraph) imports() []string { fn (v &V) module_path(mod string) string { // submodule support if mod.contains('.') { - //return mod.replace('.', os.PathSeparator) - return mod.replace('.', '/') + return mod.replace('.', os.PathSeparator) + // return mod.replace('.', '/') } return mod } @@ -45,15 +45,15 @@ fn (v &V) module_path(mod string) string { fn (v &V) find_module_path(mod string) string { mod_path := v.module_path(mod) // First check for local modules in the same directory - mut import_path := os.getwd() + '/$mod_path' + mut import_path := os.getwd() + '${os.PathSeparator}$mod_path' // Now search in vlib/ if !os.dir_exists(import_path) { - import_path = '$v.lang_dir/vlib/$mod_path' + import_path = '$v.lang_dir${os.PathSeparator}vlib${os.PathSeparator}$mod_path' } //println('ip=$import_path') // Finally try modules installed with vpm (~/.vmodules) if !os.dir_exists(import_path) { - import_path = '$v_modules_path/$mod_path' + import_path = '$v_modules_path${os.PathSeparator}$mod_path' if !os.dir_exists(import_path){ verror('module "$mod" not found') } diff --git a/compiler/parser.v b/compiler/parser.v index 666e7cca1c..629a842fcd 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -119,10 +119,10 @@ 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('/'), + file_name: path.all_after(os.PathSeparator), file_platform: path_platform, file_pcguard: path_pcguard, - is_script: (v.pref.is_script && path == v.dir) + is_script: (v.pref.is_script && os.realpath(path) == os.realpath(path)) } if p.pref.building_v { p.scanner.should_print_relative_paths_on_error = false diff --git a/compiler/scanner.v b/compiler/scanner.v index dbeb6bc4af..aa4a3d4e8a 100644 --- a/compiler/scanner.v +++ b/compiler/scanner.v @@ -724,7 +724,7 @@ fn (s mut Scanner) debug_tokens() { s.pos = 0 s.debug = true - fname := s.file_path.all_after('/') + fname := s.file_path.all_after(os.PathSeparator) println('\n===DEBUG TOKENS $fname===') for { diff --git a/compiler/table.v b/compiler/table.v index f675f89c37..f8fdc0da5d 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -4,6 +4,7 @@ module main +import os import math import strings @@ -862,7 +863,7 @@ fn (table &Table) qualify_module(mod string, file_path string) string { for m in table.imports { if m.contains('.') && m.contains(mod) { m_parts := m.split('.') - m_path := m_parts.join('/') + m_path := m_parts.join(os.PathSeparator) if mod == m_parts[m_parts.len-1] && file_path.contains(m_path) { return m }