mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
module aliasing & file import scope
This commit is contained in:
parent
56b7c9e35f
commit
9a957ccc18
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
module main
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
struct CGen {
|
struct CGen {
|
||||||
out os.File
|
out os.File
|
||||||
out_path string
|
out_path string
|
||||||
|
@ -6,6 +6,7 @@ module main
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import strings
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = '0.1.14'
|
Version = '0.1.14'
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
module main
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
import rand
|
import rand
|
||||||
|
import strings
|
||||||
|
|
||||||
struct Var {
|
struct Var {
|
||||||
mut:
|
mut:
|
||||||
@ -40,6 +42,7 @@ mut:
|
|||||||
lit string
|
lit string
|
||||||
cgen *CGen
|
cgen *CGen
|
||||||
table *Table
|
table *Table
|
||||||
|
import_table *FileImportTable // Holds imports for just the file being parsed
|
||||||
run Pass // TODO rename `run` to `pass`
|
run Pass // TODO rename `run` to `pass`
|
||||||
os OS
|
os OS
|
||||||
mod string
|
mod string
|
||||||
@ -83,6 +86,7 @@ fn (c mut V) new_parser(path string, run Pass) Parser {
|
|||||||
file_name: path.all_after('/')
|
file_name: path.all_after('/')
|
||||||
scanner: new_scanner(path)
|
scanner: new_scanner(path)
|
||||||
table: c.table
|
table: c.table
|
||||||
|
import_table: new_file_import_table(path)
|
||||||
cur_fn: EmptyFn
|
cur_fn: EmptyFn
|
||||||
cgen: c.cgen
|
cgen: c.cgen
|
||||||
is_script: (c.pref.is_script && path == c.dir)
|
is_script: (c.pref.is_script && path == c.dir)
|
||||||
@ -132,7 +136,11 @@ fn (p mut Parser) parse() {
|
|||||||
p.builtin_pkg = p.mod == 'builtin'
|
p.builtin_pkg = p.mod == 'builtin'
|
||||||
p.can_chash = p.mod == 'ft' || p.mod == 'http' || p.mod == 'glfw' || p.mod=='ui' // TODO tmp remove
|
p.can_chash = p.mod == 'ft' || p.mod == 'http' || p.mod == 'glfw' || p.mod=='ui' // 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
|
||||||
p.table.register_package(p.mod)
|
// fully qualify the module name, eg base64 to encoding.base64
|
||||||
|
fq_mod := p.table.qualify_module(p.mod, p.file_path)
|
||||||
|
p.table.register_package(fq_mod)
|
||||||
|
// replace "." with "_" for C variable names
|
||||||
|
p.mod = fq_mod.replace('.', '_')
|
||||||
if p.run == .imports {
|
if p.run == .imports {
|
||||||
for p.tok == .key_import && p.peek() != .key_const {
|
for p.tok == .key_import && p.peek() != .key_const {
|
||||||
p.import_statement()
|
p.import_statement()
|
||||||
@ -284,6 +292,9 @@ fn (p mut Parser) import_statement() {
|
|||||||
for p.tok != .rpar && p.tok != .eof {
|
for p.tok != .rpar && p.tok != .eof {
|
||||||
pkg := p.lit.trim_space()
|
pkg := p.lit.trim_space()
|
||||||
p.next()
|
p.next()
|
||||||
|
// TODO: aliased for import() syntax
|
||||||
|
// p.import_table.register_alias(alias, pkg)
|
||||||
|
// p.import_table.register_import(pkg)
|
||||||
if p.table.imports.contains(pkg) {
|
if p.table.imports.contains(pkg) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -297,6 +308,11 @@ fn (p mut Parser) import_statement() {
|
|||||||
if p.tok != .name {
|
if p.tok != .name {
|
||||||
p.error('bad import format')
|
p.error('bad import format')
|
||||||
}
|
}
|
||||||
|
// aliasing (import b64 encoding.base64)
|
||||||
|
mut alias := ''
|
||||||
|
if p.tok == .name && p.peek() == .name {
|
||||||
|
alias = p.check_name()
|
||||||
|
}
|
||||||
mut pkg := p.lit.trim_space()
|
mut pkg := p.lit.trim_space()
|
||||||
// submodule support
|
// submodule support
|
||||||
mut depth := 1
|
mut depth := 1
|
||||||
@ -304,13 +320,17 @@ fn (p mut Parser) import_statement() {
|
|||||||
for p.tok == .dot {
|
for p.tok == .dot {
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
submodule := p.check_name()
|
submodule := p.check_name()
|
||||||
|
if alias == '' { alias = submodule }
|
||||||
pkg += '.' + submodule
|
pkg += '.' + submodule
|
||||||
depth++
|
depth++
|
||||||
if depth > MaxModuleDepth {
|
if depth > MaxModuleDepth {
|
||||||
p.error('module depth of $MaxModuleDepth exceeded: $pkg')
|
p.error('module depth of $MaxModuleDepth exceeded: $pkg')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if alias == '' { alias = pkg }
|
||||||
p.fgenln(' ' + pkg)
|
p.fgenln(' ' + pkg)
|
||||||
|
// add import to file scope import table
|
||||||
|
p.import_table.register_alias(alias, pkg)
|
||||||
// Make sure there are no duplicate imports
|
// Make sure there are no duplicate imports
|
||||||
if p.table.imports.contains(pkg) {
|
if p.table.imports.contains(pkg) {
|
||||||
return
|
return
|
||||||
@ -1283,9 +1303,14 @@ fn (p mut Parser) name_expr() string {
|
|||||||
// //////////////////////////
|
// //////////////////////////
|
||||||
// module ?
|
// module ?
|
||||||
// Allow shadowing (gg = gg.newcontext(); gg.draw_triangle())
|
// Allow shadowing (gg = gg.newcontext(); gg.draw_triangle())
|
||||||
if p.table.known_pkg(name) && !p.cur_fn.known_var(name) && !is_c {
|
if ((name == p.mod && p.table.known_pkg(name)) || p.import_table.known_alias(name))
|
||||||
// println('"$name" is a known pkg')
|
&& !p.cur_fn.known_var(name) && !is_c {
|
||||||
pkg := name
|
mut pkg := name
|
||||||
|
// must be aliased module
|
||||||
|
if name != p.mod && p.import_table.known_alias(name) {
|
||||||
|
// we replaced "." with "_" in p.mod for C variable names, do same here.
|
||||||
|
pkg = p.import_table.resolve_alias(name).replace('.', '_')
|
||||||
|
}
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
name = p.lit
|
name = p.lit
|
||||||
@ -1408,7 +1433,8 @@ fn (p mut Parser) name_expr() string {
|
|||||||
if !p.first_run() {
|
if !p.first_run() {
|
||||||
// println('name_expr():')
|
// println('name_expr():')
|
||||||
// If orig_name is a pkg, then printing undefined: `pkg` tells us nothing
|
// If orig_name is a pkg, then printing undefined: `pkg` tells us nothing
|
||||||
if p.table.known_pkg(orig_name) {
|
// if p.table.known_pkg(orig_name) {
|
||||||
|
if p.table.known_pkg(orig_name) && p.import_table.known_alias(orig_name) {
|
||||||
name = name.replace('__', '.')
|
name = name.replace('__', '.')
|
||||||
p.error('undefined: `$name`')
|
p.error('undefined: `$name`')
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
module main
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
|
import strings
|
||||||
|
|
||||||
struct Scanner {
|
struct Scanner {
|
||||||
mut:
|
mut:
|
||||||
file_path string
|
file_path string
|
||||||
|
@ -19,6 +19,13 @@ mut:
|
|||||||
obfuscate bool
|
obfuscate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Holds import information scoped to the parsed file
|
||||||
|
struct FileImportTable {
|
||||||
|
mut:
|
||||||
|
file_path string
|
||||||
|
imports map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
enum AccessMod {
|
enum AccessMod {
|
||||||
private // private imkey_mut
|
private // private imkey_mut
|
||||||
private_mut // private key_mut
|
private_mut // private key_mut
|
||||||
@ -657,3 +664,61 @@ fn is_valid_int_const(val, typ string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once we have a module format we can read from module file instead
|
||||||
|
// this is not optimal
|
||||||
|
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('/')
|
||||||
|
if mod == m_parts[m_parts.len-1] && file_path.contains(m_path) {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mod
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_file_import_table(file_path string) *FileImportTable {
|
||||||
|
mut t := &FileImportTable{
|
||||||
|
file_path: file_path
|
||||||
|
imports: map[string]string{}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit FileImportTable) known_import(mod string) bool {
|
||||||
|
return fit.imports.exists(mod) || fit.is_aliased(mod)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit mut FileImportTable) register_import(mod string) {
|
||||||
|
fit.register_alias(mod, mod)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
|
||||||
|
if !fit.imports.exists(alias) {
|
||||||
|
fit.imports[alias] = mod
|
||||||
|
} else {
|
||||||
|
panic('Cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit &FileImportTable) known_alias(alias string) bool {
|
||||||
|
return fit.imports.exists(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit &FileImportTable) is_aliased(mod string) bool {
|
||||||
|
for i in fit.imports.keys() {
|
||||||
|
if fit.imports[i] == mod {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fit &FileImportTable) resolve_alias(alias string) string {
|
||||||
|
if fit.imports.exists(alias) {
|
||||||
|
return fit.imports[alias]
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
@ -7,6 +7,8 @@ module gg
|
|||||||
import stbi
|
import stbi
|
||||||
import glm
|
import glm
|
||||||
import gl
|
import gl
|
||||||
|
import gx
|
||||||
|
import os
|
||||||
|
|
||||||
struct Vec2 {
|
struct Vec2 {
|
||||||
x int
|
x int
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import os
|
import os
|
||||||
import gl
|
import gl
|
||||||
import gg
|
import gg
|
||||||
|
import glm
|
||||||
|
|
||||||
fn cmp(a, b f32) bool {
|
fn cmp(a, b f32) bool {
|
||||||
return int(a * 1000) == int(b * 1000)
|
return int(a * 1000) == int(b * 1000)
|
||||||
|
Loading…
Reference in New Issue
Block a user