vh types + fn receiver name check
							parent
							
								
									27e254c738
								
							
						
					
					
						commit
						e69117a8f3
					
				|  | @ -71,7 +71,7 @@ fn (v mut V) cc() { | |||
| 		} | ||||
| 		if v.pref.ccompiler == 'cc' && os.file_exists(tcc_path) { | ||||
| 			// TODO tcc bug, needs an empty libtcc1.a fila
 | ||||
| 			//os.mkdir('/var/tmp/tcc/lib/tcc/') 
 | ||||
| 			//os.mkdir('/var/tmp/tcc/lib/tcc/')
 | ||||
| 			//os.create('/var/tmp/tcc/lib/tcc/libtcc1.a')
 | ||||
| 			v.pref.ccompiler = tcc_path | ||||
| 		} | ||||
|  | @ -253,7 +253,7 @@ fn (v mut V) cc() { | |||
| 			} | ||||
| 		} | ||||
| 		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 | ||||
| 	// Print the C command
 | ||||
|  |  | |||
|  | @ -193,7 +193,7 @@ fn (p mut Parser) fn_decl() { | |||
| 	*/ | ||||
| 	mut f := Fn{ | ||||
| 		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_deprecated: p.attr == 'deprecated' | ||||
| 	} | ||||
|  | @ -219,22 +219,25 @@ fn (p mut Parser) fn_decl() { | |||
| 			p.check_space(p.tok) | ||||
| 		} | ||||
| 		receiver_typ = p.get_type() | ||||
| 		T := p.table.find_type(receiver_typ) | ||||
| 		if T.cat == .interface_ { | ||||
| 		t := p.table.find_type(receiver_typ) | ||||
| 		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)') | ||||
| 		} | ||||
| 		// Don't allow modifying types from a different module
 | ||||
| 		if !p.first_pass() && !p.builtin_mod && T.mod != p.mod && | ||||
| 			p.file_path_id != 'vgen' { // allow .str() on builtin arrays
 | ||||
| 			println('T.mod=$T.mod') | ||||
| 			println('p.mod=$p.mod') | ||||
| 		if !p.first_pass() && !p.builtin_mod && t.mod != p.mod && | ||||
| 			p.file_path_id != 'vgen' // allow .str() on builtin arrays
 | ||||
| 		{ | ||||
| 			//println('T.mod=$T.mod')
 | ||||
| 			//println('p.mod=$p.mod')
 | ||||
| 			p.error('cannot define new methods on non-local type `$receiver_typ`') | ||||
| 		} | ||||
| 		// `(f *Foo)` instead of `(f mut Foo)` is a common mistake
 | ||||
| 		//if !p.builtin_mod && receiver_typ.contains('*') {
 | ||||
| 		if receiver_typ.ends_with('*') { | ||||
| 			t := receiver_typ.replace('*', '') | ||||
| 			p.error('use `($receiver_name mut $t)` instead of `($receiver_name *$t)`') | ||||
| 			tt := receiver_typ.replace('*', '') | ||||
| 			p.error('use `($receiver_name mut $tt)` instead of `($receiver_name *$tt)`') | ||||
| 		} | ||||
| 		f.receiver_typ = receiver_typ | ||||
| 		if is_mut || is_amp { | ||||
|  | @ -281,6 +284,7 @@ fn (p mut Parser) fn_decl() { | |||
| 	} | ||||
| 	else if !p.pref.translated { | ||||
| 		if contains_capital(f.name) && !p.fileis('view.v') { | ||||
| 			println('`$f.name`') | ||||
| 			p.error('function names cannot contain uppercase letters, use snake_case instead') | ||||
| 		} | ||||
| 		if f.name[0] == `_` { | ||||
|  |  | |||
|  | @ -37,13 +37,18 @@ fn generate_vh(mod string) { | |||
| 	// Consts
 | ||||
| 	println(full_mod_path) | ||||
| 	mut vfiles := os.walk_ext(full_mod_path, '.v') | ||||
| 	filtered := vfiles.filter(!it.ends_with('test.v') && | ||||
| 		!it.ends_with('_windows.v') && !it.ends_with('_win.v')) // TODO merge once filter allows it
 | ||||
| 	//mut vfiles := os.ls(full_mod_path) or {
 | ||||
| 		//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) | ||||
| 	mut v := new_v(['foo.v']) | ||||
| 	//v.pref.generating_vh = true
 | ||||
| 	mut consts := strings.new_builder(100) | ||||
| 	mut fns := strings.new_builder(100) | ||||
| 	mut types := strings.new_builder(100) | ||||
| 	for file in filtered { | ||||
| 		mut p := v.new_parser_from_file(file) | ||||
| 		p.scanner.is_vh = true | ||||
|  | @ -55,10 +60,13 @@ fn generate_vh(mod string) { | |||
| 			match tok.tok { | ||||
| 				TokenKind.key_fn {	fns.writeln(generate_fn(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.close() | ||||
| } | ||||
|  | @ -107,6 +115,22 @@ fn generate_const(tokens []Token, i int) string { | |||
| 	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() { | ||||
| 	println('\n\n\n\nGenerating a V header file for module `$v.mod`') | ||||
|  |  | |||
|  | @ -9,14 +9,6 @@ import ( | |||
| 	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 { | ||||
| 	file_path_id   string // unique id. if parsing file will be path eg, "/home/user/hello.v"
 | ||||
| 	file_name      string // "hello.v"
 | ||||
|  | @ -532,7 +524,12 @@ fn (p mut Parser) const_decl() { | |||
| 		mut typ := '' | ||||
| 		if p.is_vh { | ||||
| 			// .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.cgen.consts << ('extern ' + | ||||
| 				p.table.cgen_name_type_pair(name, typ)) + ';' | ||||
|  |  | |||
|  | @ -4,6 +4,15 @@ | |||
| 
 | ||||
| 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 { | ||||
| 	eof | ||||
| 	name        // user
 | ||||
|  | @ -281,6 +290,9 @@ fn (t []TokenKind) contains(val TokenKind) bool { | |||
| } | ||||
| 
 | ||||
| fn (t Token) str() string { | ||||
| 	if t.tok == .str { | ||||
| 		return "'$t.lit'" | ||||
| 	}	 | ||||
| 	if t.tok < .plus { | ||||
| 		return t.lit // string, number etc
 | ||||
| 	}	 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue