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
|
amortization = 0.95
|
||||||
)
|
)
|
||||||
|
|
||||||
fn get_webgl() (&JS.HTMLCanvasElement, JS.WebGLRenderingContext) {
|
fn get_webgl() (JS.HTMLCanvasElement, JS.WebGLRenderingContext) {
|
||||||
JS.console.log(dom.document)
|
JS.console.log(dom.document)
|
||||||
elem := dom.document.getElementById('myCanvas'.str) or { panic('cannot get canvas') }
|
elem := dom.document.getElementById('myCanvas'.str) or { panic('cannot get canvas') }
|
||||||
match elem {
|
match elem {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import js.dom
|
import js.dom
|
||||||
|
|
||||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {
|
||||||
match elem {
|
match elem {
|
||||||
JS.HTMLCanvasElement {
|
JS.HTMLCanvasElement {
|
||||||
return elem
|
return elem
|
||||||
|
@ -294,7 +294,7 @@ pub mut:
|
|||||||
// *before* the current event was different
|
// *before* the current event was different
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {
|
||||||
match elem {
|
match elem {
|
||||||
JS.HTMLCanvasElement {
|
JS.HTMLCanvasElement {
|
||||||
return elem
|
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
|
// 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) {
|
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)
|
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_ }
|
mut expr := unsafe { expr_ }
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.SelectorExpr {
|
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 left_sym.kind == .interface_ {
|
||||||
if right_sym.kind != .interface_ {
|
if right_sym.kind != .interface_ {
|
||||||
c.type_implements(right_type, expr_type, node.pos)
|
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 {
|
} else if !c.check_types(right_type, expr_type) && left_sym.kind != .sum_type {
|
||||||
expect_str := c.table.type_to_str(right_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('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||||
if i != 0 {
|
if field_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||||
dot := if field.typ.is_ptr() { '->' } else { '.' }
|
ptr := '*'.repeat(field.typ.nr_muls())
|
||||||
sum_type_deref_field += ')$dot'
|
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))')
|
||||||
if cast_sym.info is ast.Aggregate {
|
return
|
||||||
agg_sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
|
|
||||||
sum_type_deref_field += '_$agg_sym.cname'
|
|
||||||
} else {
|
} 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 {
|
for i, typ in node.obj.smartcasts {
|
||||||
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
cast_sym := g.table.sym(g.unwrap_generic(typ))
|
||||||
mut is_ptr := false
|
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
|
||||||
if i == 0 {
|
ptr := '*'.repeat(node.obj.typ.nr_muls())
|
||||||
g.write(name)
|
g.write('I_${obj_sym.cname}_as_I_${cast_sym.cname}($ptr$node.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 {
|
} 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(')')
|
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() {
|
fn (mut w Window) init() {
|
||||||
for wd in w.initables {
|
for wd in w.initables {
|
||||||
if mut wd is Container {
|
if wd is Container {
|
||||||
mut c := wd as Container
|
mut c := unsafe { wd }
|
||||||
c.layout()
|
c.layout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user