diff --git a/vlib/compiler/comptime.v b/vlib/compiler/comptime.v index 49e6981a8e..443a360b39 100644 --- a/vlib/compiler/comptime.v +++ b/vlib/compiler/comptime.v @@ -202,7 +202,7 @@ fn (p mut Parser) chash() { else if hash.contains('embed') { pos := hash.index('embed') + 5 file := hash.right(pos) - if p.pref.build_mode != BuildMode.default_mode { + if p.pref.build_mode != .default_mode { p.genln('#include $file') } } @@ -210,10 +210,6 @@ fn (p mut Parser) chash() { // Move defines on top p.cgen.includes << '#$hash' } - else if hash == 'v' { - println('v script') - //p.v_script = true - } // Don't parse a non-JS V file (`#-js` flag) else if hash == '-js' { $if js { diff --git a/vlib/compiler/fn.v b/vlib/compiler/fn.v index 617ab6b317..c552079351 100644 --- a/vlib/compiler/fn.v +++ b/vlib/compiler/fn.v @@ -662,7 +662,12 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin //println('r=$receiver.typ RT=$receiver_type') if receiver.is_mut && !p.expr_var.is_mut { //println('$method_call recv=$receiver.name recv_mut=$receiver.is_mut') - p.error('`$p.expr_var.name` is immutable, declare it with `mut`') + if p.expr_var.is_for_var { + p.error('`$p.expr_var.name` is immutable, `for` variables' + + ' always are') + } else { + p.error('`$p.expr_var.name` is immutable, declare it with `mut`') + } } if !p.expr_var.is_changed { p.mark_var_changed(p.expr_var) diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index da6444b773..7ddfb22d2d 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -556,6 +556,15 @@ pub fn (v mut V) add_v_files_to_compile() { for file in v.get_user_files() { mut p := v.new_parser_from_file(file) p.parse(.imports) + if p.v_script { + v.log('imports0:') + println(v.table.imports) + println(v.files) + p.import_table.register_alias('os', 'os', 0) + p.table.imports << 'os' + p.table.register_module('os') + println('got v script') + } //if p.pref.autofree { p.scanner.text.free() free(p.scanner) } v.add_parser(p) } @@ -609,12 +618,13 @@ pub fn (v &V) get_builtin_files() []string { pub fn (v &V) get_user_files() []string { mut dir := v.dir v.log('get_v_files($dir)') - // Need to store user files separately, because they have to be added after libs, but we dont know - // which libs need to be added yet + // Need to store user files separately, because they have to be added after + // libs, but we dont know which libs need to be added yet mut user_files := []string if v.pref.is_test && v.pref.is_stats { - user_files << [v.vroot, 'vlib', 'benchmark', 'tests', 'always_imported.v'].join( os.path_separator ) + user_files << os.join(v.vroot, 'vlib', 'benchmark', 'tests', + 'always_imported.v') } // v volt/slack_test.v: compile all .v files to get the environment @@ -624,9 +634,9 @@ pub fn (v &V) get_user_files() []string { if is_test_with_imports { user_files << dir pos := dir.last_index(os.path_separator) - dir = dir.left(pos) + os.path_separator// TODO WHY IS THIS .neEDED? + dir = dir.left(pos) + os.path_separator// TODO why is this needed } - if dir.ends_with('.v') { + if dir.ends_with('.v') || dir.ends_with('.vsh') { // Just compile one file and get parent dir user_files << dir dir = dir.all_before(os.path_separator) @@ -792,7 +802,7 @@ pub fn new_v(args[]string) &V { */ } is_test := dir.ends_with('_test.v') - is_script := dir.ends_with('.v') + is_script := dir.ends_with('.v') || dir.ends_with('.vsh') if is_script && !os.file_exists(dir) { println('`$dir` does not exist') exit(1) diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 54bfd13e42..03f83a8d1d 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -148,7 +148,11 @@ fn (v mut V) new_parser(scanner &Scanner, id string) Parser { vroot: v.vroot local_vars: [Var{}].repeat(MaxLocalVars) import_table: v.table.get_file_import_table(id) + v_script: id.ends_with('.vsh') } + if p.v_script { + println('new_parser: V script') + } $if js { p.is_js = true } @@ -742,7 +746,7 @@ fn (p mut Parser) struct_decl() { } if p.tok == .key_mut { if is_mut { - p.error('structs can only have one `mut:`, all private key_mut fields have to be grouped') + p.error('structs can only have one `mut:`, all private mutable fields have to be grouped') } is_mut = true p.fmt_dec() @@ -1928,23 +1932,17 @@ fn (p mut Parser) name_expr() string { } return typ } - // Function (not method btw, methods are handled in dot()) - mut f := p.table.find_fn(name) or { - // We are in the second pass, that means this function was not defined, throw an error. + // Function (not method btw, methods are handled in `dot()`) + mut f := p.table.find_fn_is_script(name, p.v_script) or { + // We are in the second pass, that means this function was not defined, + // throw an error. if !p.first_pass() { - // V script? Try os module. - // TODO - if p.v_script { - //name = name.replace('main__', 'os__') - //f = p.table.find_fn(name) - } // check for misspelled function / variable / module suggested := p.identify_typo(name, p.import_table) if suggested != '' { p.error('undefined: `$name`. did you mean:$suggested') } // If orig_name is a mod, then printing undefined: `mod` tells us nothing - // if p.table.known_mod(orig_name) { if p.table.known_mod(orig_name) || p.import_table.known_alias(orig_name) { name = name.replace('__', '.') p.error('undefined: `$name`') @@ -1955,6 +1953,8 @@ fn (p mut Parser) name_expr() string { } else { p.next() // First pass, the function can be defined later. + // Only in const definitions? (since fn bodies are skipped + // in the first pass). return 'void' } return 'void' @@ -3560,6 +3560,8 @@ fn (p mut Parser) for_st() { typ: var_type ptr: typ.contains('*') is_changed: true + is_mut: false + is_for_var: true }) } } else { diff --git a/vlib/compiler/table.v b/vlib/compiler/table.v index 5acf8b3700..8f780b8ec0 100644 --- a/vlib/compiler/table.v +++ b/vlib/compiler/table.v @@ -105,6 +105,7 @@ mut: is_moved bool line_nr int token_idx int // this is a token index, which will be used by error reporting + is_for_var bool } struct Type { @@ -362,6 +363,22 @@ fn (t &Table) find_fn(name string) ?Fn { return none } +fn (t &Table) find_fn_is_script(name string, is_script bool) ?Fn { + mut f := t.fns[name] + if f.name.str != 0 { // TODO + return f + } + // V script? Try os module. + if is_script { + println('trying replace $name') + f = t.fns[name.replace('main__', 'os__')] + if f.name.str != 0 { + return f + } + } + return none +} + fn (t &Table) known_fn(name string) bool { _ = t.find_fn(name) or { return false } return true diff --git a/vlib/os/os.v b/vlib/os/os.v index df893b5274..c22c677a18 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -4,6 +4,8 @@ module os +import strings + #include #include #include @@ -864,3 +866,14 @@ pub fn mkdir_all(path string) { } } } + +// TODO use []string.join once ...string becomes "[]string" +pub fn join(base string, dirs ...string) string { + mut path := strings.new_builder(50) + path.write(base.trim_right('\\/')) + for d in dirs { + path.write(os.path_separator) + path.write(d) + } + return path.str() +}