cgen: print results of failed callexprs in `assert fn() == fn2()` (#6665)
parent
6d11caf784
commit
ab137e4164
|
@ -9,8 +9,8 @@ import v.errors
|
|||
|
||||
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
||||
|
||||
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
|
||||
ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral |
|
||||
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CTempVar | CallExpr |
|
||||
CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral |
|
||||
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||
MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr |
|
||||
SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | StructInit |
|
||||
|
@ -439,9 +439,9 @@ pub struct InfixExpr {
|
|||
pub:
|
||||
op token.Kind
|
||||
pos token.Position
|
||||
pub mut:
|
||||
left Expr
|
||||
right Expr
|
||||
pub mut:
|
||||
left_type table.Type
|
||||
right_type table.Type
|
||||
auto_locked string
|
||||
|
@ -826,8 +826,9 @@ pub mut:
|
|||
|
||||
pub struct AssertStmt {
|
||||
pub:
|
||||
expr Expr
|
||||
pos token.Position
|
||||
pub mut:
|
||||
expr Expr
|
||||
}
|
||||
|
||||
// `if [x := opt()] {`
|
||||
|
@ -1025,6 +1026,7 @@ pub fn (expr Expr) position() token.Position {
|
|||
pub fn (expr Expr) is_lvalue() bool {
|
||||
match expr {
|
||||
Ident { return true }
|
||||
CTempVar { return true }
|
||||
IndexExpr { return expr.left.is_lvalue() }
|
||||
SelectorExpr { return expr.expr.is_lvalue() }
|
||||
else {}
|
||||
|
@ -1058,6 +1060,15 @@ pub fn (stmt Stmt) check_c_expr() ? {
|
|||
return error('unsupported statement (`${typeof(stmt)}`)')
|
||||
}
|
||||
|
||||
// CTempVar is used in cgen only, to hold nodes for temporary variables
|
||||
pub struct CTempVar {
|
||||
pub:
|
||||
name string // the name of the C temporary variable; used by g.expr(x)
|
||||
orig Expr // the original expression, which produced the C temp variable; used by x.str()
|
||||
typ table.Type // the type of the original expression
|
||||
is_ptr bool // whether the type is a pointer
|
||||
}
|
||||
|
||||
pub fn (stmt Stmt) position() token.Position {
|
||||
match stmt {
|
||||
AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl { return stmt.pos }
|
||||
|
|
|
@ -177,6 +177,9 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
|||
// string representation of expr
|
||||
pub fn (x Expr) str() string {
|
||||
match x {
|
||||
CTempVar {
|
||||
return x.orig.str()
|
||||
}
|
||||
BoolLiteral {
|
||||
return x.val.str()
|
||||
}
|
||||
|
@ -188,6 +191,9 @@ pub fn (x Expr) str() string {
|
|||
if x.is_method {
|
||||
return '${x.left.str()}.${x.name}($sargs)'
|
||||
}
|
||||
if x.name.starts_with('${x.mod}.') {
|
||||
return util.strip_main_name('${x.name}($sargs)')
|
||||
}
|
||||
return '${x.mod}.${x.name}($sargs)'
|
||||
}
|
||||
CharLiteral {
|
||||
|
|
|
@ -2563,6 +2563,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
|||
return table.void_type
|
||||
}
|
||||
match mut node {
|
||||
ast.CTempVar {
|
||||
return node.typ
|
||||
}
|
||||
ast.AnonFn {
|
||||
keep_fn := c.cur_fn
|
||||
c.cur_fn = &node.decl
|
||||
|
|
|
@ -711,6 +711,9 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
|||
eprintln('expr: ${node.position():-42} | node: ${typeof(node):-20} | $node.str()')
|
||||
}
|
||||
match mut node {
|
||||
ast.CTempVar {
|
||||
eprintln('ast.CTempVar of $node.orig.str() should be generated/used only in cgen')
|
||||
}
|
||||
ast.AnonFn {
|
||||
f.fn_decl(node.decl)
|
||||
}
|
||||
|
|
|
@ -1272,8 +1272,40 @@ fn (mut g Gen) gen_attrs(attrs []table.Attr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
||||
fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) {
|
||||
mut a := original_assert_statement
|
||||
g.writeln('// assert')
|
||||
mut tl_name := ''
|
||||
mut tr_name := ''
|
||||
if a.expr is ast.InfixExpr {
|
||||
mut aie := a.expr as ast.InfixExpr
|
||||
if aie.left is ast.CallExpr {
|
||||
tl_styp := g.typ(aie.left_type)
|
||||
tl_name = g.new_tmp_var()
|
||||
g.write('$tl_styp $tl_name = ')
|
||||
g.expr(aie.left)
|
||||
g.writeln(';')
|
||||
aie.left = ast.Expr(ast.CTempVar{
|
||||
name: tl_name
|
||||
typ: aie.left_type
|
||||
is_ptr: aie.left_type.is_ptr()
|
||||
orig: aie.left
|
||||
})
|
||||
}
|
||||
if aie.right is ast.CallExpr {
|
||||
tr_styp := g.typ(aie.right_type)
|
||||
tr_name = g.new_tmp_var()
|
||||
g.write('$tr_styp $tr_name = ')
|
||||
g.expr(aie.right)
|
||||
g.writeln(';')
|
||||
aie.right = ast.Expr(ast.CTempVar{
|
||||
name: tr_name
|
||||
typ: aie.right_type
|
||||
is_ptr: aie.right_type.is_ptr()
|
||||
orig: aie.right
|
||||
})
|
||||
}
|
||||
}
|
||||
g.inside_ternary++
|
||||
g.write('if (')
|
||||
g.expr(a.expr)
|
||||
|
@ -1338,7 +1370,7 @@ fn (mut g Gen) gen_assert_metainfo(a ast.AssertStmt) string {
|
|||
fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) {
|
||||
unknown_value := '*unknown value*'
|
||||
match e {
|
||||
ast.CallExpr, ast.CastExpr, ast.IndexExpr, ast.PrefixExpr, ast.MatchExpr {
|
||||
ast.CastExpr, ast.IndexExpr, ast.PrefixExpr, ast.MatchExpr {
|
||||
g.write(ctoslit(unknown_value))
|
||||
}
|
||||
ast.Type {
|
||||
|
@ -1962,6 +1994,7 @@ fn (mut g Gen) gen_anon_fn_decl(it ast.AnonFn) {
|
|||
|
||||
fn (mut g Gen) expr(node ast.Expr) {
|
||||
// println('cgen expr() line_nr=$node.pos.line_nr')
|
||||
// NB: please keep the type names in the match here in alphabetical order:
|
||||
match node {
|
||||
ast.AnonFn {
|
||||
// TODO: dont fiddle with buffers
|
||||
|
@ -2084,6 +2117,10 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
ast.ConcatExpr {
|
||||
g.concat_expr(node)
|
||||
}
|
||||
ast.CTempVar {
|
||||
// g.write('/*ctmp .orig: $node.orig.str() , .typ: $node.typ, .is_ptr: $node.is_ptr */ ')
|
||||
g.write(node.name)
|
||||
}
|
||||
ast.EnumVal {
|
||||
// g.write('${it.mod}${it.enum_name}_$it.val')
|
||||
styp := g.typ(node.typ)
|
||||
|
@ -4366,6 +4403,11 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
|
|||
g.write('($s)')
|
||||
}
|
||||
}
|
||||
if expr is ast.CTempVar {
|
||||
if expr.is_ptr {
|
||||
g.write('*')
|
||||
}
|
||||
}
|
||||
g.expr(expr)
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
if is_p {
|
||||
|
|
|
@ -520,6 +520,9 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
|||
|
||||
fn (mut g JsGen) expr(node ast.Expr) {
|
||||
match node {
|
||||
ast.CTempVar {
|
||||
g.write('/* ast.CTempVar: node.name */')
|
||||
}
|
||||
ast.AnonFn {
|
||||
g.gen_fn_decl(node.decl)
|
||||
}
|
||||
|
@ -673,17 +676,17 @@ fn (mut g JsGen) gen_assert_stmt(a ast.AssertStmt) {
|
|||
mut mod_path := g.file.path.replace('\\', '\\\\')
|
||||
if g.is_test {
|
||||
g.writeln(' g_test_oks++;')
|
||||
g.writeln(' cb_assertion_ok("$mod_path", ${a.pos.line_nr+1}, "assert $s_assertion", "${g.fn_decl.name}()" );')
|
||||
g.writeln(' cb_assertion_ok("$mod_path", ${a.pos.line_nr + 1}, "assert $s_assertion", "${g.fn_decl.name}()" );')
|
||||
g.writeln('} else {')
|
||||
g.writeln(' g_test_fails++;')
|
||||
g.writeln(' cb_assertion_failed("$mod_path", ${a.pos.line_nr+1}, "assert $s_assertion", "${g.fn_decl.name}()" );')
|
||||
g.writeln(' cb_assertion_failed("$mod_path", ${a.pos.line_nr + 1}, "assert $s_assertion", "${g.fn_decl.name}()" );')
|
||||
g.writeln(' exit(1);')
|
||||
g.writeln('}')
|
||||
return
|
||||
}
|
||||
g.writeln('} else {')
|
||||
g.inc_indent()
|
||||
g.writeln('builtin.eprintln("$mod_path:${a.pos.line_nr+1}: FAIL: fn ${g.fn_decl.name}(): assert $s_assertion");')
|
||||
g.writeln('builtin.eprintln("$mod_path:${a.pos.line_nr + 1}: FAIL: fn ${g.fn_decl.name}(): assert $s_assertion");')
|
||||
g.writeln('builtin.exit(1);')
|
||||
g.dec_indent()
|
||||
g.writeln('}')
|
||||
|
|
Loading…
Reference in New Issue