parser: do not allow duplicate methods; builder: cleaning up

pull/4274/head
Alexander Medvednikov 2020-04-07 01:02:48 +02:00
parent 8d150d427a
commit b7560fe4bf
3 changed files with 39 additions and 82 deletions

View File

@ -11,59 +11,6 @@ import (
strings strings
) )
/*
pub struct V {
pub mut:
mod_file_cacher &builder.ModFileCacher // used during lookup for v.mod to support @VROOT
out_name_c string // name of the temporary C file
files []string // all V files that need to be parsed and compiled
compiled_dir string // contains os.real_path() of the dir of the final file beeing compiled, or the dir itself when doing `v .`
pref &pref.Preferences // all the preferences and settings extracted to a struct for reusability
vgen_buf strings.Builder // temporary buffer for generated V code (.str() etc)
file_parser_idx map[string]int // map absolute file path to v.parsers index
gen_parser_idx map[string]int
cached_mods []string
module_lookup_paths []string
v_fmt_all bool // << input set by cmd/tools/vfmt.v
v_fmt_file string // << file given by the user from cmd/tools/vfmt.v
v_fmt_file_result string // >> file with formatted output generated by vlib/compiler/vfmt.v
}
pub fn new_v(pref &pref.Preferences) &V {
rdir := os.real_path(pref.path)
mut out_name_c := get_vtmp_filename(pref.out_name, '.tmp.c')
if pref.is_so {
out_name_c = get_vtmp_filename(pref.out_name, '.tmp.so.c')
}
mut vgen_buf := strings.new_builder(1000)
vgen_buf.writeln('module vgen\nimport strings')
compiled_dir:=if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
return &V{
mod_file_cacher: builder.new_mod_file_cacher()
compiled_dir:compiled_dir// if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
out_name_c: out_name_c
pref: pref
vgen_buf: vgen_buf
}
}
*/
/*
// make v2 from v1
fn (v &V) new_v2() builder.Builder {
mut b := builder.new_builder(v.pref)
b = { b|
os: v.pref.os,
module_path: pref.default_module_path,
compiled_dir: v.compiled_dir,
module_search_paths: v.module_lookup_paths
}
return b
}
*/
fn get_vtmp_folder() string { fn get_vtmp_folder() string {
vtmp := os.join_path(os.temp_dir(), 'v') vtmp := os.join_path(os.temp_dir(), 'v')
if !os.is_dir(vtmp) { if !os.is_dir(vtmp) {
@ -76,8 +23,7 @@ fn get_vtmp_folder() string {
fn get_vtmp_filename(base_file_name, postfix string) string { fn get_vtmp_filename(base_file_name, postfix string) string {
vtmp := get_vtmp_folder() vtmp := get_vtmp_folder()
return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) + return os.real_path(os.join_path(vtmp, os.file_name(os.real_path(base_file_name)) + postfix))
postfix))
} }
pub fn compile(command string, pref &pref.Preferences) { pub fn compile(command string, pref &pref.Preferences) {
@ -109,7 +55,7 @@ pub fn compile(command string, pref &pref.Preferences) {
// v.add_v_files_to_compile() // v.add_v_files_to_compile()
// v.files << v.dir // v.files << v.dir
// v2 compiler // v2 compiler
//b.set_module_lookup_paths() // b.set_module_lookup_paths()
files << b.get_builtin_files() files << b.get_builtin_files()
files << b.get_user_files() files << b.get_user_files()
b.set_module_lookup_paths() b.set_module_lookup_paths()
@ -117,7 +63,7 @@ pub fn compile(command string, pref &pref.Preferences) {
println('all .v files:') println('all .v files:')
println(files) println(files)
} }
//b.build_c(files, b.out_name_c) // v.pref.out_name + '.c') // b.build_c(files, b.out_name_c) // v.pref.out_name + '.c')
b.build_c(files, pref.out_name + '.c') b.build_c(files, pref.out_name + '.c')
b.cc() b.cc()
} }
@ -196,9 +142,9 @@ fn (v mut Builder) set_module_lookup_paths() {
} }
} }
pub fn (v &Builder) get_builtin_files() []string { pub fn (v Builder) get_builtin_files() []string {
//println('get_builtin_files() lookuppath:') // println('get_builtin_files() lookuppath:')
//println(v.pref.lookup_path) // println(v.pref.lookup_path)
// Lookup for built-in folder in lookup path. // Lookup for built-in folder in lookup path.
// Assumption: `builtin/` folder implies usable implementation of builtin // Assumption: `builtin/` folder implies usable implementation of builtin
for location in v.pref.lookup_path { for location in v.pref.lookup_path {
@ -219,7 +165,7 @@ Did you forget to add vlib to the path? (Use @vlib for default vlib)')
panic('Unreachable code reached.') panic('Unreachable code reached.')
} }
pub fn (v &Builder) get_user_files() []string { pub fn (v Builder) get_user_files() []string {
mut dir := v.pref.path mut dir := v.pref.path
v.log('get_v_files($dir)') v.log('get_v_files($dir)')
// Need to store user files separately, because they have to be added after // Need to store user files separately, because they have to be added after
@ -297,4 +243,3 @@ pub fn (v &Builder) get_user_files() []string {
} }
return user_files return user_files
} }

View File

@ -652,6 +652,12 @@ fn (c mut Checker) stmt(node ast.Stmt) {
c.expected_type = table.void_type c.expected_type = table.void_type
} }
ast.FnDecl { ast.FnDecl {
//if it.is_method {
//sym := c.table.get_type_symbol(it.receiver.typ)
//if sym.has_method(it.name) {
//c.warn('duplicate method `$it.name`', it.pos)
//}
//}
c.expected_type = table.void_type c.expected_type = table.void_type
c.fn_return_type = it.return_type c.fn_return_type = it.return_type
c.stmts(it.stmts) c.stmts(it.stmts)

View File

@ -12,7 +12,13 @@ import (
pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr { pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
tok := p.tok tok := p.tok
name := p.check_name() name := p.check_name()
fn_name := if is_c { 'C.$name' } else if mod.len > 0 { '${mod}.$name' } else { name } fn_name := if is_c {
'C.$name'
} else if mod.len > 0 {
'${mod}.$name'
} else {
name
}
p.check(.lpar) p.check(.lpar)
args := p.call_args() args := p.call_args()
mut or_stmts := []ast.Stmt mut or_stmts := []ast.Stmt
@ -33,13 +39,12 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
node := ast.CallExpr{ node := ast.CallExpr{
name: fn_name name: fn_name
args: args args: args
// tok: tok
mod: p.mod mod: p.mod
pos: tok.position() pos: tok.position()
is_c: is_c is_c: is_c
or_block: ast.OrExpr{ or_block: ast.OrExpr{
stmts: or_stmts stmts: or_stmts
} }
} }
return node return node
} }
@ -111,9 +116,12 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
if !is_c && !p.pref.translated && scanner.contains_capital(name) { if !is_c && !p.pref.translated && scanner.contains_capital(name) {
p.error('function names cannot contain uppercase letters, use snake_case instead') p.error('function names cannot contain uppercase letters, use snake_case instead')
} }
if is_method && p.table.get_type_symbol(rec_type).has_method(name) {
p.warn('duplicate method `$name`')
}
} }
if p.tok.kind in [.plus, .minus, .mul, .div, .mod] { if p.tok.kind in [.plus, .minus, .mul, .div, .mod] {
name = p.tok.kind.str() // op_to_fn_name() name = p.tok.kind.str() // op_to_fn_name()
p.next() p.next()
} }
// <T> // <T>
@ -123,7 +131,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.check(.gt) p.check(.gt)
} }
// Args // Args
args2,is_variadic := p.fn_args() args2, is_variadic := p.fn_args()
args << args2 args << args2
for arg in args { for arg in args {
p.scope.register(arg.name, ast.Var{ p.scope.register(arg.name, ast.Var{
@ -146,12 +154,10 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
return_type: return_type return_type: return_type
is_variadic: is_variadic is_variadic: is_variadic
}) })
} } else {
else {
if is_c { if is_c {
name = 'C.$name' name = 'C.$name'
} } else {
else {
name = p.prepend_mod(name) name = p.prepend_mod(name)
} }
p.table.register_fn(table.Fn{ p.table.register_fn(table.Fn{
@ -178,9 +184,9 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
is_pub: is_pub is_pub: is_pub
is_variadic: is_variadic is_variadic: is_variadic
receiver: ast.Field{ receiver: ast.Field{
name: rec_name name: rec_name
typ: rec_type typ: rec_type
} }
is_method: is_method is_method: is_method
rec_mut: rec_mut rec_mut: rec_mut
is_c: is_c is_c: is_c
@ -189,14 +195,15 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
} }
} }
fn (p mut Parser) fn_args() ([]table.Arg,bool) { fn (p mut Parser) fn_args() ([]table.Arg, bool) {
p.check(.lpar) p.check(.lpar)
mut args := []table.Arg mut args := []table.Arg
mut is_variadic := false mut is_variadic := false
// `int, int, string` (no names, just types) // `int, int, string` (no names, just types)
types_only := p.tok.kind in [.amp, .and] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || p.peek_tok.kind == .rpar types_only := p.tok.kind in [.amp, .and] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
p.peek_tok.kind == .rpar
if types_only { if types_only {
//p.warn('types only') // p.warn('types only')
mut arg_no := 1 mut arg_no := 1
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
arg_name := 'arg_$arg_no' arg_name := 'arg_$arg_no'
@ -225,8 +232,7 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) {
} }
arg_no++ arg_no++
} }
} } else {
else {
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
mut arg_names := [p.check_name()] mut arg_names := [p.check_name()]
// `a, b, c int` // `a, b, c int`
@ -263,9 +269,9 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) {
} }
} }
p.check(.rpar) p.check(.rpar)
return args,is_variadic return args, is_variadic
} }
fn (p &Parser) fileis(s string) bool { fn (p Parser) fileis(s string) bool {
return p.file_name.contains(s) return p.file_name.contains(s)
} }