1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

v2: typeof()

This commit is contained in:
Delyan Angelov 2020-03-28 18:37:22 +02:00 committed by GitHub
parent 837bffd03a
commit a9724fd38d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 3 deletions

View File

@ -641,6 +641,8 @@ pub:
pub struct TypeOf {
pub:
expr Expr
mut:
expr_type table.Type
}
pub struct LineComment {

View File

@ -779,6 +779,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
return it.typ
}
ast.TypeOf {
it.expr_type = c.expr(it.expr)
return table.string_type
}
/*

View File

@ -107,12 +107,34 @@ pub fn (g mut Gen) init() {
g.definitions.writeln('\nstring _STR_TMP(const char*, ...);\n')
g.write_builtin_types()
g.write_typedef_types()
g.write_typeof_functions()
g.write_str_definitions()
g.write_sorted_types()
g.write_multi_return_types()
g.definitions.writeln('// end of definitions #endif')
}
pub fn (g mut Gen) write_typeof_functions() {
g.writeln('// >> typeof() support for sum types')
for typ in g.table.types {
if typ.kind == .sum_type {
sum_info := typ.info as table.SumType
tidx := g.table.find_type_idx( typ.name )
g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* ${typ.name} */ ')
g.writeln(' switch(sidx) {')
g.writeln(' case $tidx: return "$typ.name";')
for v in sum_info.variants {
subtype := g.table.get_type_symbol(v)
g.writeln(' case $v: return "$subtype.name";')
}
g.writeln(' default: return "unknown ${typ.name}";')
g.writeln(' }')
g.writeln('}')
}
}
g.writeln('// << typeof() support for sum types')
}
// V type to C type
pub fn (g mut Gen) typ(t table.Type) string {
nr_muls := table.type_nr_muls(t)
@ -188,7 +210,7 @@ pub fn (g mut Gen) write_typedef_types() {
else {
continue
}
}
}
}
}
@ -772,7 +794,7 @@ fn (g mut Gen) free_scope_vars(pos int) {
else {
g.writeln('// other ' + t)
}
}
}
g.writeln('string_free($var.name); // autofreed')
}
}
@ -1165,7 +1187,7 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write('$type_idx /* $sym.name */')
}
ast.TypeOf {
g.write('tos3("TYPEOF_TODO")')
g.typeof_expr(it)
}
else {
// #printf("node=%d\n", node.typ);
@ -1174,6 +1196,20 @@ fn (g mut Gen) expr(node ast.Expr) {
}
}
fn (g mut Gen) typeof_expr(node ast.TypeOf) {
sym := g.table.get_type_symbol(node.expr_type)
if sym.kind == .sum_type {
// When encountering a .sum_type, typeof() should be done at runtime,
// because the subtype of the expression may change:
sum_type_idx := table.type_idx( node.expr_type )
g.write('tos3( /* ${sym.name} */ v_typeof_sumtype_${sum_type_idx}( (')
g.expr(node.expr)
g.write(').typ ))')
}else{
g.write('tos3("${sym.name}")')
}
}
fn (g mut Gen) infix_expr(node ast.InfixExpr) {
// println('infix_expr() op="$node.op.str()" line_nr=$node.pos.line_nr')
// g.write('/*infix*/')

View File

@ -0,0 +1,66 @@
struct Abc {
x int
}
struct Xyz {
y int
}
struct XxYyZz {
y int
}
type MySumType = Abc | Xyz
type AnotherSumType = XxYyZz | int
type SuperSumType = MySumType | AnotherSumType | string
fn test_typeof_for_builtin_int_types() {
assert typeof(1) == 'int'
assert typeof(i64(1)) == 'i64'
assert typeof(u32(1)) == 'u32'
assert typeof(u64(1)) == 'u64'
}
fn test_typeof_for_builtin_float_types() {
assert typeof(f32(1.0)) == 'f32'
assert typeof(1.0) == 'f64'
}
fn test_typeof_for_builtin_string_type() {
assert typeof('abc') == 'string'
assert typeof('/v/nv/vlib/v/tests/typeof_simple_types_test.v') == 'string'
assert typeof('22') == 'string'
}
fn test_typeof_for_structs() {
assert typeof(Abc{}) == 'Abc'
assert typeof(Xyz{}) == 'Xyz'
}
//
fn mysumtype_typeof(x MySumType) string {
return typeof(x)
}
fn test_typeof_for_sumtypes() {
z_abc := Abc{}
z_xyz := Xyz{}
assert mysumtype_typeof(z_abc) == 'Abc'
assert mysumtype_typeof(z_xyz) == 'Xyz'
}
//
fn supersumtype_typeof(x SuperSumType) string {
return typeof(x)
}
fn mst(x MySumType) MySumType {
return x
}
fn test_typeof_for_sumtypes_of_sumtypes() {
assert supersumtype_typeof('abc') == 'string'
assert supersumtype_typeof(mst(Abc{})) == 'MySumType'
}