From c32ed8af519db9a6c9cfd4cce6efa5f3af8de2cb Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 3 Apr 2020 18:05:50 +0200 Subject: [PATCH] cgen: struct str() generation; go() fixes --- vlib/v/gen/cgen.v | 63 ++++++++++++++++++++++++++++++++---------- vlib/v/parser/parser.v | 9 ++++-- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index e9bc06b1d1..8ecb9cf123 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -557,20 +557,16 @@ fn (g mut Gen) gen_assert_stmt(a ast.AssertStmt) { g.writeln('// assert') g.write('if( ') g.expr(a.expr) - g.write(' )') s_assertion := a.expr.str().replace('"', "\'") - mut mod_path := g.file.path - $if windows { - mod_path = g.file.path.replace('\\', '\\\\') - } + g.write(' )') if g.is_test { g.writeln('{') g.writeln(' g_test_oks++;') - g.writeln(' cb_assertion_ok( _STR("${mod_path}"), ${a.pos.line_nr}, _STR("assert ${s_assertion}"), _STR("${g.fn_decl.name}()") );') + g.writeln(' cb_assertion_ok( _STR("${g.file.path}"), ${a.pos.line_nr}, _STR("assert ${s_assertion}"), _STR("${g.fn_decl.name}()") );') // g.writeln(' println(_STR("OK ${g.file.path}:${a.pos.line_nr}: fn ${g.fn_decl.name}(): assert $s_assertion"));') g.writeln('}else{') g.writeln(' g_test_fails++;') - g.writeln(' cb_assertion_failed( _STR("${mod_path}"), ${a.pos.line_nr}, _STR("assert ${s_assertion}"), _STR("${g.fn_decl.name}()") );') + g.writeln(' cb_assertion_failed( _STR("${g.file.path}"), ${a.pos.line_nr}, _STR("assert ${s_assertion}"), _STR("${g.fn_decl.name}()") );') g.writeln(' exit(1);') g.writeln(' // TODO') g.writeln(' // Maybe print all vars in a test function if it fails?') @@ -578,7 +574,7 @@ fn (g mut Gen) gen_assert_stmt(a ast.AssertStmt) { return } g.writeln('{}else{') - g.writeln(' println(_STR("${mod_path}:${a.pos.line_nr}: FAIL: fn ${g.fn_decl.name}(): assert $s_assertion"));') + g.writeln(' eprintln(_STR("${g.file.path}:${a.pos.line_nr}: FAIL: fn ${g.fn_decl.name}(): assert $s_assertion"));') g.writeln(' exit(1);') g.writeln('}') } @@ -2027,7 +2023,6 @@ fn verror(s string) { fn (g mut Gen) write_init_function() { g.writeln('void _vinit() {') - g.writeln('init(); // builtin.init') g.writeln(g.inits.str()) g.writeln('}') if g.autofree { @@ -2432,7 +2427,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { styp = styp.replace('*', '') } g.str_types << typ - g.definitions.writeln('string ${styp}_str($styp x) { return tos3("TODO_str"); }') + g.gen_str_for_type(sym, styp) } if g.autofree && !table.type_is_optional(typ) { // Create a temporary variable so that the value can be freed @@ -2808,7 +2803,7 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { // x := node.call_expr as ast.CallEpxr // TODO match node.call_expr { ast.CallExpr{ - mut name := it.name + mut name := it.name.replace('.', '__') if it.is_method { receiver_sym := g.table.get_type_symbol(it.receiver_type) name = receiver_sym.name + '_' + name @@ -2836,12 +2831,12 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { } g.definitions.writeln('\ntypedef struct $wrapper_struct_name {') if it.is_method { - sym := g.table.get_type_symbol(it.receiver_type) - g.definitions.writeln('\t$sym.name arg0;') + styp := g.typ(it.receiver_type) + g.definitions.writeln('\t$styp arg0;') } for i, arg in it.args { - sym := g.table.get_type_symbol(arg.typ) - g.definitions.writeln('\t$sym.name arg${i+1};') + styp := g.typ(arg.typ) + g.definitions.writeln('\t$styp arg${i+1};') } g.definitions.writeln('} $wrapper_struct_name;') g.definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg) {') @@ -2866,3 +2861,41 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) { } } +// already generated styp, reuse it +fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) { + s := styp.replace('.', '__') + match sym.info { + table.Struct{} + else { + println('str() not a struct $sym.name') + return + } + } + info := sym.info as table.Struct + g.definitions.write('string ${s}_str($styp a) { return _STR("$styp {\\n') + for field in info.fields { + fmt := type_to_fmt(field.typ) + g.definitions.write('\t$field.name: $fmt\\n') + + } + g.definitions.write('\\n}", ') + for i, field in info.fields { + g.definitions.write('a.' + field.name) + if field.typ == table.string_type { + g.definitions.write('.len, a.${field.name}.str') + } + if i < info.fields.len - 1 { + g.definitions.write(', ') + } + } + g.definitions.writeln('); }') +} + +fn type_to_fmt(typ table.Type) string { + n := int(typ) + if n == table.string_type { + return '%.*s' + } + return '%d' +} + diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 1945c9696f..e54d5f07f1 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -38,6 +38,7 @@ mut: ast_imports []ast.Import is_amp bool returns bool + inside_match_case bool // to separate `match_expr { }` from `Struct{}` } // for tests @@ -668,8 +669,9 @@ pub fn (p mut Parser) name_expr() ast.Expr { // (p.builtin_mod && p.tok.lit in table.builtin_type_names)) && // - (p.tok.lit.len == 1 || !p.tok.lit[p.tok.lit.len - 1].is_capital()) + (p.tok.lit.len == 1 || !p.tok.lit[p.tok.lit.len - 1].is_capital()) && // + !p.inside_match_case { // || p.table.known_type(p.tok.lit)) { return p.struct_init(false) // short_syntax: false @@ -1779,7 +1781,8 @@ fn (p mut Parser) match_expr() ast.MatchExpr { p.next() } // Sum type match - else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) { + else if p.tok.kind == .name && + (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) { // if sym.kind == .sum_type { // p.warn('is sum') // TODO `exprs << ast.Type{...}` @@ -1804,7 +1807,9 @@ fn (p mut Parser) match_expr() ast.MatchExpr { else { // Expression match for { + p.inside_match_case = true expr := p.expr(0) + p.inside_match_case = false exprs << expr if p.tok.kind != .comma { break