v.gen.c: fix assert `f().len == 1` calling f() twice (closes issue 11501)
parent
c175b4fd48
commit
0a18690a4f
|
@ -12,19 +12,11 @@ fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) {
|
|||
mut node := original_assert_statement
|
||||
g.writeln('// assert')
|
||||
if mut node.expr is ast.InfixExpr {
|
||||
if mut node.expr.left is ast.CallExpr {
|
||||
node.expr.left = g.new_ctemp_var_then_gen(node.expr.left, node.expr.left_type)
|
||||
} else if mut node.expr.left is ast.ParExpr {
|
||||
if node.expr.left.expr is ast.CallExpr {
|
||||
node.expr.left = g.new_ctemp_var_then_gen(node.expr.left.expr, node.expr.left_type)
|
||||
}
|
||||
}
|
||||
if mut node.expr.right is ast.CallExpr {
|
||||
node.expr.right = g.new_ctemp_var_then_gen(node.expr.right, node.expr.right_type)
|
||||
} else if mut node.expr.right is ast.ParExpr {
|
||||
if node.expr.right.expr is ast.CallExpr {
|
||||
node.expr.right = g.new_ctemp_var_then_gen(node.expr.right.expr, node.expr.right_type)
|
||||
if subst_expr := g.assert_subexpression_to_ctemp(node.expr.left, node.expr.left_type) {
|
||||
node.expr.left = subst_expr
|
||||
}
|
||||
if subst_expr := g.assert_subexpression_to_ctemp(node.expr.right, node.expr.right_type) {
|
||||
node.expr.right = subst_expr
|
||||
}
|
||||
}
|
||||
g.inside_ternary++
|
||||
|
@ -60,6 +52,39 @@ fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) {
|
|||
}
|
||||
}
|
||||
|
||||
struct UnsupportedAssertCtempTransform {
|
||||
msg string
|
||||
code int
|
||||
}
|
||||
|
||||
const unsupported_ctemp_assert_transform = IError(UnsupportedAssertCtempTransform{})
|
||||
|
||||
fn (mut g Gen) assert_subexpression_to_ctemp(expr ast.Expr, expr_type ast.Type) ?ast.Expr {
|
||||
match expr {
|
||||
ast.CallExpr {
|
||||
return g.new_ctemp_var_then_gen(expr, expr_type)
|
||||
}
|
||||
ast.ParExpr {
|
||||
if expr.expr is ast.CallExpr {
|
||||
return g.new_ctemp_var_then_gen(expr.expr, expr_type)
|
||||
}
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
if expr.expr is ast.CallExpr {
|
||||
sym := g.table.get_final_type_symbol(g.unwrap_generic(expr.expr.return_type))
|
||||
if sym.kind == .struct_ {
|
||||
if (sym.info as ast.Struct).is_union {
|
||||
return c.unsupported_ctemp_assert_transform
|
||||
}
|
||||
}
|
||||
return g.new_ctemp_var_then_gen(expr, expr_type)
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return c.unsupported_ctemp_assert_transform
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_assert_postfailure_mode(node ast.AssertStmt) {
|
||||
g.write_v_source_line_info(node.pos)
|
||||
match g.pref.assert_failure_mode {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
int _t1 = main__fn_returning_array().len;
|
||||
if (!(_t1 == 1)) {
|
||||
v_assert_meta_info__t2.src = _SLIT("fn_returning_array().len == 1");
|
||||
v_assert_meta_info__t2.llabel = _SLIT("fn_returning_array().len");
|
||||
|
||||
int _t3 = main__fn_returning_struct().x;
|
||||
if (!(_t3 == 123)) {
|
||||
v_assert_meta_info__t4.src = _SLIT("fn_returning_struct().x == 123");
|
||||
v_assert_meta_info__t4.llabel = _SLIT("fn_returning_struct().x");
|
|
@ -0,0 +1,4 @@
|
|||
[1]
|
||||
Abc{
|
||||
x: 123
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
struct Abc {
|
||||
x int
|
||||
}
|
||||
|
||||
fn fn_returning_array() []int {
|
||||
return [1]
|
||||
}
|
||||
|
||||
fn fn_returning_struct() Abc {
|
||||
return Abc{123}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert fn_returning_array().len == 1
|
||||
assert fn_returning_struct().x == 123
|
||||
println(fn_returning_array())
|
||||
println(fn_returning_struct())
|
||||
}
|
|
@ -39,7 +39,9 @@ pub fn new_sourcemap(file string, source_root string, sources_content_inline boo
|
|||
|
||||
// Add a single mapping from original source line and column to the generated source's line and column for this source map being created.
|
||||
pub fn (mut sm SourceMap) add_mapping(source_name string, source_position SourcePositionType, gen_line u32, gen_column u32, name string) {
|
||||
assert source_name.len != 0
|
||||
if source_name.len == 0 {
|
||||
panic('add_mapping, source_name should not be ""')
|
||||
}
|
||||
|
||||
sources_ind := sm.sources.add(source_name)
|
||||
|
||||
|
@ -53,7 +55,9 @@ pub fn (mut sm SourceMap) add_mapping(source_name string, source_position Source
|
|||
|
||||
// Add multiple mappings from the same source
|
||||
pub fn (mut sm SourceMap) add_mapping_list(source_name string, mapping_list []MappingInput) ? {
|
||||
assert source_name.len != 0
|
||||
if source_name.len == 0 {
|
||||
panic('add_mapping_list, source_name should not be ""')
|
||||
}
|
||||
|
||||
sources_ind := sm.sources.add(source_name)
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
struct Abc {
|
||||
ncalls int
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn fn_that_should_be_called_just_once_array() []int {
|
||||
mut static ncalls := 0
|
||||
ncalls++
|
||||
println('${@FN} calls: $ncalls')
|
||||
if ncalls > 1 {
|
||||
assert false
|
||||
}
|
||||
return []int{len: ncalls, init: ncalls}
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn fn_that_should_be_called_just_once_struct() Abc {
|
||||
mut static ncalls := 0
|
||||
ncalls++
|
||||
println('${@FN} calls: $ncalls')
|
||||
if ncalls > 1 {
|
||||
assert false
|
||||
}
|
||||
return Abc{
|
||||
ncalls: ncalls
|
||||
}
|
||||
}
|
||||
|
||||
fn test_assert_calls_a_function_returning_an_array_just_once() {
|
||||
unsafe {
|
||||
assert fn_that_should_be_called_just_once_array().len == 1
|
||||
}
|
||||
}
|
||||
|
||||
fn test_assert_calls_a_function_returning_a_struct_just_once() {
|
||||
unsafe {
|
||||
assert fn_that_should_be_called_just_once_struct().ncalls == 1
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue