mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parent
0afa2f76c8
commit
041e90b2e2
@ -197,7 +197,7 @@ const (
|
||||
amortization = 0.95
|
||||
)
|
||||
|
||||
fn get_webgl() (&JS.HTMLCanvasElement, JS.WebGLRenderingContext) {
|
||||
fn get_webgl() (JS.HTMLCanvasElement, JS.WebGLRenderingContext) {
|
||||
JS.console.log(dom.document)
|
||||
elem := dom.document.getElementById('myCanvas'.str) or { panic('cannot get canvas') }
|
||||
match elem {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import js.dom
|
||||
|
||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
||||
fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
return elem
|
||||
|
@ -294,7 +294,7 @@ pub mut:
|
||||
// *before* the current event was different
|
||||
}
|
||||
|
||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
||||
fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
return elem
|
||||
|
@ -2903,7 +2903,11 @@ pub fn (mut c Checker) concat_expr(mut node ast.ConcatExpr) ast.Type {
|
||||
// smartcast takes the expression with the current type which should be smartcasted to the target type in the given scope
|
||||
fn (mut c Checker) smartcast(expr_ ast.Expr, cur_type ast.Type, to_type_ ast.Type, mut scope ast.Scope) {
|
||||
sym := c.table.sym(cur_type)
|
||||
to_type := if sym.kind == .interface_ { to_type_.ref() } else { to_type_ }
|
||||
to_type := if sym.kind == .interface_ && c.table.sym(to_type_).kind != .interface_ {
|
||||
to_type_.ref()
|
||||
} else {
|
||||
to_type_
|
||||
}
|
||||
mut expr := unsafe { expr_ }
|
||||
match mut expr {
|
||||
ast.SelectorExpr {
|
||||
|
@ -311,8 +311,6 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
|
||||
if left_sym.kind == .interface_ {
|
||||
if right_sym.kind != .interface_ {
|
||||
c.type_implements(right_type, expr_type, node.pos)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else if !c.check_types(right_type, expr_type) && left_sym.kind != .sum_type {
|
||||
expect_str := c.table.type_to_str(right_type)
|
||||
|
@ -3331,15 +3331,22 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
g.write('*')
|
||||
}
|
||||
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||
if i != 0 {
|
||||
dot := if field.typ.is_ptr() { '->' } else { '.' }
|
||||
sum_type_deref_field += ')$dot'
|
||||
}
|
||||
if cast_sym.info is ast.Aggregate {
|
||||
agg_sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
|
||||
sum_type_deref_field += '_$agg_sym.cname'
|
||||
if field_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||
ptr := '*'.repeat(field.typ.nr_muls())
|
||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
||||
g.write('I_${field_sym.cname}_as_I_${cast_sym.cname}($ptr$node.expr$dot$node.field_name))')
|
||||
return
|
||||
} else {
|
||||
sum_type_deref_field += '_$cast_sym.cname'
|
||||
if i != 0 {
|
||||
dot := if field.typ.is_ptr() { '->' } else { '.' }
|
||||
sum_type_deref_field += ')$dot'
|
||||
}
|
||||
if cast_sym.info is ast.Aggregate {
|
||||
agg_sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
|
||||
sum_type_deref_field += '_$agg_sym.cname'
|
||||
} else {
|
||||
sum_type_deref_field += '_$cast_sym.cname'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3894,19 +3901,24 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
}
|
||||
for i, typ in node.obj.smartcasts {
|
||||
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||
mut is_ptr := false
|
||||
if i == 0 {
|
||||
g.write(name)
|
||||
if node.obj.orig_type.is_ptr() {
|
||||
is_ptr = true
|
||||
}
|
||||
}
|
||||
dot := if is_ptr || is_auto_heap { '->' } else { '.' }
|
||||
if cast_sym.info is ast.Aggregate {
|
||||
sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
|
||||
g.write('${dot}_$sym.cname')
|
||||
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||
ptr := '*'.repeat(node.obj.typ.nr_muls())
|
||||
g.write('I_${obj_sym.cname}_as_I_${cast_sym.cname}($ptr$node.name)')
|
||||
} else {
|
||||
g.write('${dot}_$cast_sym.cname')
|
||||
mut is_ptr := false
|
||||
if i == 0 {
|
||||
g.write(name)
|
||||
if node.obj.orig_type.is_ptr() {
|
||||
is_ptr = true
|
||||
}
|
||||
}
|
||||
dot := if is_ptr || is_auto_heap { '->' } else { '.' }
|
||||
if cast_sym.info is ast.Aggregate {
|
||||
sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
|
||||
g.write('${dot}_$sym.cname')
|
||||
} else {
|
||||
g.write('${dot}_$cast_sym.cname')
|
||||
}
|
||||
}
|
||||
g.write(')')
|
||||
}
|
||||
|
47
vlib/v/tests/interface_embedding_smartcast_test.v
Normal file
47
vlib/v/tests/interface_embedding_smartcast_test.v
Normal file
@ -0,0 +1,47 @@
|
||||
// Common interface to all error custom types.
|
||||
interface ESpeaker {
|
||||
IError
|
||||
speak() string
|
||||
}
|
||||
|
||||
// One custom error implementation.
|
||||
struct MyError {
|
||||
// Mandatory fields from IError.
|
||||
msg string
|
||||
code int
|
||||
// Custom field.
|
||||
blah string
|
||||
}
|
||||
|
||||
// Interface implementation for this example custom type.
|
||||
fn (e MyError) speak() string {
|
||||
return e.blah
|
||||
}
|
||||
|
||||
fn (e MyError) msg() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
fn (e MyError) code() int {
|
||||
return e.code
|
||||
}
|
||||
|
||||
// An example function that returns a custom error.
|
||||
fn foo() ?string {
|
||||
return IError(MyError{
|
||||
msg: 'foo'
|
||||
blah: 'world'
|
||||
})
|
||||
}
|
||||
|
||||
fn test_interface_embedding_smartcast() {
|
||||
x := foo() or {
|
||||
if err is ESpeaker {
|
||||
err.speak()
|
||||
} else {
|
||||
'undefined'
|
||||
}
|
||||
}
|
||||
println(x)
|
||||
assert x == 'world'
|
||||
}
|
@ -34,8 +34,8 @@ mut:
|
||||
|
||||
fn (mut w Window) init() {
|
||||
for wd in w.initables {
|
||||
if mut wd is Container {
|
||||
mut c := wd as Container
|
||||
if wd is Container {
|
||||
mut c := unsafe { wd }
|
||||
c.layout()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user