fix single file programs without `fn main` and REPL (allow imports,

function definitions, consts, etc)
pull/751/head
Alexander Medvednikov 2019-06-28 12:41:09 +02:00
parent fd9163f715
commit bd49977feb
5 changed files with 31 additions and 28 deletions

View File

@ -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?

View File

@ -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()

View File

@ -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++
// 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
}
// println('is script')
p.print_tok()
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

View File

@ -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) {

View File

@ -1 +1,2 @@
println('Hello, World!')