do not allow duplicate methods; fix os_win.v; minor fixes and docs
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.fgen('fn ')
|
||||
//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
|
||||
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
|
||||
//if !p.builtin_mod && receiver_typ.contains('*') {
|
||||
if receiver_typ.contains('*') {
|
||||
if receiver_typ.ends_with('*') {
|
||||
t := receiver_typ.replace('*', '')
|
||||
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
|
||||
p.register_var(receiver)
|
||||
}
|
||||
// +-/* methods
|
||||
if p.tok == .plus || p.tok == .minus || p.tok == .mul {
|
||||
f.name = p.tok.str()
|
||||
p.next()
|
||||
|
@ -398,28 +410,7 @@ fn (p mut Parser) fn_decl() {
|
|||
// First pass? Skip the body for now
|
||||
// Look for generic calls.
|
||||
if !is_sig && !is_fn_header {
|
||||
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
|
||||
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()
|
||||
}
|
||||
p.skip_fn_body()
|
||||
}
|
||||
// Live code reloading? Load all fns from .so
|
||||
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() {
|
||||
for var in p.local_vars {
|
||||
if var.name == '' {
|
||||
|
@ -894,6 +914,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||
}
|
||||
got := typ
|
||||
expected := arg.typ
|
||||
got_ptr := got.ends_with('*')
|
||||
exp_ptr := expected.ends_with('*')
|
||||
// println('fn arg got="$got" exp="$expected"')
|
||||
if !p.check_types_no_throw(got, expected) {
|
||||
mut j := i
|
||||
|
@ -912,18 +934,23 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||
'argument to `$f.name()`')
|
||||
}
|
||||
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 {
|
||||
// Dereference
|
||||
if got.ends_with('*') && !expected.ends_with('*') {
|
||||
if got_ptr && !exp_ptr {
|
||||
p.cgen.set_placeholder(ph, '*')
|
||||
}
|
||||
// Reference
|
||||
// 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,
|
||||
// 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.gen('}[0] ')
|
||||
}
|
||||
|
@ -937,9 +964,8 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||
}
|
||||
}
|
||||
}
|
||||
// interface?
|
||||
if is_interface {
|
||||
if !got.contains('*') {
|
||||
else if is_interface {
|
||||
if !got_ptr {
|
||||
p.cgen.set_placeholder(ph, '&')
|
||||
}
|
||||
// Pass all interface methods
|
||||
|
@ -985,7 +1011,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
|||
}
|
||||
|
||||
// "fn (int, string) int"
|
||||
fn (f Fn) typ_str() string {
|
||||
fn (f &Fn) typ_str() string {
|
||||
mut sb := strings.new_builder(50)
|
||||
sb.write('fn (')
|
||||
for i, arg in f.args {
|
||||
|
@ -1001,6 +1027,10 @@ fn (f Fn) typ_str() string {
|
|||
return sb.str()
|
||||
}
|
||||
|
||||
fn (f &Fn) v_definition() string {
|
||||
return 'todo'
|
||||
}
|
||||
|
||||
// f.args => "int a, string b"
|
||||
fn (f &Fn) str_args(table &Table) string {
|
||||
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 { '' }
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
// For debugging types
|
||||
fn (t Type) str() string {
|
||||
mut s := 'type "$t.name" {'
|
||||
|
@ -146,6 +147,7 @@ fn (t Type) str() string {
|
|||
s += '}\n'
|
||||
return s
|
||||
}
|
||||
*/
|
||||
|
||||
const (
|
||||
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) {
|
||||
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
|
||||
mut t := p.table.typesmap[type_name]
|
||||
if type_name == 'str' {
|
||||
println(t.methods.len)
|
||||
}
|
||||
|
||||
if f.name != 'str' && f in t.methods {
|
||||
p.error('redefinition of method `${type_name}.$f.name`')
|
||||
}
|
||||
t.methods << f
|
||||
if type_name == 'str' {
|
||||
println(t.methods.len)
|
||||
}
|
||||
p.table.typesmap[type_name] = t
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
- bring back vdoc and regenerate all module docs
|
||||
- optimize the parser (reduce map lookups)
|
||||
- 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
|
||||
- rewrite objective c code in v (ui_mac.m)
|
||||
- v ui for macos
|
||||
|
|
|
@ -13,14 +13,14 @@ type HANDLE voidptr
|
|||
|
||||
// win: FILETIME
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
|
||||
struct filetime {
|
||||
struct Filetime {
|
||||
dwLowDateTime u32
|
||||
dwHighDateTime u32
|
||||
}
|
||||
|
||||
// win: WIN32_FIND_DATA
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-_win32_find_dataw
|
||||
struct win32finddata {
|
||||
struct Win32finddata {
|
||||
mut:
|
||||
dwFileAttributes u32
|
||||
ftCreationTime filetime
|
||||
|
@ -52,7 +52,7 @@ fn init_os_args(argc int, argv &byteptr) []string {
|
|||
|
||||
|
||||
pub fn ls(path string) []string {
|
||||
mut find_file_data := win32finddata{}
|
||||
mut find_file_data := Win32finddata{}
|
||||
mut dir_files := []string
|
||||
// We can also check if the handle is valid. but using dir_exists instead
|
||||
// h_find_dir := C.FindFirstFile(path.str, &find_file_data)
|
||||
|
|
Loading…
Reference in New Issue