1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: struct str() generation; go() fixes

This commit is contained in:
Alexander Medvednikov 2020-04-03 18:05:50 +02:00
parent 31c4b1cda6
commit c32ed8af51
2 changed files with 55 additions and 17 deletions

View File

@ -557,20 +557,16 @@ fn (g mut Gen) gen_assert_stmt(a ast.AssertStmt) {
g.writeln('// assert') g.writeln('// assert')
g.write('if( ') g.write('if( ')
g.expr(a.expr) g.expr(a.expr)
g.write(' )')
s_assertion := a.expr.str().replace('"', "\'") s_assertion := a.expr.str().replace('"', "\'")
mut mod_path := g.file.path g.write(' )')
$if windows {
mod_path = g.file.path.replace('\\', '\\\\')
}
if g.is_test { if g.is_test {
g.writeln('{') g.writeln('{')
g.writeln(' g_test_oks++;') 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(' println(_STR("OK ${g.file.path}:${a.pos.line_nr}: fn ${g.fn_decl.name}(): assert $s_assertion"));')
g.writeln('}else{') g.writeln('}else{')
g.writeln(' g_test_fails++;') 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(' exit(1);')
g.writeln(' // TODO') g.writeln(' // TODO')
g.writeln(' // Maybe print all vars in a test function if it fails?') 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 return
} }
g.writeln('{}else{') 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(' exit(1);')
g.writeln('}') g.writeln('}')
} }
@ -2027,7 +2023,6 @@ fn verror(s string) {
fn (g mut Gen) write_init_function() { fn (g mut Gen) write_init_function() {
g.writeln('void _vinit() {') g.writeln('void _vinit() {')
g.writeln('init(); // builtin.init')
g.writeln(g.inits.str()) g.writeln(g.inits.str())
g.writeln('}') g.writeln('}')
if g.autofree { if g.autofree {
@ -2432,7 +2427,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
styp = styp.replace('*', '') styp = styp.replace('*', '')
} }
g.str_types << typ 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) { if g.autofree && !table.type_is_optional(typ) {
// Create a temporary variable so that the value can be freed // 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 // x := node.call_expr as ast.CallEpxr // TODO
match node.call_expr { match node.call_expr {
ast.CallExpr{ ast.CallExpr{
mut name := it.name mut name := it.name.replace('.', '__')
if it.is_method { if it.is_method {
receiver_sym := g.table.get_type_symbol(it.receiver_type) receiver_sym := g.table.get_type_symbol(it.receiver_type)
name = receiver_sym.name + '_' + name 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 {') g.definitions.writeln('\ntypedef struct $wrapper_struct_name {')
if it.is_method { if it.is_method {
sym := g.table.get_type_symbol(it.receiver_type) styp := g.typ(it.receiver_type)
g.definitions.writeln('\t$sym.name arg0;') g.definitions.writeln('\t$styp arg0;')
} }
for i, arg in it.args { for i, arg in it.args {
sym := g.table.get_type_symbol(arg.typ) styp := g.typ(arg.typ)
g.definitions.writeln('\t$sym.name arg${i+1};') g.definitions.writeln('\t$styp arg${i+1};')
} }
g.definitions.writeln('} $wrapper_struct_name;') g.definitions.writeln('} $wrapper_struct_name;')
g.definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg) {') 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'
}

View File

@ -38,6 +38,7 @@ mut:
ast_imports []ast.Import ast_imports []ast.Import
is_amp bool is_amp bool
returns bool returns bool
inside_match_case bool // to separate `match_expr { }` from `Struct{}`
} }
// for tests // 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.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)) { // || p.table.known_type(p.tok.lit)) {
return p.struct_init(false) // short_syntax: false return p.struct_init(false) // short_syntax: false
@ -1779,7 +1781,8 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
p.next() p.next()
} }
// Sum type match // 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 { // if sym.kind == .sum_type {
// p.warn('is sum') // p.warn('is sum')
// TODO `exprs << ast.Type{...}` // TODO `exprs << ast.Type{...}`
@ -1804,7 +1807,9 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
else { else {
// Expression match // Expression match
for { for {
p.inside_match_case = true
expr := p.expr(0) expr := p.expr(0)
p.inside_match_case = false
exprs << expr exprs << expr
if p.tok.kind != .comma { if p.tok.kind != .comma {
break break