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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										154
									
								
								compiler/main.v
								
								
								
								
							
							
						
						
									
										154
									
								
								compiler/main.v
								
								
								
								
							| 
						 | 
					@ -58,32 +58,38 @@ enum Pass {
 | 
				
			||||||
	main
 | 
						main
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
struct V {
 | 
					
 | 
				
			||||||
 | 
					struct Preferences {
 | 
				
			||||||
	mut:
 | 
						mut:
 | 
				
			||||||
		build_mode     BuildMode
 | 
							build_mode     BuildMode
 | 
				
			||||||
	os         Os // the OS to build for
 | 
					 | 
				
			||||||
		nofmt          bool // disable vfmt
 | 
							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 {
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
 | 
						os         Os // the OS to build for
 | 
				
			||||||
	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,7 +696,7 @@ 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)
 | 
				
			||||||
| 
						 | 
					@ -824,6 +825,24 @@ fn new_v(args []string) *V {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	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