From fe2d2bd2a3d86395fa906a639091d15f69e1e0f1 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 17 Aug 2019 22:19:37 +0300 Subject: [PATCH] fmt: remove trailing spaces --- compiler/fn.v | 284 ++++++------- compiler/jsgen.v | 16 +- compiler/main.v | 490 +++++++++++----------- compiler/parser.v | 932 +++++++++++++++++++++--------------------- compiler/scanner.v | 50 +-- compiler/table.v | 180 ++++---- compiler/token.v | 72 ++-- compiler/vfmt.v | 8 +- vlib/builtin/string.v | 66 +-- 9 files changed, 1049 insertions(+), 1049 deletions(-) diff --git a/compiler/fn.v b/compiler/fn.v index b3537b3f9b..03431c2f0b 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -4,7 +4,7 @@ module main -import strings +import strings const ( MaxLocalVars = 50 @@ -30,7 +30,7 @@ mut: returns_error bool is_decl bool // type myfn fn(int, int) defer_text []string - //gen_types []string + //gen_types []string } fn (f &Fn) find_var(name string) Var { @@ -114,12 +114,12 @@ fn new_fn(mod string, is_public bool) *Fn { // Function signatures are added to the top of the .c file in the first run. fn (p mut Parser) fn_decl() { p.fgen('fn ') - //defer { p.fgenln('\n') } - is_pub := p.tok == .key_pub - is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live - if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so { - println('INFO: run `v -live program.v` if you want to use [live] functions') - } + //defer { p.fgenln('\n') } + is_pub := p.tok == .key_pub + is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live + if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so { + println('INFO: run `v -live program.v` if you want to use [live] functions') + } if is_pub { p.next() } @@ -136,7 +136,7 @@ fn (p mut Parser) fn_decl() { is_mut := p.tok == .key_mut is_amp := p.tok == .amp if is_mut || is_amp { - p.check_space(p.tok) + p.check_space(p.tok) } receiver_typ = p.get_type() T := p.table.find_type(receiver_typ) @@ -159,7 +159,7 @@ fn (p mut Parser) fn_decl() { receiver_typ += '*' } p.check(.rpar) - p.fspace() + p.fspace() receiver := Var { name: receiver_name is_arg: true @@ -180,7 +180,7 @@ fn (p mut Parser) fn_decl() { f.name = p.check_name() } // 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 // is_sig := p.builtin_mod && p.pref.build_mode == default_mode // is_sig := p.pref.build_mode == default_mode && (p.builtin_mod || p.file.contains(LANG_TMP)) @@ -228,12 +228,12 @@ fn (p mut Parser) fn_decl() { p.error('only `T` is allowed as a generic type for now') } p.check(.gt) - if p.first_pass() { - p.table.register_generic_fn(f.name) - } else { - //gen_types := p.table.fn_gen_types(f.name) - //println(gen_types) - } + if p.first_pass() { + p.table.register_generic_fn(f.name) + } else { + //gen_types := p.table.fn_gen_types(f.name) + //println(gen_types) + } } // Args (...) p.fn_args(mut f) @@ -252,7 +252,7 @@ fn (p mut Parser) fn_decl() { typ = p.get_type() } // Translated C code can have empty functions (just definitions) - is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr + is_fn_header := !is_c && !is_sig && (p.pref.translated || p.pref.is_test) && p.tok != .lcbr if is_fn_header { f.is_decl = true } @@ -279,12 +279,12 @@ fn (p mut Parser) fn_decl() { dll_export_linkage := if p.os == .msvc && p.attr == 'live' && p.pref.is_so { '__declspec(dllexport) ' } else { - '' - } - if !p.is_vweb { + '' + } + if !p.is_vweb { p.cur_fn = f - } - // Generate `User_register()` instead of `register()` + } + // Generate `User_register()` instead of `register()` // Internally it's still stored as "register" in type User mut fn_name_cgen := p.table.cgen_name(f) // Start generation of the function body @@ -293,27 +293,27 @@ fn (p mut Parser) fn_decl() { if p.pref.obfuscate { p.genln('; // $f.name') } - // Generate this function's body for all generic types - if is_generic { - gen_types := p.table.fn_gen_types(f.name) + // Generate this function's body for all generic types + if is_generic { + gen_types := p.table.fn_gen_types(f.name) // Remember current scanner position, go back here for each type - // TODO remove this once tokens are cached in `new_parser()` - cur_pos := p.scanner.pos - cur_tok := p.tok - cur_lit := p.lit + // TODO remove this once tokens are cached in `new_parser()` + cur_pos := p.scanner.pos + cur_tok := p.tok + cur_lit := p.lit for gen_type in gen_types { - p.genln('$dll_export_linkage$typ ${fn_name_cgen}_$gen_type($str_args) {') - p.genln('// T start $p.pass ${p.strtok()}') - p.cur_gen_type = gen_type // TODO support more than T + p.genln('$dll_export_linkage$typ ${fn_name_cgen}_$gen_type($str_args) {') + p.genln('// T start $p.pass ${p.strtok()}') + p.cur_gen_type = gen_type // TODO support more than T p.statements() - p.scanner.pos = cur_pos - p.tok = cur_tok - p.lit = cur_lit - } - } - else { + p.scanner.pos = cur_pos + p.tok = cur_tok + p.lit = cur_lit + } + } + else { p.genln('$dll_export_linkage$typ $fn_name_cgen($str_args) {') - } + } } if is_fn_header { p.genln('$typ $fn_name_cgen($str_args);') @@ -329,11 +329,11 @@ fn (p mut Parser) fn_decl() { // struct declaration later will modify it instead of creating a new one. if p.first_pass() && receiver_t.name == '' { // println('fn decl !!!!!!! REG PH $receiver_typ') - p.table.register_type2(Type { + p.table.register_type2(Type { name: receiver_typ.replace('*', '') mod: p.mod is_placeholder: true - }) + }) } // f.idx = p.table.fn_cnt receiver_t.add_method(f) @@ -343,8 +343,8 @@ fn (p mut Parser) fn_decl() { p.table.register_fn(f) } if is_sig || p.first_pass() || is_live || is_fn_header || skip_main_in_test { - // First pass? Skip the body for now - // Look for generic calls. + // First pass? Skip the body for now + // Look for generic calls. if !is_sig && !is_fn_header { mut opened_scopes := 0 mut closed_scopes := 0 @@ -357,23 +357,23 @@ fn (p mut Parser) fn_decl() { closed_scopes++ } p.next() - // find `foo()` in function bodies and register generic types - // TODO remove this once tokens are cached + // find `foo()` in function bodies and register generic types + // TODO remove this once tokens are cached if p.tok == .gt && p.prev_tok == .name && p.prev_tok2 == .lt && p.scanner.text[p.scanner.pos-1] != `T` { temp_scanner_pos = p.scanner.pos - p.scanner.pos -= 3 - for p.scanner.pos > 0 && (is_name_char(p.scanner.text[p.scanner.pos]) || + p.scanner.pos -= 3 + for p.scanner.pos > 0 && (is_name_char(p.scanner.text[p.scanner.pos]) || p.scanner.text[p.scanner.pos] == `.` || - p.scanner.text[p.scanner.pos] == `<` ) { - p.scanner.pos-- - } - p.scanner.pos-- - p.next() - // Run the function in the firt pass to register the generic type - p.name_expr() + p.scanner.text[p.scanner.pos] == `<` ) { + p.scanner.pos-- + } + p.scanner.pos-- + p.next() + // Run the function in the firt pass to register the generic type + p.name_expr() p.scanner.pos = temp_scanner_pos - } + } if p.tok.is_decl() && !(p.prev_tok == .dot && p.tok == .key_type) { break } @@ -382,16 +382,16 @@ fn (p mut Parser) fn_decl() { if p.tok == .lsbr { break } - } + } } } // Live code reloading? Load all fns from .so if is_live && p.first_pass() && p.mod == 'main' { - //println('ADDING SO FN $fn_name_cgen') + //println('ADDING SO FN $fn_name_cgen') p.cgen.so_fns << fn_name_cgen fn_name_cgen = '(* $fn_name_cgen )' } - // Function definition that goes to the top of the C file. + // Function definition that goes to the top of the C file. mut fn_decl := '$dll_export_linkage$typ $fn_name_cgen($str_args)' if p.pref.obfuscate { fn_decl += '; // $f.name' @@ -422,15 +422,15 @@ fn (p mut Parser) fn_decl() { } // We are in live code reload mode, call the .so loader in bg if p.pref.is_live { - file_base := p.file_path.replace('.v', '') + file_base := p.file_path.replace('.v', '') if p.os != .windows && p.os != .msvc { so_name := file_base + '.so' - p.genln(' -load_so("$so_name"); + p.genln(' +load_so("$so_name"); pthread_t _thread_so; pthread_create(&_thread_so , NULL, &reload_so, NULL); ') } else { - so_name := file_base + if p.os == .msvc {'.dll'} else {'.so'} + so_name := file_base + if p.os == .msvc {'.dll'} else {'.so'} p.genln(' live_fn_mutex = CreateMutexA(0, 0, 0); load_so("$so_name"); @@ -454,20 +454,20 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0); cgen_name := p.table.cgen_name(f) f.defer_text[f.scope_level] = ' ${cgen_name}_time += time__ticks() - _PROF_START;' } - if is_generic { - // Don't need to generate body for the actual generic definition - p.cgen.nogen = true - } + if is_generic { + // Don't need to generate body for the actual generic definition + p.cgen.nogen = true + } p.statements_no_rcbr() - p.cgen.nogen = false + p.cgen.nogen = false // Print counting result after all statements in main if p.pref.is_prof && f.name == 'main' { p.genln(p.print_prof_counters()) } // Counting or not, always need to add defer before the end - if !p.is_vweb { + if !p.is_vweb { p.genln(f.defer_text[f.scope_level]) - } + } if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' { p.error('$f.name must return "$typ"') } @@ -485,16 +485,16 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0); // Make sure all vars in this function are used (only in main for now) // if p.builtin_mod || p.mod == 'os' ||p.mod=='http'{ if p.mod != 'main' { - if !is_generic { + if !is_generic { p.genln('}') - } + } return } p.check_unused_variables() p.cur_fn = EmptyFn - if !is_generic { + if !is_generic { p.genln('}') - } + } } fn (p mut Parser) check_unused_variables() { @@ -508,7 +508,7 @@ fn (p mut Parser) check_unused_variables() { } if !var.is_changed && var.is_mut && !p.pref.is_repl && !var.is_arg && !p.pref.translated && var.name != '_' { p.scanner.line_nr = var.line_nr - 1 - p.error('`$var.name` is declared as mutable, but it was never changed') + p.error('`$var.name` is declared as mutable, but it was never changed') } } } @@ -524,7 +524,7 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type // Normal function => just its name, method => TYPE_FN.name mut fn_name := f.name if f.is_method { - fn_name = receiver_type.replace('*', '') + '_' + f.name + fn_name = receiver_type.replace('*', '') + '_' + f.name //fn_name = '${receiver_type}_${f.name}' } // Generate tmp struct with args @@ -592,39 +592,39 @@ 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) { - if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod { + if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod { p.error('function `$f.name` is private') } p.calling_c = f.is_c if f.is_c && !p.builtin_mod { if f.name == 'free' { - p.error('use `free()` instead of `C.free()`') + p.error('use `free()` instead of `C.free()`') } else if f.name == 'malloc' { - p.error('use `malloc()` instead of `C.malloc()`') - } - } + p.error('use `malloc()` instead of `C.malloc()`') + } + } mut cgen_name := p.table.cgen_name(f) p.next() - mut gen_type := '' + mut gen_type := '' if p.tok == .lt { p.check(.lt) - gen_type = p.check_name() - // run => run_App + gen_type = p.check_name() + // run => run_App if gen_type == 'T' && p.cur_gen_type != '' { - gen_type = p.cur_gen_type - } - // `foo()` - // If we are in the first pass, we need to add `Bar` type to the generic function `foo`, - // so that generic `foo`s body can be generated for each type in the second pass. + gen_type = p.cur_gen_type + } + // `foo()` + // If we are in the first pass, we need to add `Bar` type to the generic function `foo`, + // so that generic `foo`s body can be generated for each type in the second pass. if p.first_pass() { - println('registering $gen_type in $f.name fname=$f.name') - p.table.register_generic_fn_type(f.name, gen_type) - // Function bodies are skipped in the first passed, we only need to register the generic type here. - return - } - cgen_name += '_' + gen_type + println('registering $gen_type in $f.name fname=$f.name') + p.table.register_generic_fn_type(f.name, gen_type) + // Function bodies are skipped in the first passed, we only need to register the generic type here. + return + } + cgen_name += '_' + gen_type p.check(.gt) - } + } // if p.pref.is_prof { // p.cur_fn.called_fns << cgen_name // } @@ -642,10 +642,10 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin 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_changed { - p.cur_fn.mark_var_changed(p.expr_var) - } + p.cur_fn.mark_var_changed(p.expr_var) + } // if receiver is key_mut or a ref (&), generate & for the first arg if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) { method_call += '& /* ? */' @@ -664,7 +664,7 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin } p.cgen.set_placeholder(method_ph, '$cast $method_call') } - // foo() + // foo() p.fn_call_args(mut f) p.gen(')') p.calling_c = false @@ -675,14 +675,14 @@ fn (p mut Parser) fn_call(f Fn, method_ph int, receiver_var, receiver_type strin // return an updated Fn object with args[] field set fn (p mut Parser) fn_args(f mut Fn) { p.check(.lpar) - defer { p.check(.rpar) } + defer { p.check(.rpar) } if f.is_interface { int_arg := Var { typ: f.receiver_typ } f.args << int_arg } - // `(int, string, int)` + // `(int, string, int)` // Just register fn arg types types_only := p.tok == .mul || (p.peek() == .comma && p.table.known_type(p.lit)) || p.peek() == .rpar// (int, string) if types_only { @@ -719,19 +719,19 @@ fn (p mut Parser) fn_args(f mut Fn) { } mut typ := p.get_type() if is_mut && is_primitive_type(typ) { - p.error('mutable arguments are only allowed for arrays, maps, and structs.' + - '\nreturn values instead: `foo(n mut int)` => `foo(n int) int`') - } + p.error('mutable arguments are only allowed for arrays, maps, and structs.' + + '\nreturn values instead: `foo(n mut int)` => `foo(n int) int`') + } for name in names { - if !p.first_pass() && !p.table.known_type(typ) { + if !p.first_pass() && !p.table.known_type(typ) { p.error('fn_args: unknown type $typ') } - if is_mut { + if is_mut { typ += '*' } v := Var { name: name - typ: typ + typ: typ is_arg: true is_mut: is_mut ptr: is_mut @@ -752,7 +752,7 @@ fn (p mut Parser) fn_args(f mut Fn) { } } -// foo *(1, 2, 3, mut bar)* +// foo *(1, 2, 3, mut bar)* fn (p mut Parser) fn_call_args(f mut Fn) *Fn { // p.gen('(') // println('fn_call_args() name=$f.name args.len=$f.args.len') @@ -795,72 +795,72 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn { break } ph := p.cgen.add_placeholder() - // `)` here means that not enough args were provided + // `)` here means that not enough args were provided if p.tok == .rpar { str_args := f.str_args(p.table)// TODO this is C args p.error('not enough arguments in call to `$f.name ($str_args)`') } - // If `arg` is mutable, the caller needs to provide `mut`: + // If `arg` is mutable, the caller needs to provide `mut`: // `mut numbers := [1,2,3]; reverse(mut numbers);` if arg.is_mut { if p.tok != .key_mut && p.tok == .name { - mut dots_example := 'mut $p.lit' + mut dots_example := 'mut $p.lit' if i > 0 { - dots_example = '.., ' + dots_example - } + dots_example = '.., ' + dots_example + } if i < f.args.len - 1 { - dots_example = dots_example + ',..' - } + dots_example = dots_example + ',..' + } p.error('`$arg.name` is a mutable argument, you need to provide `mut`: `$f.name($dots_example)`') } if p.peek() != .name { p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`') } p.check(.key_mut) - var_name := p.lit - v := p.cur_fn.find_var(var_name) - if v.name == '' { + var_name := p.lit + v := p.cur_fn.find_var(var_name) + if v.name == '' { p.error('`$arg.name` is a mutable argument, you need to provide a variable to modify: `$f.name(... mut a...)`') - } + } if !v.is_changed { - p.cur_fn.mark_var_changed(v) - } - } - p.expected_type = arg.typ + p.cur_fn.mark_var_changed(v) + } + } + p.expected_type = arg.typ typ := p.bool_expression() // Optimize `println`: replace it with `printf` to avoid extra allocations and - // function calls. `println(777)` => `printf("%d\n", 777)` - // (If we don't check for void, then V will compile `println(func())`) + // function calls. `println(777)` => `printf("%d\n", 777)` + // (If we don't check for void, then V will compile `println(func())`) if i == 0 && f.name == 'println' && typ != 'string' && typ != 'void' { T := p.table.find_type(typ) $if !windows { fmt := p.typ_to_fmt(typ, 0) if fmt != '' { p.cgen.resetln(p.cgen.cur_line.replace('println (', '/*opt*/printf ("' + fmt + '\\n", ')) - continue + continue } } if typ.ends_with('*') { p.cgen.set_placeholder(ph, 'ptr_str(') p.gen(')') - continue + continue } // Make sure this type has a `str()` method if !T.has_method('str') { - // Arrays have automatic `str()` methods + // Arrays have automatic `str()` methods if T.name.starts_with('array_') { - p.gen_array_str(mut T) + p.gen_array_str(mut T) p.cgen.set_placeholder(ph, '${typ}_str(') p.gen(')') - continue - } + continue + } error_msg := ('`$typ` needs to have method `str() string` to be printable') if T.fields.len > 0 { mut index := p.cgen.cur_line.len - 1 for index > 0 && p.cgen.cur_line[index] != ` ` { index-- } name := p.cgen.cur_line.right(index + 1) if name == '}' { - p.error(error_msg) + p.error(error_msg) } p.cgen.resetln(p.cgen.cur_line.left(index)) p.scanner.create_type_string(T, name) @@ -868,7 +868,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn { p.next() return p.fn_call_args(mut f) } - p.error(error_msg) + p.error(error_msg) } p.cgen.set_placeholder(ph, '${typ}_str(') p.gen(')') @@ -893,18 +893,18 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn { // TODO ptr hacks. DOOM hacks, fix please. if !got.contains('*') && expected.contains('*') && got != 'voidptr' { // Special case for mutable arrays. We can't `&` function results, - // have to use `(array[]){ expr }` hack. - if expected.starts_with('array_') && expected.ends_with('*') { - p.cgen.set_placeholder(ph, '& /*111*/ (array[]){') - p.gen('} ') - } + // have to use `(array[]){ expr }` hack. + if expected.starts_with('array_') && expected.ends_with('*') { + p.cgen.set_placeholder(ph, '& /*111*/ (array[]){') + p.gen('} ') + } // println('\ne:"$expected" got:"$got"') else if ! (expected == 'void*' && got == 'int') && ! (expected == 'byte*' && got.contains(']byte')) && ! (expected == 'byte*' && got == 'string') && - //! (expected == 'void*' && got == 'array_int') { - ! (expected == 'byte*' && got == 'byteptr') { - p.cgen.set_placeholder(ph, '& /*112 EXP:"$expected" GOT:"$got" */') + //! (expected == 'void*' && got == 'array_int') { + ! (expected == 'byte*' && got == 'byteptr') { + p.cgen.set_placeholder(ph, '& /*112 EXP:"$expected" GOT:"$got" */') } } } diff --git a/compiler/jsgen.v b/compiler/jsgen.v index 6d4329049e..b3ef5cd209 100644 --- a/compiler/jsgen.v +++ b/compiler/jsgen.v @@ -57,23 +57,23 @@ fn (p mut Parser) gen_json_for_type(typ Type) { p.table.register_fn(enc_fn) // Code gen decoder dec += ' -//$t $dec_fn.name(cJSON* root) { -Option $dec_fn.name(cJSON* root, $t* res) { -// $t res; +//$t $dec_fn.name(cJSON* root) { +Option $dec_fn.name(cJSON* root, $t* res) { +// $t res; if (!root) { const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { fprintf(stderr, "Error in decode() for $t error_ptr=: %%s\\n", error_ptr); -// printf("\\nbad js=%%s\\n", js.str); +// printf("\\nbad js=%%s\\n", js.str); return v_error(tos2(error_ptr)); } } ' // Code gen encoder enc += ' -cJSON* $enc_fn.name($t val) { +cJSON* $enc_fn.name($t val) { cJSON *o = cJSON_CreateObject(); -string res = tos2(""); +string res = tos2(""); ' // Handle arrays if t.starts_with('array_') { @@ -144,7 +144,7 @@ fn (p mut Parser) decode_array(array_type string) string { const cJSON *jsval = NULL; cJSON_ArrayForEach(jsval, root) { -$s +$s array__push(res, &val); } ' @@ -167,7 +167,7 @@ fn (p &Parser) encode_array(array_type string) string { o = cJSON_CreateArray(); for (int i = 0; i < val.len; i++){ cJSON_AddItemToArray(o, $fn_name( (($typ*)val.data)[i] )); -} +} ' } diff --git a/compiler/main.v b/compiler/main.v index b841c2b053..a77ec5358b 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -9,7 +9,7 @@ import time import strings const ( - Version = '0.1.18' + Version = '0.1.18' ) enum BuildMode { @@ -29,7 +29,7 @@ fn modules_path() string { } const ( - SupportedPlatforms = ['windows', 'mac', 'linux', 'freebsd', 'openbsd', 'netbsd', 'dragonfly', 'msvc'] + SupportedPlatforms = ['windows', 'mac', 'linux', 'freebsd', 'openbsd', 'netbsd', 'dragonfly', 'msvc'] ModPath = modules_path() ) @@ -37,11 +37,11 @@ enum OS { mac linux windows - freebsd - openbsd - netbsd - dragonfly - msvc + freebsd + openbsd + netbsd + dragonfly + msvc } enum Pass { @@ -70,7 +70,7 @@ mut: lang_dir string // "~/code/v" out_name string // "program.exe" vroot string - mod string // module being built with -lib + mod string // module being built with -lib } struct Preferences { @@ -93,7 +93,7 @@ mut: sanitize bool // use Clang's new "-fsanitize" option is_debuggable bool is_debug bool // keep compiled C files - no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers) + no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers) cflags string // Additional options which will be passed to the C compiler. // For example, passing -cflags -Os will cause the C compiler to optimize the generated binaries for size. // You could pass several -cflags XXX arguments. They will be merged with each other. @@ -114,32 +114,32 @@ fn main() { return } if 'translate' in args { - println('Translating C to V will be available in V 0.3') - return - } + println('Translating C to V will be available in V 0.3') + return + } if 'up' in args { - update_v() - return - } + update_v() + return + } if 'get' in args { - println('use `v install` to install modules from vpm.vlang.io') - return - } + println('use `v install` to install modules from vpm.vlang.io') + return + } if args.join(' ').contains(' test v') { - test_v() - return - } + test_v() + return + } if 'install' in args { if args.len < 3 { println('usage: v install [module] [module] [...]') - return + return } names := args.slice(2, args.len) vexec := os.executable() vroot := os.dir(vexec) vget := '$vroot/tools/vget' if true { - //println('Building vget...') + //println('Building vget...') os.chdir(vroot + '/tools') _ := os.exec('$vexec -o $vget vget.v') or { panic(err) @@ -150,18 +150,18 @@ fn main() { panic(err) } return - } - // TODO quit if the compiler is too old + } + // TODO quit if the compiler is too old // u := os.file_last_mod_unix('v') // If there's no tmp path with current version yet, the user must be using a pre-built package // Copy the `vlib` directory to the tmp path. -/* - // TODO +/* + // TODO if !os.file_exists(TmpPath) && os.file_exists('vlib') { } -*/ +*/ // Just fmt and exit - if 'fmt' in args { + if 'fmt' in args { file := args.last() if !os.file_exists(file) { println('"$file" does not exist') @@ -174,13 +174,13 @@ fn main() { println('vfmt is temporarily disabled') return } - // v get sqlite - if 'get' in args { - // Create the modules directory if it's not there. - if !os.file_exists(ModPath) { + // v get sqlite + if 'get' in args { + // Create the modules directory if it's not there. + if !os.file_exists(ModPath) { os.mkdir(ModPath) - } - } + } + } // No args? REPL if args.len < 2 || (args.len == 2 && args[1] == '-') { run_repl() @@ -192,24 +192,24 @@ fn main() { println(args) } // Generate the docs and exit - if 'doc' in args { + if 'doc' in args { // v.gen_doc_html_for_module(args.last()) exit(0) } - + if 'run' in args { // always recompile for now, too error prone to skip recompilation otherwise // for example for -repl usage, especially when piping lines to v - v.compile() + v.compile() v.run_compiled_executable_and_exit() } - + v.compile() - + if v.pref.is_test { v.run_compiled_executable_and_exit() } - + } fn (v mut V) compile() { @@ -227,7 +227,7 @@ fn (v mut V) compile() { } // First pass (declarations) for file in v.files { - mut p := v.new_parser(file, Pass.decl) + mut p := v.new_parser(file, Pass.decl) p.parse() } // Main pass @@ -238,13 +238,13 @@ fn (v mut V) compile() { if v.pref.is_debug { cgen.genln('#define VDEBUG (1) ') } - cgen.genln(' -#include // TODO remove all these includes, define all function signatures and types manually + cgen.genln(' +#include // TODO remove all these includes, define all function signatures and types manually #include #include -#include // for va_list -#include // int64_t etc -#include // memcpy +#include // for va_list +#include // int64_t etc +#include // memcpy #define STRUCT_DEFAULT_VALUE {} #define EMPTY_STRUCT_DECLARATION @@ -255,7 +255,7 @@ fn (v mut V) compile() { #define WIN32_LEAN_AND_MEAN #include -// must be included after +// must be included after #include #include // _waccess @@ -285,10 +285,10 @@ void pthread_mutex_unlock(HANDLE *m) { ReleaseMutex(*m); } #else -#include -#endif +#include +#endif -//================================== TYPEDEFS ================================*/ +//================================== TYPEDEFS ================================*/ typedef unsigned char byte; typedef unsigned int uint; @@ -302,38 +302,38 @@ typedef uint16_t u16; typedef uint8_t u8; typedef uint32_t rune; typedef float f32; -typedef double f64; +typedef double f64; typedef unsigned char* byteptr; typedef int* intptr; typedef void* voidptr; typedef struct array array; typedef struct map map; -typedef array array_string; -typedef array array_int; -typedef array array_byte; -typedef array array_uint; -typedef array array_float; -typedef array array_f32; -typedef array array_f64; -typedef map map_int; -typedef map map_string; +typedef array array_string; +typedef array array_int; +typedef array array_byte; +typedef array array_uint; +typedef array array_float; +typedef array array_f32; +typedef array array_f64; +typedef map map_int; +typedef map map_string; #ifndef bool typedef int bool; #define true 1 #define false 0 #endif -//============================== HELPER C MACROS =============================*/ +//============================== HELPER C MACROS =============================*/ #define _PUSH(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push(arr, &tmp);} #define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push_many(arr, tmp.data, tmp.len);} -#define _IN(typ, val, arr) array_##typ##_contains(arr, val) -#define _IN_MAP(val, m) map__exists(m, val) -#define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type)) +#define _IN(typ, val, arr) array_##typ##_contains(arr, val) +#define _IN_MAP(val, m) map__exists(m, val) +#define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type)) -//================================== GLOBALS =================================*/ -//int V_ZERO = 0; -byteptr g_str_buf; +//================================== GLOBALS =================================*/ +//int V_ZERO = 0; +byteptr g_str_buf; int load_so(byteptr); void reload_so(); void init_consts();') @@ -341,14 +341,14 @@ void init_consts();') if v.os != .windows && v.os != .msvc { if v.pref.is_so { cgen.genln('pthread_mutex_t live_fn_mutex;') - } + } if v.pref.is_live { cgen.genln('pthread_mutex_t live_fn_mutex = PTHREAD_MUTEX_INITIALIZER;') } } else { if v.pref.is_so { cgen.genln('HANDLE live_fn_mutex;') - } + } if v.pref.is_live { cgen.genln('HANDLE live_fn_mutex = 0;') } @@ -380,7 +380,7 @@ void init_consts();') //cgen.genln('i64 total_m = 0; // For counting total RAM allocated') cgen.genln('int g_test_ok = 1; ') if v.table.imports.contains('json') { - cgen.genln(' + cgen.genln(' #define js_get(object, key) cJSON_GetObjectItemCaseSensitive((object), (key)) ') } @@ -419,49 +419,49 @@ void init_consts();') cgen.lines.set(defs_pos, dd)// TODO `def.str()` doesn't compile // if v.build_mode in [.default, .embed_vlib] { if v.pref.build_mode == .default_mode || v.pref.build_mode == .embed_vlib { - mut consts_init_body := cgen.consts_init.join_lines() + mut consts_init_body := cgen.consts_init.join_lines() for imp in v.table.imports { if imp == 'http' { - consts_init_body += '\n http__init_module();' - } - } + consts_init_body += '\n http__init_module();' + } + } // vlib can't have `init_consts()` - cgen.genln('void init_consts() { + cgen.genln('void init_consts() { #ifdef _WIN32\n _setmode(_fileno(stdout), _O_U8TEXT); -SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_PROCESSED_OUTPUT | 0x0004); +SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_PROCESSED_OUTPUT | 0x0004); // ENABLE_VIRTUAL_TERMINAL_PROCESSING\n#endif\n g_str_buf=malloc(1000); -$consts_init_body +$consts_init_body }') // _STR function can't be defined in vlib cgen.genln(' string _STR(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); - size_t len = vsnprintf(0, 0, fmt, argptr) + 1; + size_t len = vsnprintf(0, 0, fmt, argptr) + 1; va_end(argptr); - byte* buf = malloc(len); + byte* buf = malloc(len); va_start(argptr, fmt); vsprintf(buf, fmt, argptr); va_end(argptr); -#ifdef DEBUG_ALLOC - puts("_STR:"); - puts(buf); -#endif +#ifdef DEBUG_ALLOC + puts("_STR:"); + puts(buf); +#endif return tos2(buf); } string _STR_TMP(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); - size_t len = vsnprintf(0, 0, fmt, argptr) + 1; + size_t len = vsnprintf(0, 0, fmt, argptr) + 1; va_end(argptr); va_start(argptr, fmt); vsprintf(g_str_buf, fmt, argptr); va_end(argptr); -#ifdef DEBUG_ALLOC - //puts("_STR_TMP:"); - //puts(g_str_buf); -#endif +#ifdef DEBUG_ALLOC + //puts("_STR_TMP:"); + //puts(g_str_buf); +#endif return tos2(g_str_buf); } @@ -480,13 +480,13 @@ string _STR_TMP(const char *fmt, ...) { } else { println('panic: function `main` is undeclared in the main module') - exit(1) + exit(1) } } // Generate `main` which calls every single test function else if v.pref.is_test { cgen.genln('int main() { init_consts();') - for key, f in v.table.fns { + for key, f in v.table.fns { if f.name.starts_with('test_') { cgen.genln('$f.name();') } @@ -494,13 +494,13 @@ string _STR_TMP(const char *fmt, ...) { cgen.genln('return g_test_ok == 0; }') } } - // Hot code reloading + // Hot code reloading if v.pref.is_live { - file := v.dir - file_base := v.dir.replace('.v', '') - so_name := file_base + '.so' - // Need to build .so file before building the live application - // The live app needs to load this .so file on initialization. + file := v.dir + file_base := v.dir.replace('.v', '') + so_name := file_base + '.so' + // Need to build .so file before building the live application + // The live app needs to load this .so file on initialization. mut vexe := os.args[0] if os.user_os() == 'windows' { @@ -518,7 +518,7 @@ string _STR_TMP(const char *fmt, ...) { debug = '-debug' } - os.system('$vexe $msvc $debug -o $file_base -shared $file') + os.system('$vexe $msvc $debug -o $file_base -shared $file') cgen.genln(' void lfnmutex_print(char *s){ @@ -537,12 +537,12 @@ void* live_lib=0; int load_so(byteptr path) { char cpath[1024]; sprintf(cpath,"./%s", path); - //printf("load_so %s\\n", cpath); + //printf("load_so %s\\n", cpath); if (live_lib) dlclose(live_lib); live_lib = dlopen(cpath, RTLD_LAZY); if (!live_lib) { - puts("open failed"); - exit(1); + puts("open failed"); + exit(1); return 0; } ') @@ -570,7 +570,7 @@ int load_so(byteptr path) { } } - cgen.genln('return 1; + cgen.genln('return 1; } int _live_reloads = 0; @@ -603,13 +603,13 @@ void reload_so() { if( !os__file_exists(tos2(new_so_name)) ) { fprintf(stderr, "Errors while compiling $file\\n"); - continue; + continue; } - + lfnmutex_print("reload_so locking..."); pthread_mutex_lock(&live_fn_mutex); lfnmutex_print("reload_so locked"); - + live_lib = 0; // hack: force skipping dlclose/1, the code may be still used... load_so(new_so_name); #ifndef _WIN32 @@ -618,28 +618,28 @@ void reload_so() { _unlink(new_so_name); #endif //if(0 == rename(new_so_name, "${so_name}")){ - // load_so("${so_name}"); + // load_so("${so_name}"); //} - lfnmutex_print("reload_so unlocking..."); - pthread_mutex_unlock(&live_fn_mutex); + lfnmutex_print("reload_so unlocking..."); + pthread_mutex_unlock(&live_fn_mutex); lfnmutex_print("reload_so unlocked"); } - time__sleep_ms(100); + time__sleep_ms(100); } } -' ) +' ) } if v.pref.is_so { cgen.genln(' int load_so(byteptr path) { return 0; }') - } + } cgen.save() if v.pref.is_verbose { v.log('flags=') println(v.table.flags) - } + } v.cc() } @@ -660,8 +660,8 @@ fn final_target_out_name(out_name string) string { fn (v V) run_compiled_executable_and_exit() { if v.pref.is_verbose { - println('============ running $v.out_name ============') - } + println('============ running $v.out_name ============') + } mut cmd := final_target_out_name(v.out_name).replace('.exe','') if os.args.len > 3 { cmd += ' ' + os.args.right(3).join(' ') @@ -671,14 +671,14 @@ fn (v V) run_compiled_executable_and_exit() { if ret != 0 { exit(1) } - } + } if v.pref.is_run { ret := os.system(cmd) - // TODO: make the runner wrapping as transparent as possible - // (i.e. use execve when implemented). For now though, the runner - // just returns the same exit code as the child process + // TODO: make the runner wrapping as transparent as possible + // (i.e. use execve when implemented). For now though, the runner + // just returns the same exit code as the child process // (see man system, man 2 waitpid: C macro WEXITSTATUS section) - exit( ret >> 8 ) + exit( ret >> 8 ) } exit(0) } @@ -700,7 +700,7 @@ fn (c mut V) cc_windows_cross() { libs = '"$ModPath/vlib/builtin.o"' if !os.file_exists(libs) { println('`builtin.o` not found') - exit(1) + exit(1) } for imp in c.table.imports { libs += ' "$ModPath/vlib/${imp}.o"' @@ -715,13 +715,13 @@ fn (c mut V) cc_windows_cross() { } } println('Cross compiling for Windows...') - winroot := '$ModPath/winroot' + winroot := '$ModPath/winroot' if !os.dir_exists(winroot) { - winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip' - println('"$winroot" not found. Download it from $winroot_url and save in $ModPath') - exit(1) - -} + winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip' + println('"$winroot" not found. Download it from $winroot_url and save in $ModPath') + exit(1) + +} mut obj_name := c.out_name obj_name = obj_name.replace('.exe', '') obj_name = obj_name.replace('.o.o', '.o') @@ -731,37 +731,37 @@ fn (c mut V) cc_windows_cross() { println(cmd) } if os.system(cmd) != 0 { - println('Cross compilation for Windows failed. Make sure you have clang installed.') - exit(1) + println('Cross compilation for Windows failed. Make sure you have clang installed.') + exit(1) } if c.pref.build_mode != .build { link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' + '$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' + '$winroot/lib/uuid.lib' if c.pref.show_c_cmd { - println(link_cmd) - } + println(link_cmd) + } - if os.system(link_cmd) != 0 { - println('Cross compilation for Windows failed. Make sure you have lld linker installed.') - exit(1) -} + if os.system(link_cmd) != 0 { + println('Cross compilation for Windows failed. Make sure you have lld linker installed.') + exit(1) +} // os.rm(obj_name) } println('Done!') } fn (v mut V) cc() { - // Cross compiling for Windows + // Cross compiling for Windows if v.os == .windows { - $if !windows { - v.cc_windows_cross() - return - } - } - $if windows { + $if !windows { + v.cc_windows_cross() + return + } + } + $if windows { if v.os == .msvc { - v.cc_msvc() + v.cc_msvc() return } } @@ -783,7 +783,7 @@ fn (v mut V) cc() { } if v.pref.is_live || v.pref.is_so { // See 'man dlopen', and test running a GUI program compiled with -live - if (v.os == .linux || os.user_os() == 'linux'){ + if (v.os == .linux || os.user_os() == 'linux'){ a << '-rdynamic' } if (v.os == .mac || os.user_os() == 'mac'){ @@ -795,7 +795,7 @@ fn (v mut V) cc() { a << '-c' } else if v.pref.build_mode == .embed_vlib { - // + // } else if v.pref.build_mode == .default_mode { libs = '"$ModPath/vlib/builtin.o"' @@ -811,8 +811,8 @@ fn (v mut V) cc() { } } // -I flags - /* -mut args := '' + /* +mut args := '' for flag in v.table.flags { if !flag.starts_with('-l') { args += flag @@ -856,14 +856,14 @@ mut args := '' a << '-x objective-c' } // Without these libs compilation will fail on Linux - // || os.user_os() == 'linux' + // || os.user_os() == 'linux' if v.pref.build_mode != .build && (v.os == .linux || v.os == .freebsd || v.os == .openbsd || - v.os == .netbsd || v.os == .dragonfly) { - a << '-lm -lpthread ' + v.os == .netbsd || v.os == .dragonfly) { + a << '-lm -lpthread ' // -ldl is a Linux only thing. BSDs have it in libc. if v.os == .linux { - a << ' -ldl ' - } + a << ' -ldl ' + } } if v.os == .windows { a << '-DUNICODE -D_UNICODE' @@ -878,7 +878,7 @@ mut args := '' mut cmd := ('cc $args') // TODO fix $if after 'string' //} $if windows { - cmd = 'gcc $args' + cmd = 'gcc $args' } if v.out_name.ends_with('.c') { os.mv( '.$v.out_name_c', v.out_name ) @@ -888,8 +888,8 @@ mut args := '' if v.pref.show_c_cmd || v.pref.is_verbose { println('\n==========') println(cmd) - } - ticks := time.ticks() + } + ticks := time.ticks() _ := os.exec(cmd) or { if v.pref.is_debug { println(err) @@ -902,10 +902,10 @@ mut args := '' panic('C error. This should never happen. ' + 'Please create a GitHub issue: https://github.com/vlang/v/issues/new/choose') } - diff := time.ticks() - ticks + diff := time.ticks() - ticks // Print the C command if v.pref.show_c_cmd || v.pref.is_verbose { - println('cc took $diff ms') + println('cc took $diff ms') println('=========\n') } // Link it if we are cross compiling and need an executable @@ -928,8 +928,8 @@ mut args := '' println('linux cross compilation done. resulting binary: "$v.out_name"') } if !v.pref.is_debug && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' { - os.rm('.$v.out_name_c') - } + os.rm('.$v.out_name_c') + } } fn (v &V) v_files_from_dir(dir string) []string { @@ -954,15 +954,15 @@ fn (v &V) v_files_from_dir(dir string) []string { if file.ends_with('_win.v') && (v.os != .windows && v.os != .msvc) { continue } - if file.ends_with('_lin.v') && v.os != .linux { + if file.ends_with('_lin.v') && v.os != .linux { continue } - if file.ends_with('_mac.v') && v.os != .mac { + if file.ends_with('_mac.v') && v.os != .mac { continue - } + } if file.ends_with('_nix.v') && (v.os == .windows || v.os == .msvc) { - continue - } + continue + } res << '$dir/$file' } return res @@ -1015,7 +1015,7 @@ fn (v mut V) add_v_files_to_compile() { p.parse() } // Parse lib imports -/* +/* if v.pref.build_mode == .default_mode { // strange ( for mod in v.table.imports ) dosent loop all items // for mod in v.table.imports { @@ -1035,12 +1035,12 @@ fn (v mut V) add_v_files_to_compile() { } } else { -*/ +*/ // strange ( for mod in v.table.imports ) dosent loop all items // for mod in v.table.imports { for i := 0; i < v.table.imports.len; i++ { mod := v.table.imports[i] - import_path := v.find_module_path(mod) + import_path := v.find_module_path(mod) vfiles := v.v_files_from_dir(import_path) if vfiles.len == 0 { panic('cannot import module $mod (no .v files in "$import_path").') @@ -1065,20 +1065,20 @@ fn (v mut V) add_v_files_to_compile() { } // add imports in correct order for mod in deps_resolved.imports() { - // Building this module? Skip. TODO it's a hack. + // Building this module? Skip. TODO it's a hack. if mod == v.mod { - continue - } - mod_path := v.find_module_path(mod) + continue + } + mod_path := v.find_module_path(mod) // If we are in default mode, we don't parse vlib .v files, but header .vh files in // TmpPath/vlib // These were generated by vfmt -/* +/* if v.pref.build_mode == .default_mode || v.pref.build_mode == .build { module_path = '$ModPath/vlib/$mod_p' } -*/ - vfiles := v.v_files_from_dir(mod_path) +*/ + vfiles := v.v_files_from_dir(mod_path) for file in vfiles { if !file in v.files { v.files << file @@ -1087,7 +1087,7 @@ fn (v mut V) add_v_files_to_compile() { } // add remaining files (not modules) for fit in v.table.file_imports { - //println('fit $fit.file_path') + //println('fit $fit.file_path') if !fit.file_path in v.files { v.files << fit.file_path } @@ -1140,31 +1140,31 @@ fn new_v(args[]string) *V { mut out_name := get_arg(joined_args, 'o', 'a.out') // build mode mut build_mode := BuildMode.default_mode - mut mod := '' + mut mod := '' //if args.contains('-lib') { - if joined_args.contains('build module ') { - build_mode = .build + if joined_args.contains('build module ') { + build_mode = .build // v -lib ~/v/os => os.o - mod = os.dir(dir) + mod = os.dir(dir) mod = mod.all_after('/') println('Building module "${mod}" dir="$dir"...') //out_name = '$TmpPath/vlib/${base}.o' out_name = mod + '.o' // Cross compiling? Use separate dirs for each os -/* +/* if target_os != os.user_os() { os.mkdir('$TmpPath/vlib/$target_os') out_name = '$TmpPath/vlib/$target_os/${base}.o' - println('target_os=$target_os user_os=${os.user_os()}') + println('target_os=$target_os user_os=${os.user_os()}') println('!Cross compiling $out_name') } -*/ +*/ } // TODO embed_vlib is temporarily the default mode. It's much slower. else if !args.contains('-embed_vlib') { build_mode = .embed_vlib } - // + // is_test := dir.ends_with('_test.v') is_script := dir.ends_with('.v') if is_script && !os.file_exists(dir) { @@ -1184,7 +1184,7 @@ fn new_v(args[]string) *V { // No OS specifed? Use current system if target_os == '' { $if linux { - _os = .linux + _os = .linux } $if mac { _os = .mac @@ -1193,16 +1193,16 @@ fn new_v(args[]string) *V { _os = .windows } $if freebsd { - _os = .freebsd + _os = .freebsd } $if openbsd { - _os = .openbsd + _os = .openbsd } $if netbsd { - _os = .netbsd + _os = .netbsd } $if dragonfly { - _os = .dragonfly + _os = .dragonfly } } else { @@ -1210,10 +1210,10 @@ fn new_v(args[]string) *V { case 'linux': _os = .linux case 'windows': _os = .windows case 'mac': _os = .mac - case 'freebsd': _os = .freebsd - case 'openbsd': _os = .openbsd - case 'netbsd': _os = .netbsd - case 'dragonfly': _os = .dragonfly + case 'freebsd': _os = .freebsd + case 'openbsd': _os = .openbsd + case 'netbsd': _os = .netbsd + case 'dragonfly': _os = .dragonfly case 'msvc': _os = .msvc } } @@ -1227,16 +1227,16 @@ fn new_v(args[]string) *V { 'option.v', ] // Location of all vlib files - vroot := os.dir(os.executable()) - //println('VROOT=$vroot') - // v.exe's parent directory should contain vlib + vroot := os.dir(os.executable()) + //println('VROOT=$vroot') + // v.exe's parent directory should contain vlib if os.dir_exists(vroot) && os.dir_exists(vroot + '/vlib/builtin') { - + } else { - println('vlib not found. It should be next to the V executable. ') + println('vlib not found. It should be next to the V executable. ') println('Go to https://vlang.io to install V.') - exit(1) - } + exit(1) + } mut out_name_c := out_name.all_after('/') + '.c' mut files := []string // Add builtin files @@ -1279,7 +1279,7 @@ fn new_v(args[]string) *V { is_repl: args.contains('-repl') build_mode: build_mode cflags: cflags - } + } if pref.is_so { out_name_c = out_name.all_after('/') + '_shared_lib.c' @@ -1290,14 +1290,14 @@ fn new_v(args[]string) *V { out_name: out_name files: files dir: dir - lang_dir: vroot + lang_dir: vroot table: new_table(obfuscate) out_name: out_name out_name_c: out_name_c cgen: new_cgen(out_name_c) - vroot: vroot + vroot: vroot pref: pref - mod: mod + mod: mod } } @@ -1307,13 +1307,13 @@ fn run_repl() []string { file := '.vrepl.v' temp_file := '.vrepl_temp.v' defer { - os.rm(file) - os.rm(temp_file) + os.rm(file) + os.rm(temp_file) os.rm(file.left(file.len - 2)) os.rm(temp_file.left(temp_file.len - 2)) - } + } mut lines := []string - vexe := os.args[0] + vexe := os.args[0] for { print('>>> ') mut line := os.get_raw_line() @@ -1331,7 +1331,7 @@ fn run_repl() []string { // but don't add this print call to the `lines` array, // so that it doesn't get called during the next print. if line.starts_with('print') { - source_code := lines.join('\n') + '\n' + line + source_code := lines.join('\n') + '\n' + line os.write_file(file, source_code) s := os.exec('$vexe run $file -repl') or { panic(err) @@ -1375,11 +1375,11 @@ Options: -prod Build an optimized executable. -o Place output into . -obf Obfuscate the resulting binary. - -show_c_cmd Print the full C compilation command and how much time it took. - -debug Leave a C file for debugging in .program.c. - -live Enable hot code reloading (required by functions marked with [live]). - fmt Run vfmt to format the source code. - up Update V. + -show_c_cmd Print the full C compilation command and how much time it took. + -debug Leave a C file for debugging in .program.c. + -live Enable hot code reloading (required by functions marked with [live]). + fmt Run vfmt to format the source code. + up Update V. run Build and execute a V program. You can add arguments after the file name. @@ -1388,13 +1388,13 @@ Files: ' ) -/* -- To disable automatic formatting: +/* +- To disable automatic formatting: v -nofmt file.v - To build a program with an embedded vlib (use this if you do not have prebuilt vlib libraries or if you -are working on vlib) -v -embed_vlib file.v +are working on vlib) +v -embed_vlib file.v */ fn env_vflags_and_os_args() []string { @@ -1413,48 +1413,48 @@ fn env_vflags_and_os_args() []string { } fn update_v() { - println('Updating V...') - vroot := os.dir(os.executable()) + println('Updating V...') + vroot := os.dir(os.executable()) s := os.exec('git -C "$vroot" pull --rebase origin master') or { panic(err) } - println(s.output) - $if windows { - os.mv('$vroot/v.exe', '$vroot/v_old.exe') + println(s.output) + $if windows { + os.mv('$vroot/v.exe', '$vroot/v_old.exe') s2 := os.exec('$vroot/make.bat') or { panic(err) } - println(s2.output) - } $else { + println(s2.output) + } $else { s2 := os.exec('make -C "$vroot"') or { panic(err) } - println(s2.output) - } -} + println(s2.output) + } +} fn test_v() { - vexe := os.args[0] - test_files := os.walk_ext('.', '_test.v') + vexe := os.args[0] + test_files := os.walk_ext('.', '_test.v') for file in test_files { - print(file + ' ') + print(file + ' ') if os.system('$vexe $file') != 0 { - println('failed') - exit(1) - } else { - println('OK') - } - } - println('\nBuilding examples...') - examples := os.walk_ext('examples', '.v') + println('failed') + exit(1) + } else { + println('OK') + } + } + println('\nBuilding examples...') + examples := os.walk_ext('examples', '.v') for file in examples { - print(file + ' ') + print(file + ' ') if os.system('$vexe $file') != 0 { - println('failed') - exit(1) - } else { - println('OK') - } - } -} + println('failed') + exit(1) + } else { + println('OK') + } + } +} diff --git a/compiler/parser.v b/compiler/parser.v index aeb50357ad..58c4885a4b 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -8,7 +8,7 @@ import ( os rand strings -) +) struct Var { mut: @@ -20,16 +20,16 @@ mut: args []Var // function args attr string // [json] etc is_mut bool - is_alloc bool + is_alloc bool ptr bool ref bool parent_fn string // Variables can only be defined in functions - mod string // module where this var is stored + mod string // module where this var is stored line_nr int access_mod AccessMod is_global bool // __global (translated from C only) is_used bool - is_changed bool + is_changed bool scope_level int } @@ -37,11 +37,11 @@ struct Parser { file_path string // "/home/user/hello.v" file_name string // "hello.v" file_platform string // ".v", "_win.v", "_nix.v", "_mac.v", "_lin.v" ... - file_pcguard string // When p.file_pcguard != '', it contains a - // C ifdef guard clause that must be put before + file_pcguard string // When p.file_pcguard != '', it contains a + // C ifdef guard clause that must be put before // the #include directives in the parsed .v file mut: - v *V + v *V scanner *Scanner // tokens []Token // TODO cache all tokens, right now they have to be scanned twice token_idx int @@ -52,8 +52,8 @@ mut: cgen *CGen table *Table import_table *FileImportTable // Holds imports for just the file being parsed - pass Pass - os OS + pass Pass + os OS mod string inside_const bool expr_var Var @@ -75,26 +75,26 @@ mut: vroot string is_c_struct_init bool can_chash bool - attr string - v_script bool // "V bash", import all os functions into global space - var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization - building_v bool - is_alloc bool // Whether current expression resulted in an allocation - cur_gen_type string // "App" to replace "T" in current generic function - is_vweb bool - is_sql bool - sql_i int // $1 $2 $3 - sql_params string // ("select * from users where id = $1", ***"100"***) + attr string + v_script bool // "V bash", import all os functions into global space + var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization + building_v bool + is_alloc bool // Whether current expression resulted in an allocation + cur_gen_type string // "App" to replace "T" in current generic function + is_vweb bool + is_sql bool + sql_i int // $1 $2 $3 + sql_params string // ("select * from users where id = $1", ***"100"***) } const ( EmptyFn = &Fn { } - MainFn= &Fn{name:'main'} + MainFn= &Fn{name:'main'} ) const ( MaxModuleDepth = 4 -) +) fn (v mut V) new_parser(path string, pass Pass) Parser { v.log('new_parser("$path")') @@ -111,7 +111,7 @@ fn (v mut V) new_parser(path string, pass Pass) Parser { } mut p := Parser { - v: v + v: v file_path: path file_name: path.all_after('/') file_platform: path_platform @@ -124,11 +124,11 @@ fn (v mut V) new_parser(path string, pass Pass) Parser { is_script: (v.pref.is_script && path == v.dir) pref: v.pref os: v.os - pass: pass + pass: pass vroot: v.vroot - building_v: !v.pref.is_repl && (path.contains('compiler/') || - path.contains('v/vlib')) - + building_v: !v.pref.is_repl && (path.contains('compiler/') || + path.contains('v/vlib')) + } v.cgen.line_directives = v.pref.is_debuggable @@ -142,19 +142,19 @@ fn (v mut V) new_parser(path string, pass Pass) Parser { fn (p mut Parser) next() { p.prev_tok2 = p.prev_tok p.prev_tok = p.tok - p.scanner.prev_tok = p.tok + p.scanner.prev_tok = p.tok res := p.scanner.scan() p.tok = res.tok p.lit = res.lit } fn (p &Parser) log(s string) { -/* +/* if !p.pref.is_verbose { return } println(s) -*/ +*/ } fn (p mut Parser) parse() { @@ -171,7 +171,7 @@ fn (p mut Parser) parse() { } else { p.check(.key_module) - p.fspace() + p.fspace() p.mod = p.check_name() } p.fgenln('\n') @@ -189,7 +189,7 @@ fn (p mut Parser) parse() { p.imports() } if p.table.imports.contains('builtin') { - p.error('module `builtin` cannot be imported') + p.error('module `builtin` cannot be imported') } // save file import table p.table.file_imports << *p.import_table @@ -205,9 +205,9 @@ fn (p mut Parser) parse() { else { // TODO remove imported consts from the language p.imports() - if p.tok != .key_import { - p.fgenln('') - } + if p.tok != .key_import { + p.fgenln('') + } } case Token.key_enum: p.next() @@ -242,7 +242,7 @@ fn (p mut Parser) parse() { case Token.lsbr: // `[` can only mean an [attribute] before a function // or a struct definition - p.attribute() + p.attribute() case Token.key_struct, Token.key_interface, Token.key_union, Token.lsbr: p.struct_decl() case Token.key_const: @@ -256,7 +256,7 @@ fn (p mut Parser) parse() { // $if, $else p.comp_time() case Token.key_global: - if !p.pref.translated && !p.pref.is_live && + if !p.pref.translated && !p.pref.is_live && !p.builtin_mod && !p.building_v { p.error('__global is only allowed in translated code') } @@ -276,7 +276,7 @@ fn (p mut Parser) parse() { g += p.cgen.end_tmp() } // p.genln('; // global') - g += '; // global' + g += '; // global' p.cgen.consts << g case Token.eof: p.log('end of parse()') @@ -286,8 +286,8 @@ fn (p mut Parser) parse() { } if false && !p.first_pass() && p.fileis('main.v') { out := os.create('/var/tmp/fmt.v') or { - panic('failed to create fmt.v') - } + panic('failed to create fmt.v') + } out.writeln(p.scanner.fmt_out.str()) out.close() } @@ -296,29 +296,29 @@ fn (p mut Parser) parse() { // no `fn main`, add this "global" statement to cgen.fn_main if p.is_script && !p.pref.is_test { // 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_pass() { if p.cur_fn.name == '' { - p.cur_fn = MainFn - } - return - } + p.cur_fn = MainFn + } + return + } if p.cur_fn.name == '' { - p.cur_fn = MainFn + p.cur_fn = MainFn if p.pref.is_repl { p.cur_fn.clear_vars() } - } + } mut start := p.cgen.lines.len p.statement(true) if p.cgen.lines[start - 1] != '' && p.cgen.fn_main != '' { start-- } - p.genln('') + p.genln('') end := p.cgen.lines.len lines := p.cgen.lines.slice(start, end) - //mut line := p.cgen.fn_main + lines.join('\n') - //line = line.trim_space() + //mut line := p.cgen.fn_main + lines.join('\n') + //line = line.trim_space() p.cgen.fn_main = p.cgen.fn_main + lines.join('\n') p.cgen.resetln('') for i := start; i < end; i++ { @@ -359,18 +359,18 @@ fn (p mut Parser) import_statement() { // submodule support mut depth := 1 for p.tok == .dot { - p.check(.dot) + p.check(.dot) submodule := p.check_name() mod_alias = submodule mod += '.' + submodule depth++ - if depth > MaxModuleDepth { - p.error('module depth of $MaxModuleDepth exceeded: $mod') + if depth > MaxModuleDepth { + p.error('module depth of $MaxModuleDepth exceeded: $mod') } } // aliasing (import encoding.base64 as b64) if p.tok == .key_as && p.peek() == .name { - p.check(.key_as) + p.check(.key_as) mod_alias = p.check_name() } // add import to file scope import table @@ -396,7 +396,7 @@ fn (p mut Parser) const_decl() { p.fspace() p.check(.lpar) p.fgenln('') - p.fmt_inc() + p.fmt_inc() for p.tok == .name { // `Age = 20` mut name := p.check_name() @@ -421,7 +421,7 @@ fn (p mut Parser) const_decl() { // cur_line has const's value right now. if it's just a number, then optimize generation: // output a #define so that we don't pollute the binary with unnecessary global vars if is_compile_time_const(p.cgen.cur_line) { - p.cgen.consts << '#define $name $p.cgen.cur_line' + p.cgen.consts << '#define $name $p.cgen.cur_line' p.cgen.resetln('') p.fgenln('') continue @@ -438,7 +438,7 @@ fn (p mut Parser) const_decl() { } p.fgenln('') } - p.fmt_dec() + p.fmt_dec() p.check(.rpar) p.fgenln('\n') p.inside_const = false @@ -491,7 +491,7 @@ fn (p mut Parser) struct_decl() { if p.tok == .lsbr { p.check(.lsbr) // `[interface:ParentInterface]` - is_objc = p.tok == .key_interface + is_objc = p.tok == .key_interface p.next() if is_objc { p.check(.colon) @@ -499,7 +499,7 @@ fn (p mut Parser) struct_decl() { } p.check(.rsbr) } - is_interface := p.tok == .key_interface + is_interface := p.tok == .key_interface is_union := p.tok == .key_union is_struct := p.tok == .key_struct p.fgen(p.tok.str() + ' ') @@ -512,14 +512,14 @@ fn (p mut Parser) struct_decl() { if is_interface && !name.ends_with('er') { p.error('interface names temporarily have to end with `er` (e.g. `Speaker`, `Reader`)') } - is_c := name == 'C' && p.tok == .dot + is_c := name == 'C' && p.tok == .dot if is_c { p.check(.dot) name = p.check_name() } if !is_c && !good_type_name(name) { - p.error('bad struct name, e.g. use `HttpRequest` instead of `HTTPRequest`') - } + p.error('bad struct name, e.g. use `HttpRequest` instead of `HTTPRequest`') + } // Specify full type name if !is_c && !p.builtin_mod && p.mod != 'main' { name = p.prepend_mod(name) @@ -568,15 +568,15 @@ fn (p mut Parser) struct_decl() { mut is_pub := false mut is_mut := false mut names := []string// to avoid dup names TODO alloc perf -/* - mut fmt_max_len := 0 +/* + mut fmt_max_len := 0 for field in typ.fields { if field.name.len > max_len { - fmt_max_len = field.name.len - } - } - println('fmt max len = $max_len nrfields=$typ.fields.len pass=$p.pass') -*/ + fmt_max_len = field.name.len + } + } + println('fmt max len = $max_len nrfields=$typ.fields.len pass=$p.pass') +*/ mut did_gen_something := false for p.tok != .rcbr { if p.tok == .key_pub { @@ -584,12 +584,12 @@ fn (p mut Parser) struct_decl() { p.error('structs can only have one `pub:`, all public fields have to be grouped') } is_pub = true - p.fmt_dec() + p.fmt_dec() p.check(.key_pub) if p.tok != .key_mut { p.check(.colon) } - p.fmt_inc() + p.fmt_inc() p.fgenln('') } if p.tok == .key_mut { @@ -597,12 +597,12 @@ fn (p mut Parser) struct_decl() { p.error('structs can only have one `mut:`, all private key_mut fields have to be grouped') } is_mut = true - p.fmt_dec() + p.fmt_dec() p.check(.key_mut) if p.tok != .key_mut { p.check(.colon) } - p.fmt_inc() + p.fmt_inc() p.fgenln('') } // if is_pub { @@ -618,7 +618,7 @@ fn (p mut Parser) struct_decl() { } if !is_c && p.mod != 'os' && contains_capital(field_name) { p.error('struct fields cannot contain uppercase letters, use snake_case instead') - } + } names << field_name // We are in an interface? // `run() string` => run is a method, not a struct field @@ -656,7 +656,7 @@ fn (p mut Parser) struct_decl() { if !is_ph && p.first_pass() { p.table.register_type2(typ) - //println('registering 1 nrfields=$typ.fields.len') + //println('registering 1 nrfields=$typ.fields.len') } p.check(.rcbr) @@ -686,14 +686,14 @@ fn (p mut Parser) enum_decl(_enum_name string) { } p.check(.lcbr) mut val := 0 - mut fields := []string + mut fields := []string for p.tok == .name { field := p.check_name() - fields << field + fields << field p.fgenln('') name := '${p.mod}__${enum_name}_$field' if p.pass == .main { - p.cgen.consts << '#define $name $val' + p.cgen.consts << '#define $name $val' } if p.tok == .comma { p.next() @@ -706,7 +706,7 @@ fn (p mut Parser) enum_decl(_enum_name string) { mod: p.mod parent: 'int' is_enum: true - enum_vals: fields + enum_vals: fields }) p.check(.rcbr) p.fgenln('\n') @@ -758,20 +758,20 @@ fn (p mut Parser) check(expected Token) { p.error(s) } if expected == .rcbr { - p.fmt_dec() + p.fmt_dec() } p.fgen(p.strtok()) // vfmt: increase indentation on `{` unless it's `{}` if expected == .lcbr && p.scanner.pos + 1 < p.scanner.text.len && p.scanner.text[p.scanner.pos + 1] != `}` { p.fgenln('') - p.fmt_inc() + p.fmt_inc() } p.next() -if p.scanner.line_comment != '' { +if p.scanner.line_comment != '' { //p.fgenln('// ! "$p.scanner.line_comment"') - //p.scanner.line_comment = '' -} + //p.scanner.line_comment = '' +} } fn (p mut Parser) error(s string) { @@ -779,9 +779,9 @@ fn (p mut Parser) error(s string) { if p.pref.is_debug { // os.write_to_file('/var/tmp/lang.types', '')//pes(p.table.types)) // os.write_to_file('/var/tmp/lang.vars', q.J(p.table.vars)) - os.write_file('fns.txt', p.table.debug_fns()) + os.write_file('fns.txt', p.table.debug_fns()) } - if p.pref.is_verbose || p.pref.is_debug { + if p.pref.is_verbose || p.pref.is_debug { println('pass=$p.pass fn=`$p.cur_fn.name`\n') } p.cgen.save() @@ -789,7 +789,7 @@ fn (p mut Parser) error(s string) { cur_path := os.getwd() if !p.pref.is_repl && !p.pref.is_test && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){ 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('lead to this error.') println('\nRun `git pull && make`, that will most likely fix it.') @@ -799,7 +799,7 @@ fn (p mut Parser) error(s string) { } // p.scanner.debug_tokens() // Print `[]int` instead of `array_int` in errors - p.scanner.error(s.replace('array_', '[]').replace('__', '.').replace('Option_', '?')) + p.scanner.error(s.replace('array_', '[]').replace('__', '.').replace('Option_', '?')) } fn (p &Parser) first_pass() bool { @@ -826,12 +826,12 @@ fn (p mut Parser) get_type() string { if debug { println('same line getting type') } - if p.tok == .name { + if p.tok == .name { f.typ = p.get_type() - } - else { + } + else { f.typ = 'void' - } + } // println('fn return typ=$f.typ') } else { @@ -877,30 +877,30 @@ fn (p mut Parser) get_type() string { p.check(.rsbr) } } - // map[string]int + // map[string]int if !p.builtin_mod && p.tok == .name && p.lit == 'map' { p.next() - p.check(.lsbr) - key_type := p.check_name() + p.check(.lsbr) + key_type := p.check_name() if key_type != 'string' { - p.error('maps only support string keys for now') - } - p.check(.rsbr) - val_type := p.get_type()// p.check_name() - typ = 'map_$val_type' + p.error('maps only support string keys for now') + } + p.check(.rsbr) + val_type := p.get_type()// p.check_name() + typ = 'map_$val_type' p.register_map(typ) - return typ - } - // + return typ + } + // for p.tok == .mul { mul = true nr_muls++ - p.check(.mul) + p.check(.mul) } if p.tok == .amp { mul = true nr_muls++ - p.check(.amp) + p.check(.amp) } typ += p.lit if !p.is_struct_init { @@ -932,7 +932,7 @@ fn (p mut Parser) get_type() string { if t.name == '' && !p.builtin_mod { // && !p.first_pass() { if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') && - !typ.starts_with('[') { + !typ.starts_with('[') { typ = p.prepend_mod(typ) } t = p.table.find_type(typ) @@ -1019,7 +1019,7 @@ fn (p mut Parser) statements_no_rcbr() string { } mut i := 0 mut last_st_typ := '' - for p.tok != .rcbr && p.tok != .eof && p.tok != .key_case && + for p.tok != .rcbr && p.tok != .eof && p.tok != .key_case && p.tok != .key_default && p.peek() != .arrow { // println(p.tok.str()) // p.print_tok() @@ -1042,7 +1042,7 @@ fn (p mut Parser) statements_no_rcbr() string { else { // p.check(.rcbr) } - //p.fmt_dec() + //p.fmt_dec() // println('close scope line=$p.scanner.line_nr') p.close_scope() return last_st_typ @@ -1060,15 +1060,15 @@ fn (p mut Parser) close_scope() { break } if false && !p.building_v && !v.is_mut && v.is_alloc { - if v.typ.starts_with('array_') { - p.genln('v_array_free($v.name); // close_scope free') - } - else if v.typ == 'string' { - p.genln('v_string_free($v.name); // close_scope free') - } + if v.typ.starts_with('array_') { + p.genln('v_array_free($v.name); // close_scope free') + } + else if v.typ == 'string' { + p.genln('v_string_free($v.name); // close_scope free') + } else if v.ptr { - //p.genln('free($v.name); // close_scope free') - } + //p.genln('free($v.name); // close_scope free') + } } } @@ -1117,7 +1117,7 @@ fn (p mut Parser) statement(add_semi bool) string { p.check(.colon) return '' } - // `a := 777` + // `a := 777` else if p.peek() == .decl_assign { p.log('var decl') p.var_decl() @@ -1127,7 +1127,7 @@ fn (p mut Parser) statement(add_semi bool) string { if p.lit == 'panic' || p.lit == 'exit' { p.returns = true } - // `a + 3`, `a(7)` or maybe just `a` + // `a + 3`, `a(7)` or maybe just `a` q = p.bool_expression() } case Token.key_goto: @@ -1148,14 +1148,14 @@ fn (p mut Parser) statement(add_semi bool) string { p.if_st(false, 0) case Token.key_for: p.for_st() - case Token.key_switch, Token.key_match: + case Token.key_switch, Token.key_match: p.switch_statement() case Token.key_mut, Token.key_static: p.var_decl() case Token.key_return: p.return_st() case Token.lcbr:// {} block - p.check(.lcbr) + p.check(.lcbr) p.genln('{') p.statements() return '' @@ -1164,13 +1164,13 @@ fn (p mut Parser) statement(add_semi bool) string { p.error('`continue` statement outside `for`') } p.genln('continue') - p.check(.key_continue) + p.check(.key_continue) case Token.key_break: if p.for_expr_cnt == 0 { p.error('`break` statement outside `for`') } p.genln('break') - p.check(.key_break) + p.check(.key_break) case Token.key_go: p.go_statement() case Token.key_assert: @@ -1200,22 +1200,22 @@ fn (p mut Parser) statement(add_semi bool) string { // this can be `user = ...` or `user.field = ...`, in both cases `v` is `user` fn (p mut Parser) assign_statement(v Var, ph int, is_map bool) { p.log('assign_statement() name=$v.name tok=') - is_vid := p.fileis('vid') // TODO remove + is_vid := p.fileis('vid') // TODO remove tok := p.tok //if !v.is_mut && !v.is_arg && !p.pref.translated && !v.is_global{ if !v.is_mut && !p.pref.translated && !v.is_global && !is_vid { if v.is_arg { if p.cur_fn.args.len > 0 && p.cur_fn.args[0].name == v.name { println('make the receiver `$v.name` mutable: -fn ($v.name mut $v.typ) $p.cur_fn.name (...) { -') - } - } +fn ($v.name mut $v.typ) $p.cur_fn.name (...) { +') + } + } p.error('`$v.name` is immutable.') } if !v.is_changed { - p.cur_fn.mark_var_changed(v) - } + p.cur_fn.mark_var_changed(v) + } is_str := v.typ == 'string' switch tok { case Token.assign: @@ -1232,7 +1232,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { default: p.gen(' ' + p.tok.str() + ' ') } p.fspace() - p.fgen(tok.str()) + p.fgen(tok.str()) p.fspace() p.next() pos := p.cgen.cur_line.len @@ -1242,7 +1242,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { println('allowing option asss') expr := p.cgen.cur_line.right(pos) left := p.cgen.cur_line.left(pos) - typ := expr_type.replace('Option_', '') + typ := expr_type.replace('Option_', '') //p.cgen.cur_line = left + 'opt_ok($expr)' p.cgen.resetln(left + 'opt_ok($expr, sizeof($typ))') } @@ -1261,7 +1261,7 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { } fn (p mut Parser) var_decl() { - p.is_alloc = false + p.is_alloc = false is_mut := p.tok == .key_mut || p.prev_tok == .key_for is_static := p.tok == .key_static if p.tok == .key_mut { @@ -1274,7 +1274,7 @@ fn (p mut Parser) var_decl() { } // println('var decl tok=${p.strtok()} ismut=$is_mut') name := p.check_name() - p.var_decl_name = name + p.var_decl_name = name // Don't allow declaring a variable with the same name. Even in a child scope // (shadowing is not allowed) if !p.builtin_mod && p.cur_fn.known_var(name) { @@ -1284,13 +1284,13 @@ fn (p mut Parser) var_decl() { if name.len > 1 && contains_capital(name) { p.error('variable names cannot contain uppercase letters, use snake_case instead') } - p.check_space(.decl_assign) // := + p.check_space(.decl_assign) // := // Generate expression to tmp because we need its type first // [TYP .name =] bool_expression() pos := p.cgen.add_placeholder() mut typ := p.bool_expression() // Option check ? or { - or_else := p.tok == .key_orelse + or_else := p.tok == .key_orelse tmp := p.get_tmp() if or_else { // Option_User tmp = get_user(1); @@ -1321,7 +1321,7 @@ fn (p mut Parser) var_decl() { name: name typ: typ is_mut: is_mut - is_alloc: p.is_alloc + is_alloc: p.is_alloc }) if !or_else { gen_name := p.table.var_cgen_name(name) @@ -1331,39 +1331,39 @@ fn (p mut Parser) var_decl() { } p.cgen.set_placeholder(pos, nt_gen) } - p.var_decl_name = '' + p.var_decl_name = '' } const ( and_or_error = 'use `()` to make the boolean expression clear\n' + 'for example: `(a && b) || c` instead of `a && b || c`' -) +) fn (p mut Parser) bool_expression() string { tok := p.tok typ := p.bterm() - mut got_and := false // to catch `a && b || c` in one expression without () - mut got_or := false + mut got_and := false // to catch `a && b || c` in one expression without () + mut got_or := false for p.tok == .and || p.tok == .logical_or { if p.tok == .and { - got_and = true - if got_or { p.error(and_or_error) } - } + got_and = true + if got_or { p.error(and_or_error) } + } if p.tok == .logical_or { - got_or = true - if got_and { p.error(and_or_error) } - } + got_or = true + if got_and { p.error(and_or_error) } + } if p.is_sql { if p.tok == .and { - p.gen(' and ') - } + p.gen(' and ') + } else if p.tok == .logical_or { - p.gen(' or ') - } - } else { + p.gen(' or ') + } + } else { p.gen(' ${p.tok.str()} ') - } - p.check_space(p.tok) + } + p.check_space(p.tok) p.check_types(p.bterm(), typ) } if typ == '' { @@ -1378,8 +1378,8 @@ fn (p mut Parser) bool_expression() string { fn (p mut Parser) bterm() string { ph := p.cgen.add_placeholder() mut typ := p.expression() - p.expected_type = typ - is_str := typ=='string' && !p.is_sql + p.expected_type = typ + is_str := typ=='string' && !p.is_sql tok := p.tok // if tok in [ .eq, .gt, .lt, .le, .ge, .ne] { if tok == .eq || (tok == .assign && p.is_sql) || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne { @@ -1388,25 +1388,25 @@ fn (p mut Parser) bterm() string { p.gen(',') } else if p.is_sql && tok == .eq { - p.gen('=') - } + p.gen('=') + } else { p.gen(tok.str()) } p.next() - // `id == user.id` => `id == $1`, `user.id` + // `id == user.id` => `id == $1`, `user.id` if p.is_sql { - p.sql_i++ - p.gen('$' + p.sql_i.str()) - p.cgen.start_cut() + p.sql_i++ + p.gen('$' + p.sql_i.str()) + p.cgen.start_cut() p.check_types(p.expression(), typ) - p.sql_params = p.sql_params + p.cgen.cut() + ',' - //println('sql params = "$p.sql_params"') - } else { + p.sql_params = p.sql_params + p.cgen.cut() + ',' + //println('sql params = "$p.sql_params"') + } else { p.check_types(p.expression(), typ) - } + } typ = 'bool' - if is_str { //&& !p.is_sql { + if is_str { //&& !p.is_sql { p.gen(')') switch tok { case Token.eq: p.cgen.set_placeholder(ph, 'string_eq(') @@ -1416,20 +1416,20 @@ fn (p mut Parser) bterm() string { case Token.gt: p.cgen.set_placeholder(ph, 'string_gt(') case Token.lt: p.cgen.set_placeholder(ph, 'string_lt(') } -/* +/* Token.eq => p.cgen.set_placeholder(ph, 'string_eq(') Token.ne => p.cgen.set_placeholder(ph, 'string_ne(') Token.le => p.cgen.set_placeholder(ph, 'string_le(') Token.ge => p.cgen.set_placeholder(ph, 'string_ge(') Token.gt => p.cgen.set_placeholder(ph, 'string_gt(') Token.lt => p.cgen.set_placeholder(ph, 'string_lt(') -*/ +*/ } } return typ } -// also called on *, &, @, . (enum) +// also called on *, &, @, . (enum) fn (p mut Parser) name_expr() string { ph := p.cgen.add_placeholder() // amp @@ -1447,7 +1447,7 @@ fn (p mut Parser) name_expr() string { p.fgen(name) // known_type := p.table.known_type(name) orig_name := name - is_c := name == 'C' && p.peek() == .dot + is_c := name == 'C' && p.peek() == .dot mut is_c_struct_init := is_c && ptr// a := &C.mycstruct{} if is_c { p.next() @@ -1459,21 +1459,21 @@ fn (p mut Parser) name_expr() string { is_c_struct_init = true } } - // enum value? (`color == .green`) + // enum value? (`color == .green`) if p.tok == .dot { - //println('got enum dot val $p.left_type pass=$p.pass $p.scanner.line_nr left=$p.left_type') - T := p.find_type(p.expected_type) + //println('got enum dot val $p.left_type pass=$p.pass $p.scanner.line_nr left=$p.left_type') + T := p.find_type(p.expected_type) if T.is_enum { - p.check(.dot) - val := p.check_name() - // Make sure this enum value exists + p.check(.dot) + val := p.check_name() + // Make sure this enum value exists if !T.has_enum_val(val) { - p.error('enum `$T.name` does not have value `$val`') - } - p.gen(T.mod + '__' + p.expected_type + '_' + val) - } - return p.expected_type - } + p.error('enum `$T.name` does not have value `$val`') + } + p.gen(T.mod + '__' + p.expected_type + '_' + val) + } + return p.expected_type + } // ////////////////////////// // module ? // Allow shadowing (gg = gg.newcontext(); gg.draw_triangle()) @@ -1497,13 +1497,13 @@ fn (p mut Parser) name_expr() string { } // Variable mut v := p.cur_fn.find_var(name) - // A hack to allow `newvar := Foo{ field: newvar }` - // Declare the variable so that it can be used in the initialization + // A hack to allow `newvar := Foo{ field: newvar }` + // Declare the variable so that it can be used in the initialization if name == 'main__' + p.var_decl_name { v.name = p.var_decl_name - v.typ = 'voidptr' - v.is_mut = true - } + v.typ = 'voidptr' + v.is_mut = true + } if v.name.len != 0 { if ptr { p.gen('& /*vvar*/ ') @@ -1551,7 +1551,7 @@ fn (p mut Parser) name_expr() string { enum_type := p.table.find_type(name) if !enum_type.is_enum { p.error('`$name` is not an enum') - } + } p.next() p.check(.dot) val := p.lit @@ -1562,11 +1562,11 @@ fn (p mut Parser) name_expr() string { } else if p.peek() == .lcbr { // go back to name start (mod.name) -/* +/* p.scanner.pos = hack_pos p.tok = hack_tok p.lit = hack_lit -*/ +*/ // TODO hack. If it's a C type, we may need to add struct before declaration: // a := &C.A{} ==> struct A* a = malloc(sizeof(struct A)); if is_c_struct_init { @@ -1577,18 +1577,18 @@ fn (p mut Parser) name_expr() string { name += '*' // `&User{}` => type `User*` } if name == 'T' { - name = p.cur_gen_type - } + name = p.cur_gen_type + } return p.struct_init(name, is_c_struct_init) } } if is_c { - // C const (`C.GLFW_KEY_LEFT`) + // C const (`C.GLFW_KEY_LEFT`) if p.peek() != .lpar { - p.gen(name) - p.next() - return 'int' - } + p.gen(name) + p.next() + return 'int' + } // C fn f := Fn { name: name// .replace('c_', '') @@ -1624,14 +1624,14 @@ fn (p mut Parser) name_expr() string { // Function (not method btw, methods are handled in dot()) mut f := p.table.find_fn(name) if f.name == '' { - // We are in a second pass, that means this function was not defined, throw an error. + // We are in a second pass, that means this function was not defined, throw an error. if !p.first_pass() { - // V script? Try os module. - if p.v_script { - name = name.replace('main__', 'os__') - f = p.table.find_fn(name) - } - if f.name == '' { + // V script? Try os module. + if p.v_script { + name = name.replace('main__', 'os__') + f = p.table.find_fn(name) + } + if f.name == '' { // 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) { @@ -1641,16 +1641,16 @@ fn (p mut Parser) name_expr() string { else { p.error('undefined: `$orig_name`') } - } - } else { + } + } else { p.next() - // First pass, the function can be defined later. + // First pass, the function can be defined later. return 'void' - } + } } // no () after func, so func is an argument, just gen its name // TODO verify this and handle errors - peek := p.peek() + peek := p.peek() if peek != .lpar && peek != .lt { p.gen(p.table.cgen_name(f)) p.next() @@ -1678,13 +1678,13 @@ fn (p mut Parser) name_expr() string { fn (p mut Parser) var_expr(v Var) string { p.log('\nvar_expr() v.name="$v.name" v.typ="$v.typ"') // println('var expr is_tmp=$p.cgen.is_tmp\n') - p.cur_fn.mark_var_used(v) + p.cur_fn.mark_var_used(v) fn_ph := p.cgen.add_placeholder() p.expr_var = v p.gen(p.table.var_cgen_name(v.name)) p.next() mut typ := v.typ - // Function pointer? + // Function pointer? if typ.starts_with('fn ') { //println('CALLING FN PTR') //p.print_tok() @@ -1702,14 +1702,14 @@ fn (p mut Parser) var_expr(v Var) string { // mut dc := 0 for p.tok ==.dot { if p.peek() == .key_select { - p.next() - return p.select_query(fn_ph) - } + p.next() + return p.select_query(fn_ph) + } if typ == 'pg__DB' && !p.fileis('pg.v') && p.peek() == .name { - p.next() - p.insert_query(fn_ph) - return 'void' - } + p.next() + p.insert_query(fn_ph) + return 'void' + } // println('dot #$dc') typ = p.dot(typ, fn_ph) p.log('typ after dot=$typ') @@ -1726,8 +1726,8 @@ fn (p mut Parser) var_expr(v Var) string { p.error('`$v.name` is immutable') } if !v.is_changed { - p.cur_fn.mark_var_changed(v) - } + p.cur_fn.mark_var_changed(v) + } if typ != 'int' { if !p.pref.translated && !is_number_type(typ) { p.error('cannot ++/-- value of type `$typ`') @@ -1735,8 +1735,8 @@ fn (p mut Parser) var_expr(v Var) string { } p.gen(p.tok.str()) p.fgen(p.tok.str()) - p.next()// ++/-- - // allow `a := c++` in translated code + p.next()// ++/-- + // allow `a := c++` in translated code if p.pref.translated { //return p.index_expr(typ, fn_ph) } @@ -1745,17 +1745,17 @@ fn (p mut Parser) var_expr(v Var) string { } } typ = p.index_expr(typ, fn_ph) - // TODO hack to allow `foo.bar[0] = 2` - if p.tok == .dot { + // TODO hack to allow `foo.bar[0] = 2` + if p.tok == .dot { for p.tok == .dot { typ = p.dot(typ, fn_ph) - } + } typ = p.index_expr(typ, fn_ph) - } + } return typ } -// for debugging only +// for debugging only fn (p &Parser) fileis(s string) bool { return p.scanner.file_path.contains(s) } @@ -1763,34 +1763,34 @@ fn (p &Parser) fileis(s string) bool { // user.name => `str_typ` is `User` // user.company.name => `str_typ` is `Company` fn (p mut Parser) dot(str_typ string, method_ph int) string { - //if p.fileis('orm_test') { - //println('ORM dot $str_typ') - //} + //if p.fileis('orm_test') { + //println('ORM dot $str_typ') + //} p.check(.dot) typ := p.find_type(str_typ) if typ.name.len == 0 { p.error('dot(): cannot find type `$str_typ`') } if p.tok == .dollar { - p.comptime_method_call(typ) - return 'void' - } + p.comptime_method_call(typ) + return 'void' + } field_name := p.lit - p.fgen(field_name) + p.fgen(field_name) p.log('dot() field_name=$field_name typ=$str_typ') //if p.fileis('main.v') { - //println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}') + //println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}') //} has_field := p.table.type_has_field(typ, field_name) mut has_method := p.table.type_has_method(typ, field_name) - // generate `.str()` - if !has_method && field_name == 'str' && typ.name.starts_with('array_') { - p.gen_array_str(mut typ) - has_method = true - } + // generate `.str()` + if !has_method && field_name == 'str' && typ.name.starts_with('array_') { + p.gen_array_str(mut typ) + has_method = true + } if !typ.is_c && !has_field && !has_method && !p.first_pass() { if typ.name.starts_with('Option_') { - opt_type := typ.name.right(7) + opt_type := typ.name.right(7) p.error('unhandled option type: $opt_type?') } //println('error in dot():') @@ -1817,14 +1817,14 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { modifying := next.is_assign() || next == .inc || next == .dec is_vi := p.fileis('vid') if !p.builtin_mod && !p.pref.translated && modifying && !field.is_mut && !is_vi { - p.error('cannot modify immutable field `$field_name` (type `$typ.name`)\n' + + p.error('cannot modify immutable field `$field_name` (type `$typ.name`)\n' + 'declare the field with `mut:` struct $typ.name { mut: - $field_name $field.typ -} -') + $field_name $field.typ +} +') } if !p.builtin_mod && p.mod != typ.mod { } @@ -1849,7 +1849,7 @@ struct $typ.name { // method method := p.table.find_method(typ, field_name) p.fn_call(method, method_ph, '', str_typ) - // Methods returning `array` should return `array_string` + // Methods returning `array` should return `array_string` if method.typ == 'array' && typ.name.starts_with('array_') { return typ.name } @@ -1865,12 +1865,12 @@ struct $typ.name { } fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { - mut typ := typ_ + mut typ := typ_ // a[0] v := p.expr_var //if p.fileis('fn_test.v') { //println('index expr typ=$typ') - //println(v.name) + //println(v.name) //} is_map := typ.starts_with('map_') is_str := typ == 'string' @@ -1982,7 +1982,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { p.gen(']/*r$typ $v.is_mut*/') } } - // TODO move this from index_expr() + // TODO move this from index_expr() // TODO if p.tok in ... // if p.tok in [.assign, .plus_assign, .minus_assign] if (p.tok == .assign && !p.is_sql) || p.tok == .plus_assign || p.tok == .minus_assign || @@ -2048,11 +2048,11 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { p.gen('$index_expr ]') } else { - if is_ptr { + if is_ptr { p.gen('( *($typ*) array__get(* $index_expr) )') - } else { + } else { p.gen('( *($typ*) array__get($index_expr) )') - } + } } } else if is_str && !p.builtin_mod { @@ -2079,7 +2079,7 @@ fn (p mut Parser) expression() string { p.cgen('/* expr start*/') ph := p.cgen.add_placeholder() mut typ := p.term() - is_str := typ=='string' + is_str := typ=='string' // a << b ==> array2_push(&a, b) if p.tok == .left_shift { if typ.contains('array_') { @@ -2088,7 +2088,7 @@ fn (p mut Parser) expression() string { // _PUSH(&a, expression(), tmp, string) tmp := p.get_tmp() tmp_typ := typ.right(6)// skip "array_" - p.check_space(.left_shift) + p.check_space(.left_shift) // Get the value we are pushing p.gen(', (') // Imkey_mut? Can we push? @@ -2096,23 +2096,23 @@ fn (p mut Parser) expression() string { p.error('`$p.expr_var.name` is immutable (can\'t <<)') } if !p.expr_var.is_changed { - p.cur_fn.mark_var_changed(p.expr_var) - } - expr_type := p.expression() - // Two arrays of the same type? + p.cur_fn.mark_var_changed(p.expr_var) + } + expr_type := p.expression() + // Two arrays of the same type? push_array := typ == expr_type - if push_array { - p.cgen.set_placeholder(ph, '_PUSH_MANY(&' ) + if push_array { + p.cgen.set_placeholder(ph, '_PUSH_MANY(&' ) p.gen('), $tmp, $typ)') - } else { + } else { p.check_types(expr_type, tmp_typ) // Pass tmp var info to the _PUSH macro // Prepend tmp initialisation and push call // Don't dereference if it's already a key_mut array argument (`fn foo(mut []int)`) - push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'} + push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'} p.cgen.set_placeholder(ph, push_call) p.gen('), $tmp, $tmp_typ)') - } + } return 'void' } else { @@ -2122,16 +2122,16 @@ fn (p mut Parser) expression() string { return 'int' } } - // `a in [1, 2, 3]` - // `key in map` + // `a in [1, 2, 3]` + // `key in map` if p.tok == .key_in { p.fgen(' ') p.check(.key_in) p.fgen(' ') p.gen(', ') arr_typ := p.expression() - is_map := arr_typ.starts_with('map_') - if !arr_typ.starts_with('array_') && !is_map { + is_map := arr_typ.starts_with('map_') + if !arr_typ.starts_with('array_') && !is_map { p.error('`in` requires an array/map') } T := p.table.find_type(arr_typ) @@ -2141,10 +2141,10 @@ fn (p mut Parser) expression() string { // `typ` is element's type if is_map { p.cgen.set_placeholder(ph, '_IN_MAP( ') - } - else { + } + else { p.cgen.set_placeholder(ph, '_IN($typ, ') - } + } p.gen(')') return 'bool' } @@ -2154,7 +2154,7 @@ fn (p mut Parser) expression() string { p.check_types(p.expression(), typ) return 'int' } - if p.tok == .dot { + if p.tok == .dot { for p.tok == .dot { typ = p.dot(typ, ph) } @@ -2164,7 +2164,7 @@ fn (p mut Parser) expression() string { // for p.tok in [.plus, .minus, .pipe, .amp, .xor] { tok_op := p.tok is_num := typ == 'void*' || typ == 'byte*' || is_number_type(typ) - p.check_space(p.tok) + p.check_space(p.tok) if is_str && tok_op == .plus { p.cgen.set_placeholder(ph, 'string_add(') p.gen(',') @@ -2255,12 +2255,12 @@ fn (p mut Parser) unary() string { switch tok { case Token.not: p.gen('!') - p.check(.not) + p.check(.not) typ = 'bool' p.bool_expression() case Token.bit_not: p.gen('~') - p.check(.bit_not) + p.check(.bit_not) typ = p.bool_expression() default: typ = p.factor() @@ -2275,19 +2275,19 @@ fn (p mut Parser) factor() string { case .number: typ = 'int' // Check if float (`1.0`, `1e+3`) but not if is hexa - if (p.lit.contains('.') || (p.lit.contains('e') || p.lit.contains('E'))) && + if (p.lit.contains('.') || (p.lit.contains('e') || p.lit.contains('E'))) && !(p.lit[0] == `0` && (p.lit[1] == `x` || p.lit[1] == `X`)) { typ = 'f32' - // typ = 'f64' // TODO + // typ = 'f64' // TODO } else { v_u64 := p.lit.u64() if u64(u32(v_u64)) < v_u64 { typ = 'u64' } } - if p.expected_type != '' && !is_valid_int_const(p.lit, p.expected_type) { - p.error('constant `$p.lit` overflows `$p.expected_type`') - } + if p.expected_type != '' && !is_valid_int_const(p.lit, p.expected_type) { + p.error('constant `$p.lit` overflows `$p.expected_type`') + } p.gen(p.lit) p.fgen(p.lit) case Token.minus: @@ -2310,8 +2310,8 @@ fn (p mut Parser) factor() string { p.gen('$sizeof_typ)') p.fgen('$sizeof_typ)') return 'int' - case Token.amp, Token.dot, Token.mul: - // (dot is for enum vals: `.green`) + case Token.amp, Token.dot, Token.mul: + // (dot is for enum vals: `.green`) return p.name_expr() case Token.name: // map[string]int @@ -2320,16 +2320,16 @@ fn (p mut Parser) factor() string { } if p.lit == 'json' && p.peek() == .dot { if !('json' in p.table.imports) { - p.error('undefined: `json`, use `import json`') - } + p.error('undefined: `json`, use `import json`') + } return p.js_decode() } - //if p.fileis('orm_test') { - //println('ORM name: $p.lit') - //} + //if p.fileis('orm_test') { + //println('ORM name: $p.lit') + //} typ = p.name_expr() return typ - case Token.key_default: + case Token.key_default: p.next() p.next() name := p.check_name() @@ -2342,7 +2342,7 @@ fn (p mut Parser) factor() string { case Token.lpar: //p.gen('(/*lpar*/') p.gen('(') - p.check(.lpar) + p.check(.lpar) typ = p.bool_expression() // Hack. If this `)` referes to a ptr cast `(*int__)__`, it was already checked // TODO: fix parser so that it doesn't think it's a par expression when it sees `(` in @@ -2375,21 +2375,21 @@ fn (p mut Parser) factor() string { // everything should do next() return p.array_init() case Token.lcbr: - // `m := { 'one': 1 }` + // `m := { 'one': 1 }` if p.peek() == .str { - return p.map_init() - } + return p.map_init() + } // { user | name :'new name' } return p.assoc() case Token.key_if: typ = p.if_st(true, 0) return typ default: - if p.pref.is_verbose || p.pref.is_debug { + if p.pref.is_verbose || p.pref.is_debug { next := p.peek() println('prev=${p.prev_tok.str()}') println('next=${next.str()}') - } + } p.error('unexpected token: `${p.tok.str()}`') } p.next()// TODO everything should next() @@ -2443,7 +2443,7 @@ fn format_str(_str string) string { mut str := _str.replace('"', '\\"') $if windows { str = str.replace('\r\n', '\\n') - } + } str = str.replace('\n', '\\n') return str } @@ -2454,28 +2454,28 @@ fn (p mut Parser) string_expr() { if p.peek() != .dollar { p.fgen('\'$str\'') f := format_str(str) - // `C.puts('hi')` => `puts("hi");` + // `C.puts('hi')` => `puts("hi");` if p.calling_c || (p.pref.translated && p.mod == 'main') { p.gen('"$f"') } else if p.is_sql { - p.gen('\'$str\'') - } + p.gen('\'$str\'') + } else { - p.gen('tos2((byte*)"$f")') + p.gen('tos2((byte*)"$f")') } p.next() return } // tmp := p.get_tmp() - p.is_alloc = true // $ interpolation means there's allocation + p.is_alloc = true // $ interpolation means there's allocation mut args := '"' mut format := '"' - p.fgen('\'') - mut complex_inter := false // for vfmt + p.fgen('\'') + mut complex_inter := false // for vfmt for p.tok == .str { // Add the string between %d's - p.fgen(p.lit) + p.fgen(p.lit) p.lit = p.lit.replace('%', '%%') format += format_str(p.lit) p.next()// skip $ @@ -2483,13 +2483,13 @@ fn (p mut Parser) string_expr() { continue } // Handle .dollar - p.check(.dollar) + p.check(.dollar) // If there's no string after current token, it means we are in - // a complex expression (`${...}`) + // a complex expression (`${...}`) if p.peek() != .str { - p.fgen('{') - complex_inter = true - } + p.fgen('{') + complex_inter = true + } // Get bool expr inside a temp var p.cgen.start_tmp() typ := p.bool_expression() @@ -2504,9 +2504,9 @@ fn (p mut Parser) string_expr() { if typ == 'ustring' { args += '.len, ${val}.s.str' } - if typ == 'bool' { + if typ == 'bool' { //args += '.len, ${val}.str' - } + } // Custom format? ${t.hour:02d} custom := p.tok == .colon if custom { @@ -2523,22 +2523,22 @@ fn (p mut Parser) string_expr() { p.next() } else { - f := p.typ_to_fmt(typ, 0) - if f == '' { + f := p.typ_to_fmt(typ, 0) + if f == '' { p.error('unhandled sprintf format "$typ" ') - } - format += f + } + format += f } } if complex_inter { - p.fgen('}') - } - p.fgen('\'') + p.fgen('}') + } + p.fgen('\'') // println("hello %d", num) optimization. if p.cgen.nogen { return } - // println: don't allocate a new string, just print it. + // println: don't allocate a new string, just print it. $if !windows { cur_line := p.cgen.cur_line.trim_space() if cur_line.contains('println (') && p.tok != .plus && @@ -2551,7 +2551,7 @@ fn (p mut Parser) string_expr() { // '$age'! means the user wants this to be a tmp string (uses global buffer, no allocation, // won't be used again) if p.tok == .not { - p.check(.not) + p.check(.not) p.gen('_STR_TMP($format$args)') } else { @@ -2561,46 +2561,46 @@ fn (p mut Parser) string_expr() { } // m := map[string]int{} -// m := { 'one': 1 } +// m := { 'one': 1 } fn (p mut Parser) map_init() string { - // m := { 'one': 1, 'two': 2 } - mut keys_gen := '' // (string[]){tos2("one"), tos2("two")} - mut vals_gen := '' // (int[]){1, 2} - mut val_type := '' // 'int' + // m := { 'one': 1, 'two': 2 } + mut keys_gen := '' // (string[]){tos2("one"), tos2("two")} + mut vals_gen := '' // (int[]){1, 2} + mut val_type := '' // 'int' if p.tok == .lcbr { p.check(.lcbr) - mut i := 0 - for { - key := p.lit - keys_gen += 'tos2("$key"), ' - p.check(.str) - p.check(.colon) - p.cgen.start_tmp() - t := p.bool_expression() - if i == 0 { - val_type = t - } - i++ + mut i := 0 + for { + key := p.lit + keys_gen += 'tos2("$key"), ' + p.check(.str) + p.check(.colon) + p.cgen.start_tmp() + t := p.bool_expression() + if i == 0 { + val_type = t + } + i++ if val_type != t { if !p.check_types_no_throw(val_type, t) { p.error('bad map element type `$val_type` instead of `$t`') } } - val_expr := p.cgen.end_tmp() - vals_gen += '$val_expr, ' + val_expr := p.cgen.end_tmp() + vals_gen += '$val_expr, ' if p.tok == .rcbr { - p.check(.rcbr) - break - } + p.check(.rcbr) + break + } if p.tok == .comma { p.check(.comma) - } - } + } + } p.gen('new_map_init($i, sizeof($val_type), ' + - '(string[]){ $keys_gen }, ($val_type []){ $vals_gen } )') - typ := 'map_$val_type' - return typ - } + '(string[]){ $keys_gen }, ($val_type []){ $vals_gen } )') + typ := 'map_$val_type' + return typ + } p.next() p.check(.lsbr) key_type := p.check_name() @@ -2619,25 +2619,25 @@ fn (p mut Parser) map_init() string { p.check(.lcbr) p.check(.rcbr) println('warning: $p.file_name:$p.scanner.line_nr ' + - 'initializaing maps no longer requires `{}`') - } + 'initializaing maps no longer requires `{}`') + } return typ } -// `nums := [1, 2, 3]` +// `nums := [1, 2, 3]` fn (p mut Parser) array_init() string { - p.is_alloc = true + p.is_alloc = true p.check(.lsbr) - mut is_integer := p.tok == .number // for `[10]int` - // fixed length arrays with a const len: `nums := [N]int`, same as `[10]int` basically - mut is_const_len := false + mut is_integer := p.tok == .number // for `[10]int` + // fixed length arrays with a const len: `nums := [N]int`, same as `[10]int` basically + mut is_const_len := false if p.tok == .name { - c := p.table.find_const(p.prepend_mod(p.lit)) + c := p.table.find_const(p.prepend_mod(p.lit)) if c.name != '' && c.typ == 'int' && p.peek() == .rsbr && !p.inside_const { - is_integer = true - is_const_len = true - } - } + is_integer = true + is_const_len = true + } + } lit := p.lit mut typ := '' new_arr_ph := p.cgen.add_placeholder() @@ -2659,9 +2659,9 @@ fn (p mut Parser) array_init() string { if p.table.known_type(name) { p.cgen.resetln('') p.gen('STRUCT_DEFAULT_VALUE') - if is_const_len { - return '[${p.mod}__$lit]$name' - } + if is_const_len { + return '[${p.mod}__$lit]$name' + } return '[$lit]$name' } else { @@ -2678,7 +2678,7 @@ fn (p mut Parser) array_init() string { if p.tok != .rsbr && p.tok != .semicolon { p.gen(', ') p.check(.comma) - p.fspace() + p.fspace() } i++ // Repeat (a = [0;5] ) @@ -2713,12 +2713,12 @@ fn (p mut Parser) array_init() string { // println('.key_goT TYP after [] $typ') } // ! after array => no malloc and no copy - no_alloc := p.tok == .not + no_alloc := p.tok == .not if no_alloc { p.next() } // [1,2,3]!! => [3]int{1,2,3} - is_fixed_size := p.tok == .not + is_fixed_size := p.tok == .not if is_fixed_size { p.next() p.gen(' }') @@ -2758,7 +2758,7 @@ fn (p mut Parser) array_init() string { fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string { p.is_struct_init = true - p.next() + p.next() p.scanner.fmt_out.cut(typ.len) ptr := typ.contains('*') // TODO tm struct struct bug @@ -2802,12 +2802,12 @@ fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string { if !t.has_field(field) { p.error('`$t.name` has no field `$field`') } - f := t.find_field(field) + f := t.find_field(field) inited_fields << field p.gen('.$field = ') p.check(.colon) p.fspace() - p.check_types(p.bool_expression(), f.typ) + p.check_types(p.bool_expression(), f.typ) if p.tok == .comma { p.next() } @@ -2907,38 +2907,38 @@ fn (p mut Parser) cast(typ string) string { p.next() } p.check(.lpar) - p.expected_type = typ + p.expected_type = typ expr_typ := p.bool_expression() - p.expected_type = '' + p.expected_type = '' // `string(buffer)` => `tos2(buffer)` // `string(buffer, len)` => `tos(buffer, len)` // `string(bytes_array, len)` => `tos(bytes_array.data, len)` - is_byteptr := expr_typ == 'byte*' || expr_typ == 'byteptr' - is_bytearr := expr_typ == 'array_byte' + is_byteptr := expr_typ == 'byte*' || expr_typ == 'byteptr' + is_bytearr := expr_typ == 'array_byte' if typ == 'string' { - if is_byteptr || is_bytearr { - if p.tok == .comma { - p.check(.comma) + if is_byteptr || is_bytearr { + if p.tok == .comma { + p.check(.comma) p.cgen.set_placeholder(pos, 'tos(') if is_bytearr { - p.gen('.data') - } - p.gen(', ') - p.check_types(p.expression(), 'int') - } else { + p.gen('.data') + } + p.gen(', ') + p.check_types(p.expression(), 'int') + } else { if is_bytearr { - p.gen('.data') - } + p.gen('.data') + } p.cgen.set_placeholder(pos, 'tos2(') - } - } + } + } // `string(234)` => error else if expr_typ == 'int' { p.error('cannot cast `$expr_typ` to `$typ`, use `str()` method instead') - } + } else { - p.error('cannot cast `$expr_typ` to `$typ`') - } + p.error('cannot cast `$expr_typ` to `$typ`') + } } else if typ == 'byte' && expr_typ == 'string' { p.error('cannot cast `$expr_typ` to `$typ`, use backquotes `` to create a `$typ` or access the value of an index of `$expr_typ` using []') @@ -2996,9 +2996,9 @@ fn (p mut Parser) if_st(is_expr bool, elif_depth int) string { p.returns = false // println('IF TYp=$typ') if p.tok == .key_else { - p.fgenln('') - p.check(.key_else) - p.fspace() + p.fgenln('') + p.check(.key_else) + p.fspace() if p.tok == .key_if { if is_expr { p.gen(') : (') @@ -3082,7 +3082,7 @@ fn (p mut Parser) for_st() { // for i, val in array else if p.peek() == .comma { // for i, val in array { ==> - // + // // array_int tmp = array; // for (int i = 0; i < tmp.len; i++) { // int val = tmp[i]; @@ -3095,15 +3095,15 @@ fn (p mut Parser) for_st() { tmp := p.get_tmp() p.cgen.start_tmp() typ := p.bool_expression() - is_arr := typ.starts_with('array_') - is_map := typ.starts_with('map_') - is_str := typ == 'string' - if !is_arr && !is_str && !is_map { - p.error('cannot range over type `$typ`') - } + is_arr := typ.starts_with('array_') + is_map := typ.starts_with('map_') + is_str := typ == 'string' + if !is_arr && !is_str && !is_map { + p.error('cannot range over type `$typ`') + } expr := p.cgen.end_tmp() p.genln('$typ $tmp = $expr ;') - pad := if is_arr { 6 } else { 4 } + pad := if is_arr { 6 } else { 4 } var_typ := typ.right(pad) // typ = strings.Replace(typ, "_ptr", "*", -1) // Register temp var @@ -3113,13 +3113,13 @@ fn (p mut Parser) for_st() { ptr: typ.contains('*') } p.register_var(val_var) - if is_arr || is_str { + if is_arr || is_str { i_var := Var { name: i typ: 'int' // parent_fn: p.cur_fn is_mut: true - is_changed: true + is_changed: true } p.register_var(i_var) p.genln(';\nfor (int $i = 0; $i < $tmp .len; $i ++) {') @@ -3130,21 +3130,21 @@ fn (p mut Parser) for_st() { name: i typ: 'string' is_mut: true - is_changed: true + is_changed: true } p.register_var(i_var) - p.genln('array_string keys_$tmp = map_keys(& $tmp ); ') - p.genln('for (int l = 0; l < keys_$tmp .len; l++) {') - p.genln(' string $i = ((string*)keys_$tmp .data)[l];') - //p.genln(' string $i = *(string*) ( array__get(keys_$tmp, l) );') + p.genln('array_string keys_$tmp = map_keys(& $tmp ); ') + p.genln('for (int l = 0; l < keys_$tmp .len; l++) {') + p.genln(' string $i = ((string*)keys_$tmp .data)[l];') + //p.genln(' string $i = *(string*) ( array__get(keys_$tmp, l) );') mut def := type_default(typ) if def == 'STRUCT_DEFAULT_VALUE' { def = '{0}' } // TODO don't call map_get() for each key, fetch values while traversing - // the tree (replace `map_keys()` above with `map_key_vals()`) - p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);') - } + // the tree (replace `map_keys()` above with `map_key_vals()`) + p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);') + } } // `for val in vals` else if p.peek() == .key_in { @@ -3168,7 +3168,7 @@ fn (p mut Parser) for_st() { is_arr := typ.contains('array') is_str := typ == 'string' if !is_arr && !is_str && !is_range { - p.error('cannot range over type `$typ`') + p.error('cannot range over type `$typ`') } p.genln('$typ $tmp = $expr;') // TODO var_type := if... @@ -3188,7 +3188,7 @@ fn (p mut Parser) for_st() { name: val typ: var_type ptr: typ.contains('*') - is_changed: true + is_changed: true } p.register_var(val_var) i := p.get_tmp() @@ -3214,9 +3214,9 @@ fn (p mut Parser) for_st() { p.check_types(p.bool_expression(), 'bool') p.genln(') {') } - p.fspace() + p.fspace() p.check(.lcbr) - p.genln('') + p.genln('') p.statements() p.close_scope() p.for_expr_cnt-- @@ -3224,28 +3224,28 @@ fn (p mut Parser) for_st() { } fn (p mut Parser) switch_statement() { - if p.tok == .key_switch { - p.check(.key_switch) + if p.tok == .key_switch { + p.check(.key_switch) } else { - p.check(.key_match) - } + p.check(.key_match) + } p.cgen.start_tmp() typ := p.bool_expression() expr := p.cgen.end_tmp() p.check(.lcbr) mut i := 0 mut all_cases_return := true - for p.tok == .key_case || p.tok == .key_default || p.peek() == .arrow || p.tok == .key_else { + for p.tok == .key_case || p.tok == .key_default || p.peek() == .arrow || p.tok == .key_else { p.returns = false - if p.tok == .key_default || p.tok == .key_else { + if p.tok == .key_default || p.tok == .key_else { p.genln('else { // default:') - if p.tok == .key_default { - p.check(.key_default) + if p.tok == .key_default { + p.check(.key_default) p.check(.colon) - } else { - p.check(.key_else) + } else { + p.check(.key_else) p.check(.arrow) - } + } p.statements() p.returns = all_cases_return && p.returns return @@ -3260,14 +3260,14 @@ fn (p mut Parser) switch_statement() { if got_comma { p.gen(') || ') } - if typ == 'string' { + if typ == 'string' { p.gen('string_eq($expr, ') } else { p.gen('($expr == ') } - if p.tok == .key_case || p.tok == .key_default { - p.check(p.tok) + if p.tok == .key_case || p.tok == .key_default { + p.check(p.tok) } p.bool_expression() if p.tok != .comma { @@ -3276,12 +3276,12 @@ fn (p mut Parser) switch_statement() { p.check(.comma) got_comma = true } - if p.tok == .colon { + if p.tok == .colon { p.check(.colon) - } - else { - p.check(.arrow) - } + } + else { + p.check(.arrow) + } p.gen(')) {') p.genln('/* case */') p.statements() @@ -3293,8 +3293,8 @@ fn (p mut Parser) switch_statement() { fn (p mut Parser) assert_statement() { if p.first_pass() { - return - } + return + } p.check(.key_assert) p.fspace() tmp := p.get_tmp() @@ -3302,21 +3302,21 @@ fn (p mut Parser) assert_statement() { p.check_types(p.bool_expression(), 'bool') // TODO print "expected: got" for failed tests filename := p.file_path.replace('\\', '\\\\') - p.genln(';\n + p.genln(';\n if (!$tmp) { println(tos2("\\x1B[31mFAILED: $p.cur_fn.name() in $filename:$p.scanner.line_nr\\x1B[0m")); -g_test_ok = 0 ; +g_test_ok = 0 ; // TODO - // Maybe print all vars in a test function if it fails? -} -else { + // Maybe print all vars in a test function if it fails? +} +else { //puts("\\x1B[32mPASSED: $p.cur_fn.name()\\x1B[0m"); }') } fn (p mut Parser) return_st() { p.check(.key_return) - p.fgen(' ') + p.fgen(' ') fn_returns := p.cur_fn.typ != 'void' if fn_returns { if p.tok == .rcbr { @@ -3329,7 +3329,7 @@ fn (p mut Parser) return_st() { if p.cur_fn.typ.ends_with(expr_type) && p.cur_fn.typ.starts_with('Option_') { tmp := p.get_tmp() ret := p.cgen.cur_line.right(ph) - typ := expr_type.replace('Option_', '') + typ := expr_type.replace('Option_', '') p.cgen.cur_line = '$expr_type $tmp = OPTION_CAST($typ)($ret);' p.cgen.resetln('$expr_type $tmp = OPTION_CAST($expr_type)($ret);') p.gen('return opt_ok(&$tmp, sizeof($typ))') @@ -3353,19 +3353,19 @@ fn (p mut Parser) return_st() { if total_text == '' || expr_type == 'void*' { p.cgen.resetln('return $ret') - } else { - tmp := p.get_tmp() + } else { + tmp := p.get_tmp() p.cgen.resetln('$expr_type $tmp = $ret;\n') p.genln(total_text) - p.genln('return $tmp;') - } + p.genln('return $tmp;') + } } p.check_types(expr_type, p.cur_fn.typ) } } else { // Don't allow `return val` in functions that don't return anything - if !p.is_vweb && (p.tok == .name || p.tok == .number || p.tok == .str) { + if !p.is_vweb && (p.tok == .name || p.tok == .number || p.tok == .str) { p.error('function `$p.cur_fn.name` should not return a value') } @@ -3415,10 +3415,10 @@ fn (p mut Parser) go_statement() { fn (p mut Parser) register_var(v Var) { if v.line_nr == 0 { //v.line_nr = p.scanner.line_nr - p.cur_fn.register_var({ v | line_nr: p.scanner.line_nr }) - } else { + p.cur_fn.register_var({ v | line_nr: p.scanner.line_nr }) + } else { p.cur_fn.register_var(v) - } + } } // user:=jsdecode(User, user_json_string) @@ -3478,35 +3478,35 @@ fn (p mut Parser) js_decode() string { return '' } -/* +/* fn (p &Parser) building_v() bool { cur_dir := os.getwd() - return p.file_path.contains('v/compiler') || cur_dir.contains('v/compiler') + return p.file_path.contains('v/compiler') || cur_dir.contains('v/compiler') } -*/ +*/ fn (p mut Parser) attribute() { p.check(.lsbr) - p.attr = p.check_name() - p.check(.rsbr) + p.attr = p.check_name() + p.check(.rsbr) if p.tok == .func { - p.fn_decl() - p.attr = '' - return - } + p.fn_decl() + p.attr = '' + return + } else if p.tok == .key_struct { - p.struct_decl() - p.attr = '' - return - } - p.error('bad attribute usage') -} + p.struct_decl() + p.attr = '' + return + } + p.error('bad attribute usage') +} fn (p mut Parser) defer_st() { p.check(.key_defer) - p.check(.lcbr) + p.check(.lcbr) - pos := p.cgen.lines.len + pos := p.cgen.lines.len // Save everything inside the defer block to `defer_text`. // It will be inserted before every `return` @@ -3515,12 +3515,12 @@ fn (p mut Parser) defer_st() { // is defined otherwise they could change over the course of the function // (make temps out of them) - p.genln('{') - p.statements() + p.genln('{') + p.statements() p.cur_fn.defer_text.last() = p.cgen.lines.right(pos).join('\n') + p.cur_fn.defer_text.last() // Rollback p.cgen.lines p.cgen.lines = p.cgen.lines.left(pos) p.cgen.resetln('') -} +} diff --git a/compiler/scanner.v b/compiler/scanner.v index c259a92a80..2088ba555f 100644 --- a/compiler/scanner.v +++ b/compiler/scanner.v @@ -23,7 +23,7 @@ mut: fmt_out strings.Builder fmt_indent int fmt_line_empty bool - prev_tok Token + prev_tok Token } fn new_scanner(file_path string) *Scanner { @@ -207,7 +207,7 @@ fn (s Scanner) has_gone_over_line_end() bool { fn (s mut Scanner) skip_whitespace() { for s.pos < s.text.len && s.text[s.pos].is_white() { - // Count \r\n as one line + // Count \r\n as one line if is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos-1) { s.line_nr++ } @@ -216,10 +216,10 @@ fn (s mut Scanner) skip_whitespace() { } fn (s mut Scanner) scan() ScanRes { - if s.line_comment != '' { + if s.line_comment != '' { //s.fgenln('// LOL "$s.line_comment"') - //s.line_comment = '' - } + //s.line_comment = '' + } if s.started { s.pos++ } @@ -388,11 +388,11 @@ fn (s mut Scanner) scan() ScanRes { case `,`: return scan_res(.comma, '') case `@`: - s.pos++ + s.pos++ name := s.ident_name() if !is_key(name) { - s.error('@ must be used before keywords (e.g. `@type string`)') - } + s.error('@ must be used before keywords (e.g. `@type string`)') + } return scan_res(.name, name) case `\r`: if nextc == `\n` { @@ -477,7 +477,7 @@ fn (s mut Scanner) scan() ScanRes { else if nextc == `>` { s.pos++ return scan_res(.arrow, '') - } + } else { return scan_res(.assign, '') } @@ -515,7 +515,7 @@ fn (s mut Scanner) scan() ScanRes { s.line_comment = s.text.substr(start + 1, s.pos) s.line_comment = s.line_comment.trim_space() s.fgenln('// ${s.prev_tok.str()} "$s.line_comment"') - // Skip the comment (return the next token) + // Skip the comment (return the next token) return s.scan() } // Multiline comments @@ -553,13 +553,13 @@ fn (s mut Scanner) scan() ScanRes { $if windows { if c == `\0` { return scan_res(.eof, '') - } - } - mut msg := 'invalid character `${c.str()}`' + } + } + mut msg := 'invalid character `${c.str()}`' if c == `"` { - msg += ', use \' to denote strings' - } - s.error(msg) + msg += ', use \' to denote strings' + } + s.error(msg) return scan_res(.eof, '') } @@ -797,17 +797,17 @@ fn contains_capital(s string) bool { } // HTTPRequest bad -// HttpRequest good +// HttpRequest good fn good_type_name(s string) bool { if s.len < 4 { - return true - } - for i in 2 .. s.len { + return true + } + for i in 2 .. s.len { if s[i].is_capital() && s[i-1].is_capital() && s[i-2].is_capital() { - return false - } - } - return true -} + return false + } + } + return true +} diff --git a/compiler/table.v b/compiler/table.v index 9726cd6b5a..cafbc61186 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -4,15 +4,15 @@ module main -import math -import strings +import math +import strings struct Table { mut: types []Type consts []Var - fns map[string]Fn - generic_fns []GenTable //map[string]GenTable // generic_fns['listen_and_serve'] == ['Blog', 'Forum'] + fns map[string]Fn + generic_fns []GenTable //map[string]GenTable // generic_fns['listen_and_serve'] == ['Blog', 'Forum'] obf_ids map[string]int // obf_ids['myfunction'] == 23 modules []string // List of all modules registered by the application imports []string // List of all imports @@ -23,9 +23,9 @@ mut: } struct GenTable { - fn_name string - types []string -} + fn_name string + types []string +} // Holds import information scoped to the parsed file struct FileImportTable { @@ -36,8 +36,8 @@ mut: } enum AccessMod { - private // private immutable - private_mut // private mutable + private // private immutable + private_mut // private mutable public // public immutable (readonly) public_mut // public, but mutable only in this module public_mut_mut // public and mutable both inside and outside (not recommended to use, that's why it's so verbose) @@ -54,13 +54,13 @@ mut: is_c bool // C.FI.le is_interface bool is_enum bool - enum_vals []string - gen_types []string + enum_vals []string + gen_types []string // This field is used for types that are not defined yet but are known to exist. // It allows having things like `fn (f Foo) bar()` before `Foo` is defined. // This information is needed in the first pass. is_placeholder bool - gen_str bool // needs `.str()` method generation + gen_str bool // needs `.str()` method generation } // For debugging types @@ -109,12 +109,12 @@ fn (f Fn) str() string { } fn (t &Table) debug_fns() string { - mut s := strings.new_builder(1000) + mut s := strings.new_builder(1000) for _, f in t.fns { - s.writeln(f.name) - } - return s.str() -} + s.writeln(f.name) + } + return s.str() +} // fn (types array_Type) print_to_file(f string) { // } @@ -124,23 +124,23 @@ const ( ) fn is_number_type(typ string) bool { - return typ in number_types + return typ in number_types } fn is_float_type(typ string) bool { - return typ in float_types + return typ in float_types } fn is_primitive_type(typ string) bool { - return is_number_type(typ) || typ == 'string' -} + return is_number_type(typ) || typ == 'string' +} fn new_table(obfuscate bool) *Table { mut t := &Table { - obf_ids: map[string]int - fns: map[string]Fn - //generic_fns: map[string]GenTable{} - generic_fns: []GenTable + obf_ids: map[string]int + fns: map[string]Fn + //generic_fns: map[string]GenTable{} + generic_fns: []GenTable obfuscate: obfuscate file_imports: []FileImportTable } @@ -223,7 +223,7 @@ fn (t mut Table) register_const(name, typ, mod string, is_imported bool) { typ: typ is_const: true is_import_const: is_imported - mod: mod + mod: mod } } @@ -234,17 +234,17 @@ fn (p mut Parser) register_global(name, typ string) { typ: typ is_const: true is_global: true - mod: p.mod - is_mut: true + mod: p.mod + is_mut: true } } fn (t mut Table) register_fn(new_fn Fn) { - t.fns[new_fn.name] = new_fn + t.fns[new_fn.name] = new_fn } fn (table &Table) known_type(typ_ string) bool { - mut typ := typ_ + mut typ := typ_ // 'byte*' => look up 'byte', but don't mess up fns if typ.ends_with('*') && !typ.contains(' ') { typ = typ.left(typ.len - 1) @@ -258,16 +258,16 @@ fn (table &Table) known_type(typ_ string) bool { } fn (t &Table) find_fn(name string) Fn { - f := t.fns[name] - if !isnil(f.name.str) { - return f - } + f := t.fns[name] + if !isnil(f.name.str) { + return f + } return Fn{} } fn (t &Table) known_fn(name string) bool { - f := t.find_fn(name) - return f.name != '' + f := t.find_fn(name) + return f.name != '' } fn (t &Table) known_const(name string) bool { @@ -318,10 +318,10 @@ if parent == 'array' { mod = 'builtin' } */ - t.types << Type { + t.types << Type { name: typ parent: parent - //mod: mod + //mod: mod } } @@ -357,7 +357,7 @@ fn (t &Type) has_field(name string) bool { } fn (t &Type) has_enum_val(name string) bool { - return name in t.enum_vals + return name in t.enum_vals } fn (t &Type) find_field(name string) Var { @@ -425,7 +425,7 @@ fn (t &Type) find_method(name string) Fn { return Fn{} } -/* +/* fn (t mut Type) add_gen_type(type_name string) { // println('add_gen_type($s)') if t.gen_types.contains(type_name) { @@ -433,7 +433,7 @@ fn (t mut Type) add_gen_type(type_name string) { } t.gen_types << type_name } -*/ +*/ fn (p &Parser) find_type(name string) &Type { typ := p.table.find_type(name) @@ -444,7 +444,7 @@ fn (p &Parser) find_type(name string) &Type { } fn (t &Table) find_type(name_ string) *Type { - mut name := name_ + mut name := name_ if name.ends_with('*') && !name.contains(' ') { name = name.left(name.len - 1) } @@ -458,8 +458,8 @@ fn (t &Table) find_type(name_ string) *Type { } fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool { - mut got := got_ - mut expected := expected_ + mut got := got_ + mut expected := expected_ p.log('check types got="$got" exp="$expected" ') if p.pref.translated { return true @@ -505,13 +505,13 @@ fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool { } if got=='byte*' && expected=='byteptr' { return true - } + } if got=='int' && expected=='byte*' { return true } //if got=='int' && expected=='voidptr*' { - //return true - //} + //return true + //} // byteptr += int if got=='int' && expected=='byteptr' { return true @@ -593,7 +593,7 @@ fn type_default(typ string) string { if typ.ends_with('*') { return '0' } - // User struct defined in another module. + // User struct defined in another module. if typ.contains('__') { return 'STRUCT_DEFAULT_VALUE' } @@ -617,7 +617,7 @@ fn type_default(typ string) string { case 'byteptr': return '0' case 'voidptr': return '0' } - return 'STRUCT_DEFAULT_VALUE' + return 'STRUCT_DEFAULT_VALUE' } // TODO PERF O(n) @@ -632,7 +632,7 @@ fn (t &Table) is_interface(name string) bool { // Do we have fn main()? fn (t &Table) main_exists() bool { - for _, f in t.fns { + for _, f in t.fns { if f.name == 'main' { return true } @@ -713,51 +713,51 @@ fn (table &Table) cgen_name_type_pair(name, typ string) string { } fn is_valid_int_const(val, typ string) bool { - x := val.int() + x := val.int() switch typ { - case 'byte', 'u8': return 0 <= x && x <= math.MaxU8 - case 'u16': return 0 <= x && x <= math.MaxU16 - //case 'u32': return 0 <= x && x <= math.MaxU32 - //case 'u64': return 0 <= x && x <= math.MaxU64 - ////////////// - case 'i8': return math.MinI8 <= x && x <= math.MaxI8 - case 'i16': return math.MinI16 <= x && x <= math.MaxI16 - case 'int', 'i32': return math.MinI32 <= x && x <= math.MaxI32 - //case 'i64': - //x64 := val.i64() - //return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1) - } - return true + case 'byte', 'u8': return 0 <= x && x <= math.MaxU8 + case 'u16': return 0 <= x && x <= math.MaxU16 + //case 'u32': return 0 <= x && x <= math.MaxU32 + //case 'u64': return 0 <= x && x <= math.MaxU64 + ////////////// + case 'i8': return math.MinI8 <= x && x <= math.MaxI8 + case 'i16': return math.MinI16 <= x && x <= math.MaxI16 + case 'int', 'i32': return math.MinI32 <= x && x <= math.MaxI32 + //case 'i64': + //x64 := val.i64() + //return i64(-(1<<63)) <= x64 && x64 <= i64((1<<63)-1) + } + return true } -fn (t mut Table) register_generic_fn(fn_name string) { - t.generic_fns << GenTable{fn_name, []string} -} +fn (t mut Table) register_generic_fn(fn_name string) { + t.generic_fns << GenTable{fn_name, []string} +} -fn (t mut Table) fn_gen_types(fn_name string) []string { +fn (t mut Table) fn_gen_types(fn_name string) []string { for _, f in t.generic_fns { if f.fn_name == fn_name { return f.types - } - } + } + } panic('function $fn_name not found') -} +} // `foo()` // fn_name == 'foo' -// typ == 'Bar' -fn (t mut Table) register_generic_fn_type(fn_name, typ string) { +// typ == 'Bar' +fn (t mut Table) register_generic_fn_type(fn_name, typ string) { for i, f in t.generic_fns { if f.fn_name == fn_name { - t.generic_fns[i].types << typ - return - } - } -} + t.generic_fns[i].types << typ + return + } + } +} fn (p mut Parser) typ_to_fmt(typ string, level int) string { t := p.table.find_type(typ) - if t.is_enum { + if t.is_enum { return '%d' } switch typ { @@ -775,12 +775,12 @@ fn (p mut Parser) typ_to_fmt(typ string, level int) string { case 'void': p.error('cannot interpolate this value') default: if typ.ends_with('*') { - return '%p' - } + return '%p' + } + } + if t.parent != '' && level == 0 { + return p.typ_to_fmt(t.parent, level+1) } - if t.parent != '' && level == 0 { - return p.typ_to_fmt(t.parent, level+1) - } return '' } @@ -818,7 +818,7 @@ fn (table &Table) qualify_module(mod string, file_path string) string { fn new_file_import_table(file_path string) *FileImportTable { return &FileImportTable{ file_path: file_path - imports: map[string]string + imports: map[string]string } } @@ -831,7 +831,7 @@ fn (fit mut FileImportTable) register_import(mod string) { } fn (fit mut FileImportTable) register_alias(alias string, mod string) { - if alias in fit.imports { + if alias in fit.imports { panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".') } if mod.contains('.internal.') { @@ -850,14 +850,14 @@ fn (fit mut FileImportTable) register_alias(alias string, mod string) { } fn (fit &FileImportTable) known_alias(alias string) bool { - return alias in fit.imports + return alias in fit.imports } fn (fit &FileImportTable) is_aliased(mod string) bool { - for _, val in fit.imports { + for _, val in fit.imports { if val == mod { - return true - } + return true + } } return false } diff --git a/compiler/token.v b/compiler/token.v index 836f3d0810..8da09622f4 100644 --- a/compiler/token.v +++ b/compiler/token.v @@ -6,35 +6,35 @@ module main enum Token { eof - name // user - number // 123 - str // 'foo' - str_inter // 'name=$user.name' - chartoken // `A` + name // user + number // 123 + str // 'foo' + str_inter // 'name=$user.name' + chartoken // `A` plus minus mul div mod - xor // ^ - pipe // | - inc // ++ - dec // -- - and // && - logical_or - not + xor // ^ + pipe // | + inc // ++ + dec // -- + and // && + logical_or + not bit_not question comma semicolon colon - arrow // => + arrow // => amp hash dollar left_shift righ_shift - //at // @ + //at // @ // = := += -= assign decl_assign @@ -63,10 +63,10 @@ enum Token { ge le // comments - //line_com - //mline_com - nl - dot + //line_com + //mline_com + nl + dot dotdot // keywords keyword_beg @@ -77,8 +77,8 @@ enum Token { key_case key_const key_continue - key_default - key_defer + key_default + key_defer key_else key_embed key_enum @@ -87,26 +87,26 @@ enum Token { func key_global key_go - key_goto - key_if + key_goto + key_if key_import - key_import_const - key_in - key_interface - key_match + key_import_const + key_in + key_interface + key_match key_module key_mut key_return - key_select + key_select key_sizeof key_struct - key_switch + key_switch key_true - key_type - //typeof + key_type + //typeof key_orelse key_union - key_pub + key_pub key_static keyword_end } @@ -114,7 +114,7 @@ enum Token { // build_keys genereates a map with keywords' string values: // Keywords['return'] == .key_return fn build_keys() map[string]int { - mut res := map[string]int + mut res := map[string]int for t := int(Token.keyword_beg) + 1; t < int(Token.keyword_end); t++ { key := TokenStr[t] res[key] = int(t) @@ -122,7 +122,7 @@ fn build_keys() map[string]int { return res } -// TODO remove once we have `enum Token { name('name') if('if') ... }` +// TODO remove once we have `enum Token { name('name') if('if') ... }` fn build_token_str() []string { mut s := [''; NrTokens] s[Token.keyword_beg] = '' @@ -246,9 +246,9 @@ fn (t Token) str() string { fn (t Token) is_decl() bool { // TODO i - //return t in [.key_enum, .key_interface, .func, .typ, .key_const, + //return t in [.key_enum, .key_interface, .func, .typ, .key_const, //.key_import_const, .key_struct, .key_pub, .eof] - return t == .key_enum || t == .key_interface || t == .func || + return t == .key_enum || t == .key_interface || t == .func || t == .key_struct || t == .key_type || t == .key_const || t == .key_import_const || t == .key_pub || t == .eof } @@ -256,7 +256,7 @@ fn (t Token) is_decl() bool { const ( AssignTokens = [ Token.assign, Token.plus_assign, Token.minus_assign, - Token.mult_assign, Token.div_assign, Token.xor_assign, + Token.mult_assign, Token.div_assign, Token.xor_assign, Token.mod_assign, Token.or_assign, Token.and_assign, Token.righ_shift_assign, Token.left_shift_assign diff --git a/compiler/vfmt.v b/compiler/vfmt.v index e92dfafb8f..74db232ac6 100644 --- a/compiler/vfmt.v +++ b/compiler/vfmt.v @@ -2,13 +2,13 @@ // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. -module main +module main -import strings +import strings // fmt helpers fn (scanner mut Scanner) fgen(s_ string) { - mut s := s_ + mut s := s_ if scanner.fmt_line_empty { s = strings.repeat(`\t`, scanner.fmt_indent) + s } @@ -17,7 +17,7 @@ fn (scanner mut Scanner) fgen(s_ string) { } fn (scanner mut Scanner) fgenln(s_ string) { - mut s := s_ + mut s := s_ if scanner.fmt_line_empty { s = strings.repeat(`\t`, scanner.fmt_indent) + s } diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 7483e6aaff..fbc2804342 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -6,7 +6,7 @@ module builtin struct string { //mut: - //hash_cache int + //hash_cache int pub: str byteptr len int @@ -22,10 +22,10 @@ pub: // For C strings only fn C.strlen(s byteptr) int -fn todo() { } +fn todo() { } -// Converts a C string to a V string. -// String data is reused, not copied. +// Converts a C string to a V string. +// String data is reused, not copied. pub fn tos(s byteptr, len int) string { // This should never happen. if isnil(s) { @@ -44,8 +44,8 @@ pub fn tos_clone(s byteptr) string { return tos2(s).clone() } -// Same as `tos`, but calculates the length. Called by `string(bytes)` casts. -// Used only internally. +// Same as `tos`, but calculates the length. Called by `string(bytes)` casts. +// Used only internally. fn tos2(s byteptr) string { if isnil(s) { panic('tos2: nil string') @@ -67,12 +67,12 @@ pub fn (a string) clone() string { return b } -/* +/* pub fn (s string) cstr() byteptr { clone := s.clone() return clone.str } -*/ +*/ pub fn (s string) replace(rep, with string) string { if s.len == 0 || rep.len == 0 { @@ -285,7 +285,7 @@ pub fn (s string) split_single(delim byte) []string { } val := s.substr(start, i) if val.len > 0 { - res << val + res << val } start = i + 1 } @@ -329,7 +329,7 @@ pub fn (s string) right(n int) string { return s.substr(n, s.len) } -// substr +// substr pub fn (s string) substr(start, end int) string { if start > end || start > s.len || end > s.len || start < 0 || end < 0 { panic('substr($start, $end) out of bounds (len=$s.len)') @@ -345,12 +345,12 @@ pub fn (s string) substr(start, end int) string { } res.str[len] = `\0` -/* +/* res := string { str: s.str + start len: len } -*/ +*/ return res } @@ -531,16 +531,16 @@ pub fn (ar []int) contains(val int) bool { return false } -/* +/* pub fn (a []string) to_c() voidptr { - mut res := malloc(sizeof(byteptr) * a.len) + mut res := malloc(sizeof(byteptr) * a.len) for i := 0; i < a.len; i++ { val := a[i] - res[i] = val.str + res[i] = val.str } - return res + return res } -*/ +*/ fn is_space(c byte) bool { return C.isspace(c) @@ -563,8 +563,8 @@ pub fn (s string) trim_space() string { end-- } if i > end + 1 { - return s - } + return s + } res := s.substr(i, end + 1) return res } @@ -599,12 +599,12 @@ pub fn (s string) trim_left(cutset string) string { pub fn (s string) trim_right(cutset string) string { if s.len == 0 { - return s - } - mut pos := s.len - 1 + return s + } + mut pos := s.len - 1 for s[pos] == cutset[0] { - pos-- - } + pos-- + } return s.left(pos+1) } @@ -743,14 +743,14 @@ pub fn (s string) free() { free(s.str) } -/* +/* fn (arr []string) free() { for s in arr { s.free() } C.free(arr.data) } -*/ +*/ // all_before('23:34:45.234', '.') == '23:34:45' pub fn (s string) all_before(dot string) string { @@ -848,14 +848,14 @@ pub fn (c byte) is_white() bool { pub fn (s string) hash() int { - //mut h := s.hash_cache - mut h := 0 - if h == 0 && s.len > 0 { - for c in s { - h = h * 31 + int(c) + //mut h := s.hash_cache + mut h := 0 + if h == 0 && s.len > 0 { + for c in s { + h = h * 31 + int(c) } - } - return h + } + return h } pub fn (s string) bytes() []byte {