mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
gen: implement type_name method for sum type instances (#6802)
This commit is contained in:
parent
2dc9a45e06
commit
50163508f8
@ -1634,8 +1634,11 @@ struct Venus {}
|
||||
type World = Moon | Mars | Venus
|
||||
|
||||
sum := World(Moon{})
|
||||
assert sum.type_name() == 'Moon'
|
||||
println(sum)
|
||||
```
|
||||
The built-in method `type_name` returns the name of the currently held
|
||||
type.
|
||||
|
||||
#### Dynamic casts
|
||||
|
||||
|
@ -294,7 +294,7 @@ pub:
|
||||
left Expr // `user` in `user.register()`
|
||||
mod string
|
||||
pub mut:
|
||||
name string
|
||||
name string // left.name()
|
||||
is_method bool
|
||||
is_field bool // temp hack, remove ASAP when re-impl CallExpr / Selector (joe)
|
||||
args []CallArg
|
||||
|
@ -1097,6 +1097,9 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
c.error('optional type cannot be called directly', call_expr.left.position())
|
||||
return table.void_type
|
||||
}
|
||||
if left_type_sym.kind == .sum_type && method_name == 'type_name' {
|
||||
return table.string_type
|
||||
}
|
||||
// TODO: remove this for actual methods, use only for compiler magic
|
||||
// FIXME: Argument count != 1 will break these
|
||||
if left_type_sym.kind == .array &&
|
||||
@ -4424,6 +4427,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
if sym.kind == .interface_ {
|
||||
c.error('interfaces cannot be used as method receiver', node.receiver_pos)
|
||||
}
|
||||
if sym.kind == .sum_type && node.name == 'type_name' {
|
||||
c.error('method overrides built-in sum type method', node.pos)
|
||||
}
|
||||
// if sym.has_method(node.name) {
|
||||
// c.warn('duplicate method `$node.name`', node.pos)
|
||||
// }
|
||||
|
@ -1,3 +1,12 @@
|
||||
vlib/v/checker/tests/incorrect_name_sum_type.vv:1:1: error: sum type `integer` must begin with capital letter
|
||||
1 | type integer = i8 | i16 | int | i64
|
||||
| ~~~~~~~~~~~~
|
||||
| ~~~~~~~~~~~~
|
||||
2 | type Integer = i8 | i16 | int | i64
|
||||
3 |
|
||||
vlib/v/checker/tests/incorrect_name_sum_type.vv:4:1: error: method overrides built-in sum type method
|
||||
2 | type Integer = i8 | i16 | int | i64
|
||||
3 |
|
||||
4 | fn (i Integer) type_name() {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
5 | }
|
||||
6 |
|
||||
|
@ -1 +1,6 @@
|
||||
type integer = i8 | i16 | int | i64
|
||||
type Integer = i8 | i16 | int | i64
|
||||
|
||||
fn (i Integer) type_name() {
|
||||
}
|
||||
|
||||
|
@ -377,6 +377,12 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
else {}
|
||||
}
|
||||
}
|
||||
if left_sym.kind == .sum_type && node.name == 'type_name' {
|
||||
g.write('tos3( /* $left_sym.name */ v_typeof_sumtype_${node.receiver_type}( (')
|
||||
g.expr(node.left)
|
||||
g.write(').typ ))')
|
||||
return
|
||||
}
|
||||
if node.name == 'str' {
|
||||
mut styp := g.typ(node.receiver_type)
|
||||
if node.receiver_type.is_ptr() {
|
||||
|
@ -65,6 +65,9 @@ fn test_typeof_on_sumtypes() {
|
||||
assert typeof(a) == 'int'
|
||||
assert typeof(b) == 'f32'
|
||||
assert typeof(c) == 'FooBar'
|
||||
assert a.type_name() == 'int'
|
||||
assert b.type_name() == 'f32'
|
||||
assert c.type_name() == 'FooBar'
|
||||
// typeof should be known at compile-time for all types
|
||||
assert typeof(a).name == 'MySumType'
|
||||
assert typeof(b).name == 'MySumType'
|
||||
@ -96,6 +99,10 @@ fn test_typeof_on_sumtypes_of_structs() {
|
||||
assert typeof(b) == 'BinExpr'
|
||||
assert typeof(c) == 'BoolExpr'
|
||||
assert typeof(d) == 'UnaryExpr'
|
||||
assert a.type_name() == 'UnaryExpr'
|
||||
assert b.type_name() == 'BinExpr'
|
||||
assert c.type_name() == 'BoolExpr'
|
||||
assert d.type_name() == 'UnaryExpr'
|
||||
}
|
||||
|
||||
fn myfn(i int) int {
|
||||
|
Loading…
Reference in New Issue
Block a user