gen: panic with correct type names (#8355)
parent
849bc6c3d8
commit
2cadb3e4d8
|
@ -4,8 +4,8 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
__global (
|
__global (
|
||||||
g_m2_buf byteptr
|
g_m2_buf byteptr
|
||||||
g_m2_ptr byteptr
|
g_m2_ptr byteptr
|
||||||
)
|
)
|
||||||
|
|
||||||
// isnil returns true if an object is nil (only for C objects).
|
// isnil returns true if an object is nil (only for C objects).
|
||||||
|
@ -29,14 +29,31 @@ pub fn print_backtrace() {
|
||||||
print_backtrace_skipping_top_frames(2)
|
print_backtrace_skipping_top_frames(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VCastTypeIndexName {
|
||||||
|
tindex int
|
||||||
|
tname string
|
||||||
|
}
|
||||||
|
|
||||||
__global (
|
__global (
|
||||||
total_m = i64(0)
|
total_m = i64(0)
|
||||||
nr_mallocs = int(0)
|
nr_mallocs = int(0)
|
||||||
|
// will be filled in cgen
|
||||||
|
as_cast_type_indexes []VCastTypeIndexName
|
||||||
)
|
)
|
||||||
|
|
||||||
fn __as_cast(obj voidptr, obj_type int, expected_type int) voidptr {
|
fn __as_cast(obj voidptr, obj_type int, expected_type int) voidptr {
|
||||||
if obj_type != expected_type {
|
if obj_type != expected_type {
|
||||||
panic('as cast: cannot cast $obj_type to $expected_type')
|
mut obj_name := as_cast_type_indexes[0].tname
|
||||||
|
mut expected_name := as_cast_type_indexes[0].tname
|
||||||
|
for x in as_cast_type_indexes {
|
||||||
|
if x.tindex == obj_type {
|
||||||
|
obj_name = x.tname
|
||||||
|
}
|
||||||
|
if x.tindex == expected_type {
|
||||||
|
expected_name = x.tname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic('as cast: cannot cast `$obj_name` to `$expected_name`')
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
@ -55,15 +72,15 @@ pub:
|
||||||
lvalue string // the stringified *actual value* of the left side of a failed assertion
|
lvalue string // the stringified *actual value* of the left side of a failed assertion
|
||||||
rvalue string // the stringified *actual value* of the right side of a failed assertion
|
rvalue string // the stringified *actual value* of the right side of a failed assertion
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __print_assert_failure(i &VAssertMetaInfo) {
|
fn __print_assert_failure(i &VAssertMetaInfo) {
|
||||||
eprintln('${i.fpath}:${i.line_nr+1}: FAIL: fn ${i.fn_name}: assert ${i.src}')
|
eprintln('$i.fpath:${i.line_nr + 1}: FAIL: fn $i.fn_name: assert $i.src')
|
||||||
if i.op.len > 0 && i.op != 'call' {
|
if i.op.len > 0 && i.op != 'call' {
|
||||||
eprintln(' left value: ${i.llabel} = ${i.lvalue}')
|
eprintln(' left value: $i.llabel = $i.lvalue')
|
||||||
if i.rlabel == i.rvalue {
|
if i.rlabel == i.rvalue {
|
||||||
eprintln(' right value: $i.rlabel')
|
eprintln(' right value: $i.rlabel')
|
||||||
}
|
} else {
|
||||||
else {
|
eprintln(' right value: $i.rlabel = $i.rvalue')
|
||||||
eprintln(' right value: ${i.rlabel} = ${i.rvalue}')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,7 @@ mut:
|
||||||
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
||||||
timers &util.Timers = util.new_timers(false)
|
timers &util.Timers = util.new_timers(false)
|
||||||
force_main_console bool // true when [console] used on fn main()
|
force_main_console bool // true when [console] used on fn main()
|
||||||
|
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
|
pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
|
||||||
|
@ -201,7 +202,6 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
}
|
}
|
||||||
g.init()
|
g.init()
|
||||||
g.timers.show('cgen init')
|
g.timers.show('cgen init')
|
||||||
//
|
|
||||||
mut tests_inited := false
|
mut tests_inited := false
|
||||||
mut autofree_used := false
|
mut autofree_used := false
|
||||||
for file in files {
|
for file in files {
|
||||||
|
@ -258,7 +258,6 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };')
|
g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// g.write_str_definitions()
|
|
||||||
// v files are finished, what remains is pure C code
|
// v files are finished, what remains is pure C code
|
||||||
g.gen_vlines_reset()
|
g.gen_vlines_reset()
|
||||||
if g.pref.build_mode != .build_module {
|
if g.pref.build_mode != .build_module {
|
||||||
|
@ -4984,6 +4983,12 @@ fn (mut g Gen) write_init_function() {
|
||||||
g.writeln('g_m2_buf = malloc(50 * 1000 * 1000);')
|
g.writeln('g_m2_buf = malloc(50 * 1000 * 1000);')
|
||||||
g.writeln('g_m2_ptr = g_m2_buf;')
|
g.writeln('g_m2_ptr = g_m2_buf;')
|
||||||
}
|
}
|
||||||
|
// NB: the as_cast table should be *before* the other constant initialize calls,
|
||||||
|
// because it may be needed during const initialization of builtin and during
|
||||||
|
// calling module init functions too, just in case they do fail...
|
||||||
|
g.write('\tas_cast_type_indexes = ')
|
||||||
|
g.writeln(g.as_cast_name_table())
|
||||||
|
//
|
||||||
g.writeln('\tbuiltin_init();')
|
g.writeln('\tbuiltin_init();')
|
||||||
g.writeln('\tvinit_string_literals();')
|
g.writeln('\tvinit_string_literals();')
|
||||||
//
|
//
|
||||||
|
@ -4999,7 +5004,6 @@ fn (mut g Gen) write_init_function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if g.pref.printfn_list.len > 0 && '_vinit' in g.pref.printfn_list {
|
if g.pref.printfn_list.len > 0 && '_vinit' in g.pref.printfn_list {
|
||||||
println(g.out.after(fn_vinit_start_pos))
|
println(g.out.after(fn_vinit_start_pos))
|
||||||
|
@ -5014,6 +5018,7 @@ fn (mut g Gen) write_init_function() {
|
||||||
g.writeln(g.cleanups[mod_name].str())
|
g.writeln(g.cleanups[mod_name].str())
|
||||||
}
|
}
|
||||||
// g.writeln('\tfree(g_str_buf);')
|
// g.writeln('\tfree(g_str_buf);')
|
||||||
|
g.writeln('\tarray_free(&as_cast_type_indexes);')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
||||||
println(g.out.after(fn_vcleanup_start_pos))
|
println(g.out.after(fn_vcleanup_start_pos))
|
||||||
|
@ -5848,22 +5853,50 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||||
styp := g.typ(node.typ)
|
styp := g.typ(node.typ)
|
||||||
sym := g.table.get_type_symbol(node.typ)
|
sym := g.table.get_type_symbol(node.typ)
|
||||||
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
||||||
if expr_type_sym.kind == .sum_type {
|
if expr_type_sym.info is table.SumType {
|
||||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
||||||
g.write('/* as */ *($styp*)__as_cast((')
|
g.write('/* as */ *($styp*)__as_cast(')
|
||||||
|
g.write('(')
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
g.write(dot)
|
g.write(dot)
|
||||||
g.write('_$sym.cname, (')
|
g.write('_$sym.cname,')
|
||||||
|
g.write('(')
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
g.write(dot)
|
g.write(dot)
|
||||||
// g.write('typ, /*expected:*/$node.typ)')
|
// g.write('typ, /*expected:*/$node.typ)')
|
||||||
sidx := g.type_sidx(node.typ)
|
sidx := g.type_sidx(node.typ)
|
||||||
g.write('typ, /*expected:*/$sidx)')
|
expected_sym := g.table.get_type_symbol(node.typ)
|
||||||
|
g.write('typ, $sidx) /*expected idx: $sidx, name: $expected_sym.name */ ')
|
||||||
|
|
||||||
|
// fill as cast name table
|
||||||
|
for variant in expr_type_sym.info.variants {
|
||||||
|
idx := variant.str()
|
||||||
|
if idx in g.as_cast_type_names {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
variant_sym := g.table.get_type_symbol(variant)
|
||||||
|
g.as_cast_type_names[idx] = variant_sym.name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g Gen) as_cast_name_table() string {
|
||||||
|
if g.as_cast_type_names.len == 0 {
|
||||||
|
return 'new_array_from_c_array(1, 1, sizeof(VCastTypeIndexName), _MOV((VCastTypeIndexName[1]){(VCastTypeIndexName){.tindex = 0,.tname = _SLIT("unknown")}}));'
|
||||||
|
}
|
||||||
|
mut name_table := strings.new_builder(1024)
|
||||||
|
casts_len := g.as_cast_type_names.len + 1
|
||||||
|
name_table.writeln('new_array_from_c_array($casts_len, $casts_len, sizeof(VCastTypeIndexName), _MOV((VCastTypeIndexName[$casts_len]){')
|
||||||
|
name_table.writeln('\t\t (VCastTypeIndexName){.tindex = 0, .tname = _SLIT("unknown")}')
|
||||||
|
for key, value in g.as_cast_type_names {
|
||||||
|
name_table.writeln('\t\t, (VCastTypeIndexName){.tindex = $key, .tname = _SLIT("$value")}')
|
||||||
|
}
|
||||||
|
name_table.writeln('\t}));')
|
||||||
|
return name_table.str()
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
eq := if node.op == .key_is { '==' } else { '!=' }
|
eq := if node.op == .key_is { '==' } else { '!=' }
|
||||||
g.write('(')
|
g.write('(')
|
||||||
|
|
|
@ -2,4 +2,4 @@ Foo
|
||||||
================ V panic ================
|
================ V panic ================
|
||||||
module: builtin
|
module: builtin
|
||||||
function: __as_cast()
|
function: __as_cast()
|
||||||
message: as cast: cannot cast
|
message: as cast: cannot cast `main.Struct` to `main.Interface`
|
||||||
|
|
Loading…
Reference in New Issue