cgen: properly support `typeof()`, sizeof(), ... in compile time `for` (#10896)
parent
12884e9eb7
commit
713a079684
|
@ -38,6 +38,7 @@ fn string_array_to_map(a []string) map[string]bool {
|
|||
struct Gen {
|
||||
pref &pref.Preferences
|
||||
module_built string
|
||||
field_data_type ast.Type // cache her to avoid map lookups
|
||||
mut:
|
||||
table &ast.Table
|
||||
out strings.Builder
|
||||
|
@ -225,6 +226,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
|||
module_built: module_built
|
||||
timers: util.new_timers(timers_should_print)
|
||||
inner_loop: &ast.EmptyStmt{}
|
||||
field_data_type: ast.Type(table.find_type_idx('FieldData'))
|
||||
}
|
||||
g.timers.start('cgen init')
|
||||
for mod in g.table.modules {
|
||||
|
@ -3422,7 +3424,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.select_expr(node)
|
||||
}
|
||||
ast.SizeOf {
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
typ := if node.typ == g.field_data_type { g.comp_for_field_value.typ } else { node.typ }
|
||||
node_typ := g.unwrap_generic(typ)
|
||||
sym := g.table.get_type_symbol(node_typ)
|
||||
if sym.language == .v && sym.kind in [.placeholder, .any] {
|
||||
g.error('unknown type `$sym.name`', node.pos)
|
||||
|
@ -3431,7 +3434,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.write('/*SizeOf*/ sizeof(${util.no_dots(styp)})')
|
||||
}
|
||||
ast.IsRefType {
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
typ := if node.typ == g.field_data_type { g.comp_for_field_value.typ } else { node.typ }
|
||||
node_typ := g.unwrap_generic(typ)
|
||||
sym := g.table.get_type_symbol(node_typ)
|
||||
if sym.language == .v && sym.kind in [.placeholder, .any] {
|
||||
g.error('unknown type `$sym.name`', node.pos)
|
||||
|
@ -3495,7 +3499,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
}
|
||||
|
||||
// T.name, typeof(expr).name
|
||||
fn (mut g Gen) type_name(typ ast.Type) {
|
||||
fn (mut g Gen) type_name(raw_type ast.Type) {
|
||||
typ := if raw_type == g.field_data_type { g.comp_for_field_value.typ } else { raw_type }
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
mut s := ''
|
||||
if sym.kind == .function {
|
||||
|
@ -3511,7 +3516,12 @@ fn (mut g Gen) type_name(typ ast.Type) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||
sym := g.table.get_type_symbol(node.expr_type)
|
||||
typ := if node.expr_type == g.field_data_type {
|
||||
g.comp_for_field_value.typ
|
||||
} else {
|
||||
node.expr_type
|
||||
}
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
if sym.kind == .sum_type {
|
||||
// When encountering a .sum_type, typeof() should be done at runtime,
|
||||
// because the subtype of the expression may change:
|
||||
|
@ -3525,11 +3535,11 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
|||
} else if sym.kind == .function {
|
||||
info := sym.info as ast.FnType
|
||||
g.write('_SLIT("${g.fn_decl_str(info)}")')
|
||||
} else if node.expr_type.has_flag(.variadic) {
|
||||
varg_elem_type_sym := g.table.get_type_symbol(g.table.value_type(node.expr_type))
|
||||
} else if typ.has_flag(.variadic) {
|
||||
varg_elem_type_sym := g.table.get_type_symbol(g.table.value_type(typ))
|
||||
g.write('_SLIT("...${util.strip_main_name(varg_elem_type_sym.name)}")')
|
||||
} else {
|
||||
x := g.table.type_to_str(node.expr_type)
|
||||
x := g.table.type_to_str(typ)
|
||||
y := util.strip_main_name(x)
|
||||
g.write('_SLIT("$y")')
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ fn test_comptime_for_with_if() {
|
|||
|
||||
fn test_comptime_for_fields() {
|
||||
println(@FN)
|
||||
mut fields_found := 0
|
||||
$for field in App.fields {
|
||||
println(' field: $field.name | ' + no_lines('$field'))
|
||||
$if field.typ is string {
|
||||
|
@ -81,5 +82,19 @@ fn test_comptime_for_fields() {
|
|||
if field.is_pub && field.is_mut {
|
||||
assert field.name in ['g', 'h']
|
||||
}
|
||||
if field.name == 'f' {
|
||||
assert sizeof(field) == 8
|
||||
assert isreftype(field) == false
|
||||
// assert typeof(field) == 'u64'
|
||||
assert typeof(field).name == 'u64'
|
||||
fields_found++
|
||||
}
|
||||
if field.name == 'g' {
|
||||
// assert typeof(field) == 'string'
|
||||
assert typeof(field).name == 'string'
|
||||
assert isreftype(field) == true
|
||||
fields_found++
|
||||
}
|
||||
}
|
||||
assert fields_found == 2
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue