gen: panic with correct type names (#8355)
parent
849bc6c3d8
commit
2cadb3e4d8
|
@ -4,8 +4,8 @@
|
|||
module builtin
|
||||
|
||||
__global (
|
||||
g_m2_buf byteptr
|
||||
g_m2_ptr byteptr
|
||||
g_m2_buf byteptr
|
||||
g_m2_ptr byteptr
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
struct VCastTypeIndexName {
|
||||
tindex int
|
||||
tname string
|
||||
}
|
||||
|
||||
__global (
|
||||
total_m = i64(0)
|
||||
nr_mallocs = int(0)
|
||||
total_m = i64(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 {
|
||||
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
|
||||
}
|
||||
|
@ -55,15 +72,15 @@ pub:
|
|||
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
|
||||
}
|
||||
|
||||
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' {
|
||||
eprintln(' left value: ${i.llabel} = ${i.lvalue}')
|
||||
eprintln(' left value: $i.llabel = $i.lvalue')
|
||||
if i.rlabel == i.rvalue {
|
||||
eprintln(' right value: $i.rlabel')
|
||||
}
|
||||
else {
|
||||
eprintln(' right value: ${i.rlabel} = ${i.rvalue}')
|
||||
} else {
|
||||
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
|
||||
timers &util.Timers = util.new_timers(false)
|
||||
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 {
|
||||
|
@ -201,7 +202,6 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
}
|
||||
g.init()
|
||||
g.timers.show('cgen init')
|
||||
//
|
||||
mut tests_inited := false
|
||||
mut autofree_used := false
|
||||
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.write_str_definitions()
|
||||
// v files are finished, what remains is pure C code
|
||||
g.gen_vlines_reset()
|
||||
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_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('\tvinit_string_literals();')
|
||||
//
|
||||
|
@ -4999,7 +5004,6 @@ fn (mut g Gen) write_init_function() {
|
|||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
g.writeln('}')
|
||||
if g.pref.printfn_list.len > 0 && '_vinit' in g.pref.printfn_list {
|
||||
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('\tfree(g_str_buf);')
|
||||
g.writeln('\tarray_free(&as_cast_type_indexes);')
|
||||
g.writeln('}')
|
||||
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
||||
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)
|
||||
sym := g.table.get_type_symbol(node.typ)
|
||||
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 { '.' }
|
||||
g.write('/* as */ *($styp*)__as_cast((')
|
||||
g.write('/* as */ *($styp*)__as_cast(')
|
||||
g.write('(')
|
||||
g.expr(node.expr)
|
||||
g.write(')')
|
||||
g.write(dot)
|
||||
g.write('_$sym.cname, (')
|
||||
g.write('_$sym.cname,')
|
||||
g.write('(')
|
||||
g.expr(node.expr)
|
||||
g.write(')')
|
||||
g.write(dot)
|
||||
// g.write('typ, /*expected:*/$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) {
|
||||
eq := if node.op == .key_is { '==' } else { '!=' }
|
||||
g.write('(')
|
||||
|
|
|
@ -2,4 +2,4 @@ Foo
|
|||
================ V panic ================
|
||||
module: builtin
|
||||
function: __as_cast()
|
||||
message: as cast: cannot cast
|
||||
message: as cast: cannot cast `main.Struct` to `main.Interface`
|
||||
|
|
Loading…
Reference in New Issue