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)
}
// 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)

View File

@ -212,7 +212,7 @@ pub:
mod Module
imports []Import
stmts []Stmt
scope Scope
scope &Scope
}
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
}
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)
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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'
}

View File

@ -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) {

View File

@ -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)

View File

@ -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

View File

@ -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
}