mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: module/type/fn name fixes, compile fixes
This commit is contained in:
parent
05329d6731
commit
fcd97f513a
@ -327,11 +327,12 @@ pub fn (v mut V) compile2() {
|
||||
println(v.files)
|
||||
}
|
||||
// v1 compiler files
|
||||
v.add_v_files_to_compile()
|
||||
//v.add_v_files_to_compile()
|
||||
//v.files << v.dir
|
||||
// v2 compiler
|
||||
//v.files << v.get_builtin_files()
|
||||
//v.files << v.get_user_files()
|
||||
v.files << v.get_builtin_files()
|
||||
v.files << v.get_user_files()
|
||||
v.set_module_lookup_paths()
|
||||
if v.pref.is_verbose {
|
||||
println('all .v files:')
|
||||
println(v.files)
|
||||
|
@ -212,7 +212,7 @@ pub:
|
||||
mod Module
|
||||
imports []Import
|
||||
stmts []Stmt
|
||||
scope Scope
|
||||
scope &Scope
|
||||
}
|
||||
|
||||
pub struct IdentFunc {
|
||||
|
@ -105,16 +105,23 @@ fn (s &Scope) contains(pos int) bool {
|
||||
return pos > s.start_pos && pos < s.end_pos
|
||||
}
|
||||
|
||||
pub fn (sc &Scope) print_vars(level int) {
|
||||
pub fn (sc &Scope) show(level int) string {
|
||||
mut out := ''
|
||||
mut indent := ''
|
||||
for _ in 0 .. level * 4 {
|
||||
indent += ' '
|
||||
}
|
||||
println('$indent# $sc.start_pos - $sc.end_pos')
|
||||
out += '$indent# $sc.start_pos - $sc.end_pos\n'
|
||||
for _, var in sc.vars {
|
||||
println('$indent * $var.name - $var.typ')
|
||||
out += '$indent * $var.name - $var.typ\n'
|
||||
}
|
||||
for child in sc.children {
|
||||
child.print_vars(level + 1)
|
||||
out += child.show(level + 1)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
pub fn (sc &Scope) str() string {
|
||||
return sc.show(0)
|
||||
}
|
||||
|
||||
|
@ -18,21 +18,18 @@ const (
|
||||
pub struct Checker {
|
||||
table &table.Table
|
||||
mut:
|
||||
file_name string
|
||||
scope &ast.Scope
|
||||
file ast.File
|
||||
nr_errors int
|
||||
}
|
||||
|
||||
pub fn new_checker(table &table.Table) Checker {
|
||||
return Checker{
|
||||
table: table
|
||||
scope: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check(ast_file ast.File) {
|
||||
c.file_name = ast_file.path
|
||||
c.scope = &ast_file.scope
|
||||
c.file = ast_file
|
||||
for stmt in ast_file.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
@ -124,30 +121,44 @@ fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
||||
|
||||
pub fn (c mut Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
||||
fn_name := call_expr.name
|
||||
if f := c.table.find_fn(fn_name) {
|
||||
// return_ti := f.return_ti
|
||||
if f.is_c || call_expr.is_c {
|
||||
return f.return_type
|
||||
}
|
||||
if call_expr.args.len < f.args.len {
|
||||
c.error('too few arguments in call to `$fn_name`', call_expr.pos)
|
||||
}
|
||||
else if !f.is_variadic && call_expr.args.len > f.args.len {
|
||||
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos)
|
||||
}
|
||||
for i, arg_expr in call_expr.args {
|
||||
arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] }
|
||||
typ := c.expr(arg_expr)
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
||||
if !c.table.check(typ, arg.typ) {
|
||||
c.error('!cannot use type `$typ_sym.name` as type `$arg_typ_sym.name` in argument ${i+1} to `$fn_name`', call_expr.pos)
|
||||
}
|
||||
|
||||
mut found := false
|
||||
// look for function in format `mod.fn` or `fn` (main/builtin)
|
||||
mut f := table.Fn{}
|
||||
if f1 := c.table.find_fn(fn_name) {
|
||||
found = true
|
||||
f = f1
|
||||
}
|
||||
// try prefix with current module as it would have never gotten prefixed
|
||||
if !found && !fn_name.contains('.') {
|
||||
if f1 := c.table.find_fn('${c.file.mod.name}.$fn_name') {
|
||||
found = true
|
||||
f = f1
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
c.error('unknown fn: $fn_name', call_expr.pos)
|
||||
}
|
||||
|
||||
if f.is_c || call_expr.is_c {
|
||||
return f.return_type
|
||||
}
|
||||
c.error('unknown fn: $fn_name', call_expr.pos)
|
||||
exit(1)
|
||||
if call_expr.args.len < f.args.len {
|
||||
c.error('too few arguments in call to `$fn_name`', call_expr.pos)
|
||||
}
|
||||
else if !f.is_variadic && call_expr.args.len > f.args.len {
|
||||
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos)
|
||||
}
|
||||
for i, arg_expr in call_expr.args {
|
||||
arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] }
|
||||
typ := c.expr(arg_expr)
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
||||
if !c.table.check(typ, arg.typ) {
|
||||
c.error('!cannot use type `$typ_sym.name` as type `$arg_typ_sym.name` in argument ${i+1} to `$fn_name`', call_expr.pos)
|
||||
}
|
||||
}
|
||||
return f.return_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
||||
@ -399,8 +410,8 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
||||
if info.typ != 0 {
|
||||
return info.typ
|
||||
}
|
||||
start_scope := c.scope.innermost(ident.pos.pos) or {
|
||||
c.scope
|
||||
start_scope := c.file.scope.innermost(ident.pos.pos) or {
|
||||
c.file.scope
|
||||
}
|
||||
mut found := true
|
||||
mut var_scope := &ast.Scope(0)
|
||||
@ -597,7 +608,7 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type {
|
||||
pub fn (c mut Checker) error(s string, pos token.Position) {
|
||||
c.nr_errors++
|
||||
print_backtrace()
|
||||
mut path := c.file_name
|
||||
mut path := c.file.path
|
||||
// Get relative path
|
||||
workdir := os.getwd() + filepath.separator
|
||||
if path.starts_with(workdir) {
|
||||
|
@ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
|
||||
name: fn_name
|
||||
args: args
|
||||
// tok: tok
|
||||
|
||||
pos: tok.position()
|
||||
is_c: is_c
|
||||
}
|
||||
@ -26,9 +25,6 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
|
||||
p.next()
|
||||
p.parse_block()
|
||||
}
|
||||
if f := p.table.find_fn(fn_name) {
|
||||
return node
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
|
@ -2,3 +2,16 @@
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module parser
|
||||
|
||||
// return true if file being parsed imports `mod`
|
||||
pub fn (p &Parser) known_import(mod string) bool {
|
||||
return mod in p.imports
|
||||
}
|
||||
|
||||
fn (p &Parser) prepend_mod(name string) string {
|
||||
if p.builtin_mod || p.mod == 'main' {
|
||||
return name
|
||||
}
|
||||
return '${p.mod}.$name'
|
||||
}
|
||||
|
||||
|
@ -101,13 +101,14 @@ pub fn (p mut Parser) parse_type() table.Type {
|
||||
// `module.Type`
|
||||
if p.peek_tok.kind == .dot {
|
||||
// /if !(p.tok.lit in p.table.imports) {
|
||||
if !p.table.known_import(p.tok.lit) {
|
||||
if !p.known_import(name) {
|
||||
println(p.table.imports)
|
||||
p.error('unknown module `$p.tok.lit`')
|
||||
}
|
||||
p.next()
|
||||
p.check(.dot)
|
||||
name += '.' + p.tok.lit
|
||||
// prefix with full module
|
||||
name = '${p.imports[name]}.$p.tok.lit'
|
||||
}
|
||||
// `Foo` in module `mod` means `mod.Foo`
|
||||
else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) {
|
||||
|
@ -109,7 +109,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||
mod: module_decl
|
||||
imports: imports
|
||||
stmts: stmts
|
||||
scope: *p.scope
|
||||
scope: p.scope
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,9 +520,10 @@ pub fn (p mut Parser) name_expr() ast.Expr {
|
||||
mut node := ast.Expr{}
|
||||
is_c := p.tok.lit == 'C'
|
||||
mut mod := ''
|
||||
if p.peek_tok.kind == .dot && (is_c || p.tok.lit in p.imports) {
|
||||
if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit)) {
|
||||
if !is_c {
|
||||
mod = p.tok.lit
|
||||
// prepend the full import
|
||||
mod = p.imports[p.tok.lit]
|
||||
}
|
||||
p.next()
|
||||
p.check(.dot)
|
||||
@ -1655,13 +1656,6 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
|
||||
}
|
||||
}
|
||||
|
||||
fn (p &Parser) prepend_mod(name string) string {
|
||||
if p.builtin_mod || p.mod == 'main' {
|
||||
return name
|
||||
}
|
||||
return '${p.mod}.${name}'
|
||||
}
|
||||
|
||||
fn verror(s string) {
|
||||
println(s)
|
||||
exit(1)
|
||||
|
@ -34,14 +34,14 @@ fn test_eval() {
|
||||
]
|
||||
/*
|
||||
table := table.new_table()
|
||||
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||
mut scope := &ast.Scope{start_pos: 0, parent: 0}
|
||||
mut stmts := []ast.Stmt
|
||||
for input in inputs {
|
||||
stmts << parse_stmt(input, table, &scope)
|
||||
stmts << parse_stmt(input, table, scope)
|
||||
}
|
||||
file := ast.File{
|
||||
stmts: stmts
|
||||
scope: &scope
|
||||
scope: scope
|
||||
}
|
||||
mut checker := checker.new_checker(table)
|
||||
checker.check(file)
|
||||
@ -87,10 +87,10 @@ fn test_one() {
|
||||
]
|
||||
expected := 'int a = 10;int b = -a;int c = 20;'
|
||||
table := table.new_table()
|
||||
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||
mut scope := &ast.Scope{start_pos: 0, parent: 0}
|
||||
mut e := []ast.Stmt
|
||||
for line in input {
|
||||
e << parse_stmt(line, table, &scope)
|
||||
e << parse_stmt(line, table, scope)
|
||||
}
|
||||
program := ast.File{
|
||||
stmts: e
|
||||
@ -179,10 +179,10 @@ fn test_parse_expr() {
|
||||
mut e := []ast.Stmt
|
||||
table := table.new_table()
|
||||
mut checker := checker.new_checker(table)
|
||||
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||
mut scope := &ast.Scope{start_pos: 0, parent: 0}
|
||||
for s in input {
|
||||
println('\n\nst="$s"')
|
||||
e << parse_stmt(s, table, &scope)
|
||||
e << parse_stmt(s, table, scope)
|
||||
}
|
||||
program := ast.File{
|
||||
stmts: e
|
||||
|
@ -3,11 +3,6 @@
|
||||
// that can be found in the LICENSE file.
|
||||
module table
|
||||
|
||||
import (
|
||||
v.token
|
||||
// v.ast
|
||||
)
|
||||
|
||||
pub struct Table {
|
||||
// struct_fields map[string][]string
|
||||
pub mut:
|
||||
@ -400,11 +395,3 @@ pub fn (t &Table) check(got, expected Type) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (t &Table) known_import(name string) bool {
|
||||
for i in t.imports {
|
||||
if i.all_after('.') == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user