runtime `as` type check: part 1
parent
f1f9e423c3
commit
2d187fb951
|
@ -170,3 +170,10 @@ pub fn is_atty(fd int) int {
|
||||||
return C.isatty(fd)
|
return C.isatty(fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn __as_cast(obj voidptr, obj_type, expected_type int) voidptr {
|
||||||
|
if obj_type != expected_type {
|
||||||
|
panic('as cast: cannot cast $obj_type to $expected_type')
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
|
@ -945,13 +945,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.AsCast {
|
ast.AsCast {
|
||||||
styp := g.typ(it.typ)
|
g.as_cast(it)
|
||||||
expr_type_sym := g.table.get_type_symbol(it.expr_type)
|
|
||||||
if expr_type_sym.kind == .sum_type {
|
|
||||||
g.write('/* as */ *($styp*)')
|
|
||||||
g.expr(it.expr)
|
|
||||||
g.write('.obj')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
g.assign_expr(it)
|
g.assign_expr(it)
|
||||||
|
@ -1396,7 +1390,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
g.expr_with_cast(node.right, node.right_type, info.elem_type)
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
}
|
}
|
||||||
} else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in [.eq, .ne] {
|
} else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in
|
||||||
|
[.eq, .ne] {
|
||||||
// floats should be compared with epsilon
|
// floats should be compared with epsilon
|
||||||
if node.left_type == table.f64_type_idx {
|
if node.left_type == table.f64_type_idx {
|
||||||
if node.op == .eq {
|
if node.op == .eq {
|
||||||
|
@ -2911,6 +2906,26 @@ fn (mut g Gen) go_stmt(node ast.GoStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||||
|
// Make sure the sum type can be cast to this type (the types
|
||||||
|
// are the same), otherwise panic.
|
||||||
|
// g.insert_before('
|
||||||
|
styp := g.typ(node.typ)
|
||||||
|
expr_type_sym := g.table.get_type_symbol(node.expr_type)
|
||||||
|
if expr_type_sym.kind == .sum_type {
|
||||||
|
g.write('/* as */ *($styp*)')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write('.obj')
|
||||||
|
/*
|
||||||
|
g.write('/* as */ *($styp*)__as_cast(')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write('.obj, ')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write('.typ, /*expected:*/$node.typ)')
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write('.typ == ')
|
g.write('.typ == ')
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Foo
|
||||||
|
V panic: as cast: cannot cast
|
|
@ -0,0 +1,13 @@
|
||||||
|
struct Struct {struct_name string }
|
||||||
|
struct Interface {interface_name string}
|
||||||
|
|
||||||
|
type Info = Struct | Interface
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut info := Info{}
|
||||||
|
info = Struct{struct_name: 'Foo'}
|
||||||
|
s := info as Struct
|
||||||
|
println(s.struct_name)
|
||||||
|
i := info as Interface // wrong
|
||||||
|
println(i.interface_name)
|
||||||
|
}
|
Loading…
Reference in New Issue