mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: implement typeof(x)
This commit is contained in:
parent
794ee6fc9d
commit
b17ade1257
@ -843,9 +843,13 @@ fn (p mut Parser) type_decl() {
|
||||
is_public: is_pub
|
||||
})
|
||||
*/
|
||||
if p.pass == .main {
|
||||
p.cgen.consts << '//// SUMTYPE: ${p.mod} | parent: ${name} | name: ${parent.name}'
|
||||
}
|
||||
// Register the rest of them
|
||||
mut idx := 0
|
||||
mut done := false
|
||||
mut ctype_names := []string
|
||||
for {
|
||||
// p.tok == .pipe {
|
||||
idx++
|
||||
@ -865,6 +869,7 @@ fn (p mut Parser) type_decl() {
|
||||
t.parent = name
|
||||
p.table.rewrite_type(t)
|
||||
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
|
||||
ctype_names << child_type_name
|
||||
}
|
||||
if done {
|
||||
break
|
||||
@ -888,7 +893,15 @@ fn (p mut Parser) type_decl() {
|
||||
mod: p.mod
|
||||
cat: .alias
|
||||
is_public: is_pub
|
||||
ctype_names: ctype_names
|
||||
})
|
||||
if p.pass == .main {
|
||||
p.cgen.consts << 'const char * __SumTypeNames__${name}[] = {'
|
||||
for ctype_name in ctype_names {
|
||||
p.cgen.consts << ' "$ctype_name",'
|
||||
}
|
||||
p.cgen.consts << '};'
|
||||
}
|
||||
p.gen_typedef('typedef struct {
|
||||
void* obj;
|
||||
int typ;
|
||||
|
@ -109,6 +109,7 @@ $c_common_macros
|
||||
#include <direct.h> // _wgetcwd
|
||||
//#include <WinSock2.h>
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// On MSVC these are the same (as long as /volatile:ms is passed)
|
||||
#define _Atomic volatile
|
||||
|
||||
|
@ -68,8 +68,7 @@ fn (p mut Parser) bool_expression() string {
|
||||
//p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type')
|
||||
T := p.table.find_type(typ)
|
||||
if T.parent == expected {
|
||||
p.cgen.set_placeholder(start_ph,
|
||||
'/*SUM TYPE CAST2*/($expected) { .obj = memdup( &($typ[]) { ')
|
||||
p.cgen.set_placeholder(start_ph, '/*SUM TYPE CAST2*/ ($expected) { .obj = memdup( &($typ[]) { ')
|
||||
tt := typ.all_after('_') // TODO
|
||||
p.gen('}, sizeof($typ) ), .typ = SumType_${tt} }')//${val}_type }')
|
||||
}
|
||||
@ -824,13 +823,29 @@ fn (p mut Parser) factor() string {
|
||||
// p.fgen('$sizeof_typ)')
|
||||
return 'int'
|
||||
}
|
||||
.key_typeof {
|
||||
p.next()
|
||||
p.check(.lpar)
|
||||
p.cgen.nogen = true
|
||||
vname := if p.tok == .name && p.peek() == .rpar { p.lit } else { '' }
|
||||
type_of_var := p.expression()
|
||||
p.cgen.nogen = false
|
||||
p.check(.rpar)
|
||||
is_sum_type := type_of_var in p.table.sum_types
|
||||
if is_sum_type && vname.len > 0 {
|
||||
// TODO: make this work for arbitrary sumtype expressions, not just simple vars
|
||||
p.gen('tos3(__SumTypeNames__${type_of_var}[${vname}.typ - 1])')
|
||||
}else{
|
||||
p.gen('tos3("$type_of_var")')
|
||||
}
|
||||
return 'string'
|
||||
}
|
||||
.key_nameof {
|
||||
p.next()
|
||||
p.check(.lpar)
|
||||
mut nameof_typ := p.get_type()
|
||||
p.check(.rpar)
|
||||
p.gen('tos3("$nameof_typ")')
|
||||
// return 'byteptr'
|
||||
return 'string'
|
||||
}
|
||||
.key_offsetof {
|
||||
|
@ -627,7 +627,21 @@ fn (p mut Parser) cast(typ string) {
|
||||
if expr_typ == 'bool' {
|
||||
p.error('cannot cast `bool` to `$typ`')
|
||||
}
|
||||
p.cgen.set_placeholder(pos, '($typ)(')
|
||||
if typ != expr_typ && typ in p.table.sum_types {
|
||||
T := p.table.find_type(typ)
|
||||
if expr_typ in T.ctype_names {
|
||||
// There is no need for a cast here, since it was already done
|
||||
// in p.bool_expression, SUM TYPE CAST2 . Besides, doubling the
|
||||
// cast here causes MSVC to complain with:
|
||||
// error C2440: 'type cast': cannot convert from 'ExprType' to 'ExprType'
|
||||
p.cgen.set_placeholder(pos, '(')
|
||||
}else{
|
||||
p.warn('only $T.ctype_names can be casted to `$typ`')
|
||||
p.error('cannot cast `$expr_typ` to `$typ`')
|
||||
}
|
||||
}else{
|
||||
p.cgen.set_placeholder(pos, '($typ)(')
|
||||
}
|
||||
}
|
||||
p.check(.rpar)
|
||||
p.gen(')')
|
||||
|
@ -127,6 +127,7 @@ pub mut:
|
||||
is_flag bool // enum bitfield flag
|
||||
// max_field_len int
|
||||
is_generic bool
|
||||
ctype_names []string
|
||||
}
|
||||
|
||||
struct TypeNode {
|
||||
|
74
vlib/compiler/tests/typeof_test.v
Normal file
74
vlib/compiler/tests/typeof_test.v
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
fn test_typeof_on_simple_expressions() {
|
||||
a := 123
|
||||
assert typeof(42) == 'int'
|
||||
assert typeof(3.14) == 'f32'
|
||||
assert typeof(2+2*10) == 'int'
|
||||
assert typeof(1.0 * 12.2) == 'f32'
|
||||
assert typeof(a) == 'int'
|
||||
}
|
||||
|
||||
fn test_typeof_on_atypes(){
|
||||
aint := []int
|
||||
astring := []string
|
||||
assert typeof(aint) == 'array_int'
|
||||
assert typeof(astring) == 'array_string'
|
||||
}
|
||||
|
||||
struct FooBar {
|
||||
x int
|
||||
}
|
||||
|
||||
fn test_typeof_on_structs(){
|
||||
assert typeof(FooBar{}) == "FooBar"
|
||||
astruct_static := [2]FooBar
|
||||
astruct_dynamic := [FooBar{}, FooBar{}]
|
||||
assert typeof(astruct_static) == '[2]FooBar'
|
||||
assert typeof(astruct_dynamic) == 'array_FooBar'
|
||||
}
|
||||
|
||||
type MySumType = int | f32 | FooBar
|
||||
pub fn (ms MySumType) str() string {
|
||||
match ms {
|
||||
int { return it.str() }
|
||||
f32 { return it.str() }
|
||||
//FooBar { return it.x.str() }
|
||||
else { return 'unknown: ' + typeof(ms) }
|
||||
}
|
||||
}
|
||||
|
||||
fn test_typeof_on_sumtypes(){
|
||||
a := MySumType(32)
|
||||
b := MySumType(123.0)
|
||||
c := MySumType(FooBar{x:43})
|
||||
assert typeof(a) == 'int'
|
||||
assert typeof(b) == 'f32'
|
||||
assert typeof(c) == 'FooBar'
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
struct UnaryExpr { a string }
|
||||
struct BinExpr { a string b string }
|
||||
struct BoolExpr { z int }
|
||||
type ExprType = BoolExpr | BinExpr | UnaryExpr
|
||||
|
||||
fn fexpr(k int) ExprType {
|
||||
match k {
|
||||
1 { return UnaryExpr{} }
|
||||
2 { return BinExpr{} }
|
||||
3 { return BoolExpr{} }
|
||||
else { return UnaryExpr{} }
|
||||
}
|
||||
}
|
||||
|
||||
fn test_typeof_on_sumtypes_of_structs() {
|
||||
a := fexpr(1)
|
||||
b := fexpr(2)
|
||||
c := fexpr(3)
|
||||
d := ExprType( UnaryExpr{} )
|
||||
assert typeof(a) == 'UnaryExpr'
|
||||
assert typeof(b) == 'BinExpr'
|
||||
assert typeof(c) == 'BoolExpr'
|
||||
assert typeof(d) == 'UnaryExpr'
|
||||
}
|
@ -115,7 +115,7 @@ enum TokenKind {
|
||||
key_switch
|
||||
key_true
|
||||
key_type
|
||||
// typeof
|
||||
key_typeof
|
||||
key_orelse
|
||||
key_union
|
||||
key_pub
|
||||
@ -224,7 +224,7 @@ fn build_token_str() []string {
|
||||
s[TokenKind.key_import] = 'import'
|
||||
s[TokenKind.key_embed] = 'embed'
|
||||
s[TokenKind.key_unsafe] = 'unsafe'
|
||||
// Tokens[key_typeof] = 'typeof'
|
||||
s[TokenKind.key_typeof] = 'typeof'
|
||||
s[TokenKind.key_enum] = 'enum'
|
||||
s[TokenKind.key_interface] = 'interface'
|
||||
s[TokenKind.key_pub] = 'pub'
|
||||
|
Loading…
Reference in New Issue
Block a user