parser: do not allow duplicate methods; builder: cleaning up
parent
8d150d427a
commit
b7560fe4bf
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue