v2: module/type/fn name fixes, compile fixes
parent
05329d6731
commit
fcd97f513a
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue