v2: module/type/fn name fixes, compile fixes

pull/3792/head
joe-conigliaro 2020-02-20 21:13:18 +11:00
parent 05329d6731
commit fcd97f513a
10 changed files with 83 additions and 73 deletions

View File

@ -327,11 +327,12 @@ pub fn (v mut V) compile2() {
println(v.files) println(v.files)
} }
// v1 compiler files // v1 compiler files
v.add_v_files_to_compile() //v.add_v_files_to_compile()
//v.files << v.dir //v.files << v.dir
// v2 compiler // v2 compiler
//v.files << v.get_builtin_files() v.files << v.get_builtin_files()
//v.files << v.get_user_files() v.files << v.get_user_files()
v.set_module_lookup_paths()
if v.pref.is_verbose { if v.pref.is_verbose {
println('all .v files:') println('all .v files:')
println(v.files) println(v.files)

View File

@ -212,7 +212,7 @@ pub:
mod Module mod Module
imports []Import imports []Import
stmts []Stmt stmts []Stmt
scope Scope scope &Scope
} }
pub struct IdentFunc { pub struct IdentFunc {

View File

@ -105,16 +105,23 @@ fn (s &Scope) contains(pos int) bool {
return pos > s.start_pos && pos < s.end_pos 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 := '' mut indent := ''
for _ in 0 .. level * 4 { for _ in 0 .. level * 4 {
indent += ' ' indent += ' '
} }
println('$indent# $sc.start_pos - $sc.end_pos') out += '$indent# $sc.start_pos - $sc.end_pos\n'
for _, var in sc.vars { for _, var in sc.vars {
println('$indent * $var.name - $var.typ') out += '$indent * $var.name - $var.typ\n'
} }
for child in sc.children { 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)
}

View File

@ -18,21 +18,18 @@ const (
pub struct Checker { pub struct Checker {
table &table.Table table &table.Table
mut: mut:
file_name string file ast.File
scope &ast.Scope
nr_errors int nr_errors int
} }
pub fn new_checker(table &table.Table) Checker { pub fn new_checker(table &table.Table) Checker {
return Checker{ return Checker{
table: table table: table
scope: 0
} }
} }
pub fn (c mut Checker) check(ast_file ast.File) { pub fn (c mut Checker) check(ast_file ast.File) {
c.file_name = ast_file.path c.file = ast_file
c.scope = &ast_file.scope
for stmt in ast_file.stmts { for stmt in ast_file.stmts {
c.stmt(stmt) 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 { pub fn (c mut Checker) call_expr(call_expr ast.CallExpr) table.Type {
fn_name := call_expr.name fn_name := call_expr.name
if f := c.table.find_fn(fn_name) {
// return_ti := f.return_ti mut found := false
if f.is_c || call_expr.is_c { // look for function in format `mod.fn` or `fn` (main/builtin)
return f.return_type mut f := table.Fn{}
} if f1 := c.table.find_fn(fn_name) {
if call_expr.args.len < f.args.len { found = true
c.error('too few arguments in call to `$fn_name`', call_expr.pos) f = f1
} }
else if !f.is_variadic && call_expr.args.len > f.args.len { // try prefix with current module as it would have never gotten prefixed
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos) if !found && !fn_name.contains('.') {
} if f1 := c.table.find_fn('${c.file.mod.name}.$fn_name') {
for i, arg_expr in call_expr.args { found = true
arg := if f.is_variadic && i >= f.args.len - 1 { f.args[f.args.len - 1] } else { f.args[i] } f = f1
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)
}
} }
}
if !found {
c.error('unknown fn: $fn_name', call_expr.pos)
}
if f.is_c || call_expr.is_c {
return f.return_type return f.return_type
} }
c.error('unknown fn: $fn_name', call_expr.pos) if call_expr.args.len < f.args.len {
exit(1) 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 { 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 { if info.typ != 0 {
return info.typ return info.typ
} }
start_scope := c.scope.innermost(ident.pos.pos) or { start_scope := c.file.scope.innermost(ident.pos.pos) or {
c.scope c.file.scope
} }
mut found := true mut found := true
mut var_scope := &ast.Scope(0) 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) { pub fn (c mut Checker) error(s string, pos token.Position) {
c.nr_errors++ c.nr_errors++
print_backtrace() print_backtrace()
mut path := c.file_name mut path := c.file.path
// Get relative path // Get relative path
workdir := os.getwd() + filepath.separator workdir := os.getwd() + filepath.separator
if path.starts_with(workdir) { if path.starts_with(workdir) {

View File

@ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
name: fn_name name: fn_name
args: args args: args
// tok: tok // tok: tok
pos: tok.position() pos: tok.position()
is_c: is_c 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.next()
p.parse_block() p.parse_block()
} }
if f := p.table.find_fn(fn_name) {
return node
}
return node return node
} }

View File

@ -2,3 +2,16 @@
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module parser 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'
}

View File

@ -101,13 +101,14 @@ pub fn (p mut Parser) parse_type() table.Type {
// `module.Type` // `module.Type`
if p.peek_tok.kind == .dot { if p.peek_tok.kind == .dot {
// /if !(p.tok.lit in p.table.imports) { // /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) println(p.table.imports)
p.error('unknown module `$p.tok.lit`') p.error('unknown module `$p.tok.lit`')
} }
p.next() p.next()
p.check(.dot) 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` // `Foo` in module `mod` means `mod.Foo`
else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) { else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) {

View File

@ -109,7 +109,7 @@ pub fn parse_file(path string, table &table.Table) ast.File {
mod: module_decl mod: module_decl
imports: imports imports: imports
stmts: stmts 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{} mut node := ast.Expr{}
is_c := p.tok.lit == 'C' is_c := p.tok.lit == 'C'
mut mod := '' 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 { if !is_c {
mod = p.tok.lit // prepend the full import
mod = p.imports[p.tok.lit]
} }
p.next() p.next()
p.check(.dot) 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) { fn verror(s string) {
println(s) println(s)
exit(1) exit(1)

View File

@ -34,14 +34,14 @@ fn test_eval() {
] ]
/* /*
table := table.new_table() 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 mut stmts := []ast.Stmt
for input in inputs { for input in inputs {
stmts << parse_stmt(input, table, &scope) stmts << parse_stmt(input, table, scope)
} }
file := ast.File{ file := ast.File{
stmts: stmts stmts: stmts
scope: &scope scope: scope
} }
mut checker := checker.new_checker(table) mut checker := checker.new_checker(table)
checker.check(file) checker.check(file)
@ -87,10 +87,10 @@ fn test_one() {
] ]
expected := 'int a = 10;int b = -a;int c = 20;' expected := 'int a = 10;int b = -a;int c = 20;'
table := table.new_table() 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 mut e := []ast.Stmt
for line in input { for line in input {
e << parse_stmt(line, table, &scope) e << parse_stmt(line, table, scope)
} }
program := ast.File{ program := ast.File{
stmts: e stmts: e
@ -179,10 +179,10 @@ fn test_parse_expr() {
mut e := []ast.Stmt mut e := []ast.Stmt
table := table.new_table() table := table.new_table()
mut checker := checker.new_checker(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 { for s in input {
println('\n\nst="$s"') println('\n\nst="$s"')
e << parse_stmt(s, table, &scope) e << parse_stmt(s, table, scope)
} }
program := ast.File{ program := ast.File{
stmts: e stmts: e

View File

@ -3,11 +3,6 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module table
import (
v.token
// v.ast
)
pub struct Table { pub struct Table {
// struct_fields map[string][]string // struct_fields map[string][]string
pub mut: pub mut:
@ -400,11 +395,3 @@ pub fn (t &Table) check(got, expected Type) bool {
return true 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
}