From e464c4acc5dcaf95808f0afd9fc43c1301c898de Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 5 Apr 2020 18:03:36 +0200 Subject: [PATCH] vfmt: more fixes + run on cgen.v --- vlib/v/ast/ast.v | 2 +- vlib/v/fmt/fmt.v | 175 +++++----- vlib/v/gen/cgen.v | 725 +++++++++++++++------------------------ vlib/v/scanner/scanner.v | 2 +- 4 files changed, 364 insertions(+), 540 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 4b23a2d5e9..f57c71783c 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -677,7 +677,7 @@ pub: is_multi bool line_nr int pos token.Position - same_line bool + //same_line bool } pub struct ConcatExpr { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 9160ce794d..a4d82a7bda 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -10,8 +10,8 @@ import ( ) const ( - tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t'] - // tabs = ['', ' ', ' ', ' ', ' '] + tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', + '\t\t\t\t\t\t\t'] max_len = 80 ) @@ -24,25 +24,23 @@ mut: line_len int single_line_if bool cur_mod string - file ast.File + file ast.File } pub fn fmt(file ast.File, table &table.Table) string { - mut f := Fmt{ + mut f := fmt.Fmt{ out: strings.new_builder(1000) table: table indent: 0 file: file } - f.mod(file.mod) - f.imports(file.imports) for stmt in file.stmts { f.stmt(stmt) } /* for comment in file.comments { - println('$comment.line_nr $comment.text') - } + println('$comment.line_nr $comment.text') + } */ return f.out.str().trim_space() + '\n' } @@ -57,7 +55,6 @@ fn (f mut Fmt) find_comment(line_nr int) { } } */ - pub fn (f mut Fmt) write(s string) { if f.indent > 0 && f.empty_line { f.out.write(tabs[f.indent]) @@ -79,9 +76,7 @@ pub fn (f mut Fmt) writeln(s string) { } fn (f mut Fmt) mod(mod ast.Module) { - if mod.name != 'main' { - f.writeln('module ${mod.name}\n') - } + f.writeln('module $mod.name\n') f.cur_mod = mod.name } @@ -89,8 +84,7 @@ fn (f mut Fmt) imports(imports []ast.Import) { if imports.len == 1 { imp_stmt_str := f.imp_stmt_str(imports[0]) f.writeln('import ${imp_stmt_str}\n') - } - else if imports.len > 1 { + } else if imports.len > 1 { f.writeln('import (') f.indent++ for imp in imports { @@ -149,7 +143,10 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.writeln('continue') } else {} - } + } + } + ast.Comment { + f.comment(it) } ast.ConstDecl { if it.is_pub { @@ -188,11 +185,11 @@ fn (f mut Fmt) stmt(node ast.Stmt) { } } ast.FnDecl { - //println('$it.name find_comment($it.pos.line_nr)') - //f.find_comment(it.pos.line_nr) + // println('$it.name find_comment($it.pos.line_nr)') + // f.find_comment(it.pos.line_nr) s := it.str(f.table) // f.write(it.str(f.table)) - f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast + f.write(s.replace(f.cur_mod + '.', '')) // `Expr` instead of `ast.Expr` in mod ast if !it.is_c { f.writeln(' {') f.stmts(it.stmts) @@ -235,13 +232,16 @@ fn (f mut Fmt) stmt(node ast.Stmt) { ast.GotoStmt { f.writeln('goto $it.name') } - ast.Comment { - f.comment(it) + ast.Import { + f.imports(f.file.imports) + } + ast.Module { + f.mod(it) } ast.Return { f.write('return') - // multiple returns if it.exprs.len > 1 { + // multiple returns f.write(' ') for i, expr in it.exprs { f.expr(expr) @@ -249,9 +249,8 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.write(', ') } } - } - // normal return - else if it.exprs.len == 1 { + } else if it.exprs.len == 1 { + // normal return f.write(' ') f.expr(it.exprs[0]) } @@ -334,11 +333,9 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) { for i, field in node.fields { if i == node.mut_pos { f.writeln('mut:') - } - else if i == node.pub_pos { + } else if i == node.pub_pos { f.writeln('pub:') - } - else if i == node.pub_mut_pos { + } else if i == node.pub_mut_pos { f.writeln('pub mut:') } if field.comment.text != '' && field.comment.pos.line_nr < field.pos.line_nr { @@ -349,22 +346,22 @@ fn (f mut Fmt) struct_decl(node ast.StructDecl) { f.write('\t$field.name ') f.write(strings.repeat(` `, max - field.name.len)) f.write(f.type_to_str(field.typ)) - //f.write('// $field.pos.line_nr') + // f.write('// $field.pos.line_nr') if field.comment.text != '' && field.comment.pos.line_nr == field.pos.line_nr { // Same line comment - f.write(' ') + f.write(' ') f.comment(field.comment) } else { - //if field.comment.text != '' { - //f.write (' // com linenr=$field.comment.pos.line_nr') - //} + // if field.comment.text != '' { + // f.write (' // com linenr=$field.comment.pos.line_nr') + // } f.writeln('') } } f.writeln('}\n') } -fn (f &Fmt) type_to_str(t table.Type) string { +fn (f Fmt) type_to_str(t table.Type) string { res := f.table.type_to_str(t) return res.replace(f.cur_mod + '.', '') } @@ -372,12 +369,11 @@ fn (f &Fmt) type_to_str(t table.Type) string { fn (f mut Fmt) expr(node ast.Expr) { match node { ast.ArrayInit { - // `x := []string` if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type { + // `x := []string` f.write(f.table.type_to_str(it.typ)) - } - // `[1,2,3]` - else { + } else { + // `[1,2,3]` // type_sym := f.table.get_type_symbol(it.typ) f.write('[') for i, expr in it.exprs { @@ -430,8 +426,7 @@ fn (f mut Fmt) expr(node ast.Expr) { f.call_args(it.args) f.write(')') f.or_expr(it.or_block) - } - else { + } else { name := short_module(it.name) f.write('${name}(') f.call_args(it.args) @@ -449,42 +444,12 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write(it.val) } ast.IfExpr { - single_line := it.branches.len == 2 && it.has_else // - && it.branches[0].stmts.len == 1 && it.branches[1].stmts.len == 1 - f.single_line_if = single_line - for i, branch in it.branches { - if i == 0 { - f.write('if ') - f.expr(branch.cond) - f.write(' {') - } - else if i < it.branches.len - 1 || !it.has_else { - f.write('} else if ') - f.expr(branch.cond) - f.write(' {') - } - else if i == it.branches.len - 1 && it.has_else { - f.write('} else {') - } - if single_line { - f.write(' ') - } - else { - f.writeln('') - } - f.stmts(branch.stmts) - if single_line { - f.write(' ') - } - } - f.write('}') - f.single_line_if = false + f.if_expr(it) } ast.Ident { if it.kind == .blank_ident { f.write('_') - } - else { + } else { name := short_module(it.name) f.write(name) } @@ -509,13 +474,12 @@ fn (f mut Fmt) expr(node ast.Expr) { f.indent++ /* mut max := 0 - for i, key in it.keys { - if key.len > max { - max = key.len - } - } - */ - + for i, key in it.keys { + if key.len > max { + max = key.len + } + } + */ for i, key in it.keys { f.expr(key) // f.write(strings.repeat(` `, max - field.name.len)) @@ -540,15 +504,13 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write(', ') } } - } - else { + } else { // else branch f.write('else') } if branch.stmts.len == 0 { f.writeln(' {}') - } - else { + } else { f.writeln(' {') f.stmts(branch.stmts) f.writeln('}') @@ -588,18 +550,13 @@ fn (f mut Fmt) expr(node ast.Expr) { f.write(it.field) } ast.StringLiteral { - if it.val.contains("'") { - f.write('"$it.val"') - } - else { - f.write("'$it.val'") - } + if it.val.contains("'") { f.write('"$it.val"') } else { f.write("'$it.val'") } } ast.StringInterLiteral { f.write("'") for i, val in it.vals { f.write(val) - if i>=it.exprs.len { + if i >= it.exprs.len { continue } f.write('$') @@ -608,7 +565,7 @@ fn (f mut Fmt) expr(node ast.Expr) { f.expr(it.exprs[i]) f.write(it.expr_fmts[i]) f.write('}') - }else{ + } else { f.expr(it.exprs[i]) } } @@ -620,8 +577,7 @@ fn (f mut Fmt) expr(node ast.Expr) { // `Foo{}` on one line if there are no fields if it.fields.len == 0 { f.write('$name{}') - } - else { + } else { f.writeln('$name{') for i, field in it.fields { f.write('\t$field: ') @@ -632,8 +588,7 @@ fn (f mut Fmt) expr(node ast.Expr) { } } ast.Type { - f.writeln(f.type_to_str(it.typ)) - + f.write(f.type_to_str(it.typ)) } ast.TypeOf { f.write('typeof(') @@ -683,7 +638,7 @@ fn (f mut Fmt) comment(node ast.Comment) { if !node.text.contains('\n') { is_separate_line := node.text.starts_with('|') if is_separate_line { - f.writeln('// ${node.text[1..]}')// $node.pos.line_nr') + f.writeln('// ${node.text[1..]}') // $node.pos.line_nr') } else { f.out.go_back(1) f.writeln('// $node.text') @@ -707,5 +662,31 @@ fn short_module(name string) string { if vals.len < 2 { return name } - return vals[vals.len-2] + '.' + vals[vals.len-1] + return vals[vals.len - 2] + '.' + vals[vals.len - 1] +} + +fn (f mut Fmt) if_expr(it ast.IfExpr) { + single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == + 1 && it.branches[1].stmts.len == 1 + f.single_line_if = single_line + for i, branch in it.branches { + if i == 0 { + f.write('if ') + f.expr(branch.cond) + f.write(' {') + } else if i < it.branches.len - 1 || !it.has_else { + f.write('} else if ') + f.expr(branch.cond) + f.write(' {') + } else if i == it.branches.len - 1 && it.has_else { + f.write('} else {') + } + if single_line { f.write(' ') } else { f.writeln('') } + f.stmts(branch.stmts) + if single_line { + f.write(' ') + } + } + f.write('}') + f.single_line_if = false } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index cdf5c45717..efb554eba4 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1,3 +1,6 @@ +// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. module gen import ( @@ -11,13 +14,11 @@ import ( v.util ) -// Full list of C reserved words, from: https://en.cppreference.com/w/c/keyword const ( - c_reserved = ['delete', 'exit', 'unix', - 'error', 'calloc', 'malloc', 'free', 'panic', - 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', - 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', - 'volatile', 'while', ] + c_reserved = ['delete', 'exit', 'unix', 'error', 'calloc', 'malloc', 'free', + 'panic', 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', + 'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', + 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'] ) struct Gen { @@ -50,18 +51,24 @@ mut: assign_op token.Kind // *=, =, etc (for array_set) defer_stmts []ast.DeferStmt defer_ifdef string - str_types []string// types that need automatic str() generation + str_types []string // types that need automatic str() generation threaded_fns []string // for generating unique wrapper types and fns for `go xxx()` } const ( - tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t', - '\t\t\t\t\t\t\t\t'] + tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', + '\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t'] ) pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string { + if true { // if + x := 10 // line + // sep + y := 20 + } else { + } // println('start cgen2') - mut g := Gen{ + mut g := gen.Gen{ out: strings.new_builder(100) typedefs: strings.new_builder(100) definitions: strings.new_builder(100) @@ -75,7 +82,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string indent: -1 } g.init() - // + // mut autofree_used := false for file in files { g.file = file @@ -89,15 +96,14 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string // cgen test or building V // println('autofree=false') g.autofree = false - } - else { + } else { g.autofree = true autofree_used = true } g.stmts(file.stmts) } if autofree_used { - g.autofree = true // so that void _vcleanup is generated + g.autofree = true // so that void _vcleanup is generated } g.write_variadic_types() // g.write_str_definitions() @@ -105,20 +111,21 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string if g.is_test { g.write_tests_main() } - // + // g.finish() - return g.hashes() + g.typedefs.str() + g.definitions.str() + g.gowrappers.str() + g.stringliterals.str() + g.out.str() + return g.hashes() + g.typedefs.str() + g.definitions.str() + g.gowrappers.str() + + g.stringliterals.str() + g.out.str() } -pub fn (g &Gen) hashes() string { - mut res := c_commit_hash_default.replace('@@@', util.vhash() ) - res += c_current_commit_hash_default.replace('@@@', util.githash( g.pref.building_v ) ) +pub fn (g Gen) hashes() string { + mut res := c_commit_hash_default.replace('@@@', util.vhash()) + res += c_current_commit_hash_default.replace('@@@', util.githash(g.pref.building_v)) return res } pub fn (g mut Gen) init() { g.definitions.writeln('// Generated by the V compiler') - g.definitions.writeln('#include ') // int64_t etc + g.definitions.writeln('#include ') // int64_t etc g.definitions.writeln(c_builtin_types) g.definitions.writeln(c_headers) g.definitions.writeln('\nstring _STR(const char*, ...);\n') @@ -130,7 +137,7 @@ pub fn (g mut Gen) init() { g.write_sorted_types() g.write_multi_return_types() g.definitions.writeln('// end of definitions #endif') - // + // g.stringliterals.writeln('') g.stringliterals.writeln('// >> string literal consts') g.stringliterals.writeln('void vinit_string_literals(){') @@ -192,7 +199,7 @@ pub fn (g mut Gen) typ(t table.Type) string { return styp } -// +// pub fn (g mut Gen) write_typedef_types() { for typ in g.table.types { match typ.kind { @@ -225,11 +232,10 @@ pub fn (g mut Gen) write_typedef_types() { g.definitions.writeln(');') } } - // else { continue } - } + } } } @@ -270,7 +276,8 @@ pub fn (g mut Gen) write_variadic_types() { } } -pub fn (g &Gen) save() {} +pub fn (g Gen) save() { +} pub fn (g mut Gen) write(s string) { if g.indent > 0 && g.empty_line { @@ -355,8 +362,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { expr := g.out.after(pos) g.out.go_back(expr.len) g.typedefs.writeln('$expr ,') - } - else { + } else { g.typedefs.writeln('\t${name}_$val, // $j') } } @@ -374,21 +380,16 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.writeln(';') } } - } + } } ast.FnDecl { - g.fn_decl = it // &it + g.fn_decl = it // &it g.gen_fn_decl(it) g.writeln('') } ast.ForCStmt { g.write('for (') - if !it.has_init { - g.write('; ') - } - else { - g.stmt(it.init) - } + if !it.has_init { g.write('; ') } else { g.stmt(it.init) } g.expr(it.cond) g.write('; ') // g.stmt(it.inc) @@ -402,12 +403,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { } ast.ForStmt { g.write('while (') - if it.is_inf { - g.write('1') - } - else { - g.expr(it.cond) - } + if it.is_inf { g.write('1') } else { g.expr(it.cond) } g.writeln(') {') g.stmts(it.stmts) g.writeln('}') @@ -473,8 +469,7 @@ fn (g mut Gen) write_defer_stmts() { g.writeln(defer_stmt.ifdef) g.stmts(defer_stmt.stmts) g.writeln('#endif') - } - else { + } else { g.stmts(defer_stmt.stmts) } } @@ -492,8 +487,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.writeln('\tint $it.val_var = $i;') g.stmts(it.stmts) g.writeln('}') - } - else if it.kind == .array { + } else if it.kind == .array { // TODO: // `for num in nums {` g.writeln('// FOR IN') @@ -502,24 +496,15 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.write('for (int $i = 0; $i < ') g.expr(it.cond) cond_type_is_ptr := table.type_is_ptr(it.cond_type) - if cond_type_is_ptr { - g.writeln('->') - } else { - g.writeln('.') - } + if cond_type_is_ptr { g.writeln('->') } else { g.writeln('.') } g.write('len; $i++) {') g.write('\t$styp $it.val_var = (($styp*)') g.expr(it.cond) - if cond_type_is_ptr { - g.writeln('->') - } else { - g.writeln('.') - } + if cond_type_is_ptr { g.writeln('->') } else { g.writeln('.') } g.write('data)[$i];') g.stmts(it.stmts) g.writeln('}') - } - else if it.kind == .map { + } else if it.kind == .map { // `for num in nums {` g.writeln('// FOR IN') key_styp := g.typ(it.key_type) @@ -538,8 +523,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.writeln(', $key, &($val_styp[]){ $zero }));') g.stmts(it.stmts) g.writeln('}') - } - else if table.type_is(it.cond_type, .variadic) { + } else if table.type_is(it.cond_type, .variadic) { g.writeln('// FOR IN') i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var } styp := g.typ(it.cond_type) @@ -551,8 +535,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.writeln('.args[$i];') g.stmts(it.stmts) g.writeln('}') - } - else if it.kind == .string { + } else if it.kind == .string { i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var } g.write('for (int $i = 0; $i < ') g.expr(it.cond) @@ -566,7 +549,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { } // use instead of expr() when you need to cast to sum type (can add other casts also) -fn (g mut Gen) expr_with_cast(expr ast.Expr, got_type table.Type, exp_type table.Type) { +fn (g mut Gen) expr_with_cast(expr ast.Expr, got_type, exp_type table.Type) { // cast to sum type if exp_type != table.void_type { exp_sym := g.table.get_type_symbol(exp_type) @@ -633,7 +616,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { return_type = it.return_type } else {} - } + } is_optional := table.type_is(return_type, .optional) mr_var_name := 'mr_$assign_stmt.pos.pos' mr_styp := g.typ(return_type) @@ -656,15 +639,13 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } g.expr(ident) if is_optional { - mr_styp2 := mr_styp[7..] // remove Option_ + mr_styp2 := mr_styp[7..] // remove Option_ g.writeln(' = (*(${mr_styp2}*)${mr_var_name}.data).arg$i;') - } - else { + } else { g.writeln(' = ${mr_var_name}.arg$i;') } } - } - else { + } else { // `a := 1` | `a,b := 1,2` for i, ident in assign_stmt.left { val := assign_stmt.right[i] @@ -680,20 +661,18 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { return_type = it.return_type } else {} - } + } gen_or := is_call && table.type_is(return_type, .optional) g.is_assign_rhs = true if ident.kind == .blank_ident { if is_call { g.expr(val) - } - else { + } else { g.write('{$styp _ = ') g.expr(val) g.writeln(';}') } - } - else { + } else { right_sym := g.table.get_type_symbol(assign_stmt.right_types[i]) mut is_fixed_array_init := false match val { @@ -701,9 +680,9 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { is_fixed_array_init = right_sym.kind == .array_fixed } else {} - } + } is_decl := assign_stmt.op == .decl_assign - //g.write('/*assign_stmt*/') + // g.write('/*assign_stmt*/') if is_decl { g.write('$styp ') } @@ -717,14 +696,9 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } if !is_fixed_array_init { g.write(' = ') - if !is_decl { - g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ) - } - else { - g.expr(val) - } - } - else if is_fixed_array_init { + if !is_decl { g.expr_with_cast(val, assign_stmt.left_types[i], + ident_var_info.typ) } else { g.expr(val) } + } else if is_fixed_array_init { g.write('= {0}') } if gen_or { @@ -758,8 +732,7 @@ fn (g mut Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, ad g.write(' array_clone(&') g.expr(val) g.write(')') - } - else if g.autofree && right_sym.kind == .string && is_ident { + } else if g.autofree && right_sym.kind == .string && is_ident { if add_eq { g.write('=') } @@ -779,23 +752,13 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { g.reset_tmp_count() is_main := it.name == 'main' if is_main { - if g.pref.os == .windows { - g.write('int wmain(int ___argc, wchar_t *___argv[], wchar_t *___envp[]') - } else { - g.write('int ${it.name}(int ___argc, char** ___argv') - } - } - else { + if g.pref.os == .windows { g.write('int wmain(int ___argc, wchar_t *___argv[], wchar_t *___envp[]') } else { g.write('int ${it.name}(int ___argc, char** ___argv') } + } else { mut name := it.name if it.is_method { name = g.table.get_type_symbol(it.receiver.typ).name + '_' + name } - if it.is_c { - name = name.replace('.', '__') - } - else { - name = c_name(name) - } + if it.is_c { name = name.replace('.', '__') } else { name = c_name(name) } if name.starts_with('_op_') { name = op_to_fn_name(name) } @@ -807,21 +770,21 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { // Receiver is the first argument /* if it.is_method { - mut styp := g.typ(it.receiver.typ) - // if table.type_nr_muls(it.receiver.typ) > 0 { - // if it.rec_mut { - // styp += '*' - // } - g.write('$styp $it.receiver.name ') - // TODO mut - g.definitions.write('$styp $it.receiver.name') - if it.args.len > 0 { - g.write(', ') - g.definitions.write(', ') - } - } + mut styp := g.typ(it.receiver.typ) + // if table.type_nr_muls(it.receiver.typ) > 0 { + // if it.rec_mut { + // styp += '*' + // } + g.write('$styp $it.receiver.name ') + // TODO mut + g.definitions.write('$styp $it.receiver.name') + if it.args.len > 0 { + g.write(', ') + g.definitions.write(', ') + } + } */ - // + // g.fn_args(it.args, it.is_variadic) if it.no_body { // Just a function header. @@ -839,11 +802,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { if g.autofree { g.writeln('free(_const_os__args.data); // empty, inited in _vinit()') } - if g.pref.os == .windows { - g.writeln('_const_os__args = os__init_os_args_wide(___argc, ___argv);') - } else { - g.writeln('_const_os__args = os__init_os_args(___argc, (byteptr*)___argv);') - } + if g.pref.os == .windows { g.writeln('_const_os__args = os__init_os_args_wide(___argc, ___argv);') } else { g.writeln('_const_os__args = os__init_os_args(___argc, (byteptr*)___argv);') } } } g.stmts(it.stmts) @@ -914,7 +873,7 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) { no_names := args.len > 0 && args[0].name == 'arg_1' for i, arg in args { arg_type_sym := g.table.get_type_symbol(arg.typ) - mut arg_type_name := g.typ(arg.typ) // arg_type_sym.name.replace('.', '__') + mut arg_type_name := g.typ(arg.typ) // arg_type_sym.name.replace('.', '__') is_varg := i == args.len - 1 && is_variadic if is_varg { varg_type_str := int(arg.typ).str() @@ -929,20 +888,17 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) { if !info.is_anon { g.write(arg_type_name + ' ' + arg.name) g.definitions.write(arg_type_name + ' ' + arg.name) - } - else { + } else { g.write('${g.typ(func.return_type)} (*$arg.name)(') g.definitions.write('${g.typ(func.return_type)} (*$arg.name)(') g.fn_args(func.args, func.is_variadic) g.write(')') g.definitions.write(')') } - } - else if no_names { + } else if no_names { g.write(arg_type_name) g.definitions.write(arg_type_name) - } - else { + } else { mut nr_muls := table.type_nr_muls(arg.typ) s := arg_type_name + ' ' + arg.name if arg.is_mut { @@ -972,8 +928,7 @@ fn (g mut Gen) expr(node ast.Expr) { elem_type_str := g.typ(it.elem_type) if it.exprs.len == 0 { g.write('new_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str))') - } - else { + } else { len := it.exprs.len g.write('new_array_from_c_array($len, $len, sizeof($elem_type_str), ') g.writeln('($elem_type_str[$len]){\t') @@ -983,8 +938,8 @@ fn (g mut Gen) expr(node ast.Expr) { } g.write('\n})') } + } else { } - else {} } ast.AsCast { styp := g.typ(it.typ) @@ -1016,12 +971,7 @@ fn (g mut Gen) expr(node ast.Expr) { sym := g.table.get_type_symbol(it.typ) if sym.kind == .string { // `tos(str, len)`, `tos2(str)` - if it.has_arg { - g.write('tos(') - } - else { - g.write('tos2(') - } + if it.has_arg { g.write('tos(') } else { g.write('tos2(') } g.expr(it.expr) expr_sym := g.table.get_type_symbol(it.expr_type) if expr_sym.kind == .array { @@ -1034,11 +984,9 @@ fn (g mut Gen) expr(node ast.Expr) { g.expr(it.arg) } g.write(')') - } - else if sym.kind == .sum_type { + } else if sym.kind == .sum_type { g.expr_with_cast(it.expr, it.expr_type, it.typ) - } - else { + } else { // styp := g.table.Type_to_str(it.typ) styp := g.typ(it.typ) // g.write('($styp)(') @@ -1082,9 +1030,8 @@ fn (g mut Gen) expr(node ast.Expr) { if it.val.starts_with('0o') { g.write('0') g.write(it.val[2..]) - } - else { - g.write(it.val) // .int().str()) + } else { + g.write(it.val) // .int().str()) } } ast.MatchExpr { @@ -1108,8 +1055,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.write(', ') } g.write('})') - } - else { + } else { g.write('new_map(1, sizeof($value_typ_str))') } } @@ -1144,20 +1090,17 @@ fn (g mut Gen) expr(node ast.Expr) { } ast.StringLiteral { if it.is_raw { - escaped_val := it.val.replace_each(['"', '\\"', - '\\', '\\\\']) + escaped_val := it.val.replace_each(['"', '\\"', '\\', '\\\\']) g.write('tos3("$escaped_val")') return } - escaped_val := it.val.replace_each(['"', '\\"', - '\r\n', '\\n', - '\n', '\\n']) + escaped_val := it.val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', + '\\n']) if g.is_c_call || it.is_c { // In C calls we have to generate C strings // `C.printf("hi")` => `printf("hi");` g.write('"$escaped_val"') - } - else { + } else { g.write('tos3("$escaped_val")') } } @@ -1173,8 +1116,7 @@ fn (g mut Gen) expr(node ast.Expr) { // if table.type_nr_muls(it.expr_type) > 0 { if table.type_is_ptr(it.expr_type) { g.write('->') - } - else { + } else { // g.write('. /*typ= $it.expr_type */') // ${g.typ(it.expr_type)} /') g.write('.') } @@ -1209,13 +1151,11 @@ fn (g mut Gen) typeof_expr(node ast.TypeOf) { g.write('tos3( /* ${sym.name} */ v_typeof_sumtype_${sum_type_idx}( (') g.expr(node.expr) g.write(').typ ))') - } - else if sym.kind == .array_fixed { + } else if sym.kind == .array_fixed { fixed_info := sym.info as table.ArrayFixed elem_sym := g.table.get_type_symbol(fixed_info.elem_type) g.write('tos3("[$fixed_info.size]${elem_sym.name}")') - } - else { + } else { g.write('tos3("${sym.name}")') } } @@ -1254,14 +1194,12 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { if ast.expr_is_blank_ident(node.left) { if is_call { g.expr(node.val) - } - else { + } else { g.write('{${g.typ(node.left_type)} _ = ') g.expr(node.val) g.writeln(';}') } - } - else { + } else { g.is_assign_lhs = true if table.type_is(node.right_type, .optional) { g.right_is_opt = true @@ -1278,8 +1216,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { // arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val` if !g.is_array_set && !str_add { g.write(' $node.op.str() ') - } - else if str_add { + } else if str_add { g.write(', ') } g.is_assign_lhs = false @@ -1298,8 +1235,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { if g.is_array_set { g.write(' })') g.is_array_set = false - } - else if str_add { + } else if str_add { g.write(')') } g.right_is_opt = false @@ -1320,37 +1256,37 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { // g.infix_op = node.op if node.left_type == table.string_type_idx && node.op != .key_in { fn_name := match node.op { - .plus{ + .plus { 'string_add(' } - .eq{ + .eq { 'string_eq(' } - .ne{ + .ne { 'string_ne(' } - .lt{ + .lt { 'string_lt(' } - .le{ + .le { 'string_le(' } - .gt{ + .gt { 'string_gt(' } - .ge{ + .ge { 'string_ge(' } else { - '/*node error*/'} - } + '/*node error*/' + } + } g.write(fn_name) g.expr(node.left) g.write(', ') g.expr(node.right) g.write(')') - } - else if node.op == .key_in { + } else if node.op == .key_in { right_sym := g.table.get_type_symbol(node.right_type) if right_sym.kind == .array { match node.right { @@ -1364,30 +1300,28 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { return } else {} - } + } styp := g.typ(node.left_type) g.write('_IN($styp, ') g.expr(node.left) g.write(', ') g.expr(node.right) g.write(')') - } - else if right_sym.kind == .map { + } else if right_sym.kind == .map { g.write('_IN_MAP(') g.expr(node.left) g.write(', ') g.expr(node.right) g.write(')') - } - else if right_sym.kind == .string { + } else if right_sym.kind == .string { g.write('string_contains(') g.expr(node.right) g.write(', ') g.expr(node.left) g.write(')') } - } - else if node.op == .left_shift && g.table.get_type_symbol(node.left_type).kind == .array { + } else if node.op == .left_shift && g.table.get_type_symbol(node.left_type).kind == + .array { // arr << val tmp := g.new_tmp_var() sym := g.table.get_type_symbol(node.left_type) @@ -1401,8 +1335,7 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { g.expr(node.right) styp := g.typ(node.left_type) g.write('), $tmp, $styp)') - } - else { + } else { // push a single element elem_type_str := g.typ(info.elem_type) // g.write('array_push(&') @@ -1412,9 +1345,8 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { g.expr(node.right) g.write('), $tmp, $elem_type_str)') } - } - else { - need_par := node.op in [.amp, .pipe, .xor] // `x & y == 0` => `(x & y) == 0` in C + } else { + need_par := node.op in [.amp, .pipe, .xor] // `x & y == 0` => `(x & y) == 0` in C if need_par { g.write('(') } @@ -1455,41 +1387,27 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) { if is_expr { // TODO too many branches. maybe separate ?: matches g.write(' : ') - } - else { + } else { g.writeln('else {') } - } - else { + } else { if j > 0 { - if is_expr { - g.write(' : ') - } - else { - g.write('else ') - } - } - if is_expr { - g.write('(') - } - else { - g.write('if (') + if is_expr { g.write(' : ') } else { g.write('else ') } } + if is_expr { g.write('(') } else { g.write('if (') } for i, expr in branch.exprs { if node.is_sum_type { g.expr(node.cond) g.write('.typ == ') // g.write('${tmp}.typ == ') // sum_type_str - } - else if type_sym.kind == .string { + } else if type_sym.kind == .string { g.write('string_eq(') - // + // g.expr(node.cond) g.write(', ') // g.write('string_eq($tmp, ') - } - else { + } else { g.expr(node.cond) g.write(' == ') // g.write('$tmp == ') @@ -1502,12 +1420,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) { g.write(' || ') } } - if is_expr { - g.write(') ? ') - } - else { - g.writeln(') {') - } + if is_expr { g.write(') ? ') } else { g.writeln(') {') } } // g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/') if node.is_sum_type && branch.exprs.len > 0 && !node.is_expr { @@ -1525,7 +1438,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) { else { verror('match sum type') } - } + } } g.stmts(branch.stmts) if !g.inside_ternary { @@ -1557,7 +1470,7 @@ fn (g mut Gen) ident(node ast.Ident) { // `println(x)` => `println(*(int*)x.data)` if it.is_optional && !(g.is_assign_lhs && g.right_is_opt) { g.write('/*opt*/') - styp := g.typ(it.typ)[7..] // Option_int => int TODO perf? + styp := g.typ(it.typ)[7..] // Option_int => int TODO perf? g.write('(*($styp*)${name}.data)') return } @@ -1581,7 +1494,8 @@ fn (g mut Gen) if_expr(node ast.IfExpr) { // one line ?: // TODO clean this up once `is` is supported // TODO: make sure only one stmt in each branch - if node.is_expr && node.branches.len >= 2 && node.has_else && type_sym.kind != .void { + if node.is_expr && node.branches.len >= 2 && node.has_else && type_sym.kind != + .void { g.inside_ternary = true g.write('(') for i, branch in node.branches { @@ -1596,8 +1510,7 @@ fn (g mut Gen) if_expr(node ast.IfExpr) { } g.write(')') g.inside_ternary = false - } - else { + } else { guard_ok := g.new_tmp_var() mut is_guard := false for i, branch in node.branches { @@ -1616,20 +1529,13 @@ fn (g mut Gen) if_expr(node ast.IfExpr) { g.expr(branch.cond) g.writeln(') {') } - } - } - else if i < node.branches.len - 1 || !node.has_else { + } + } else if i < node.branches.len - 1 || !node.has_else { g.write('} else if (') g.expr(branch.cond) g.writeln(') {') - } - else if i == node.branches.len - 1 && node.has_else { - if is_guard { - g.writeln('} if (!$guard_ok) { /* else */') - } - else { - g.writeln('} else {') - } + } else if i == node.branches.len - 1 && node.has_else { + if is_guard { g.writeln('} if (!$guard_ok) { /* else */') } else { g.writeln('} else {') } } // Assign ret value // if i == node.stmts.len - 1 && type_sym.kind != .void {} @@ -1653,12 +1559,10 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { if sym.kind == .string { g.write('string_substr(') g.expr(node.left) - } - else if sym.kind == .array { + } else if sym.kind == .array { g.write('array_slice(') g.expr(node.left) - } - else if sym.kind == .array_fixed { + } else if sym.kind == .array_fixed { // Convert a fixed array to V array when doing `fixed_arr[start..end]` g.write('array_slice(new_array_from_c_array(_ARR_LEN(') g.expr(node.left) @@ -1669,22 +1573,15 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.write('[0]), ') g.expr(node.left) g.write(')') - } - else { + } else { g.expr(node.left) } g.write(', ') - if it.has_low { - g.expr(it.low) - } - else { - g.write('0') - } + if it.has_low { g.expr(it.low) } else { g.write('0') } g.write(', ') if it.has_high { g.expr(it.high) - } - else { + } else { g.expr(node.left) g.write('.len') } @@ -1702,8 +1599,7 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.write('[') g.expr(node.index) g.write(']') - } - else if sym.kind == .array { + } else if sym.kind == .array { info := sym.info as table.Array elem_type_str := g.typ(info.elem_type) // `vals[i].field = x` is an exception and requires `array_get`: @@ -1736,16 +1632,16 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.expr(node.index) g.write(') ') op := match g.assign_op { - .mult_assign{ + .mult_assign { '*' } else { - ''} - } + '' + } + } g.write(op) } - } - else { + } else { g.write('(*($elem_type_str*)array_get(') if left_is_ptr { g.write('*') @@ -1755,8 +1651,7 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.expr(node.index) g.write('))') } - } - else if sym.kind == .map { + } else if sym.kind == .map { info := sym.info as table.Map elem_type_str := g.typ(info.value_type) if g.is_assign_lhs { @@ -1769,14 +1664,13 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.write(', ') g.expr(node.index) g.write(', &($elem_type_str[]) { ') - } - else { + } else { /* g.write('(*($elem_type_str*)map_get2(') - g.expr(node.left) - g.write(', ') - g.expr(node.index) - g.write('))') + g.expr(node.left) + g.write(', ') + g.expr(node.index) + g.write('))') */ zero := g.type_default(info.value_type) g.write('(*($elem_type_str*)map_get3(') @@ -1785,15 +1679,13 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { g.expr(node.index) g.write(', &($elem_type_str[]){ $zero }))') } - } - else if sym.kind == .string && !table.type_is_ptr(node.left_type) { + } else if sym.kind == .string && !table.type_is_ptr(node.left_type) { g.write('string_at(') g.expr(node.left) g.write(', ') g.expr(node.index) g.write(')') - } - else { + } else { g.expr(node.left) g.write('[') g.expr(node.index) @@ -1816,7 +1708,7 @@ fn (g mut Gen) return_statement(node ast.Return) { mr_info := typ_sym.info as table.MultiReturn mut styp := g.typ(g.fn_decl.return_type) if fn_return_is_optional { - styp = styp[7..] // remove 'Option_' + styp = styp[7..] // remove 'Option_' g.write('opt_ok(& ($styp []) { ') } g.write('($styp){') @@ -1831,8 +1723,7 @@ fn (g mut Gen) return_statement(node ast.Return) { if fn_return_is_optional { g.write(' }, sizeof($styp))') } - } - else if node.exprs.len == 1 { + } else if node.exprs.len == 1 { // normal return g.write(' ') // `return opt_ok(expr)` for functions that expect an optional @@ -1847,13 +1738,13 @@ fn (g mut Gen) return_statement(node ast.Return) { ast.CallExpr { // TODO: why? if !it.is_method { - is_error = true // TODO check name 'error' + is_error = true // TODO check name 'error' } } else {} - } + } if !is_none && !is_error { - styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' + styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' g.write('opt_ok(& ($styp []) { ') g.expr(node.exprs[0]) g.writeln(' }, sizeof($styp));') @@ -1880,10 +1771,10 @@ fn (g mut Gen) const_decl(node ast.ConstDecl) { g.out.go_back(val.len) match field.expr { ast.CharLiteral { - g.const_decl_simple_define( name, val ) + g.const_decl_simple_define(name, val) } ast.IntegerLiteral { - g.const_decl_simple_define( name, val ) + g.const_decl_simple_define(name, val) } ast.StringLiteral { g.definitions.writeln('string _const_$name; // a string literal, inited later') @@ -1896,11 +1787,11 @@ fn (g mut Gen) const_decl(node ast.ConstDecl) { g.definitions.writeln('$styp _const_$name; // inited later') g.inits.writeln('\t_const_$name = $val;') } - } + } } } -fn (g mut Gen) const_decl_simple_define(name, val string){ +fn (g mut Gen) const_decl_simple_define(name, val string) { // Simple expressions should use a #define // so that we don't pollute the binary with unnecessary global vars // Do not do this when building a module, otherwise the consts @@ -1922,21 +1813,19 @@ fn (g mut Gen) struct_init(it ast.StructInit) { styp := g.typ(it.typ) is_amp := g.is_amp if is_amp { - g.out.go_back(1) // delete the & already generated in `prefix_expr() + g.out.go_back(1) // delete the & already generated in `prefix_expr() g.write('($styp*)memdup(&($styp){') - } - else { + } else { g.writeln('($styp){') } mut fields := []string - mut inited_fields := []string // TODO this is done in checker, move to ast node + mut inited_fields := []string // TODO this is done in checker, move to ast node if it.fields.len == 0 && it.exprs.len > 0 { // Get fields for {a,b} short syntax. Fields array wasn't set in the parser. for f in info.fields { fields << f.name } - } - else { + } else { fields = it.fields } // / User set fields @@ -1955,7 +1844,7 @@ fn (g mut Gen) struct_init(it ast.StructInit) { } field_name := c_name(field.name) zero := g.type_default(field.typ) - g.writeln('\t.$field_name = $zero,') // zer0') + g.writeln('\t.$field_name = $zero,') // zer0') } } if it.fields.len == 0 && info.fields.len == 0 { @@ -1998,7 +1887,8 @@ fn (g mut Gen) assoc(node ast.Assoc) { } fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { - is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len - 1], .variadic) + is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len - + 1], .variadic) mut arg_no := 0 for arg in args { if is_variadic && arg_no == expected_types.len - 1 { @@ -2006,12 +1896,7 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { } // some c fn definitions dont have args (cfns.v) or are not updated in checker // when these are fixed we wont need this check - if arg_no < expected_types.len { - g.ref_or_deref_arg(arg, expected_types[arg_no]) - } - else { - g.expr(arg.expr) - } + if arg_no < expected_types.len { g.ref_or_deref_arg(arg, expected_types[arg_no]) } else { g.expr(arg.expr) } if arg_no < args.len - 1 || is_variadic { g.write(', ') } @@ -2026,28 +1911,25 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { g.variadic_args[varg_type_str] = variadic_count } g.write('($struct_name){.len=$variadic_count,.args={') - if variadic_count > 0 { - for j in arg_no .. args.len { - g.ref_or_deref_arg(args[j], varg_type) - if j < args.len - 1 { + if variadic_count > 0 { for j in arg_no .. args.len { + g.ref_or_deref_arg(args[j], varg_type)if j < args.len - 1 { g.write(', ') } } - } else { - g.write('0') - } + } else { g.write('0') + } g.write('}}') } } [inline] fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { - arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs + arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in + table.pointer_type_idxs expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs if arg.is_mut && !arg_is_ptr { g.write('&/*mut*/') - } - else if arg_is_ptr && !expr_is_ptr { + } else if arg_is_ptr && !expr_is_ptr { if arg.is_mut { sym := g.table.get_type_symbol(expected_type) if sym.kind == .array { @@ -2060,8 +1942,7 @@ fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { } } g.write('&/*qq*/') - } - else if !arg_is_ptr && expr_is_ptr { + } else if !arg_is_ptr && expr_is_ptr { // Dereference a pointer if a value is required g.write('*/*d*/') } @@ -2132,7 +2013,7 @@ const ( ) fn (g mut Gen) write_builtin_types() { - mut builtin_types := []table.TypeSymbol // builtin types + mut builtin_types := []table.TypeSymbol // builtin types // builtin types need to be on top // everything except builtin will get sorted for builtin_name in builtins { @@ -2145,7 +2026,7 @@ fn (g mut Gen) write_builtin_types() { // Sort the types, make sure types that are referenced by other types // are added before them. fn (g mut Gen) write_sorted_types() { - mut types := []table.TypeSymbol // structs that need to be sorted + mut types := []table.TypeSymbol // structs that need to be sorted for typ in g.table.types { if !(typ.name in builtins) { types << typ @@ -2171,17 +2052,13 @@ fn (g mut Gen) write_types(types []table.TypeSymbol) { info := typ.info as table.Struct // g.definitions.writeln('typedef struct {') g.definitions.writeln('struct $name {') - if info.fields.len > 0 { - for field in info.fields { + if info.fields.len > 0 { for field in info.fields { type_name := g.typ(field.typ) field_name := c_name(field.name) - g.definitions.writeln('\t$type_name $field_name;') - } - } else { - g.definitions.writeln('EMPTY_STRUCT_DECLARATION;') - } + g.definitions.writeln('\t$type_name $field_name;')} + } else { g.definitions.writeln('EMPTY_STRUCT_DECLARATION;') } // g.definitions.writeln('} $name;\n') - // + // g.definitions.writeln('};\n') } table.Alias { @@ -2196,22 +2073,22 @@ int typ; } $name;') } table.ArrayFixed { - // .array_fixed { + // .array_fixed { styp := typ.name.replace('.', '__') // array_fixed_char_300 => char x[300] mut fixed := styp[12..] len := styp.after('_') fixed = fixed[..fixed.len - len.len - 1] g.definitions.writeln('typedef $fixed $styp [$len];') - // } + // } } else {} - } + } } } // sort structs by dependant fields -fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol { +fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol { mut dep_graph := depgraph.new_dep_graph() // types name list mut type_names := []string @@ -2241,14 +2118,16 @@ fn (g &Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol { } } else {} - } + } // add type and dependant types to graph dep_graph.add(t.name, field_deps) } // sort graph dep_graph_sorted := dep_graph.resolve() if !dep_graph_sorted.acyclic { - verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' + dep_graph_sorted.display_cycles() + '\nyou can solve this by making one or both of the dependant struct fields references, eg: field &MyStruct' + '\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro') + verror('cgen.sort_structs(): the following structs form a dependency cycle:\n' + + dep_graph_sorted.display_cycles() + '\nyou can solve this by making one or both of the dependant struct fields references, eg: field &MyStruct' + + '\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro') } // sort types mut types_sorted := []table.TypeSymbol @@ -2262,9 +2141,7 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('_STR("') // Build the string with % for i, val in node.vals { - escaped_val := val.replace_each(['"', '\\"', - '\r\n', '\\n', - '\n', '\\n']) + escaped_val := val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n']) g.write(escaped_val) if i >= node.exprs.len { continue @@ -2286,11 +2163,9 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) { verror('only V strings can be formatted with a ${sfmt} format') } g.write('%' + sfmt[1..]) - } - else if node.expr_types[i] == table.string_type { + } else if node.expr_types[i] == table.string_type { g.write('%.*s') - } - else { + } else { g.write('%d') } } @@ -2303,19 +2178,16 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) { if fspec == `s` && node.expr_types[i] == table.string_type { g.expr(expr) g.write('.str') - } - else { + } else { g.expr(expr) } - } - else if node.expr_types[i] == table.string_type { + } else if node.expr_types[i] == table.string_type { // `name.str, name.len,` g.expr(expr) g.write('.len, ') g.expr(expr) g.write('.str') - } - else { + } else { g.expr(expr) } if i < node.exprs.len - 1 { @@ -2328,7 +2200,7 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) { // `nums.filter(it % 2 == 0)` fn (g mut Gen) gen_filter(node ast.CallExpr) { tmp := g.new_tmp_var() - s := g.out.after(g.stmt_start_pos) // the already generated part of current statement + s := g.out.after(g.stmt_start_pos) // the already generated part of current statement g.out.go_back(s.len) // println('filter s="$s"') sym := g.table.get_type_symbol(node.return_type) @@ -2347,7 +2219,7 @@ fn (g mut Gen) gen_filter(node ast.CallExpr) { g.expr(node.left) g.writeln('.data)[i];') g.write('if (') - g.expr(node.args[0].expr) // the first arg is the filter condition + g.expr(node.args[0].expr) // the first arg is the filter condition g.writeln(') array_push(&$tmp, &it); \n }') g.write(s) g.write(' ') @@ -2368,12 +2240,7 @@ fn (g mut Gen) call_expr(node ast.CallExpr) { styp := g.typ(node.return_type) g.write('$styp $tmp_opt = ') } - if node.is_method { - g.method_call(node) - } - else { - g.fn_call(node) - } + if node.is_method { g.method_call(node) } else { g.fn_call(node) } if gen_or { g.or_block(tmp_opt, node.or_block.stmts, node.return_type) } @@ -2392,9 +2259,8 @@ fn (g mut Gen) method_call(node ast.CallExpr) { return } // TODO performance, detect `array` method differently - if typ_sym.kind == .array && node.name in - ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', - 'first', 'last', 'clone', 'reverse', 'slice'] { + if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', + 'push_many', 'trim', 'first', 'last', 'clone', 'reverse', 'slice'] { // && rec_sym.name == 'array' { // && rec_sym.name == 'array' && receiver_name.starts_with('array') { // `array_byte_clone` => `array_clone` @@ -2415,27 +2281,26 @@ fn (g mut Gen) method_call(node ast.CallExpr) { // Add `&` automatically. // TODO same logic in call_args() g.write('&') - } - else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) { + } else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) { g.write('/*rec*/*') } g.expr(node.left) - is_variadic := node.expected_arg_types.len > 0 && - table.type_is(node.expected_arg_types[node.expected_arg_types.len - 1], .variadic) + is_variadic := node.expected_arg_types.len > 0 && table.type_is(node.expected_arg_types[node.expected_arg_types.len - + 1], .variadic) if node.args.len > 0 || is_variadic { g.write(', ') } // ///////// /* - if name.contains('subkeys') { - println('call_args $name $node.arg_types.len') - for t in node.arg_types { - sym := g.table.get_type_symbol(t) - print('$sym.name ') - } - println('') - } - */ + if name.contains('subkeys') { + println('call_args $name $node.arg_types.len') + for t in node.arg_types { + sym := g.table.get_type_symbol(t) + print('$sym.name ') + } + println('') + } + */ // /////// g.call_args(node.args, node.expected_arg_types) g.write(')') @@ -2447,33 +2312,27 @@ fn (g mut Gen) method_call(node ast.CallExpr) { fn (g mut Gen) fn_call(node ast.CallExpr) { mut name := node.name is_print := name == 'println' || name == 'print' - print_method := if name == 'println' { - 'println' - } - else { - 'print' - } + print_method := if name == 'println' { 'println' } else { 'print' } if node.is_c { // Skip "C." g.is_c_call = true name = name[2..].replace('.', '__') - } - else { + } else { name = c_name(name) } // Generate tmp vars for values that have to be freed. /* - mut tmps := []string - for arg in node.args { - if arg.typ == table.string_type_idx || is_print { - tmp := g.new_tmp_var() - tmps << tmp - g.write('string $tmp = ') - g.expr(arg.expr) - g.writeln('; //memory') - } - } - */ + mut tmps := []string + for arg in node.args { + if arg.typ == table.string_type_idx || is_print { + tmp := g.new_tmp_var() + tmps << tmp + g.write('string $tmp = ') + g.expr(arg.expr) + g.writeln('; //memory') + } + } + */ if is_print && node.args[0].typ != table.string_type_idx { typ := node.args[0].typ mut styp := g.typ(typ) @@ -2493,13 +2352,11 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { g.write('string $tmp = ${styp}_str(') g.expr(node.args[0].expr) g.writeln('); ${print_method}($tmp); string_free($tmp); //MEM2 $styp') - } - else if sym.kind == .enum_ { + } else if sym.kind == .enum_ { g.write('${print_method}(tos3("') g.enum_expr(node.args[0].expr) g.write('"))') - } - else { + } else { // `println(int_str(10))` // sym := g.table.get_type_symbol(node.args[0].typ) if table.type_is_ptr(typ) { @@ -2509,13 +2366,12 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { g.write('${print_method}(${styp}_str(') if table.type_is_ptr(typ) { // dereference - //g.write('*') + // g.write('*') } g.expr(node.args[0].expr) g.write('))') } - } - else { + } else { g.write('${name}(') g.call_args(node.args, node.expected_arg_types) g.write(')') @@ -2532,17 +2388,16 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { // `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }` fn (g mut Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) { mr_styp := g.typ(return_type) - mr_styp2 := mr_styp[7..] // remove Option_ - g.writeln(';') // or') + mr_styp2 := mr_styp[7..] // remove Option_ + g.writeln(';') // or') g.writeln('if (!${var_name}.ok) {') g.writeln('\tstring err = ${var_name}.v_error;') g.writeln('\tint errcode = ${var_name}.ecode;') - - last_type, type_of_last_expression := g.type_of_last_statement( stmts ) + last_type, type_of_last_expression := g.type_of_last_statement(stmts) if last_type == 'v.ast.ExprStmt' && type_of_last_expression != 'void' { g.indent++ for i, stmt in stmts { - if i == stmts.len-1 { + if i == stmts.len - 1 { g.indent-- g.write('\t*(${mr_styp2}*) ${var_name}.data = ') } @@ -2554,12 +2409,11 @@ fn (g mut Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Typ g.write('}') } - -fn (g mut Gen) type_of_last_statement(stmts []ast.Stmt) (string,string) { +fn (g mut Gen) type_of_last_statement(stmts []ast.Stmt) (string, string) { mut last_type := '' mut last_expr_result_type := '' if stmts.len > 0 { - last_stmt := stmts[stmts.len-1] + last_stmt := stmts[stmts.len - 1] last_type = typeof(last_stmt) if last_type == 'v.ast.ExprStmt' { match last_stmt { @@ -2568,7 +2422,7 @@ fn (g mut Gen) type_of_last_statement(stmts []ast.Stmt) (string,string) { if it_expr_type == 'v.ast.CallExpr' { g.writeln('\t // typeof it_expr_type: $it_expr_type') last_expr_result_type = g.type_of_call_expr(it.expr) - }else{ + } else { last_expr_result_type = it_expr_type } } @@ -2595,7 +2449,6 @@ fn (g mut Gen) type_of_call_expr(node ast.Expr) string { return '' } - // `a in [1,2,3]` => `a == 1 || a == 2 || a == 3` fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) { is_str := right.elem_type == table.string_type @@ -2604,12 +2457,7 @@ fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) { g.write('string_eq(') } g.expr(left) - if is_str { - g.write(', ') - } - else { - g.write(' == ') - } + if is_str { g.write(', ') } else { g.write(' == ') } g.expr(array_expr) if is_str { g.write(')') @@ -2622,23 +2470,24 @@ fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) { fn op_to_fn_name(name string) string { return match name { - '+'{ + '+' { '_op_plus' } - '-'{ + '-' { '_op_minus' } - '*'{ + '*' { '_op_mul' } - '/'{ + '/' { '_op_div' } - '%'{ + '%' { '_op_mod' } else { - 'bad op $name'} + 'bad op $name' + } } } @@ -2704,15 +2553,14 @@ fn comp_if_to_ifdef(name string) string { 'no_bounds_checking' { return 'NO_BOUNDS_CHECK' } - 'x64' { - return 'TARGET_IS_64BIT' - } - 'x32' { - return 'TARGET_IS_32BIT' - } + 'x64' { + return 'TARGET_IS_64BIT' + } + 'x32' { + return 'TARGET_IS_32BIT' + } 'little_endian' { return 'TARGET_ORDER_IS_LITTLE' - } 'big_endian' { return 'TARGET_ORDER_IS_BIG' @@ -2734,7 +2582,7 @@ fn c_name(name_ string) string { return name } -fn (g &Gen) type_default(typ table.Type) string { +fn (g Gen) type_default(typ table.Type) string { sym := g.table.get_type_symbol(typ) if sym.kind == .array { elem_sym := g.table.get_type_symbol(sym.array_info().elem_type) @@ -2765,13 +2613,12 @@ fn (g &Gen) type_default(typ table.Type) string { } /* match idx { - table.bool_type_idx { - return '0' - } - else {} - } + table.bool_type_idx { + return '0' + } + else {} + } */ - match sym.name { 'string' { return 'tos3("")' @@ -2787,25 +2634,24 @@ fn (g &Gen) type_default(typ table.Type) string { // - Empty ee= (Empty) { . = {0} } ; /* return match typ { - 'bool'{ '0'} - 'string'{ 'tos3("")'} - 'i8'{ '0'} - 'i16'{ '0'} - 'i64'{ '0'} - 'u16'{ '0'} - 'u32'{ '0'} - 'u64'{ '0'} - 'byte'{ '0'} - 'int'{ '0'} - 'rune'{ '0'} - 'f32'{ '0.0'} - 'f64'{ '0.0'} - 'byteptr'{ '0'} - 'voidptr'{ '0'} - else { '{0} '} - } + 'bool'{ '0'} + 'string'{ 'tos3("")'} + 'i8'{ '0'} + 'i16'{ '0'} + 'i64'{ '0'} + 'u16'{ '0'} + 'u32'{ '0'} + 'u64'{ '0'} + 'byte'{ '0'} + 'int'{ '0'} + 'rune'{ '0'} + 'f32'{ '0.0'} + 'f64'{ '0.0'} + 'byteptr'{ '0'} + 'voidptr'{ '0'} + else { '{0} '} + } */ - } pub fn (g mut Gen) write_tests_main() { @@ -2840,7 +2686,7 @@ pub fn (g mut Gen) write_tests_main() { g.writeln('}') } -fn (g &Gen) get_all_test_function_names() []string { +fn (g Gen) get_all_test_function_names() []string { mut tfuncs := []string mut tsuite_begin := '' mut tsuite_end := '' @@ -2887,7 +2733,7 @@ fn (g &Gen) get_all_test_function_names() []string { return all_tfuncs_c } -fn (g &Gen) is_importing_os() bool { +fn (g Gen) is_importing_os() bool { return 'os' in g.table.imports } @@ -2896,8 +2742,7 @@ fn (g mut Gen) comp_if(it ast.CompIf) { if it.is_not { g.writeln('\n#ifndef ' + ifdef) g.writeln('// #if not $it.val') - } - else { + } else { g.writeln('\n#ifdef ' + ifdef) g.writeln('// #if $it.val') } @@ -2920,7 +2765,7 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { tmp := g.new_tmp_var() // x := node.call_expr as ast.CallEpxr // TODO match node.call_expr { - ast.CallExpr{ + ast.CallExpr { mut name := it.name.replace('.', '__') if it.is_method { receiver_sym := g.table.get_type_symbol(it.receiver_type) @@ -2963,7 +2808,6 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { } g.definitions.writeln('} $wrapper_struct_name;') g.definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg);') - g.gowrappers.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg) {') g.gowrappers.write('\t${name}(') if it.is_method { @@ -2972,19 +2816,18 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { g.gowrappers.write(', ') } } - for i in 0..it.args.len { + for i in 0 .. it.args.len { g.gowrappers.write('arg->arg${i+1}') if i < it.args.len - 1 { g.gowrappers.write(', ') } } - g.gowrappers.writeln(');') g.gowrappers.writeln('\treturn 0;') g.gowrappers.writeln('}') g.threaded_fns << name } - else{} + else {} } } @@ -2992,7 +2835,7 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) { s := styp.replace('.', '__') match sym.info { - table.Struct{} + table.Struct {} else { println('str() not a struct $sym.name') return diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 7a2216ff91..351658a613 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -736,7 +736,7 @@ pub fn (s mut Scanner) scan() token.Token { if s.comments_mode == .parse_comments { // Find out if this comment is on its own line (for vfmt) mut is_separate_line_comment := true - for j := start-2; s.text[j] != `\n`; j-- { + for j := start-2; j >= 0 && s.text[j] != `\n`; j-- { if !(s.text[j] in [`\t`, ` `]) { is_separate_line_comment = false }