remove duplication by using a new Preferences struct
							parent
							
								
									42a622c10f
								
							
						
					
					
						commit
						74d234f8cd
					
				|  | @ -95,7 +95,7 @@ fn (f mut Fn) clear_vars() { | ||||||
| 
 | 
 | ||||||
| // vlib header file?
 | // vlib header file?
 | ||||||
| fn (p mut Parser) is_sig() bool { | fn (p mut Parser) is_sig() bool { | ||||||
| 	return (p.build_mode == DEFAULT_MODE || p.build_mode == BUILD) && | 	return (p.pref.build_mode == DEFAULT_MODE || p.pref.build_mode == BUILD) && | ||||||
| 	(p.file_path.contains(TmpPath)) | 	(p.file_path.contains(TmpPath)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -173,8 +173,8 @@ fn (p mut Parser) fn_decl() { | ||||||
| 	// C function header def? (fn C.NSMakeRect(int,int,int,int))
 | 	// C function header def? (fn C.NSMakeRect(int,int,int,int))
 | ||||||
| 	is_c := f.name == 'C' && p.tok == DOT | 	is_c := f.name == 'C' && p.tok == DOT | ||||||
| 	// Just fn signature? only builtin.v + default build mode
 | 	// Just fn signature? only builtin.v + default build mode
 | ||||||
| 	// is_sig := p.builtin_pkg && p.build_mode == DEFAULT_MODE
 | 	// is_sig := p.builtin_pkg && p.pref.build_mode == DEFAULT_MODE
 | ||||||
| 	// is_sig := p.build_mode == DEFAULT_MODE && (p.builtin_pkg || p.file.contains(LANG_TMP))
 | 	// is_sig := p.pref.build_mode == DEFAULT_MODE && (p.builtin_pkg || p.file.contains(LANG_TMP))
 | ||||||
| 	is_sig := p.is_sig() | 	is_sig := p.is_sig() | ||||||
| 	// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_pkg')
 | 	// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_pkg')
 | ||||||
| 	if is_c { | 	if is_c { | ||||||
|  | @ -182,7 +182,7 @@ fn (p mut Parser) fn_decl() { | ||||||
| 		f.name = p.check_name() | 		f.name = p.check_name() | ||||||
| 		f.is_c = true | 		f.is_c = true | ||||||
| 	} | 	} | ||||||
| 	else if !p.translated && !p.file_path.contains('view.v') { | 	else if !p.pref.translated && !p.file_path.contains('view.v') { | ||||||
| 		if contains_capital(f.name) { | 		if contains_capital(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') | ||||||
| 		} | 		} | ||||||
|  | @ -237,7 +237,7 @@ fn (p mut Parser) fn_decl() { | ||||||
| 		typ = p.get_type() | 		typ = p.get_type() | ||||||
| 	} | 	} | ||||||
| 	// Translated C code can have empty functions (just definitions)
 | 	// Translated C code can have empty functions (just definitions)
 | ||||||
| 	is_fn_header := !is_c && !is_sig && (p.translated || p.is_test) && | 	is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && | ||||||
| 	(p.tok != LCBR)// || (p.tok == NAME && p.peek() != LCBR))
 | 	(p.tok != LCBR)// || (p.tok == NAME && p.peek() != LCBR))
 | ||||||
| 	if is_fn_header { | 	if is_fn_header { | ||||||
| 		f.is_decl = true | 		f.is_decl = true | ||||||
|  | @ -274,10 +274,10 @@ fn (p mut Parser) fn_decl() { | ||||||
| 	// }
 | 	// }
 | ||||||
| 	mut fn_name_cgen := p.table.cgen_name(f) | 	mut fn_name_cgen := p.table.cgen_name(f) | ||||||
| 	// Start generation of the function body
 | 	// Start generation of the function body
 | ||||||
| 	is_live := p.is_live && f.name != 'main' && f.name != 'reload_so' | 	is_live := p.pref.is_live && f.name != 'main' && f.name != 'reload_so' | ||||||
| 	skip_main_in_test := f.name == 'main' && p.is_test | 	skip_main_in_test := f.name == 'main' && p.pref.is_test | ||||||
| 	if !is_c && !is_live && !is_sig && !is_fn_header && !skip_main_in_test { | 	if !is_c && !is_live && !is_sig && !is_fn_header && !skip_main_in_test { | ||||||
| 		if p.obfuscate { | 		if p.pref.obfuscate { | ||||||
| 			p.genln('; // ${f.name}')
 | 			p.genln('; // ${f.name}')
 | ||||||
| 		} | 		} | ||||||
| 		p.genln('$typ $fn_name_cgen($str_args) {') | 		p.genln('$typ $fn_name_cgen($str_args) {') | ||||||
|  | @ -332,13 +332,13 @@ fn (p mut Parser) fn_decl() { | ||||||
| 		} | 		} | ||||||
| 		// Actual fn declaration!
 | 		// Actual fn declaration!
 | ||||||
| 		mut fn_decl := '$typ $fn_name_cgen($str_args)' | 		mut fn_decl := '$typ $fn_name_cgen($str_args)' | ||||||
| 		if p.obfuscate { | 		if p.pref.obfuscate { | ||||||
| 			fn_decl += '; // ${f.name}'
 | 			fn_decl += '; // ${f.name}'
 | ||||||
| 		} | 		} | ||||||
| 		// Add function definition to the top
 | 		// Add function definition to the top
 | ||||||
| 		if !is_c && f.name != 'main' && p.first_run() { | 		if !is_c && f.name != 'main' && p.first_run() { | ||||||
| 			// TODO hack to make Volt compile without -embed_vlib
 | 			// TODO hack to make Volt compile without -embed_vlib
 | ||||||
| 			if f.name == 'darwin__nsstring' && p.build_mode == DEFAULT_MODE { | 			if f.name == 'darwin__nsstring' && p.pref.build_mode == DEFAULT_MODE { | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			p.cgen.fns << fn_decl + ';' | 			p.cgen.fns << fn_decl + ';' | ||||||
|  | @ -357,13 +357,13 @@ fn (p mut Parser) fn_decl() { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// We are in live code reload mode, call the .so loader in bg
 | 		// We are in live code reload mode, call the .so loader in bg
 | ||||||
| 		if p.is_live { | 		if p.pref.is_live { | ||||||
| 			p.genln('  | 			p.genln('  | ||||||
| load_so("bounce.so");  | load_so("bounce.so");  | ||||||
| pthread_t _thread_so; | pthread_t _thread_so; | ||||||
| pthread_create(&_thread_so , NULL, &reload_so, NULL); ') | pthread_create(&_thread_so , NULL, &reload_so, NULL); ') | ||||||
| 		} | 		} | ||||||
| 		if p.is_test && !p.scanner.file_path.contains('/volt') { | 		if p.pref.is_test && !p.scanner.file_path.contains('/volt') { | ||||||
| 			p.error('tests cannot have function `main`') | 			p.error('tests cannot have function `main`') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -374,14 +374,14 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ') | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// We are in profile mode? Start counting at the beginning of the function (save current time).
 | 	// We are in profile mode? Start counting at the beginning of the function (save current time).
 | ||||||
| 	if p.is_prof && f.name != 'main' && f.name != 'time__ticks' { | 	if p.pref.is_prof && f.name != 'main' && f.name != 'time__ticks' { | ||||||
| 		p.genln('double _PROF_START = time__ticks();//$f.name')
 | 		p.genln('double _PROF_START = time__ticks();//$f.name')
 | ||||||
| 		cgen_name := p.table.cgen_name(f) | 		cgen_name := p.table.cgen_name(f) | ||||||
| 		f.defer = '  ${cgen_name}_time += time__ticks() - _PROF_START;' | 		f.defer = '  ${cgen_name}_time += time__ticks() - _PROF_START;' | ||||||
| 	} | 	} | ||||||
| 	p.statements_no_curly_end() | 	p.statements_no_curly_end() | ||||||
| 	// Print counting result after all statements in main
 | 	// Print counting result after all statements in main
 | ||||||
| 	if p.is_prof && f.name == 'main' { | 	if p.pref.is_prof && f.name == 'main' { | ||||||
| 		p.genln(p.print_prof_counters()) | 		p.genln(p.print_prof_counters()) | ||||||
| 	} | 	} | ||||||
| 	// Counting or not, always need to add defer before the end
 | 	// Counting or not, always need to add defer before the end
 | ||||||
|  | @ -414,14 +414,14 @@ fn (p mut Parser) check_unused_variables() { | ||||||
| 		if var.name == '' { | 		if var.name == '' { | ||||||
| 			break | 			break | ||||||
| 		} | 		} | ||||||
| 		if !var.is_used && !var.is_arg && !p.translated && var.name != '_' { | 		if !var.is_used && !var.is_arg && !p.pref.translated && var.name != '_' { | ||||||
| 			p.scanner.line_nr = var.line_nr - 1 | 			p.scanner.line_nr = var.line_nr - 1 | ||||||
| 			p.error('`$var.name` declared and not used') | 			p.error('`$var.name` declared and not used') | ||||||
| 		} | 		} | ||||||
| 		// Very basic automatic memory management at the end of the function.
 | 		// Very basic automatic memory management at the end of the function.
 | ||||||
| 		// This is inserted right before the final `}`, so if the object is being returned,
 | 		// This is inserted right before the final `}`, so if the object is being returned,
 | ||||||
| 		// the free method will not be called.
 | 		// the free method will not be called.
 | ||||||
| 		if p.is_test && var.typ.contains('array_') { | 		if p.pref.is_test && var.typ.contains('array_') { | ||||||
| 			// p.genln('v_${var.typ}_free($var.name); // !!!! XAXA')
 | 			// p.genln('v_${var.typ}_free($var.name); // !!!! XAXA')
 | ||||||
| 			// p.genln('free(${var.name}.data); // !!!! XAXA')
 | 			// p.genln('free(${var.name}.data); // !!!! XAXA')
 | ||||||
| 		} | 		} | ||||||
|  | @ -500,19 +500,19 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type string) { | fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type string) { | ||||||
| 	if !f.is_public && !f.is_c && !p.is_test && f.pkg != p.pkg  {  | 	if !f.is_public && !f.is_c && !p.pref.is_test && f.pkg != p.pkg  {  | ||||||
| 		p.error('function `$f.name` is private') | 		p.error('function `$f.name` is private') | ||||||
| 	} | 	} | ||||||
| 	p.calling_c = f.is_c | 	p.calling_c = f.is_c | ||||||
| 	is_print := p.is_prod &&// Hide prints only in prod
 | 	is_print := p.pref.is_prod &&// Hide prints only in prod
 | ||||||
| 	!p.is_test && | 	!p.pref.is_test && | ||||||
| 	!p.builtin_pkg &&// Allow prints in builtin  pkgs
 | 	!p.builtin_pkg &&// Allow prints in builtin  pkgs
 | ||||||
| 	f.is_c && f.name == 'printf' | 	f.is_c && f.name == 'printf' | ||||||
| 	if !p.cgen.nogen { | 	if !p.cgen.nogen { | ||||||
| 		p.cgen.nogen = is_print | 		p.cgen.nogen = is_print | ||||||
| 	} | 	} | ||||||
| 	cgen_name := p.table.cgen_name(f) | 	cgen_name := p.table.cgen_name(f) | ||||||
| 	// if p.is_prof {
 | 	// if p.pref.is_prof {
 | ||||||
| 	// p.cur_fn.called_fns << cgen_name
 | 	// p.cur_fn.called_fns << cgen_name
 | ||||||
| 	// }
 | 	// }
 | ||||||
| 	// Normal function call
 | 	// Normal function call
 | ||||||
|  | @ -853,4 +853,3 @@ fn (f &Fn) str_args(table *Table) string { | ||||||
| 	} | 	} | ||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										158
									
								
								compiler/main.v
								
								
								
								
							
							
						
						
									
										158
									
								
								compiler/main.v
								
								
								
								
							|  | @ -58,32 +58,38 @@ enum Pass { | ||||||
| 	main | 	main | ||||||
| } | } | ||||||
| */ | */ | ||||||
|  | 
 | ||||||
|  | struct Preferences { | ||||||
|  | 	mut: | ||||||
|  | 		build_mode     BuildMode | ||||||
|  | 		nofmt          bool // disable vfmt
 | ||||||
|  | 		is_test        bool // `v test string_test.v`
 | ||||||
|  | 		is_script      bool // single file mode (`v program.v`), `fn main(){}` can be skipped
 | ||||||
|  | 		is_live        bool // for hot code reloading
 | ||||||
|  | 		is_so          bool | ||||||
|  | 		is_prof        bool // benchmark every function
 | ||||||
|  | 		translated     bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
 | ||||||
|  | 		is_prod        bool // use "-O2"
 | ||||||
|  | 		is_verbose     bool // print extra information with `v.log()`
 | ||||||
|  | 		obfuscate      bool // `v -obf program.v`, renames functions to "f_XXX"
 | ||||||
|  | 		is_play        bool // playground mode
 | ||||||
|  | 		is_repl        bool | ||||||
|  | 		is_run         bool | ||||||
|  | 		show_c_cmd     bool // `v -show_c_cmd` prints the C command to build program.v.c
 | ||||||
|  | 		sanitize       bool // use Clang's new "-fsanitize" option
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct V { | struct V { | ||||||
| mut: | mut: | ||||||
| 	build_mode BuildMode |  | ||||||
| 	os         Os // the OS to build for
 | 	os         Os // the OS to build for
 | ||||||
| 	nofmt      bool // disable vfmt
 |  | ||||||
| 	out_name_c string // name of the temporary C file
 | 	out_name_c string // name of the temporary C file
 | ||||||
| 	files      []string // all V files that need to be parsed and compiled
 | 	files      []string // all V files that need to be parsed and compiled
 | ||||||
| 	dir        string // directory (or file) being compiled (TODO rename to path?)
 | 	dir        string // directory (or file) being compiled (TODO rename to path?)
 | ||||||
| 	table      *Table // table with types, vars, functions etc
 | 	table      *Table // table with types, vars, functions etc
 | ||||||
| 	cgen       *CGen // C code generator
 | 	cgen       *CGen // C code generator
 | ||||||
| 	is_test    bool // `v test string_test.v`
 | 	pref       *Preferences // all the prefrences and settings extracted to a struct for reusability
 | ||||||
| 	is_script  bool // single file mode (`v program.v`), `fn main(){}` can be skipped
 | 	lang_dir   string // "~/code/v"
 | ||||||
| 	is_so      bool |  | ||||||
| 	is_live    bool // for hot code reloading
 |  | ||||||
| 	is_prof    bool // benchmark every function
 |  | ||||||
| 	translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
 |  | ||||||
| 	obfuscate  bool // `v -obf program.v`, renames functions to "f_XXX"
 |  | ||||||
| 	lang_dir   string // path to V repo
 |  | ||||||
| 	is_verbose bool // print extra information with `v.log()`
 |  | ||||||
| 	is_run     bool // `v run program.v`
 |  | ||||||
| 	is_play    bool // playground mode
 |  | ||||||
| 	show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c
 |  | ||||||
| 	sanitize   bool // use Clang's new "-fsanitize" option
 |  | ||||||
| 	out_name   string // "program.exe"
 | 	out_name   string // "program.exe"
 | ||||||
| 	is_prod    bool // use "-O2"
 |  | ||||||
| 	is_repl    bool |  | ||||||
| 	vroot      string | 	vroot      string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -137,7 +143,7 @@ fn main() { | ||||||
| 	} | 	} | ||||||
| 	// Construct the V object from command line arguments
 | 	// Construct the V object from command line arguments
 | ||||||
| 	mut c := new_v(args) | 	mut c := new_v(args) | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		println(args) | 		println(args) | ||||||
| 	} | 	} | ||||||
| 	// Generate the docs and exit
 | 	// Generate the docs and exit
 | ||||||
|  | @ -153,7 +159,7 @@ fn (c mut V) compile() { | ||||||
| 	cgen.genln('// Generated by V')
 | 	cgen.genln('// Generated by V')
 | ||||||
| 	// Add user files to compile
 | 	// Add user files to compile
 | ||||||
| 	c.add_user_v_files() | 	c.add_user_v_files() | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		println('all .v files:') | 		println('all .v files:') | ||||||
| 		println(c.files) | 		println(c.files) | ||||||
| 	} | 	} | ||||||
|  | @ -164,7 +170,7 @@ fn (c mut V) compile() { | ||||||
| 	} | 	} | ||||||
| 	// Main pass
 | 	// Main pass
 | ||||||
| 	cgen.run = RUN_MAIN | 	cgen.run = RUN_MAIN | ||||||
| 	if c.is_play { | 	if c.pref.is_play { | ||||||
| 		cgen.genln('#define VPLAY (1) ') | 		cgen.genln('#define VPLAY (1) ') | ||||||
| 	} | 	} | ||||||
| 	cgen.genln('    | 	cgen.genln('    | ||||||
|  | @ -238,23 +244,23 @@ void reload_so(); | ||||||
| void init_consts();') | void init_consts();') | ||||||
| 	imports_json := c.table.imports.contains('json') | 	imports_json := c.table.imports.contains('json') | ||||||
| 	// TODO remove global UI hack
 | 	// TODO remove global UI hack
 | ||||||
| 	if c.os == MAC && ((c.build_mode == EMBED_VLIB && c.table.imports.contains('ui')) || | 	if c.os == MAC && ((c.pref.build_mode == EMBED_VLIB && c.table.imports.contains('ui')) || | ||||||
| 	(c.build_mode == BUILD && c.dir.contains('/ui'))) { | 	(c.pref.build_mode == BUILD && c.dir.contains('/ui'))) { | ||||||
| 		cgen.genln('id defaultFont = 0; // main.v')
 | 		cgen.genln('id defaultFont = 0; // main.v')
 | ||||||
| 	} | 	} | ||||||
| 	// TODO remove ugly .c include once V has its own json parser
 | 	// TODO remove ugly .c include once V has its own json parser
 | ||||||
| 	// Embed cjson either in embedvlib or in json.o
 | 	// Embed cjson either in embedvlib or in json.o
 | ||||||
| 	if imports_json && c.build_mode == EMBED_VLIB || | 	if imports_json && c.pref.build_mode == EMBED_VLIB || | ||||||
| 	(c.build_mode == BUILD && c.out_name.contains('json.o')) { | 	(c.pref.build_mode == BUILD && c.out_name.contains('json.o')) { | ||||||
| 		cgen.genln('#include "cJSON.c" ') | 		cgen.genln('#include "cJSON.c" ') | ||||||
| 	} | 	} | ||||||
| 	// We need the cjson header for all the json decoding user will do in default mode
 | 	// We need the cjson header for all the json decoding user will do in default mode
 | ||||||
| 	if c.build_mode == DEFAULT_MODE { | 	if c.pref.build_mode == DEFAULT_MODE { | ||||||
| 		if imports_json { | 		if imports_json { | ||||||
| 			cgen.genln('#include "cJSON.h"') | 			cgen.genln('#include "cJSON.h"') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if c.build_mode == EMBED_VLIB || c.build_mode == DEFAULT_MODE { | 	if c.pref.build_mode == EMBED_VLIB || c.pref.build_mode == DEFAULT_MODE { | ||||||
| 		// If we declare these for all modes, then when running `v a.v` we'll get
 | 		// If we declare these for all modes, then when running `v a.v` we'll get
 | ||||||
| 		// `/usr/bin/ld: multiple definition of 'total_m'`
 | 		// `/usr/bin/ld: multiple definition of 'total_m'`
 | ||||||
| 		// TODO
 | 		// TODO
 | ||||||
|  | @ -277,7 +283,7 @@ void init_consts();') | ||||||
| 		p.parse() | 		p.parse() | ||||||
| 		// p.g.gen_x64()
 | 		// p.g.gen_x64()
 | ||||||
| 		// Format all files (don't format automatically generated vlib headers)
 | 		// Format all files (don't format automatically generated vlib headers)
 | ||||||
| 		if !c.nofmt && !file.contains('/vlib/') { | 		if !c.pref.nofmt && !file.contains('/vlib/') { | ||||||
| 			// new vfmt is not ready yet
 | 			// new vfmt is not ready yet
 | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -292,14 +298,14 @@ void init_consts();') | ||||||
| 	d.writeln(cgen.fns.join_lines()) | 	d.writeln(cgen.fns.join_lines()) | ||||||
| 	d.writeln(cgen.consts.join_lines()) | 	d.writeln(cgen.consts.join_lines()) | ||||||
| 	d.writeln(cgen.thread_args.join_lines()) | 	d.writeln(cgen.thread_args.join_lines()) | ||||||
| 	if c.is_prof { | 	if c.pref.is_prof { | ||||||
| 		d.writeln('; // Prof counters:')
 | 		d.writeln('; // Prof counters:')
 | ||||||
| 		d.writeln(c.prof_counters()) | 		d.writeln(c.prof_counters()) | ||||||
| 	} | 	} | ||||||
| 	dd := d.str() | 	dd := d.str() | ||||||
| 	cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile
 | 	cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile
 | ||||||
| 	// if c.build_mode in [.default, .embed_vlib] {
 | 	// if c.build_mode in [.default, .embed_vlib] {
 | ||||||
| 	if c.build_mode == DEFAULT_MODE || c.build_mode == EMBED_VLIB { | 	if c.pref.build_mode == DEFAULT_MODE || c.pref.build_mode == EMBED_VLIB { | ||||||
| 		// vlib can't have `init_consts()`
 | 		// vlib can't have `init_consts()`
 | ||||||
| 		cgen.genln('void init_consts() { g_str_buf=malloc(1000); ${cgen.consts_init.join_lines()} }') | 		cgen.genln('void init_consts() { g_str_buf=malloc(1000); ${cgen.consts_init.join_lines()} }') | ||||||
| 		// _STR function can't be defined in vlib
 | 		// _STR function can't be defined in vlib
 | ||||||
|  | @ -339,10 +345,10 @@ string _STR_TMP(const char *fmt, ...) { | ||||||
| 	} | 	} | ||||||
| 	// Make sure the main function exists
 | 	// Make sure the main function exists
 | ||||||
| 	// Obviously we don't need it in libraries
 | 	// Obviously we don't need it in libraries
 | ||||||
| 	if c.build_mode != BUILD { | 	if c.pref.build_mode != BUILD { | ||||||
| 		if !c.table.main_exists() && !c.is_test { | 		if !c.table.main_exists() && !c.pref.is_test { | ||||||
| 			// It can be skipped in single file programs
 | 			// It can be skipped in single file programs
 | ||||||
| 			if c.is_script { | 			if c.pref.is_script { | ||||||
| 				//println('Generating main()...')
 | 				//println('Generating main()...')
 | ||||||
| 				cgen.genln('int main() { $cgen.fn_main; return 0; }') | 				cgen.genln('int main() { $cgen.fn_main; return 0; }') | ||||||
| 			} | 			} | ||||||
|  | @ -351,7 +357,7 @@ string _STR_TMP(const char *fmt, ...) { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// Generate `main` which calls every single test function
 | 		// Generate `main` which calls every single test function
 | ||||||
| 		else if c.is_test { | 		else if c.pref.is_test { | ||||||
| 			cgen.genln('int main() { init_consts();') | 			cgen.genln('int main() { init_consts();') | ||||||
| 			for v in c.table.fns { | 			for v in c.table.fns { | ||||||
| 				if v.name.starts_with('test_') { | 				if v.name.starts_with('test_') { | ||||||
|  | @ -361,7 +367,7 @@ string _STR_TMP(const char *fmt, ...) { | ||||||
| 			cgen.genln('return g_test_ok == 0; }') | 			cgen.genln('return g_test_ok == 0; }') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if c.is_live { | 	if c.pref.is_live { | ||||||
| 		cgen.genln(' int load_so(byteptr path) { | 		cgen.genln(' int load_so(byteptr path) { | ||||||
| 	 printf("load_so %s\\n", path); dlclose(live_lib); live_lib = dlopen(path, RTLD_LAZY); | 	 printf("load_so %s\\n", path); dlclose(live_lib); live_lib = dlopen(path, RTLD_LAZY); | ||||||
| 	 if (!live_lib) {puts("open failed"); exit(1); return 0;} | 	 if (!live_lib) {puts("open failed"); exit(1); return 0;} | ||||||
|  | @ -372,13 +378,13 @@ string _STR_TMP(const char *fmt, ...) { | ||||||
| 		cgen.genln('return 1; }') | 		cgen.genln('return 1; }') | ||||||
| 	} | 	} | ||||||
| 	cgen.save() | 	cgen.save() | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		c.log('flags=') | 		c.log('flags=') | ||||||
| 		println(c.table.flags) | 		println(c.table.flags) | ||||||
| 	} | 	} | ||||||
| 	c.cc() | 	c.cc() | ||||||
| 	if c.is_test || c.is_run { | 	if c.pref.is_test || c.pref.is_run { | ||||||
| 		if true || c.is_verbose { | 		if true || c.pref.is_verbose { | ||||||
| 			println('============ running $c.out_name ============')  | 			println('============ running $c.out_name ============')  | ||||||
| 		} | 		} | ||||||
| 		mut cmd := if c.out_name.starts_with('/') { | 		mut cmd := if c.out_name.starts_with('/') { | ||||||
|  | @ -405,32 +411,31 @@ string _STR_TMP(const char *fmt, ...) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (c mut V) cc() { | fn (c mut V) cc() { | ||||||
| 	ticks := time.ticks()  |  | ||||||
| 	linux_host := os.user_os() == 'linux' | 	linux_host := os.user_os() == 'linux' | ||||||
| 	c.log('cc() isprod=$c.is_prod outname=$c.out_name') | 	c.log('cc() isprod=$c.pref.is_prod outname=$c.out_name') | ||||||
| 	mut a := ['-w']// arguments for the C compiler
 | 	mut a := ['-w']// arguments for the C compiler
 | ||||||
| 	flags := c.table.flags.join(' ') | 	flags := c.table.flags.join(' ') | ||||||
| 	/*  | 	/*  | ||||||
| 	mut shared := '' | 	mut shared := '' | ||||||
| 	if c.is_so { | 	if c.pref.is_so { | ||||||
| 		a << '-shared'// -Wl,-z,defs'
 | 		a << '-shared'// -Wl,-z,defs'
 | ||||||
| 		c.out_name = c.out_name + '.so' | 		c.out_name = c.out_name + '.so' | ||||||
| 	} | 	} | ||||||
| */ | */ | ||||||
| 	if c.is_prod { | 	if c.pref.is_prod { | ||||||
| 		a << '-O2' | 		a << '-O2' | ||||||
| 	} | 	} | ||||||
| 	else { | 	else { | ||||||
| 		a << '-g' | 		a << '-g' | ||||||
| 	} | 	} | ||||||
| 	mut libs := ''// builtin.o os.o http.o etc
 | 	mut libs := ''// builtin.o os.o http.o etc
 | ||||||
| 	if c.build_mode == BUILD { | 	if c.pref.build_mode == BUILD { | ||||||
| 		a << '-c' | 		a << '-c' | ||||||
| 	} | 	} | ||||||
| 	else if c.build_mode == EMBED_VLIB { | 	else if c.pref.build_mode == EMBED_VLIB { | ||||||
| 		// 
 | 		// 
 | ||||||
| 	} | 	} | ||||||
| 	else if c.build_mode == DEFAULT_MODE { | 	else if c.pref.build_mode == DEFAULT_MODE { | ||||||
| 		libs = '$TmpPath/vlib/builtin.o' | 		libs = '$TmpPath/vlib/builtin.o' | ||||||
| 		if !os.file_exists(libs) { | 		if !os.file_exists(libs) { | ||||||
| 			println('`builtin.o` not found') | 			println('`builtin.o` not found') | ||||||
|  | @ -453,7 +458,7 @@ mut args := '' | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| */ | */ | ||||||
| 	if c.sanitize { | 	if c.pref.sanitize { | ||||||
| 		a << '-fsanitize=leak' | 		a << '-fsanitize=leak' | ||||||
| 	} | 	} | ||||||
| 	// Cross compiling linux
 | 	// Cross compiling linux
 | ||||||
|  | @ -485,11 +490,11 @@ mut args := '' | ||||||
| 		a << '-x objective-c' | 		a << '-x objective-c' | ||||||
| 	} | 	} | ||||||
| 	// Without these libs compilation will fail on Linux
 | 	// Without these libs compilation will fail on Linux
 | ||||||
| 	if c.os == LINUX && c.build_mode != BUILD { | 	if c.os == LINUX && c.pref.build_mode != BUILD { | ||||||
| 		a << '-lm -ldl -lpthread' | 		a << '-lm -ldl -lpthread' | ||||||
| 	} | 	} | ||||||
| 	// Find clang executable
 | 	// Find clang executable
 | ||||||
| 	fast_clang := 'ff'///usr/local/Cellar/llvm/8.0.0/bin/clang'
 | 	fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang' | ||||||
| 	args := a.join(' ') | 	args := a.join(' ') | ||||||
| 	mut cmd := if os.file_exists(fast_clang) { | 	mut cmd := if os.file_exists(fast_clang) { | ||||||
| 		'$fast_clang $args' | 		'$fast_clang $args' | ||||||
|  | @ -501,7 +506,7 @@ mut args := '' | ||||||
| 		cmd = 'gcc $args'  | 		cmd = 'gcc $args'  | ||||||
| 	}  | 	}  | ||||||
| 	// Print the C command
 | 	// Print the C command
 | ||||||
| 	if c.show_c_cmd || c.is_verbose { | 	if c.pref.show_c_cmd || c.pref.is_verbose { | ||||||
| 		println('\n==========\n$cmd\n=========\n') | 		println('\n==========\n$cmd\n=========\n') | ||||||
| 	} | 	} | ||||||
| 	// Run
 | 	// Run
 | ||||||
|  | @ -512,7 +517,7 @@ mut args := '' | ||||||
| 		panic('clang error') | 		panic('clang error') | ||||||
| 	} | 	} | ||||||
| 	// Link it if we are cross compiling and need an executable
 | 	// Link it if we are cross compiling and need an executable
 | ||||||
| 	if c.os == LINUX && !linux_host && c.build_mode != BUILD { | 	if c.os == LINUX && !linux_host && c.pref.build_mode != BUILD { | ||||||
| 		c.out_name = c.out_name.replace('.o', '') | 		c.out_name = c.out_name.replace('.o', '') | ||||||
| 		obj_file := c.out_name + '.o' | 		obj_file := c.out_name + '.o' | ||||||
| 		println('linux obj_file=$obj_file out_name=$c.out_name') | 		println('linux obj_file=$obj_file out_name=$c.out_name') | ||||||
|  | @ -531,10 +536,6 @@ mut args := '' | ||||||
| 		} | 		} | ||||||
| 		println('linux cross compilation done. resulting binary: "$c.out_name"') | 		println('linux cross compilation done. resulting binary: "$c.out_name"') | ||||||
| 	} | 	} | ||||||
| 	if c.show_c_cmd {  |  | ||||||
| 		diff := time.ticks() - ticks  |  | ||||||
| 		println('cc() took $diff ms ') |  | ||||||
| 	}  |  | ||||||
| 	//os.rm('$TmpPath/$c.out_name_c') 
 | 	//os.rm('$TmpPath/$c.out_name_c') 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -546,7 +547,7 @@ fn (c &V) v_files_from_dir(dir string) []string { | ||||||
| 		panic('$dir isn\'t a directory') | 		panic('$dir isn\'t a directory') | ||||||
| 	} | 	} | ||||||
| 	mut files := os.ls(dir) | 	mut files := os.ls(dir) | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		println('v_files_from_dir ("$dir")') | 		println('v_files_from_dir ("$dir")') | ||||||
| 	} | 	} | ||||||
| 	// println(files.len)
 | 	// println(files.len)
 | ||||||
|  | @ -617,7 +618,7 @@ fn (c mut V) add_user_v_files() { | ||||||
| 		println('No input .v files') | 		println('No input .v files') | ||||||
| 		exit(1) | 		exit(1) | ||||||
| 	} | 	} | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		c.log('user_files:') | 		c.log('user_files:') | ||||||
| 		println(user_files) | 		println(user_files) | ||||||
| 	} | 	} | ||||||
|  | @ -627,7 +628,7 @@ fn (c mut V) add_user_v_files() { | ||||||
| 		p.parse() | 		p.parse() | ||||||
| 	} | 	} | ||||||
| 	// Parse lib imports
 | 	// Parse lib imports
 | ||||||
| 	if c.build_mode == DEFAULT_MODE { | 	if c.pref.build_mode == DEFAULT_MODE { | ||||||
| 		for i := 0; i < c.table.imports.len; i++ { | 		for i := 0; i < c.table.imports.len; i++ { | ||||||
| 			pkg := c.table.imports[i] | 			pkg := c.table.imports[i] | ||||||
| 			vfiles := c.v_files_from_dir('$TmpPath/vlib/$pkg') | 			vfiles := c.v_files_from_dir('$TmpPath/vlib/$pkg') | ||||||
|  | @ -652,7 +653,7 @@ fn (c mut V) add_user_v_files() { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if c.is_verbose { | 	if c.pref.is_verbose { | ||||||
| 		c.log('imports:') | 		c.log('imports:') | ||||||
| 		println(c.table.imports) | 		println(c.table.imports) | ||||||
| 	} | 	} | ||||||
|  | @ -662,7 +663,7 @@ fn (c mut V) add_user_v_files() { | ||||||
| 		// If we are in default mode, we don't parse vlib .v files, but header .vh files in
 | 		// If we are in default mode, we don't parse vlib .v files, but header .vh files in
 | ||||||
| 		// TmpPath/vlib
 | 		// TmpPath/vlib
 | ||||||
| 		// These were generated by vfmt
 | 		// These were generated by vfmt
 | ||||||
| 		if c.build_mode == DEFAULT_MODE || c.build_mode == BUILD { | 		if c.pref.build_mode == DEFAULT_MODE || c.pref.build_mode == BUILD { | ||||||
| 			module_path = '$TmpPath/vlib/$pkg' | 			module_path = '$TmpPath/vlib/$pkg' | ||||||
| 		} | 		} | ||||||
| 		vfiles := c.v_files_from_dir(module_path) | 		vfiles := c.v_files_from_dir(module_path) | ||||||
|  | @ -695,13 +696,13 @@ fn get_arg(joined_args, arg, def string) string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (c &V) log(s string) { | fn (c &V) log(s string) { | ||||||
| 	if !c.is_verbose { | 	if !c.pref.is_verbose { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	println(s) | 	println(s) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn new_v(args []string) *V { | fn new_v(args[]string) *V { | ||||||
| 	mut dir := args.last() | 	mut dir := args.last() | ||||||
| 	if args.contains('run') { | 	if args.contains('run') { | ||||||
| 		dir = args[2] | 		dir = args[2] | ||||||
|  | @ -823,7 +824,25 @@ fn new_v(args []string) *V { | ||||||
| 			files << f | 			files << f | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	obfuscate := args.contains('-obf')  | 	obfuscate := args.contains('-obf') | ||||||
|  | 	pref := &Preferences { | ||||||
|  | 		is_test: is_test | ||||||
|  | 		is_script: is_script | ||||||
|  | 		is_so: args.contains('-shared') | ||||||
|  | 		is_play: args.contains('play') | ||||||
|  | 		is_prod: args.contains('-prod') | ||||||
|  | 		is_verbose: args.contains('-verbose') | ||||||
|  | 		obfuscate: obfuscate | ||||||
|  | 		is_prof: args.contains('-prof') | ||||||
|  | 		is_live: args.contains('-live') | ||||||
|  | 		sanitize: args.contains('-sanitize') | ||||||
|  | 		nofmt: args.contains('-nofmt') | ||||||
|  | 		show_c_cmd: args.contains('-show_c_cmd') | ||||||
|  | 		translated: args.contains('translated') | ||||||
|  | 		is_run: args.contains('run') | ||||||
|  | 		is_repl: args.contains('-repl') | ||||||
|  | 		build_mode: build_mode | ||||||
|  | 	} | ||||||
| 	return &V { | 	return &V { | ||||||
| 		os: _os | 		os: _os | ||||||
| 		out_name: out_name | 		out_name: out_name | ||||||
|  | @ -833,24 +852,9 @@ fn new_v(args []string) *V { | ||||||
| 		table: new_table(obfuscate) | 		table: new_table(obfuscate) | ||||||
| 		out_name: out_name | 		out_name: out_name | ||||||
| 		out_name_c: out_name_c | 		out_name_c: out_name_c | ||||||
| 		is_test: is_test |  | ||||||
| 		is_script: is_script |  | ||||||
| 		is_so: args.contains('-shared') |  | ||||||
| 		is_play: args.contains('play') |  | ||||||
| 		is_prod: args.contains('-prod') |  | ||||||
| 		is_verbose: args.contains('-verbose') |  | ||||||
| 		obfuscate: args.contains('-obf')  |  | ||||||
| 		is_prof: args.contains('-prof') |  | ||||||
| 		is_live: args.contains('-live') |  | ||||||
| 		sanitize: args.contains('-sanitize') |  | ||||||
| 		nofmt: args.contains('-nofmt') |  | ||||||
| 		show_c_cmd: args.contains('-show_c_cmd') |  | ||||||
| 		translated: args.contains('translated') |  | ||||||
| 		cgen: new_cgen(out_name_c) | 		cgen: new_cgen(out_name_c) | ||||||
| 		build_mode: build_mode |  | ||||||
| 		is_run: args.contains('run') |  | ||||||
| 		is_repl: args.contains('-repl') |  | ||||||
| 		vroot: lang_dir | 		vroot: lang_dir | ||||||
|  | 		pref: pref | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -48,19 +48,20 @@ mut: | ||||||
| 	assigned_type  string | 	assigned_type  string | ||||||
| 	tmp_cnt        int | 	tmp_cnt        int | ||||||
| 	// TODO all these options are copy-pasted from the V struct. Create a Settings struct instead?
 | 	// TODO all these options are copy-pasted from the V struct. Create a Settings struct instead?
 | ||||||
| 	is_test        bool | 	// is_test        bool
 | ||||||
| 	is_script      bool | 	is_script      bool | ||||||
| 	is_live        bool | 	pref           *Preferences // Setting and Preferences shared from V struct
 | ||||||
| 	is_so          bool | 	// is_live        bool
 | ||||||
| 	is_prof        bool | 	// is_so          bool
 | ||||||
| 	translated     bool | 	// is_prof        bool
 | ||||||
| 	is_prod        bool | 	// translated     bool
 | ||||||
| 	is_verbose     bool | 	// is_prod        bool
 | ||||||
| 	obfuscate      bool | 	// is_verbose     bool
 | ||||||
| 	is_play        bool | 	// obfuscate      bool
 | ||||||
| 	is_repl        bool | 	// is_play        bool
 | ||||||
|  | 	// is_repl        bool
 | ||||||
| 	builtin_pkg    bool | 	builtin_pkg    bool | ||||||
| 	build_mode     BuildMode | 	// build_mode     BuildMode
 | ||||||
| 	vh_lines       []string | 	vh_lines       []string | ||||||
| 	inside_if_expr bool | 	inside_if_expr bool | ||||||
| 	is_struct_init bool | 	is_struct_init bool | ||||||
|  | @ -90,18 +91,19 @@ fn (c mut V) new_parser(path string, run Pass) Parser { | ||||||
| 		table: c.table | 		table: c.table | ||||||
| 		cur_fn: EmptyFn | 		cur_fn: EmptyFn | ||||||
| 		cgen: c.cgen | 		cgen: c.cgen | ||||||
| 		is_test: c.is_test | 		// is_test: c.pref.is_test
 | ||||||
| 		is_script: (c.is_script && path == c.dir) | 		is_script: (c.pref.is_script && path == c.dir) | ||||||
| 		is_so: c.is_so | 		pref: c.pref | ||||||
|  | 		// is_so: c.is_so
 | ||||||
| 		os: c.os | 		os: c.os | ||||||
| 		is_prof: c.is_prof | 		// is_prof: c.is_prof
 | ||||||
| 		is_prod: c.is_prod | 		// is_prod: c.is_prod
 | ||||||
| 		is_play: c.is_play | 		// is_play: c.is_play
 | ||||||
| 		translated: c.translated | 		// translated: c.translated
 | ||||||
| 		obfuscate: c.obfuscate | 		// obfuscate: c.obfuscate
 | ||||||
| 		is_verbose: c.is_verbose | 		// is_verbose: c.is_verbose
 | ||||||
| 		build_mode: c.build_mode | 		// build_mode: c.build_mode
 | ||||||
| 		is_repl: c.is_repl | 		// is_repl: c.is_repl
 | ||||||
| 		run: run | 		run: run | ||||||
| 		vroot: c.vroot | 		vroot: c.vroot | ||||||
| 	} | 	} | ||||||
|  | @ -119,7 +121,7 @@ fn (p mut Parser) next() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (p &Parser) log(s string) { | fn (p &Parser) log(s string) { | ||||||
| 	if !p.is_verbose { | 	if !p.pref.is_verbose { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	println(s) | 	println(s) | ||||||
|  | @ -128,7 +130,7 @@ fn (p &Parser) log(s string) { | ||||||
| fn (p mut Parser) parse() { | fn (p mut Parser) parse() { | ||||||
| 	p.log('\nparse() run=$p.run file=$p.file_name tok=${p.strtok()}')// , "script_file=", script_file)
 | 	p.log('\nparse() run=$p.run file=$p.file_name tok=${p.strtok()}')// , "script_file=", script_file)
 | ||||||
| 	// `module main` is not required if it's a single file program
 | 	// `module main` is not required if it's a single file program
 | ||||||
| 	if p.is_script || p.is_test { | 	if p.is_script || p.pref.is_test { | ||||||
| 		p.pkg = 'main' | 		p.pkg = 'main' | ||||||
| 		// User may still specify `module main`
 | 		// User may still specify `module main`
 | ||||||
| 		if p.tok == PACKAGE { | 		if p.tok == PACKAGE { | ||||||
|  | @ -175,7 +177,7 @@ fn (p mut Parser) parse() { | ||||||
| 			// enum without a name, only allowed in code, translated from C
 | 			// enum without a name, only allowed in code, translated from C
 | ||||||
| 			// it's a very bad practice in C as well, but is used unfortunately (for example, by DOOM)
 | 			// it's a very bad practice in C as well, but is used unfortunately (for example, by DOOM)
 | ||||||
| 			// such fields are basically int consts
 | 			// such fields are basically int consts
 | ||||||
| 			else if p.translated { | 			else if p.pref.translated { | ||||||
| 				p.enum_decl('int') | 				p.enum_decl('int') | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
|  | @ -207,7 +209,7 @@ fn (p mut Parser) parse() { | ||||||
| 			// $if, $else
 | 			// $if, $else
 | ||||||
| 			p.comp_time() | 			p.comp_time() | ||||||
| 		case GLOBAL: | 		case GLOBAL: | ||||||
| 			if !p.translated && !p.builtin_pkg && !p.building_v() { | 			if !p.pref.translated && !p.builtin_pkg && !p.building_v() { | ||||||
| 				p.error('__global is only allowed in translated code') | 				p.error('__global is only allowed in translated code') | ||||||
| 			} | 			} | ||||||
| 			p.next() | 			p.next() | ||||||
|  | @ -230,7 +232,7 @@ fn (p mut Parser) parse() { | ||||||
| 			p.cgen.consts << g | 			p.cgen.consts << g | ||||||
| 		case EOF: | 		case EOF: | ||||||
| 			p.log('end of parse()') | 			p.log('end of parse()') | ||||||
| 			if p.is_script && !p.is_test { | 			if p.is_script && !p.pref.is_test { | ||||||
| 				p.cur_fn = MainFn | 				p.cur_fn = MainFn | ||||||
| 				p.check_unused_variables() | 				p.check_unused_variables() | ||||||
| 			} | 			} | ||||||
|  | @ -242,7 +244,7 @@ fn (p mut Parser) parse() { | ||||||
| 			return | 			return | ||||||
| 		default: | 		default: | ||||||
| 			// no `fn main`, add this "global" statement to cgen.fn_main
 | 			// no `fn main`, add this "global" statement to cgen.fn_main
 | ||||||
| 			if p.is_script && !p.is_test { | 			if p.is_script && !p.pref.is_test { | ||||||
| 				// cur_fn is empty since there was no fn main declared
 | 				// cur_fn is empty since there was no fn main declared
 | ||||||
| 				// we need to set it to save and find variables 
 | 				// we need to set it to save and find variables 
 | ||||||
| 				if p.first_run() { | 				if p.first_run() { | ||||||
|  | @ -253,7 +255,7 @@ fn (p mut Parser) parse() { | ||||||
| 				}  | 				}  | ||||||
| 				if p.cur_fn.name == '' { | 				if p.cur_fn.name == '' { | ||||||
| 					p.cur_fn = MainFn  | 					p.cur_fn = MainFn  | ||||||
| 					if p.is_repl { | 					if p.pref.is_repl { | ||||||
| 						p.cur_fn.clear_vars() | 						p.cur_fn.clear_vars() | ||||||
| 					} | 					} | ||||||
| 				}  | 				}  | ||||||
|  | @ -324,7 +326,7 @@ fn (p mut Parser) const_decl() { | ||||||
| 	for p.tok == NAME { | 	for p.tok == NAME { | ||||||
| 		// `Age = 20`
 | 		// `Age = 20`
 | ||||||
| 		mut name := p.check_name() | 		mut name := p.check_name() | ||||||
| 		if p.is_play && ! (name[0] >= `A` && name[0] <= `Z`) { | 		if p.pref.is_play && ! (name[0] >= `A` && name[0] <= `Z`) { | ||||||
| 			p.error('const name must be capitalized') | 			p.error('const name must be capitalized') | ||||||
| 		} | 		} | ||||||
| 		// Imported consts (like GL_TRIANGLES) dont need pkg prepended (gl__GL_TRIANGLES)
 | 		// Imported consts (like GL_TRIANGLES) dont need pkg prepended (gl__GL_TRIANGLES)
 | ||||||
|  | @ -407,7 +409,7 @@ fn (p mut Parser) struct_decl() { | ||||||
| 	// Get type name
 | 	// Get type name
 | ||||||
| 	p.next() | 	p.next() | ||||||
| 	mut name := p.check_name() | 	mut name := p.check_name() | ||||||
| 	if name.contains('_') && !p.translated { | 	if name.contains('_') && !p.pref.translated { | ||||||
| 		p.error('type names cannot contain `_`') | 		p.error('type names cannot contain `_`') | ||||||
| 	} | 	} | ||||||
| 	if is_interface && !name.ends_with('er') { | 	if is_interface && !name.ends_with('er') { | ||||||
|  | @ -521,7 +523,7 @@ fn (p mut Parser) struct_decl() { | ||||||
| 				is_method: true | 				is_method: true | ||||||
| 				receiver_typ: name | 				receiver_typ: name | ||||||
| 			} | 			} | ||||||
| 			//println('is interface. field=$field_name run=$p.run')
 | 			println('is interface. field=$field_name run=$p.run') | ||||||
| 			p.fn_args(mut interface_method) | 			p.fn_args(mut interface_method) | ||||||
| 			p.fspace() | 			p.fspace() | ||||||
| 			interface_method.typ = p.get_type()// method return type
 | 			interface_method.typ = p.get_type()// method return type
 | ||||||
|  | @ -670,13 +672,13 @@ fn (p mut Parser) error(s string) { | ||||||
| 		file_types.close() | 		file_types.close() | ||||||
| 		file_vars.close() | 		file_vars.close() | ||||||
| 	} | 	} | ||||||
| 	if !p.is_repl { | 	if !p.pref.is_repl { | ||||||
| 		println('pass=$p.run fn=`$p.cur_fn.name`') | 		println('pass=$p.run fn=`$p.cur_fn.name`') | ||||||
| 	} | 	} | ||||||
| 	p.cgen.save() | 	p.cgen.save() | ||||||
| 	// V git pull hint
 | 	// V git pull hint
 | ||||||
| 	cur_path := os.getwd() | 	cur_path := os.getwd() | ||||||
| 	if !p.is_repl && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){ | 	if !p.pref.is_repl && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){ | ||||||
| 		println('\n=========================') | 		println('\n=========================') | ||||||
| 		println('It looks like you are building V. It is being frequently updated every day.')  | 		println('It looks like you are building V. It is being frequently updated every day.')  | ||||||
| 		println('If you didn\'t modify the compiler\'s code, most likely there was a change that ') | 		println('If you didn\'t modify the compiler\'s code, most likely there was a change that ') | ||||||
|  | @ -797,7 +799,7 @@ fn (p mut Parser) get_type() string { | ||||||
| 				typ = p.prepend_pkg(typ) | 				typ = p.prepend_pkg(typ) | ||||||
| 			} | 			} | ||||||
| 			t = p.table.find_type(typ) | 			t = p.table.find_type(typ) | ||||||
| 			if t.name == '' && !p.translated && !p.first_run() && !typ.starts_with('[') { | 			if t.name == '' && !p.pref.translated && !p.first_run() && !typ.starts_with('[') { | ||||||
| 				println('get_type() bad type') | 				println('get_type() bad type') | ||||||
| 				// println('all registered types:')
 | 				// println('all registered types:')
 | ||||||
| 				// for q in p.table.types {
 | 				// for q in p.table.types {
 | ||||||
|  | @ -837,7 +839,7 @@ fn (p mut Parser) get_type() string { | ||||||
| 		return 'byte*' | 		return 'byte*' | ||||||
| 	} | 	} | ||||||
| 	if typ == 'voidptr' { | 	if typ == 'voidptr' { | ||||||
| 		//if !p.builtin_pkg && p.pkg != 'os' && p.pkg != 'gx' && p.pkg != 'gg' && !p.translated {
 | 		//if !p.builtin_pkg && p.pkg != 'os' && p.pkg != 'gx' && p.pkg != 'gg' && !p.pref.translated {
 | ||||||
| 			//p.error('voidptr can only be used in unsafe code')
 | 			//p.error('voidptr can only be used in unsafe code')
 | ||||||
| 		//}
 | 		//}
 | ||||||
| 		return 'void*' | 		return 'void*' | ||||||
|  | @ -936,7 +938,7 @@ fn (p mut Parser) statement(add_semi bool) string { | ||||||
| 	switch tok { | 	switch tok { | ||||||
| 	case NAME: | 	case NAME: | ||||||
| 		next := p.peek() | 		next := p.peek() | ||||||
| 		if p.is_verbose { | 		if p.pref.is_verbose { | ||||||
| 			println(next.str()) | 			println(next.str()) | ||||||
| 		} | 		} | ||||||
| 		// goto_label:
 | 		// goto_label:
 | ||||||
|  | @ -1028,7 +1030,7 @@ fn (p mut Parser) statement(add_semi bool) string { | ||||||
| fn (p mut Parser) assign_statement(v Var, ph int, is_map bool) { | fn (p mut Parser) assign_statement(v Var, ph int, is_map bool) { | ||||||
| 	p.log('assign_statement() name=$v.name tok=') | 	p.log('assign_statement() name=$v.name tok=') | ||||||
| 	tok := p.tok | 	tok := p.tok | ||||||
| 	if !v.is_mut && !v.is_arg && !p.translated && !v.is_global{ | 	if !v.is_mut && !v.is_arg && !p.pref.translated && !v.is_global{ | ||||||
| 		p.error('`$v.name` is immutable') | 		p.error('`$v.name` is immutable') | ||||||
| 	} | 	} | ||||||
| 	is_str := v.typ == 'string' | 	is_str := v.typ == 'string' | ||||||
|  | @ -1202,7 +1204,7 @@ fn (p mut Parser) name_expr() string { | ||||||
| 		p.next() | 		p.next() | ||||||
| 	} | 	} | ||||||
| 	if deref { | 	if deref { | ||||||
| 		if p.is_play && !p.builtin_pkg { | 		if p.pref.is_play && !p.builtin_pkg { | ||||||
| 			p.error('dereferencing is temporarily disabled on the playground, will be fixed soon') | 			p.error('dereferencing is temporarily disabled on the playground, will be fixed soon') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1428,11 +1430,11 @@ fn (p mut Parser) var_expr(v Var) string { | ||||||
| 	} | 	} | ||||||
| 	// a++ and a--
 | 	// a++ and a--
 | ||||||
| 	if p.tok == INC || p.tok == DEC { | 	if p.tok == INC || p.tok == DEC { | ||||||
| 		if !v.is_mut && !v.is_arg && !p.translated { | 		if !v.is_mut && !v.is_arg && !p.pref.translated { | ||||||
| 			p.error('`$v.name` is immutable') | 			p.error('`$v.name` is immutable') | ||||||
| 		} | 		} | ||||||
| 		if typ != 'int' { | 		if typ != 'int' { | ||||||
| 			if !p.translated && !is_number_type(typ) { | 			if !p.pref.translated && !is_number_type(typ) { | ||||||
| 				// if T.parent != 'int' {
 | 				// if T.parent != 'int' {
 | ||||||
| 				p.error('cannot ++/-- value of type `$typ`') | 				p.error('cannot ++/-- value of type `$typ`') | ||||||
| 			} | 			} | ||||||
|  | @ -1441,7 +1443,7 @@ fn (p mut Parser) var_expr(v Var) string { | ||||||
| 		p.fgen(p.tok.str()) | 		p.fgen(p.tok.str()) | ||||||
| 		p.next()// ++
 | 		p.next()// ++
 | ||||||
| 		// allow a := c++ in translated
 | 		// allow a := c++ in translated
 | ||||||
| 		if p.translated { | 		if p.pref.translated { | ||||||
| 			return p.index_expr(typ, fn_ph) | 			return p.index_expr(typ, fn_ph) | ||||||
| 			// return typ
 | 			// return typ
 | ||||||
| 		} | 		} | ||||||
|  | @ -1502,14 +1504,14 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { | ||||||
| 		next := p.peek() | 		next := p.peek() | ||||||
| 		modifying := next.is_assign() || next == INC || next == DEC | 		modifying := next.is_assign() || next == INC || next == DEC | ||||||
| 		is_vi := p.fileis('vi') | 		is_vi := p.fileis('vi') | ||||||
| 		if !p.builtin_pkg && !p.translated && modifying && !field.is_mut && !is_vi { | 		if !p.builtin_pkg && !p.pref.translated && modifying && !field.is_mut && !is_vi { | ||||||
| 			p.error('cannot modify immutable field `$field_name` (type `$typ.name`)') | 			p.error('cannot modify immutable field `$field_name` (type `$typ.name`)') | ||||||
| 		} | 		} | ||||||
| 		if !p.builtin_pkg && p.pkg != typ.pkg { | 		if !p.builtin_pkg && p.pkg != typ.pkg { | ||||||
| 		} | 		} | ||||||
| 		// if p.is_play && field.access_mod == PRIVATE && !p.builtin_pkg && p.pkg != typ.pkg {
 | 		// if p.pref.is_play && field.access_mod == PRIVATE && !p.builtin_pkg && p.pkg != typ.pkg {
 | ||||||
| 		// Don't allow `arr.data`
 | 		// Don't allow `arr.data`
 | ||||||
| 		if field.access_mod == PRIVATE && !p.builtin_pkg && !p.translated && p.pkg != typ.pkg { | 		if field.access_mod == PRIVATE && !p.builtin_pkg && !p.pref.translated && p.pkg != typ.pkg { | ||||||
| 			// println('$typ.name :: $field.name ')
 | 			// println('$typ.name :: $field.name ')
 | ||||||
| 			// println(field.access_mod)
 | 			// println(field.access_mod)
 | ||||||
| 			p.error('cannot refer to unexported field `$field_name` (type `$typ.name`)') | 			p.error('cannot refer to unexported field `$field_name` (type `$typ.name`)') | ||||||
|  | @ -1521,7 +1523,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { | ||||||
| 			// println('HOHOH')
 | 			// println('HOHOH')
 | ||||||
| 			// println(next.str())
 | 			// println(next.str())
 | ||||||
| 			// }
 | 			// }
 | ||||||
| 			if !field.is_mut && !p.translated && modifying { | 			if !field.is_mut && !p.pref.translated && modifying { | ||||||
| 				p.error('cannot modify public immutable field `$field_name` (type `$typ.name`)') | 				p.error('cannot modify public immutable field `$field_name` (type `$typ.name`)') | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1624,7 +1626,7 @@ fn (p mut Parser) index_expr(typ string, fn_ph int) string { | ||||||
| 				typ = 'void*' | 				typ = 'void*' | ||||||
| 			} | 			} | ||||||
| 			// No bounds check in translated from C code
 | 			// No bounds check in translated from C code
 | ||||||
| 			if p.translated { | 			if p.pref.translated { | ||||||
| 				// Cast void* to typ*: add (typ*) to the beginning of the assignment :
 | 				// Cast void* to typ*: add (typ*) to the beginning of the assignment :
 | ||||||
| 				// ((int*)a.data = ...
 | 				// ((int*)a.data = ...
 | ||||||
| 				p.cgen.set_placeholder(fn_ph, '(($typ*)(') | 				p.cgen.set_placeholder(fn_ph, '(($typ*)(') | ||||||
|  | @ -1705,7 +1707,7 @@ fn (p mut Parser) index_expr(typ string, fn_ph int) string { | ||||||
| 		return typ | 		return typ | ||||||
| 		return 'void' | 		return 'void' | ||||||
| 	} | 	} | ||||||
| 	// else if p.is_verbose && p.assigned_var != '' {
 | 	// else if p.pref.is_verbose && p.assigned_var != '' {
 | ||||||
| 	// p.error('didnt assign')
 | 	// p.error('didnt assign')
 | ||||||
| 	// }
 | 	// }
 | ||||||
| 	// m[key]. no =, just a getter
 | 	// m[key]. no =, just a getter
 | ||||||
|  | @ -1724,7 +1726,7 @@ fn (p mut Parser) index_expr(typ string, fn_ph int) string { | ||||||
| 			p.cgen.insert_before('$typ $tmp = $def; bool $tmp_ok = map_get($index_expr, & $tmp);') | 			p.cgen.insert_before('$typ $tmp = $def; bool $tmp_ok = map_get($index_expr, & $tmp);') | ||||||
| 		} | 		} | ||||||
| 		else if is_arr { | 		else if is_arr { | ||||||
| 			if p.translated { | 			if p.pref.translated { | ||||||
| 				p.gen('$index_expr ]') | 				p.gen('$index_expr ]') | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
|  | @ -1768,7 +1770,7 @@ fn (p mut Parser) expression() string { | ||||||
| 			// Get the value we are pushing
 | 			// Get the value we are pushing
 | ||||||
| 			p.gen(', (') | 			p.gen(', (') | ||||||
| 			// Immutable? Can we push?
 | 			// Immutable? Can we push?
 | ||||||
| 			if !p.expr_var.is_mut && !p.translated { | 			if !p.expr_var.is_mut && !p.pref.translated { | ||||||
| 				p.error('`$p.expr_var.name` is immutable (can\'t <<)') | 				p.error('`$p.expr_var.name` is immutable (can\'t <<)') | ||||||
| 			} | 			} | ||||||
| 			p.check_types(p.expression(), tmp_typ) | 			p.check_types(p.expression(), tmp_typ) | ||||||
|  | @ -1833,7 +1835,7 @@ fn (p mut Parser) expression() string { | ||||||
| 		} | 		} | ||||||
| 		// Vec + Vec
 | 		// Vec + Vec
 | ||||||
| 		else { | 		else { | ||||||
| 			if p.translated { | 			if p.pref.translated { | ||||||
| 				p.gen(tok_op.str() + ' /*doom hack*/')// TODO hack to fix DOOM's angle_t
 | 				p.gen(tok_op.str() + ' /*doom hack*/')// TODO hack to fix DOOM's angle_t
 | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
|  | @ -1845,7 +1847,7 @@ fn (p mut Parser) expression() string { | ||||||
| 			p.gen(')') | 			p.gen(')') | ||||||
| 		} | 		} | ||||||
| 		// Make sure operators are used with correct types
 | 		// Make sure operators are used with correct types
 | ||||||
| 		if !p.translated && !is_str && !is_num { | 		if !p.pref.translated && !is_str && !is_num { | ||||||
| 			T := p.table.find_type(typ) | 			T := p.table.find_type(typ) | ||||||
| 			if tok_op == PLUS { | 			if tok_op == PLUS { | ||||||
| 				if T.has_method('+') { | 				if T.has_method('+') { | ||||||
|  | @ -2122,7 +2124,7 @@ fn (p mut Parser) string_expr() { | ||||||
| 		// println('before format: "$str"')
 | 		// println('before format: "$str"')
 | ||||||
| 		f := format_str(str) | 		f := format_str(str) | ||||||
| 		// println('after format: "$str"')
 | 		// println('after format: "$str"')
 | ||||||
| 		if p.calling_c || p.translated { | 		if p.calling_c || p.pref.translated { | ||||||
| 			p.gen('"$f"') | 			p.gen('"$f"') | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
|  | @ -2182,7 +2184,7 @@ fn (p mut Parser) string_expr() { | ||||||
| 	} | 	} | ||||||
| 	// Don't allocate a new string, just print	it. TODO HACK PRINT OPT
 | 	// Don't allocate a new string, just print	it. TODO HACK PRINT OPT
 | ||||||
| 	cur_line := p.cgen.cur_line.trim_space() | 	cur_line := p.cgen.cur_line.trim_space() | ||||||
| 	if cur_line.contains('println(') && p.tok != PLUS && !p.is_prod && !cur_line.contains('string_add') { | 	if cur_line.contains('println(') && p.tok != PLUS && !p.pref.is_prod && !cur_line.contains('string_add') { | ||||||
| 		p.cgen.cur_line = cur_line.replace('println(', 'printf(') | 		p.cgen.cur_line = cur_line.replace('println(', 'printf(') | ||||||
| 		p.gen('$format\\n$args') | 		p.gen('$format\\n$args') | ||||||
| 		return | 		return | ||||||
|  | @ -2587,10 +2589,10 @@ fn (p mut Parser) chash() { | ||||||
| 		// p.cgen.nogen = true
 | 		// p.cgen.nogen = true
 | ||||||
| 	} | 	} | ||||||
| 	if hash == 'live' { | 	if hash == 'live' { | ||||||
| 		if p.is_so { | 		if p.pref.is_so { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		p.is_live = true | 		p.pref.is_live = true | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	if hash.starts_with('flag ') { | 	if hash.starts_with('flag ') { | ||||||
|  | @ -2635,7 +2637,7 @@ fn (p mut Parser) chash() { | ||||||
| 	else if hash.contains('embed') { | 	else if hash.contains('embed') { | ||||||
| 		pos := hash.index('embed') + 5 | 		pos := hash.index('embed') + 5 | ||||||
| 		file := hash.right(pos) | 		file := hash.right(pos) | ||||||
| 		if p.build_mode != DEFAULT_MODE { | 		if p.pref.build_mode != DEFAULT_MODE { | ||||||
| 			p.genln('#include $file') | 			p.genln('#include $file') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -3142,5 +3144,3 @@ fn (p mut Parser) fspace() { | ||||||
| fn (p mut Parser) fgenln(s string) { | fn (p mut Parser) fgenln(s string) { | ||||||
| 	//p.scanner.fgenln(s)
 | 	//p.scanner.fgenln(s)
 | ||||||
| } | } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -414,7 +414,7 @@ fn (t &Table) find_type(name string) *Type { | ||||||
| 
 | 
 | ||||||
| fn (p mut Parser) _check_types(got, expected string, throw bool) bool { | fn (p mut Parser) _check_types(got, expected string, throw bool) bool { | ||||||
| 	p.log('check types got="$got" exp="$expected"  ') | 	p.log('check types got="$got" exp="$expected"  ') | ||||||
| 	if p.translated { | 	if p.pref.translated { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	// Allow ints to be used as floats
 | 	// Allow ints to be used as floats
 | ||||||
|  | @ -443,7 +443,7 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool { | ||||||
| 	// Todo void* allows everything right now
 | 	// Todo void* allows everything right now
 | ||||||
| 	if got=='void*' || expected=='void*' { | 	if got=='void*' || expected=='void*' { | ||||||
| 		// if !p.builtin_pkg {
 | 		// if !p.builtin_pkg {
 | ||||||
| 		if p.is_play { | 		if p.pref.is_play { | ||||||
| 			return false | 			return false | ||||||
| 		} | 		} | ||||||
| 		return true | 		return true | ||||||
|  | @ -475,7 +475,7 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	// NsColor* return 0
 | 	// NsColor* return 0
 | ||||||
| 	if !p.is_play { | 	if !p.pref.is_play { | ||||||
| 		if expected.ends_with('*') && got == 'int' { | 		if expected.ends_with('*') && got == 'int' { | ||||||
| 			return true | 			return true | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue