From bd49977feb360bdee5452b81ec6bb0270981b43c Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 28 Jun 2019 12:41:09 +0200 Subject: [PATCH] fix single file programs without `fn main` and REPL (allow imports, function definitions, consts, etc) --- compiler/fn.v | 2 +- compiler/main.v | 9 ++++----- compiler/parser.v | 38 +++++++++++++++++++++----------------- compiler/table.v | 7 +++---- examples/hello_world.v | 3 ++- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/compiler/fn.v b/compiler/fn.v index da86dc7dae..22e1ad27e0 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -84,8 +84,8 @@ fn (f mut Fn) register_var(v Var) { } else { f.local_vars[f.var_idx] = new_var - f.var_idx++ } + f.var_idx++ } // vlib header file? diff --git a/compiler/main.v b/compiler/main.v index 22d0de8c7d..c787725313 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -343,7 +343,7 @@ string _STR_TMP(const char *fmt, ...) { if !c.table.main_exists() && !c.is_test { // It can be skipped in single file programs if c.is_script { - println('Generating main()...') + //println('Generating main()...') cgen.genln('int main() { $cgen.fn_main; return 0; }') } else { @@ -372,14 +372,14 @@ string _STR_TMP(const char *fmt, ...) { cgen.genln('return 1; }') } cgen.save() - c.log('flags=') if c.is_verbose { + c.log('flags=') println(c.table.flags) } c.cc() if c.is_test || c.is_run { if true || c.is_verbose { - println('============running $c.out_name==============================') + println('============ running $c.out_name ============') } mut cmd := if c.out_name.starts_with('/') { c.out_name @@ -866,10 +866,9 @@ 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') { - // TODO remove this once files without main compile correctly void_line := line.substr(line.index('(') + 1, line.len - 1) lines << void_line - source_code := 'fn main(){' + lines.join('\n') + '\n' + line + '}' + source_code := lines.join('\n') + '\n' + line os.write_file(file, source_code) mut v := new_v( ['v', '-repl', file]) v.compile() diff --git a/compiler/parser.v b/compiler/parser.v index 8ec039c664..ec959e72fa 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -77,6 +77,7 @@ mut: const ( EmptyFn = &Fn { } + MainFn= &Fn{name:'main'} ) fn (c mut V) new_parser(path string, run Pass) Parser { @@ -225,7 +226,7 @@ fn (p mut Parser) parse() { g += p.cgen.end_tmp() } // p.genln('; // global') - g += ('; // global') + g += '; // global' p.cgen.consts << g case EOF: p.log('end of parse()') @@ -238,25 +239,29 @@ fn (p mut Parser) parse() { default: // no `fn main`, add this "global" statement to cgen.fn_main if p.is_script && !p.is_test { - if p.cur_fn.scope_level == 0 { - // p.cur_fn.scope_level++ - } - // println('is script') - p.print_tok() + // cur_fn is empty since there was no fn main declared + // we need to set it to save and find variables + if p.first_run() { + if p.cur_fn.name == '' { + p.cur_fn = MainFn + } + return + } + if p.cur_fn.name == '' { + p.cur_fn = MainFn + } start := p.cgen.lines.len p.statement(true) + p.genln('') end := p.cgen.lines.len lines := p.cgen.lines.slice(start, end) - // p.cgen.fn_main << p.cgen.prev_line - // println('fn line:') - // println(p.cgen.fn_main + lines.join('\n')) + //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.cur_line = '' for i := start; i < end; i++ { - // p.cgen.lines[p.cgen.lines.len - 1] = '' p.cgen.lines[i] = '' } - // exit('') } else { p.error('unexpected token `${p.strtok()}`') @@ -664,13 +669,14 @@ fn (p mut Parser) error(s string) { p.cgen.save() // V git pull hint cur_path := os.getwd() - if p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') { + if !p.is_repl && ( 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('If you didn\'t modify the compiler\'s code, most likely there was a change that ') println('lead to this error.') - println('\nTry to run `git pull && make clean && make`, that will most likely fix it.') - println('\nIf this doesn\'t help, re-install V from source or download a precompiled' + ' binary from\nhttps://vlang.io.') + println('\nRun `git pull && make`, that will most likely fix it.') + //println('\nIf this doesn\'t help, re-install V from source or download a precompiled' + ' binary from\nhttps://vlang.io.') + println('\nIf this doesn\'t help, please create a GitHub issue.') println('=========================\n') } // p.scanner.debug_tokens() @@ -1349,9 +1355,7 @@ fn (p mut Parser) name_expr() string { // Function (not method btw, methods are handled in dot()) f := p.table.find_fn(name) if f.name == '' { - println(p.cur_fn.name) - println(p.cur_fn.args.len) - // if !p.first_run() && !p.translated { + // We are in a second pass, that means this function was not defined, throw an error. if !p.first_run() { // println('name_expr():') // If orig_name is a pkg, then printing undefined: `pkg` tells us nothing diff --git a/compiler/table.v b/compiler/table.v index 1b70b6a384..d067c91f09 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -210,7 +210,7 @@ fn (table &Table) known_type(typ string) bool { return false } -// TODO PERF O(N) this slows down the comiler a lot! +// TODO PERF O(N) this slows down the compiler a lot! fn (t &Table) find_fn(name string) Fn { for f in t.fns { if f.name == name { @@ -220,7 +220,7 @@ fn (t &Table) find_fn(name string) Fn { return Fn{} } -// TODO PERF O(N) this slows down the comiler a lot! +// TODO PERF O(N) this slows down the compiler a lot! fn (t &Table) known_fn(name string) bool { for f in t.fns { if f.name == name { @@ -249,10 +249,9 @@ fn (t mut Table) register_type(typ string) { // if t.types.filter( _.name == typ.name).len > 0 { // return // } - datyp := Type { + t.types << Type { name: typ } - t.types << datyp } fn (p mut Parser) register_type_with_parent(strtyp, parent string) { diff --git a/examples/hello_world.v b/examples/hello_world.v index fb964162bb..bdb69bc160 100644 --- a/examples/hello_world.v +++ b/examples/hello_world.v @@ -1 +1,2 @@ -println('Hello, World!') +println('Hello, World!') +