cgen: support `typeof(expr).name` (#6253)

pull/6266/head
Nick Treleaven 2020-08-30 07:56:18 +01:00 committed by GitHub
parent 95ce9f33a9
commit 5d3d14da53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 1 deletions

View File

@ -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)
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
sym := c.table.get_type_symbol(c.unwrap_generic(typ))
field_name := selector_expr.field_name

View File

@ -2102,6 +2102,11 @@ fn (mut g Gen) expr(node ast.Expr) {
g.struct_init(node)
}
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)
if sym.kind == .array_fixed {
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) {
sym := g.table.get_type_symbol(node.expr_type)
if sym.kind == .sum_type {

View File

@ -6,6 +6,7 @@ fn test_typeof_on_simple_expressions() {
assert typeof(f64(1.0) * 12.2) == 'f64'
// assert typeof(1.0 * f32(12.2)) == 'f32'
assert typeof(a) == 'int'
assert typeof(a).name == 'int'
// a2 := 123
// assert typeof(a2) == 'any_int'
// assert typeof(42) == 'any_int'
@ -19,6 +20,7 @@ fn test_typeof_on_atypes() {
astring := []string{}
assert typeof(aint) == 'array_int'
assert typeof(astring) == 'array_string'
assert typeof(astring).name == '[]string'
}
struct FooBar {
@ -27,10 +29,12 @@ struct FooBar {
fn test_typeof_on_structs() {
assert typeof(FooBar{}) == 'FooBar'
astruct_static := [2]FooBar
astruct_static := [2]FooBar{}
astruct_dynamic := [FooBar{}, FooBar{}]
assert typeof(astruct_static) == '[2]FooBar'
assert typeof(astruct_static).name == '[2]FooBar'
assert typeof(astruct_dynamic) == 'array_FooBar'
assert typeof(astruct_dynamic).name == '[]FooBar'
}
type MySumType = int | f32 | FooBar
@ -51,6 +55,9 @@ fn test_typeof_on_sumtypes() {
assert typeof(a) == 'int'
assert typeof(b) == 'f32'
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(myfn3) == 'fn (int, string) byte'
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)
}