vh types + fn receiver name check
parent
27e254c738
commit
e69117a8f3
|
@ -253,7 +253,7 @@ fn (v mut V) cc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verror('C error. This should never happen. ' +
|
verror('C error. This should never happen. ' +
|
||||||
'Please create a GitHub issue: https://github.com/vlang/v/issues/new/choose')
|
'\nPlease create a GitHub issue: https://github.com/vlang/v/issues/new/choose')
|
||||||
}
|
}
|
||||||
diff := time.ticks() - ticks
|
diff := time.ticks() - ticks
|
||||||
// Print the C command
|
// Print the C command
|
||||||
|
|
|
@ -193,7 +193,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
*/
|
*/
|
||||||
mut f := Fn{
|
mut f := Fn{
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
is_public: p.tok == .key_pub
|
is_public: p.tok == .key_pub || p.is_vh // functions defined in .vh are always public
|
||||||
is_unsafe: p.attr == 'unsafe_fn'
|
is_unsafe: p.attr == 'unsafe_fn'
|
||||||
is_deprecated: p.attr == 'deprecated'
|
is_deprecated: p.attr == 'deprecated'
|
||||||
}
|
}
|
||||||
|
@ -219,22 +219,25 @@ fn (p mut Parser) fn_decl() {
|
||||||
p.check_space(p.tok)
|
p.check_space(p.tok)
|
||||||
}
|
}
|
||||||
receiver_typ = p.get_type()
|
receiver_typ = p.get_type()
|
||||||
T := p.table.find_type(receiver_typ)
|
t := p.table.find_type(receiver_typ)
|
||||||
if T.cat == .interface_ {
|
if (t.name == '' || t.is_placeholder) && !p.first_pass() {
|
||||||
|
p.error('unknown receiver type `$receiver_typ`')
|
||||||
|
}
|
||||||
|
if t.cat == .interface_ {
|
||||||
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
|
p.error('invalid receiver type `$receiver_typ` (`$receiver_typ` is an interface)')
|
||||||
}
|
}
|
||||||
// Don't allow modifying types from a different module
|
// Don't allow modifying types from a different module
|
||||||
if !p.first_pass() && !p.builtin_mod && T.mod != p.mod &&
|
if !p.first_pass() && !p.builtin_mod && t.mod != p.mod &&
|
||||||
p.file_path_id != 'vgen' { // allow .str() on builtin arrays
|
p.file_path_id != 'vgen' // allow .str() on builtin arrays
|
||||||
println('T.mod=$T.mod')
|
{
|
||||||
println('p.mod=$p.mod')
|
//println('T.mod=$T.mod')
|
||||||
|
//println('p.mod=$p.mod')
|
||||||
p.error('cannot define new methods on non-local type `$receiver_typ`')
|
p.error('cannot define new methods on non-local type `$receiver_typ`')
|
||||||
}
|
}
|
||||||
// `(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 receiver_typ.ends_with('*') {
|
if receiver_typ.ends_with('*') {
|
||||||
t := receiver_typ.replace('*', '')
|
tt := receiver_typ.replace('*', '')
|
||||||
p.error('use `($receiver_name mut $t)` instead of `($receiver_name *$t)`')
|
p.error('use `($receiver_name mut $tt)` instead of `($receiver_name *$tt)`')
|
||||||
}
|
}
|
||||||
f.receiver_typ = receiver_typ
|
f.receiver_typ = receiver_typ
|
||||||
if is_mut || is_amp {
|
if is_mut || is_amp {
|
||||||
|
@ -281,6 +284,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
}
|
}
|
||||||
else if !p.pref.translated {
|
else if !p.pref.translated {
|
||||||
if contains_capital(f.name) && !p.fileis('view.v') {
|
if contains_capital(f.name) && !p.fileis('view.v') {
|
||||||
|
println('`$f.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 f.name[0] == `_` {
|
if f.name[0] == `_` {
|
||||||
|
|
|
@ -37,13 +37,18 @@ fn generate_vh(mod string) {
|
||||||
// Consts
|
// Consts
|
||||||
println(full_mod_path)
|
println(full_mod_path)
|
||||||
mut vfiles := os.walk_ext(full_mod_path, '.v')
|
mut vfiles := os.walk_ext(full_mod_path, '.v')
|
||||||
filtered := vfiles.filter(!it.ends_with('test.v') &&
|
//mut vfiles := os.ls(full_mod_path) or {
|
||||||
!it.ends_with('_windows.v') && !it.ends_with('_win.v')) // TODO merge once filter allows it
|
//exit(1)
|
||||||
|
//}
|
||||||
|
filtered := vfiles.filter(it.ends_with('.v') && !it.ends_with('test.v') &&
|
||||||
|
!it.ends_with('_windows.v') && !it.ends_with('_win.v') &&
|
||||||
|
!it.contains('/js')) // TODO merge once filter allows it
|
||||||
println(filtered)
|
println(filtered)
|
||||||
mut v := new_v(['foo.v'])
|
mut v := new_v(['foo.v'])
|
||||||
//v.pref.generating_vh = true
|
//v.pref.generating_vh = true
|
||||||
mut consts := strings.new_builder(100)
|
mut consts := strings.new_builder(100)
|
||||||
mut fns := strings.new_builder(100)
|
mut fns := strings.new_builder(100)
|
||||||
|
mut types := strings.new_builder(100)
|
||||||
for file in filtered {
|
for file in filtered {
|
||||||
mut p := v.new_parser_from_file(file)
|
mut p := v.new_parser_from_file(file)
|
||||||
p.scanner.is_vh = true
|
p.scanner.is_vh = true
|
||||||
|
@ -55,10 +60,13 @@ fn generate_vh(mod string) {
|
||||||
match tok.tok {
|
match tok.tok {
|
||||||
TokenKind.key_fn { fns.writeln(generate_fn(p.tokens, i)) }
|
TokenKind.key_fn { fns.writeln(generate_fn(p.tokens, i)) }
|
||||||
TokenKind.key_const { consts.writeln(generate_const(p.tokens, i)) }
|
TokenKind.key_const { consts.writeln(generate_const(p.tokens, i)) }
|
||||||
|
TokenKind.key_struct { types.writeln(generate_type(p.tokens, i)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := consts.str() + fns.str().replace('\n\n\n', '\n').replace('\n\n', '\n')
|
result := consts.str() + types.str() +
|
||||||
|
fns.str().replace('\n\n\n', '\n').replace('\n\n', '\n')
|
||||||
|
|
||||||
out.writeln(result.replace('[ ] ', '[]').replace('? ', '?'))
|
out.writeln(result.replace('[ ] ', '[]').replace('? ', '?'))
|
||||||
out.close()
|
out.close()
|
||||||
}
|
}
|
||||||
|
@ -107,6 +115,22 @@ fn generate_const(tokens []Token, i int) string {
|
||||||
return out.str()
|
return out.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_type(tokens []Token, i int) string {
|
||||||
|
mut out := strings.new_builder(100)
|
||||||
|
mut tok := tokens[i]
|
||||||
|
for i < tokens.len && tok.tok != .rcbr {
|
||||||
|
out.write(tok.str())
|
||||||
|
out.write(' ')
|
||||||
|
if tokens[i+1].line_nr != tokens[i].line_nr {
|
||||||
|
out.write('\n\t')
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
tok = tokens[i]
|
||||||
|
}
|
||||||
|
out.writeln('\n}')
|
||||||
|
return out.str()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fn (v &V) generate_vh_old() {
|
fn (v &V) generate_vh_old() {
|
||||||
println('\n\n\n\nGenerating a V header file for module `$v.mod`')
|
println('\n\n\n\nGenerating a V header file for module `$v.mod`')
|
||||||
|
|
|
@ -9,14 +9,6 @@ import (
|
||||||
strings
|
strings
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Token {
|
|
||||||
tok TokenKind // the token number/enum; for quick comparisons
|
|
||||||
lit string // literal representation of the token
|
|
||||||
line_nr int // the line number in the source where the token occured
|
|
||||||
name_idx int // name table index for O(1) lookup
|
|
||||||
col int // the column where the token ends
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
file_path_id string // unique id. if parsing file will be path eg, "/home/user/hello.v"
|
file_path_id string // unique id. if parsing file will be path eg, "/home/user/hello.v"
|
||||||
file_name string // "hello.v"
|
file_name string // "hello.v"
|
||||||
|
@ -532,7 +524,12 @@ fn (p mut Parser) const_decl() {
|
||||||
mut typ := ''
|
mut typ := ''
|
||||||
if p.is_vh {
|
if p.is_vh {
|
||||||
// .vh files don't have const values, just types: `const (a int)`
|
// .vh files don't have const values, just types: `const (a int)`
|
||||||
typ = p.get_type()
|
if p.tok == .assign {
|
||||||
|
p.next()
|
||||||
|
typ = p.expression()
|
||||||
|
} else {
|
||||||
|
typ = p.get_type()
|
||||||
|
}
|
||||||
p.table.register_const(name, typ, p.mod)
|
p.table.register_const(name, typ, p.mod)
|
||||||
p.cgen.consts << ('extern ' +
|
p.cgen.consts << ('extern ' +
|
||||||
p.table.cgen_name_type_pair(name, typ)) + ';'
|
p.table.cgen_name_type_pair(name, typ)) + ';'
|
||||||
|
|
|
@ -4,6 +4,15 @@
|
||||||
|
|
||||||
module compiler
|
module compiler
|
||||||
|
|
||||||
|
struct Token {
|
||||||
|
tok TokenKind // the token number/enum; for quick comparisons
|
||||||
|
lit string // literal representation of the token
|
||||||
|
line_nr int // the line number in the source where the token occured
|
||||||
|
name_idx int // name table index for O(1) lookup
|
||||||
|
col int // the column where the token ends
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum TokenKind {
|
enum TokenKind {
|
||||||
eof
|
eof
|
||||||
name // user
|
name // user
|
||||||
|
@ -281,6 +290,9 @@ fn (t []TokenKind) contains(val TokenKind) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t Token) str() string {
|
fn (t Token) str() string {
|
||||||
|
if t.tok == .str {
|
||||||
|
return "'$t.lit'"
|
||||||
|
}
|
||||||
if t.tok < .plus {
|
if t.tok < .plus {
|
||||||
return t.lit // string, number etc
|
return t.lit // string, number etc
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue