mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: allow a type to be used as a variant of multiple sum types
This commit is contained in:
parent
bc3d1eaf6e
commit
c4e83faa57
@ -850,6 +850,7 @@ fn (p mut Parser) type_decl() {
|
|||||||
mut idx := 0
|
mut idx := 0
|
||||||
mut done := false
|
mut done := false
|
||||||
mut ctype_names := []string
|
mut ctype_names := []string
|
||||||
|
mut sum_variants := []string
|
||||||
for {
|
for {
|
||||||
// p.tok == .pipe {
|
// p.tok == .pipe {
|
||||||
idx++
|
idx++
|
||||||
@ -862,14 +863,17 @@ fn (p mut Parser) type_decl() {
|
|||||||
if p.pass == .main {
|
if p.pass == .main {
|
||||||
// Update the type's parent
|
// Update the type's parent
|
||||||
// println('child=$child_type_name parent=$name')
|
// println('child=$child_type_name parent=$name')
|
||||||
mut t := p.find_type(child_type_name)
|
t := p.find_type(child_type_name)
|
||||||
if t.name == '' {
|
if t.name == '' {
|
||||||
p.error('unknown type `$child_type_name`')
|
p.error('unknown type `$child_type_name`')
|
||||||
}
|
}
|
||||||
t.parent = name
|
p.cgen.consts << '#define SumType_${name}_$child_type_name $idx // DEF2'
|
||||||
p.table.rewrite_type(t)
|
|
||||||
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
|
|
||||||
ctype_names << child_type_name
|
ctype_names << child_type_name
|
||||||
|
sum_variants << if p.mod in ['builtin', 'main'] || child_type_name in builtin_types {
|
||||||
|
child_type_name
|
||||||
|
} else {
|
||||||
|
p.prepend_mod(child_type_name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if done {
|
if done {
|
||||||
break
|
break
|
||||||
@ -882,10 +886,7 @@ fn (p mut Parser) type_decl() {
|
|||||||
// p.fgen_nl()
|
// p.fgen_nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.pass == .decl {
|
p.table.sum_types[name] = sum_variants
|
||||||
p.table.sum_types << name
|
|
||||||
// println(p.table.sum_types)
|
|
||||||
}
|
|
||||||
// Register the actual sum type
|
// Register the actual sum type
|
||||||
// println('registering sum $name')
|
// println('registering sum $name')
|
||||||
p.table.register_type(Type{
|
p.table.register_type(Type{
|
||||||
|
@ -66,11 +66,10 @@ fn (p mut Parser) bool_expression() string {
|
|||||||
// e.g. `return InfixExpr{}` in a function expecting `Expr`
|
// e.g. `return InfixExpr{}` in a function expecting `Expr`
|
||||||
if expected != typ && expected in p.table.sum_types { // TODO perf
|
if expected != typ && expected in p.table.sum_types { // TODO perf
|
||||||
//p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type')
|
//p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type')
|
||||||
T := p.table.find_type(typ)
|
if typ in p.table.sum_types[expected] {
|
||||||
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
|
tt := typ.all_after('_') // TODO
|
||||||
p.gen('}, sizeof($typ) ), .typ = SumType_${tt} }')//${val}_type }')
|
p.gen('}, sizeof($typ) ), .typ = SumType_${expected}_${tt} }')//${val}_type }')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `as` cast
|
// `as` cast
|
||||||
@ -90,10 +89,8 @@ fn (p mut Parser) key_as(typ string, start_ph int) string {
|
|||||||
p.error('casting `$typ` to `$cast_typ` is not needed')
|
p.error('casting `$typ` to `$cast_typ` is not needed')
|
||||||
}
|
}
|
||||||
if typ in p.table.sum_types {
|
if typ in p.table.sum_types {
|
||||||
T := p.table.find_type(cast_typ)
|
if !(cast_typ in p.table.sum_types[typ]) {
|
||||||
if T.parent != typ {
|
p.error('cannot cast `$typ` to `$cast_typ`. `$cast_typ` is not a variant of `$typ`')
|
||||||
p.error('cannot cast `$typ` to `$cast_typ`. `$cast_typ` is not a variant of `$typ`' +
|
|
||||||
'parent=$T.parent')
|
|
||||||
}
|
}
|
||||||
p.cgen.set_placeholder(start_ph, '*($cast_typ*)')
|
p.cgen.set_placeholder(start_ph, '*($cast_typ*)')
|
||||||
p.gen('.obj')
|
p.gen('.obj')
|
||||||
@ -102,7 +99,7 @@ fn (p mut Parser) key_as(typ string, start_ph int) string {
|
|||||||
sum_type:= p.cgen.cur_line.all_after('*) (').replace('.obj', '.typ')
|
sum_type:= p.cgen.cur_line.all_after('*) (').replace('.obj', '.typ')
|
||||||
|
|
||||||
n := cast_typ.all_after('__')
|
n := cast_typ.all_after('__')
|
||||||
p.cgen.insert_before('if (($sum_type != SumType_$n) {
|
p.cgen.insert_before('if (($sum_type != SumType_${typ}_$n) {
|
||||||
puts("runtime error: $p.file_name:$p.scanner.line_nr cannot cast sum type `$typ` to `$n`");
|
puts("runtime error: $p.file_name:$p.scanner.line_nr cannot cast sum type `$typ` to `$n`");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ fn (p mut Parser) match_statement(is_expr bool) string {
|
|||||||
if is_sum_type {
|
if is_sum_type {
|
||||||
sum_child_type = p.get_type2().name
|
sum_child_type = p.get_type2().name
|
||||||
tt := sum_child_type.all_after('_')
|
tt := sum_child_type.all_after('_')
|
||||||
p.gen('SumType_$tt')
|
p.gen('SumType_${typ}_$tt')
|
||||||
// println('got child $sum_child_type')
|
// println('got child $sum_child_type')
|
||||||
p.register_var(Var{
|
p.register_var(Var{
|
||||||
name: 'it'
|
name: 'it'
|
||||||
|
@ -21,8 +21,8 @@ pub mut:
|
|||||||
// names []Name
|
// names []Name
|
||||||
max_field_len map[string]int // for vfmt: max_field_len['Parser'] == 12
|
max_field_len map[string]int // for vfmt: max_field_len['Parser'] == 12
|
||||||
generic_struct_params map[string][]string
|
generic_struct_params map[string][]string
|
||||||
tuple_variants map[string][]string // enum( Bool(BoolExpr) )
|
tuple_variants map[string][]string // enum( Bool(BoolExpr) )
|
||||||
sum_types []string
|
sum_types map[string][]string // SumType -> [Variants]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VargAccess {
|
struct VargAccess {
|
||||||
@ -191,6 +191,8 @@ const (
|
|||||||
float_types = ['f32', 'f64']
|
float_types = ['f32', 'f64']
|
||||||
reserved_type_param_names = ['R', 'S', 'T', 'U', 'W']
|
reserved_type_param_names = ['R', 'S', 'T', 'U', 'W']
|
||||||
pointer_types = ['byte*', 'byteptr', 'char*', 'charptr', 'void*', 'voidptr', 'voidptr*', 'intptr']
|
pointer_types = ['byte*', 'byteptr', 'char*', 'charptr', 'void*', 'voidptr', 'voidptr*', 'intptr']
|
||||||
|
builtin_types = ['int', 'i8', 'char', 'byte', 'i16', 'u16', 'u32', 'i64', 'u64',
|
||||||
|
'f64', 'f32', 'byteptr', 'charptr', 'voidptr', 'intptr', 'string', 'ustring']
|
||||||
)
|
)
|
||||||
|
|
||||||
fn is_number_type(typ string) bool {
|
fn is_number_type(typ string) bool {
|
||||||
@ -745,8 +747,7 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
|
|||||||
// Sum type
|
// Sum type
|
||||||
if expected in p.table.sum_types {
|
if expected in p.table.sum_types {
|
||||||
//println('checking sum')
|
//println('checking sum')
|
||||||
child := p.table.find_type(got)
|
if got in p.table.sum_types[expected] {
|
||||||
if child.parent == expected {
|
|
||||||
//println('yep $expected')
|
//println('yep $expected')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,9 @@ fn test_person_str() {
|
|||||||
|
|
||||||
struct Foo {}
|
struct Foo {}
|
||||||
|
|
||||||
type Expr = Foo | BoolExpr | BinExpr | UnaryExpr
|
type Expr = Foo | BoolExpr | BinExpr | UnaryExpr | DeclExprA | DeclExprB
|
||||||
|
|
||||||
|
type DeclExpr = DeclExprA | DeclExprB
|
||||||
|
|
||||||
struct BoolExpr {
|
struct BoolExpr {
|
||||||
foo int
|
foo int
|
||||||
@ -31,6 +33,14 @@ struct BinExpr {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DeclExprA {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeclExprB {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
fn expr1() Expr {
|
fn expr1() Expr {
|
||||||
mut e := Expr{}
|
mut e := Expr{}
|
||||||
e = BinExpr{'binexpr'}
|
e = BinExpr{'binexpr'}
|
||||||
@ -46,11 +56,14 @@ struct UnaryExpr {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn handle_expr(e Expr) {
|
fn handle_expr(e Expr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_decl_expr(de DeclExpr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_bool() BoolExpr {
|
fn parse_bool() BoolExpr {
|
||||||
return BoolExpr{}
|
return BoolExpr{}
|
||||||
}
|
}
|
||||||
@ -64,6 +77,10 @@ fn test_sum_type_cast() {
|
|||||||
fn test_sum_types() {
|
fn test_sum_types() {
|
||||||
b := parse_bool()
|
b := parse_bool()
|
||||||
handle_expr(b)
|
handle_expr(b)
|
||||||
|
|
||||||
|
de := DeclExprA{}
|
||||||
|
handle_expr(de)
|
||||||
|
handle_decl_expr(de)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user