mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker/cgen: interface smart casts
This commit is contained in:
parent
912bc8bca1
commit
d547f74cb0
@ -2983,7 +2983,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||
c.error('non-bool type `$typ_sym.source_name` used as if condition', branch.pos)
|
||||
}
|
||||
}
|
||||
// smartcast sumtypes when using `is`
|
||||
// smartcast sumtypes and interfaces when using `is`
|
||||
if branch.cond is ast.InfixExpr {
|
||||
infix := branch.cond as ast.InfixExpr
|
||||
if infix.op == .key_is &&
|
||||
@ -2994,7 +2994,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||
// Register shadow variable or `as` variable with actual type
|
||||
if is_variable {
|
||||
left_sym := c.table.get_type_symbol(infix.left_type)
|
||||
if left_sym.kind == .sum_type && branch.left_as_name.len > 0 {
|
||||
if left_sym.kind in [.sum_type, .interface_] && branch.left_as_name.len > 0 {
|
||||
mut is_mut := false
|
||||
mut scope := c.file.scope.innermost(branch.body_pos.pos)
|
||||
if infix.left is ast.Ident as infix_left {
|
||||
|
@ -1134,20 +1134,20 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
|
||||
got_sym := g.table.get_type_symbol(got_type)
|
||||
if expected_is_ptr && got_is_ptr {
|
||||
exp_der_styp := g.typ(expected_deref_type)
|
||||
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = ')
|
||||
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){._object = ')
|
||||
g.expr(expr)
|
||||
g.write(', .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))')
|
||||
} else if expected_is_ptr {
|
||||
exp_der_styp := g.typ(expected_deref_type)
|
||||
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = memdup(&($got_styp[]) {')
|
||||
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){._object = memdup(&($got_styp[]) {')
|
||||
g.expr(expr)
|
||||
g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))')
|
||||
} else if got_is_ptr {
|
||||
g.write('/* sum type cast */ ($exp_styp) {.obj = ')
|
||||
g.write('/* sum type cast */ ($exp_styp) {._object = ')
|
||||
g.expr(expr)
|
||||
g.write(', .typ = $got_idx /* $got_sym.name */}')
|
||||
} else {
|
||||
g.write('/* sum type cast */ ($exp_styp) {.obj = memdup(&($got_styp[]) {')
|
||||
g.write('/* sum type cast */ ($exp_styp) {._object = memdup(&($got_styp[]) {')
|
||||
g.expr(expr)
|
||||
g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}')
|
||||
}
|
||||
@ -2604,7 +2604,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||
g.expr(node.cond)
|
||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||
g.write(dot_or_ptr)
|
||||
g.writeln('obj; // ST it')
|
||||
g.writeln('_object; // ST it')
|
||||
if node.var_name.len > 0 {
|
||||
// for now we just copy it
|
||||
g.writeln('\t$it_type* $node.var_name = it;')
|
||||
@ -2788,7 +2788,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
} else {
|
||||
g.write('.')
|
||||
}
|
||||
g.writeln('obj;')
|
||||
g.writeln('_object;')
|
||||
g.writeln('\t$it_type* $branch.left_as_name = _sc_tmp_$branch.pos.pos;')
|
||||
}
|
||||
g.stmts(branch.stmts)
|
||||
@ -3773,7 +3773,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||
g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
|
||||
}
|
||||
g.type_definitions.writeln('typedef struct {')
|
||||
g.type_definitions.writeln(' void* obj;')
|
||||
g.type_definitions.writeln(' void* _object;')
|
||||
g.type_definitions.writeln(' int typ;')
|
||||
g.type_definitions.writeln('} $name;')
|
||||
g.type_definitions.writeln('')
|
||||
@ -4704,7 +4704,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||
g.write('/* as */ ($styp*)__as_cast(')
|
||||
g.expr(node.expr)
|
||||
g.write(dot)
|
||||
g.write('obj, ')
|
||||
g.write('_object, ')
|
||||
g.expr(node.expr)
|
||||
g.write(dot)
|
||||
g.write('typ, /*expected:*/$node.typ)')
|
||||
|
@ -23,7 +23,7 @@ fn (c &Cat) speak(s string) {
|
||||
}
|
||||
|
||||
fn (c Cat) name_detailed(pet_name string) string {
|
||||
return '$pet_name the ${typeof(c)}, breed:${c.breed}'
|
||||
return '$pet_name the ${typeof(c)}, breed:$c.breed'
|
||||
}
|
||||
|
||||
fn (mut c Cat) set_breed(new string) {
|
||||
@ -46,7 +46,7 @@ fn (d Dog) name() string {
|
||||
}
|
||||
|
||||
fn (d Dog) name_detailed(pet_name string) string {
|
||||
return '$pet_name the ${typeof(d)}, breed:${d.breed}'
|
||||
return '$pet_name the ${typeof(d)}, breed:$d.breed'
|
||||
}
|
||||
|
||||
fn (mut d Dog) set_breed(new string) {
|
||||
@ -67,10 +67,12 @@ fn perform_speak(a Animal) {
|
||||
assert name == 'Dog' || name == 'Cat'
|
||||
if a is Dog {
|
||||
assert name == 'Dog'
|
||||
assert a.breed == 'Labrador Retriever' // test smart casting
|
||||
println(a.breed)
|
||||
}
|
||||
println(a.name())
|
||||
println('Got animal of type: ${typeof(a)}') // TODO: get implementation type (if possible)
|
||||
// assert a is Dog || a is Cat // TODO: enable when available
|
||||
assert a is Dog || a is Cat
|
||||
}
|
||||
|
||||
fn perform_speak_on_ptr(a &Animal) {
|
||||
@ -78,12 +80,12 @@ fn perform_speak_on_ptr(a &Animal) {
|
||||
assert true
|
||||
name := a.name()
|
||||
assert name == 'Dog' || name == 'Cat'
|
||||
// if a is Dog {
|
||||
// assert name == 'Dog'
|
||||
// }
|
||||
if a is Dog {
|
||||
assert name == 'Dog'
|
||||
}
|
||||
println(a.name())
|
||||
println('Got animal of type: ${typeof(a)}') // TODO: get implementation type (if possible)
|
||||
// assert a is Dog || a is Cat // TODO: enable when available
|
||||
assert a is Dog || a is Cat
|
||||
}
|
||||
|
||||
fn test_perform_speak() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user