1
0
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:
joe-conigliaro 2020-03-16 17:42:45 +11:00
parent 66adf7a6b9
commit c947e6ebe6
3 changed files with 68 additions and 15 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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(';')
} }