mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: cast to sum type
This commit is contained in:
parent
66adf7a6b9
commit
c947e6ebe6
@ -189,6 +189,8 @@ pub struct Return {
|
|||||||
pub:
|
pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
|
mut:
|
||||||
|
types []table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -416,10 +418,13 @@ pub:
|
|||||||
|
|
||||||
pub struct AssignStmt {
|
pub struct AssignStmt {
|
||||||
pub:
|
pub:
|
||||||
left []Ident
|
left []Ident
|
||||||
right []Expr
|
right []Expr
|
||||||
op token.Kind
|
op token.Kind
|
||||||
pos token.Position
|
pos token.Position
|
||||||
|
mut:
|
||||||
|
left_types []table.Type
|
||||||
|
right_types []table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsCast {
|
pub struct AsCast {
|
||||||
@ -490,12 +495,13 @@ pub:
|
|||||||
|
|
||||||
pub struct AssignExpr {
|
pub struct AssignExpr {
|
||||||
pub:
|
pub:
|
||||||
op token.Kind
|
op token.Kind
|
||||||
pos token.Position
|
pos token.Position
|
||||||
left Expr
|
left Expr
|
||||||
val Expr
|
val Expr
|
||||||
mut:
|
mut:
|
||||||
left_type table.Type
|
left_type table.Type
|
||||||
|
right_type table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GotoLabel {
|
pub struct GotoLabel {
|
||||||
|
@ -169,6 +169,7 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
|||||||
// t := c.table.get_type_symbol(left_type)
|
// t := c.table.get_type_symbol(left_type)
|
||||||
// println('setting exp type to $c.expected_type $t.name')
|
// println('setting exp type to $c.expected_type $t.name')
|
||||||
right_type := c.expr(assign_expr.val)
|
right_type := c.expr(assign_expr.val)
|
||||||
|
assign_expr.right_type = right_type
|
||||||
if !c.table.check(right_type, left_type) {
|
if !c.table.check(right_type, left_type) {
|
||||||
left_type_sym := c.table.get_type_symbol(left_type)
|
left_type_sym := c.table.get_type_symbol(left_type)
|
||||||
right_type_sym := c.table.get_type_symbol(right_type)
|
right_type_sym := c.table.get_type_symbol(right_type)
|
||||||
@ -352,7 +353,7 @@ pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: non deferred
|
// TODO: non deferred
|
||||||
pub fn (c mut Checker) return_stmt(return_stmt ast.Return) {
|
pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
|
||||||
c.expected_type = c.fn_return_type
|
c.expected_type = c.fn_return_type
|
||||||
if return_stmt.exprs.len == 0 {
|
if return_stmt.exprs.len == 0 {
|
||||||
return
|
return
|
||||||
@ -370,6 +371,7 @@ pub fn (c mut Checker) return_stmt(return_stmt ast.Return) {
|
|||||||
typ := c.expr(expr)
|
typ := c.expr(expr)
|
||||||
got_types << typ
|
got_types << typ
|
||||||
}
|
}
|
||||||
|
return_stmt.types = got_types
|
||||||
// allow `none` & `error (Option)` return types for function that returns optional
|
// allow `none` & `error (Option)` return types for function that returns optional
|
||||||
if exp_is_optional && table.type_idx(got_types[0]) in [table.none_type_idx, c.table.type_idxs['Option']] {
|
if exp_is_optional && table.type_idx(got_types[0]) in [table.none_type_idx, c.table.type_idxs['Option']] {
|
||||||
return
|
return
|
||||||
@ -406,12 +408,14 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
|||||||
assign_stmt.left[i] = ident
|
assign_stmt.left[i] = ident
|
||||||
if assign_stmt.op == .assign {
|
if assign_stmt.op == .assign {
|
||||||
var_type := c.expr(ident)
|
var_type := c.expr(ident)
|
||||||
|
assign_stmt.left_types << var_type
|
||||||
if !c.table.check(val_type, var_type) {
|
if !c.table.check(val_type, var_type) {
|
||||||
val_type_sym := c.table.get_type_symbol(val_type)
|
val_type_sym := c.table.get_type_symbol(val_type)
|
||||||
var_type_sym := c.table.get_type_symbol(var_type)
|
var_type_sym := c.table.get_type_symbol(var_type)
|
||||||
c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos)
|
c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assign_stmt.right_types << val_type
|
||||||
scope.override_var(ast.Var{
|
scope.override_var(ast.Var{
|
||||||
name: ident.name
|
name: ident.name
|
||||||
typ: mr_info.types[i]
|
typ: mr_info.types[i]
|
||||||
@ -426,16 +430,18 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
|||||||
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
||||||
for i, _ in assign_stmt.left {
|
for i, _ in assign_stmt.left {
|
||||||
mut ident := assign_stmt.left[i]
|
mut ident := assign_stmt.left[i]
|
||||||
|
mut ident_var_info := ident.var_info()
|
||||||
val_type := c.expr(assign_stmt.right[i])
|
val_type := c.expr(assign_stmt.right[i])
|
||||||
if assign_stmt.op == .assign {
|
if assign_stmt.op == .assign {
|
||||||
var_type := c.expr(ident)
|
var_type := c.expr(ident)
|
||||||
|
assign_stmt.left_types << var_type
|
||||||
if !c.table.check(val_type, var_type) {
|
if !c.table.check(val_type, var_type) {
|
||||||
val_type_sym := c.table.get_type_symbol(val_type)
|
val_type_sym := c.table.get_type_symbol(val_type)
|
||||||
var_type_sym := c.table.get_type_symbol(var_type)
|
var_type_sym := c.table.get_type_symbol(var_type)
|
||||||
c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos)
|
c.error('assign stmt: cannot use `$val_type_sym.name` as `$var_type_sym.name`', assign_stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut ident_var_info := ident.var_info()
|
assign_stmt.right_types << val_type
|
||||||
ident_var_info.typ = val_type
|
ident_var_info.typ = val_type
|
||||||
ident.info = ident_var_info
|
ident.info = ident_var_info
|
||||||
assign_stmt.left[i] = ident
|
assign_stmt.left[i] = ident
|
||||||
@ -556,7 +562,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||||||
// ast.HashStmt {}
|
// ast.HashStmt {}
|
||||||
ast.Import {}
|
ast.Import {}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
c.return_stmt(it)
|
c.return_stmt(mut it)
|
||||||
}
|
}
|
||||||
// ast.StructDecl {}
|
// ast.StructDecl {}
|
||||||
ast.UnsafeStmt {
|
ast.UnsafeStmt {
|
||||||
|
@ -326,6 +326,29 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g &Gen) is_sum_cast(got_type table.Type, exp_type table.Type) bool {
|
||||||
|
if exp_type != table.void_type && exp_type != 0 && got_type != 0{
|
||||||
|
exp_sym := g.table.get_type_symbol(exp_type)
|
||||||
|
// got_sym := g.table.get_type_symbol(got_type)
|
||||||
|
if exp_sym.kind == .sum_type {
|
||||||
|
sum_info := exp_sym.info as table.SumType
|
||||||
|
if got_type in sum_info.variants {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) sum_cast(got_type table.Type, exp_type table.Type, expr ast.Expr) {
|
||||||
|
got_styp := g.typ(got_type)
|
||||||
|
exp_styp := g.typ(exp_type)
|
||||||
|
got_idx := table.type_idx(got_type)
|
||||||
|
g.write('/* SUM TYPE CAST */ ($exp_styp) {.obj = memdup(&(${got_styp}[]) {')
|
||||||
|
g.expr(expr)
|
||||||
|
g.writeln('}, sizeof($got_styp)), .typ = $got_idx};')
|
||||||
|
}
|
||||||
|
|
||||||
fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
// multi return
|
// multi return
|
||||||
// g.write('/*assign*/')
|
// g.write('/*assign*/')
|
||||||
@ -394,13 +417,20 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
mut is_sum_cast := false
|
||||||
if assign_stmt.op == .decl_assign {
|
if assign_stmt.op == .decl_assign {
|
||||||
g.write('$styp ')
|
g.write('$styp ')
|
||||||
|
} else {
|
||||||
|
is_sum_cast = g.is_sum_cast(assign_stmt.right_types[i], assign_stmt.left_types[i])
|
||||||
}
|
}
|
||||||
g.expr(ident)
|
g.expr(ident)
|
||||||
if !is_fixed_array_init {
|
if !is_fixed_array_init {
|
||||||
g.write(' = ')
|
g.write(' = ')
|
||||||
g.expr(val)
|
if is_sum_cast {
|
||||||
|
g.sum_cast(ident_var_info.typ, assign_stmt.left_types[i], val)
|
||||||
|
} else {
|
||||||
|
g.expr(val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
@ -549,7 +579,11 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
g.is_assign_expr = false
|
g.is_assign_expr = false
|
||||||
g.expr(it.val)
|
if g.is_sum_cast(it.left_type, it.right_type) {
|
||||||
|
g.sum_cast(it.left_type, it.right_type, it.val)
|
||||||
|
} else {
|
||||||
|
g.expr(it.val)
|
||||||
|
}
|
||||||
if g.is_array_set {
|
if g.is_array_set {
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
g.is_array_set = false
|
g.is_array_set = false
|
||||||
@ -1135,6 +1169,8 @@ fn (g mut Gen) return_statement(it ast.Return) {
|
|||||||
g.write('return')
|
g.write('return')
|
||||||
// multiple returns
|
// multiple returns
|
||||||
if it.exprs.len > 1 {
|
if it.exprs.len > 1 {
|
||||||
|
typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
||||||
|
mr_info := typ_sym.info as table.MultiReturn
|
||||||
styp := g.typ(g.fn_decl.return_type)
|
styp := g.typ(g.fn_decl.return_type)
|
||||||
g.write(' ($styp){')
|
g.write(' ($styp){')
|
||||||
for i, expr in it.exprs {
|
for i, expr in it.exprs {
|
||||||
@ -1171,7 +1207,12 @@ fn (g mut Gen) return_statement(it ast.Return) {
|
|||||||
}
|
}
|
||||||
// g.write('/*OPTIONAL*/')
|
// g.write('/*OPTIONAL*/')
|
||||||
}
|
}
|
||||||
g.expr(it.exprs[0])
|
if g.is_sum_cast(it.types[0], g.fn_decl.return_type) {
|
||||||
|
g.sum_cast(it.types[0], g.fn_decl.return_type, it.exprs[0])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.expr(it.exprs[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user