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)`
 | 
				
			||||||
 | 
								if p.tok == .assign {
 | 
				
			||||||
 | 
									p.next()
 | 
				
			||||||
 | 
									typ = p.expression()
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				typ = p.get_type()
 | 
									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