mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
do not allow duplicate methods; fix os_win.v; minor fixes and docs
This commit is contained in:
parent
d482b1f824
commit
a52662fca0
103
compiler/fn.v
103
compiler/fn.v
@ -146,7 +146,18 @@ fn (p mut Parser) fn_decl() {
|
|||||||
p.clear_vars() // clear local vars every time a new fn is started
|
p.clear_vars() // clear local vars every time a new fn is started
|
||||||
p.fgen('fn ')
|
p.fgen('fn ')
|
||||||
//defer { p.fgenln('\n') }
|
//defer { p.fgenln('\n') }
|
||||||
mut f := Fn {
|
// If we are in the first pass, create a new function.
|
||||||
|
// In the second pass fetch the one we created.
|
||||||
|
/*
|
||||||
|
mut f := if p.first_pass {
|
||||||
|
Fn{
|
||||||
|
mod: p.mod
|
||||||
|
is_public: p.tok == .key_pub
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
mut f := Fn{
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
is_public: p.tok == .key_pub
|
is_public: p.tok == .key_pub
|
||||||
}
|
}
|
||||||
@ -185,7 +196,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
// `(f *Foo)` instead of `(f mut Foo)` is a common mistake
|
// `(f *Foo)` instead of `(f mut Foo)` is a common mistake
|
||||||
//if !p.builtin_mod && receiver_typ.contains('*') {
|
//if !p.builtin_mod && receiver_typ.contains('*') {
|
||||||
if receiver_typ.contains('*') {
|
if receiver_typ.ends_with('*') {
|
||||||
t := receiver_typ.replace('*', '')
|
t := receiver_typ.replace('*', '')
|
||||||
p.error('use `($receiver_name mut $t)` instead of `($receiver_name *$t)`')
|
p.error('use `($receiver_name mut $t)` instead of `($receiver_name *$t)`')
|
||||||
}
|
}
|
||||||
@ -208,6 +219,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
f.args << receiver
|
f.args << receiver
|
||||||
p.register_var(receiver)
|
p.register_var(receiver)
|
||||||
}
|
}
|
||||||
|
// +-/* methods
|
||||||
if p.tok == .plus || p.tok == .minus || p.tok == .mul {
|
if p.tok == .plus || p.tok == .minus || p.tok == .mul {
|
||||||
f.name = p.tok.str()
|
f.name = p.tok.str()
|
||||||
p.next()
|
p.next()
|
||||||
@ -398,28 +410,7 @@ fn (p mut Parser) fn_decl() {
|
|||||||
// First pass? Skip the body for now
|
// First pass? Skip the body for now
|
||||||
// Look for generic calls.
|
// Look for generic calls.
|
||||||
if !is_sig && !is_fn_header {
|
if !is_sig && !is_fn_header {
|
||||||
mut opened_scopes := 0
|
p.skip_fn_body()
|
||||||
mut closed_scopes := 0
|
|
||||||
for {
|
|
||||||
if p.tok == .lcbr {
|
|
||||||
opened_scopes++
|
|
||||||
}
|
|
||||||
if p.tok == .rcbr {
|
|
||||||
closed_scopes++
|
|
||||||
}
|
|
||||||
// find `foo<Bar>()` in function bodies and register generic types
|
|
||||||
// TODO
|
|
||||||
if p.tok.is_decl() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// fn body ended, and a new fn attribute declaration like [live] is starting?
|
|
||||||
if closed_scopes > opened_scopes && p.prev_tok == .rcbr {
|
|
||||||
if p.tok == .lsbr {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Live code reloading? Load all fns from .so
|
// Live code reloading? Load all fns from .so
|
||||||
if is_live && p.first_pass() && p.mod == 'main' {
|
if is_live && p.first_pass() && p.mod == 'main' {
|
||||||
@ -510,6 +501,35 @@ fn (p mut Parser) fn_decl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
// Skips the entire function's body in the first pass.
|
||||||
|
fn (p mut Parser) skip_fn_body() {
|
||||||
|
mut opened_scopes := 0
|
||||||
|
mut closed_scopes := 0
|
||||||
|
for {
|
||||||
|
if p.tok == .lcbr {
|
||||||
|
opened_scopes++
|
||||||
|
}
|
||||||
|
if p.tok == .rcbr {
|
||||||
|
closed_scopes++
|
||||||
|
}
|
||||||
|
// find `foo<Bar>()` in function bodies and register generic types
|
||||||
|
// TODO
|
||||||
|
// ...
|
||||||
|
// Reached a declaration token? (fn, struct, const etc) Stop.
|
||||||
|
if p.tok.is_decl() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// fn body ended, and a new fn attribute declaration like [live] is starting?
|
||||||
|
if closed_scopes > opened_scopes && p.prev_tok == .rcbr {
|
||||||
|
if p.tok == .lsbr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (p mut Parser) check_unused_variables() {
|
fn (p mut Parser) check_unused_variables() {
|
||||||
for var in p.local_vars {
|
for var in p.local_vars {
|
||||||
if var.name == '' {
|
if var.name == '' {
|
||||||
@ -894,6 +914,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||||||
}
|
}
|
||||||
got := typ
|
got := typ
|
||||||
expected := arg.typ
|
expected := arg.typ
|
||||||
|
got_ptr := got.ends_with('*')
|
||||||
|
exp_ptr := expected.ends_with('*')
|
||||||
// println('fn arg got="$got" exp="$expected"')
|
// println('fn arg got="$got" exp="$expected"')
|
||||||
if !p.check_types_no_throw(got, expected) {
|
if !p.check_types_no_throw(got, expected) {
|
||||||
mut j := i
|
mut j := i
|
||||||
@ -912,18 +934,23 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||||||
'argument to `$f.name()`')
|
'argument to `$f.name()`')
|
||||||
}
|
}
|
||||||
is_interface := p.table.is_interface(arg.typ)
|
is_interface := p.table.is_interface(arg.typ)
|
||||||
// Add `&` or `*` before an argument?
|
// Automatically add `&` or `*` before an argument.
|
||||||
|
// V, unlike C and Go, simplifies this aspect:
|
||||||
|
// `foo(bar)` is allowed where `foo(&bar)` is expected.
|
||||||
|
// The argument is not mutable, so it won't be changed by the function.
|
||||||
|
// It doesn't matter whether it's passed by referencee or by value
|
||||||
|
// to the end user.
|
||||||
if !is_interface {
|
if !is_interface {
|
||||||
// Dereference
|
// Dereference
|
||||||
if got.ends_with('*') && !expected.ends_with('*') {
|
if got_ptr && !exp_ptr {
|
||||||
p.cgen.set_placeholder(ph, '*')
|
p.cgen.set_placeholder(ph, '*')
|
||||||
}
|
}
|
||||||
// Reference
|
// Reference
|
||||||
// TODO ptr hacks. DOOM hacks, fix please.
|
// TODO ptr hacks. DOOM hacks, fix please.
|
||||||
if !got.ends_with('*') && expected.ends_with('*') && got != 'voidptr' {
|
if !got_ptr && exp_ptr && got != 'voidptr' {
|
||||||
// Special case for mutable arrays. We can't `&` function results,
|
// Special case for mutable arrays. We can't `&` function results,
|
||||||
// have to use `(array[]){ expr }` hack.
|
// have to use `(array[]){ expr }` hack.
|
||||||
if expected.starts_with('array_') && expected.ends_with('*') {
|
if expected.starts_with('array_') && exp_ptr {
|
||||||
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
|
p.cgen.set_placeholder(ph, '& /*111*/ (array[]){')
|
||||||
p.gen('}[0] ')
|
p.gen('}[0] ')
|
||||||
}
|
}
|
||||||
@ -937,9 +964,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// interface?
|
else if is_interface {
|
||||||
if is_interface {
|
if !got_ptr {
|
||||||
if !got.contains('*') {
|
|
||||||
p.cgen.set_placeholder(ph, '&')
|
p.cgen.set_placeholder(ph, '&')
|
||||||
}
|
}
|
||||||
// Pass all interface methods
|
// Pass all interface methods
|
||||||
@ -985,7 +1011,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "fn (int, string) int"
|
// "fn (int, string) int"
|
||||||
fn (f Fn) typ_str() string {
|
fn (f &Fn) typ_str() string {
|
||||||
mut sb := strings.new_builder(50)
|
mut sb := strings.new_builder(50)
|
||||||
sb.write('fn (')
|
sb.write('fn (')
|
||||||
for i, arg in f.args {
|
for i, arg in f.args {
|
||||||
@ -1001,6 +1027,10 @@ fn (f Fn) typ_str() string {
|
|||||||
return sb.str()
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (f &Fn) v_definition() string {
|
||||||
|
return 'todo'
|
||||||
|
}
|
||||||
|
|
||||||
// f.args => "int a, string b"
|
// f.args => "int a, string b"
|
||||||
fn (f &Fn) str_args(table &Table) string {
|
fn (f &Fn) str_args(table &Table) string {
|
||||||
mut s := ''
|
mut s := ''
|
||||||
@ -1056,3 +1086,12 @@ fn (p &Parser) find_misspelled_local_var(name string, min_match f32) string {
|
|||||||
}
|
}
|
||||||
return if closest >= min_match { closest_var } else { '' }
|
return if closest >= min_match { closest_var } else { '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (fns []Fn) contains(f Fn) bool {
|
||||||
|
for ff in fns {
|
||||||
|
if ff.name == f.name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -126,6 +126,7 @@ struct TypeNode {
|
|||||||
typ Type
|
typ Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// For debugging types
|
// For debugging types
|
||||||
fn (t Type) str() string {
|
fn (t Type) str() string {
|
||||||
mut s := 'type "$t.name" {'
|
mut s := 'type "$t.name" {'
|
||||||
@ -146,6 +147,7 @@ fn (t Type) str() string {
|
|||||||
s += '}\n'
|
s += '}\n'
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CReserved = [
|
CReserved = [
|
||||||
@ -321,6 +323,8 @@ fn (p mut Parser) register_global(name, typ string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only for module functions, not methods.
|
||||||
|
// That's why searching by fn name works.
|
||||||
fn (t mut Table) register_fn(new_fn Fn) {
|
fn (t mut Table) register_fn(new_fn Fn) {
|
||||||
t.fns[new_fn.name] = new_fn
|
t.fns[new_fn.name] = new_fn
|
||||||
}
|
}
|
||||||
@ -469,14 +473,10 @@ fn (p mut Parser) add_method(type_name string, f Fn) {
|
|||||||
}
|
}
|
||||||
// TODO table.typesmap[type_name].methods << f
|
// TODO table.typesmap[type_name].methods << f
|
||||||
mut t := p.table.typesmap[type_name]
|
mut t := p.table.typesmap[type_name]
|
||||||
if type_name == 'str' {
|
if f.name != 'str' && f in t.methods {
|
||||||
println(t.methods.len)
|
p.error('redefinition of method `${type_name}.$f.name`')
|
||||||
}
|
}
|
||||||
|
|
||||||
t.methods << f
|
t.methods << f
|
||||||
if type_name == 'str' {
|
|
||||||
println(t.methods.len)
|
|
||||||
}
|
|
||||||
p.table.typesmap[type_name] = t
|
p.table.typesmap[type_name] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
- bring back vdoc and regenerate all module docs
|
- bring back vdoc and regenerate all module docs
|
||||||
- optimize the parser (reduce map lookups)
|
- optimize the parser (reduce map lookups)
|
||||||
- cache vlib (right now it's re-compiled every time)
|
- cache vlib (right now it's re-compiled every time)
|
||||||
- fix openssl on older linux distros
|
+ fix openssl on older linux distros
|
||||||
- chat.vlang.io
|
- chat.vlang.io
|
||||||
- rewrite objective c code in v (ui_mac.m)
|
- rewrite objective c code in v (ui_mac.m)
|
||||||
- v ui for macos
|
- v ui for macos
|
||||||
|
@ -13,14 +13,14 @@ type HANDLE voidptr
|
|||||||
|
|
||||||
// win: FILETIME
|
// win: FILETIME
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
|
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
|
||||||
struct filetime {
|
struct Filetime {
|
||||||
dwLowDateTime u32
|
dwLowDateTime u32
|
||||||
dwHighDateTime u32
|
dwHighDateTime u32
|
||||||
}
|
}
|
||||||
|
|
||||||
// win: WIN32_FIND_DATA
|
// win: WIN32_FIND_DATA
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-_win32_find_dataw
|
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-_win32_find_dataw
|
||||||
struct win32finddata {
|
struct Win32finddata {
|
||||||
mut:
|
mut:
|
||||||
dwFileAttributes u32
|
dwFileAttributes u32
|
||||||
ftCreationTime filetime
|
ftCreationTime filetime
|
||||||
@ -52,7 +52,7 @@ fn init_os_args(argc int, argv &byteptr) []string {
|
|||||||
|
|
||||||
|
|
||||||
pub fn ls(path string) []string {
|
pub fn ls(path string) []string {
|
||||||
mut find_file_data := win32finddata{}
|
mut find_file_data := Win32finddata{}
|
||||||
mut dir_files := []string
|
mut dir_files := []string
|
||||||
// We can also check if the handle is valid. but using dir_exists instead
|
// We can also check if the handle is valid. but using dir_exists instead
|
||||||
// h_find_dir := C.FindFirstFile(path.str, &find_file_data)
|
// h_find_dir := C.FindFirstFile(path.str, &find_file_data)
|
||||||
|
Loading…
Reference in New Issue
Block a user