cgen: cast to sum type

pull/4038/head
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:
pos token.Position
exprs []Expr
mut:
types []table.Type
}
/*
@ -416,10 +418,13 @@ pub:
pub struct AssignStmt {
pub:
left []Ident
right []Expr
op token.Kind
pos token.Position
left []Ident
right []Expr
op token.Kind
pos token.Position
mut:
left_types []table.Type
right_types []table.Type
}
pub struct AsCast {
@ -490,12 +495,13 @@ pub:
pub struct AssignExpr {
pub:
op token.Kind
pos token.Position
left Expr
val Expr
op token.Kind
pos token.Position
left Expr
val Expr
mut:
left_type table.Type
left_type table.Type
right_type table.Type
}
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)
// println('setting exp type to $c.expected_type $t.name')
right_type := c.expr(assign_expr.val)
assign_expr.right_type = right_type
if !c.table.check(right_type, left_type) {
left_type_sym := c.table.get_type_symbol(left_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
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
if return_stmt.exprs.len == 0 {
return
@ -370,6 +371,7 @@ pub fn (c mut Checker) return_stmt(return_stmt ast.Return) {
typ := c.expr(expr)
got_types << typ
}
return_stmt.types = got_types
// 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']] {
return
@ -406,12 +408,14 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
assign_stmt.left[i] = ident
if assign_stmt.op == .assign {
var_type := c.expr(ident)
assign_stmt.left_types << var_type
if !c.table.check(val_type, var_type) {
val_type_sym := c.table.get_type_symbol(val_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)
}
}
assign_stmt.right_types << val_type
scope.override_var(ast.Var{
name: ident.name
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)
for i, _ in assign_stmt.left {
mut ident := assign_stmt.left[i]
mut ident_var_info := ident.var_info()
val_type := c.expr(assign_stmt.right[i])
if assign_stmt.op == .assign {
var_type := c.expr(ident)
assign_stmt.left_types << var_type
if !c.table.check(val_type, var_type) {
val_type_sym := c.table.get_type_symbol(val_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)
}
}
mut ident_var_info := ident.var_info()
assign_stmt.right_types << val_type
ident_var_info.typ = val_type
ident.info = ident_var_info
assign_stmt.left[i] = ident
@ -556,7 +562,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
// ast.HashStmt {}
ast.Import {}
ast.Return {
c.return_stmt(it)
c.return_stmt(mut it)
}
// ast.StructDecl {}
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) {
// multi return
// g.write('/*assign*/')
@ -394,13 +417,20 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
}
else {}
}
mut is_sum_cast := false
if assign_stmt.op == .decl_assign {
g.write('$styp ')
} else {
is_sum_cast = g.is_sum_cast(assign_stmt.right_types[i], assign_stmt.left_types[i])
}
g.expr(ident)
if !is_fixed_array_init {
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(';')
@ -549,7 +579,11 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write(', ')
}
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 {
g.write(' })')
g.is_array_set = false
@ -1135,6 +1169,8 @@ fn (g mut Gen) return_statement(it ast.Return) {
g.write('return')
// multiple returns
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)
g.write(' ($styp){')
for i, expr in it.exprs {
@ -1171,7 +1207,12 @@ fn (g mut Gen) return_statement(it ast.Return) {
}
// 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(';')
}