cgen: support `typeof(expr).name` (#6253)
parent
95ce9f33a9
commit
5d3d14da53
|
@ -1474,6 +1474,14 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
||||||
c.error('unknown selector expression', selector_expr.pos)
|
c.error('unknown selector expression', selector_expr.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
if selector_expr.expr is ast.TypeOf as left {
|
||||||
|
if selector_expr.field_name == 'name' {
|
||||||
|
return table.string_type
|
||||||
|
} else {
|
||||||
|
c.error('expected `.name`, not `.$selector_expr.field_name` after `typeof` expression',
|
||||||
|
selector_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
selector_expr.expr_type = typ
|
selector_expr.expr_type = typ
|
||||||
sym := c.table.get_type_symbol(c.unwrap_generic(typ))
|
sym := c.table.get_type_symbol(c.unwrap_generic(typ))
|
||||||
field_name := selector_expr.field_name
|
field_name := selector_expr.field_name
|
||||||
|
|
|
@ -2102,6 +2102,11 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.struct_init(node)
|
g.struct_init(node)
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
|
if node.expr is ast.TypeOf as left {
|
||||||
|
// typeof(expr).name
|
||||||
|
g.typeof_name(left)
|
||||||
|
return
|
||||||
|
}
|
||||||
sym := g.table.get_type_symbol(node.expr_type)
|
sym := g.table.get_type_symbol(node.expr_type)
|
||||||
if sym.kind == .array_fixed {
|
if sym.kind == .array_fixed {
|
||||||
assert node.field_name == 'len'
|
assert node.field_name == 'len'
|
||||||
|
@ -2157,6 +2162,22 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// typeof(expr).name
|
||||||
|
fn (mut g Gen) typeof_name(node ast.TypeOf) {
|
||||||
|
sym := g.table.get_type_symbol(node.expr_type)
|
||||||
|
if sym.kind == .array {
|
||||||
|
info := sym.info as table.Array
|
||||||
|
mut s := g.table.get_type_name(info.elem_type)
|
||||||
|
s = util.strip_main_name(s)
|
||||||
|
g.write('tos_lit("[]$s")')
|
||||||
|
} else if sym.kind == .sum_type {
|
||||||
|
// new typeof() must be known at compile-time
|
||||||
|
g.write('tos_lit("${util.strip_main_name(sym.name)}")')
|
||||||
|
} else {
|
||||||
|
g.typeof_expr(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||||
sym := g.table.get_type_symbol(node.expr_type)
|
sym := g.table.get_type_symbol(node.expr_type)
|
||||||
if sym.kind == .sum_type {
|
if sym.kind == .sum_type {
|
||||||
|
|
|
@ -6,6 +6,7 @@ fn test_typeof_on_simple_expressions() {
|
||||||
assert typeof(f64(1.0) * 12.2) == 'f64'
|
assert typeof(f64(1.0) * 12.2) == 'f64'
|
||||||
// assert typeof(1.0 * f32(12.2)) == 'f32'
|
// assert typeof(1.0 * f32(12.2)) == 'f32'
|
||||||
assert typeof(a) == 'int'
|
assert typeof(a) == 'int'
|
||||||
|
assert typeof(a).name == 'int'
|
||||||
// a2 := 123
|
// a2 := 123
|
||||||
// assert typeof(a2) == 'any_int'
|
// assert typeof(a2) == 'any_int'
|
||||||
// assert typeof(42) == 'any_int'
|
// assert typeof(42) == 'any_int'
|
||||||
|
@ -19,6 +20,7 @@ fn test_typeof_on_atypes() {
|
||||||
astring := []string{}
|
astring := []string{}
|
||||||
assert typeof(aint) == 'array_int'
|
assert typeof(aint) == 'array_int'
|
||||||
assert typeof(astring) == 'array_string'
|
assert typeof(astring) == 'array_string'
|
||||||
|
assert typeof(astring).name == '[]string'
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FooBar {
|
struct FooBar {
|
||||||
|
@ -27,10 +29,12 @@ struct FooBar {
|
||||||
|
|
||||||
fn test_typeof_on_structs() {
|
fn test_typeof_on_structs() {
|
||||||
assert typeof(FooBar{}) == 'FooBar'
|
assert typeof(FooBar{}) == 'FooBar'
|
||||||
astruct_static := [2]FooBar
|
astruct_static := [2]FooBar{}
|
||||||
astruct_dynamic := [FooBar{}, FooBar{}]
|
astruct_dynamic := [FooBar{}, FooBar{}]
|
||||||
assert typeof(astruct_static) == '[2]FooBar'
|
assert typeof(astruct_static) == '[2]FooBar'
|
||||||
|
assert typeof(astruct_static).name == '[2]FooBar'
|
||||||
assert typeof(astruct_dynamic) == 'array_FooBar'
|
assert typeof(astruct_dynamic) == 'array_FooBar'
|
||||||
|
assert typeof(astruct_dynamic).name == '[]FooBar'
|
||||||
}
|
}
|
||||||
|
|
||||||
type MySumType = int | f32 | FooBar
|
type MySumType = int | f32 | FooBar
|
||||||
|
@ -51,6 +55,9 @@ fn test_typeof_on_sumtypes() {
|
||||||
assert typeof(a) == 'int'
|
assert typeof(a) == 'int'
|
||||||
assert typeof(b) == 'f32'
|
assert typeof(b) == 'f32'
|
||||||
assert typeof(c) == 'FooBar'
|
assert typeof(c) == 'FooBar'
|
||||||
|
assert typeof(a).name == 'MySumType'
|
||||||
|
assert typeof(b).name == 'MySumType'
|
||||||
|
assert typeof(c).name == 'MySumType'
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -96,4 +103,8 @@ fn test_typeof_on_fn() {
|
||||||
assert typeof(myfn2) == 'fn ()'
|
assert typeof(myfn2) == 'fn ()'
|
||||||
assert typeof(myfn3) == 'fn (int, string) byte'
|
assert typeof(myfn3) == 'fn (int, string) byte'
|
||||||
assert typeof(myfn4) == 'fn () i8'
|
assert typeof(myfn4) == 'fn () i8'
|
||||||
|
assert typeof(myfn).name == typeof(myfn)
|
||||||
|
assert typeof(myfn2).name == typeof(myfn2)
|
||||||
|
assert typeof(myfn3).name == typeof(myfn3)
|
||||||
|
assert typeof(myfn4).name == typeof(myfn4)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue