checker/cgen: interface match

pull/5142/head
Alexander Medvednikov 2020-05-31 10:22:18 +02:00
parent c4241f90e6
commit f87e872fa2
5 changed files with 42 additions and 15 deletions

View File

@ -439,6 +439,7 @@ pub mut:
cond_type table.Type // type of `x` in `match x {` cond_type table.Type // type of `x` in `match x {`
expected_type table.Type // for debugging only expected_type table.Type // for debugging only
is_sum_type bool is_sum_type bool
is_interface bool
} }
pub struct MatchBranch { pub struct MatchBranch {

View File

@ -1039,7 +1039,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
return f.return_type return f.return_type
} }
fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position) { fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position) bool {
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
inter_sym := c.table.get_type_symbol(inter_typ) inter_sym := c.table.get_type_symbol(inter_typ)
styp := c.table.type_to_str(typ) styp := c.table.type_to_str(typ)
@ -1048,6 +1048,7 @@ fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position
if !imethod.is_same_method_as(method) { if !imethod.is_same_method_as(method) {
c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.name`, expected `${c.table.fn_to_str(imethod)}`', c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.name`, expected `${c.table.fn_to_str(imethod)}`',
pos) pos)
return false
} }
continue continue
} }
@ -1057,6 +1058,7 @@ fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position
if typ !in inter_info.types && typ_sym.kind != .interface_ { if typ !in inter_info.types && typ_sym.kind != .interface_ {
inter_info.types << typ inter_info.types << typ
} }
return true
} }
// return the actual type of the expression, once the optional is handled // return the actual type of the expression, once the optional is handled
@ -2037,11 +2039,11 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
if cond_type == 0 { if cond_type == 0 {
c.error('match 0 cond type', node.pos) c.error('match 0 cond type', node.pos)
} }
type_sym := c.table.get_type_symbol(cond_type) cond_type_sym := c.table.get_type_symbol(cond_type)
if type_sym.kind != .sum_type { if cond_type_sym.kind !in [.sum_type, .interface_] {
node.is_sum_type = false node.is_sum_type = false
} }
c.match_exprs(mut node, type_sym) c.match_exprs(mut node, cond_type_sym)
c.expected_type = cond_type c.expected_type = cond_type
mut ret_type := table.void_type mut ret_type := table.void_type
for branch in node.branches { for branch in node.branches {
@ -2049,12 +2051,17 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
c.expected_type = cond_type c.expected_type = cond_type
typ := c.expr(expr) typ := c.expr(expr)
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
if !node.is_sum_type && !c.check_types(typ, cond_type) { if node.is_sum_type || node.is_interface {
exp_sym := c.table.get_type_symbol(cond_type) ok := if cond_type_sym.kind == .sum_type {
c.error('cannot use `$typ_sym.name` as `$exp_sym.name` in `match`', node.pos) // TODO verify sum type
true // c.check_types(typ, cond_type)
} else {
c.type_implements(typ, cond_type, node.pos)
}
if !ok {
c.error('cannot use `$typ_sym.name` as `$cond_type_sym.name` in `match`',
node.pos)
} }
// TODO:
if typ_sym.kind == .sum_type {
} }
} }
c.stmts(branch.stmts) c.stmts(branch.stmts)

View File

@ -1888,9 +1888,14 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
for i, expr in branch.exprs { for i, expr in branch.exprs {
if node.is_sum_type { if node.is_sum_type {
g.expr(node.cond) g.expr(node.cond)
sym := g.table.get_type_symbol(node.cond_type)
// branch_sym := g.table.get_type_symbol(branch.typ)
if sym.kind == .sum_type {
g.write('.typ == ') g.write('.typ == ')
// g.write('${tmp}.typ == ') } else if sym.kind == .interface_ {
// sum_type_str // g.write('._interface_idx == _${sym.name}_${branch_sym} ')
g.write('._interface_idx == ')
}
} else if type_sym.kind == .string { } else if type_sym.kind == .string {
g.write('string_eq(') g.write('string_eq(')
// //

View File

@ -12,7 +12,7 @@ import v.util
import v.errors import v.errors
import os import os
import runtime import runtime
import sync //import sync
import time import time
pub struct Parser { pub struct Parser {
@ -140,6 +140,7 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
} }
} }
/*
struct Queue { struct Queue {
mut: mut:
idx int idx int
@ -171,10 +172,12 @@ fn (mut q Queue) run() {
println('run done(idx=$idx)') println('run done(idx=$idx)')
} }
} }
*/
pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, global_scope &ast.Scope) []ast.File { pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, global_scope &ast.Scope) []ast.File {
// println('nr_cpus= $nr_cpus') // println('nr_cpus= $nr_cpus')
$if macos { $if macos {
/*
if pref.is_parallel && paths[0].contains('/array.v') { if pref.is_parallel && paths[0].contains('/array.v') {
println('\n\n\nparse_files() nr_files=$paths.len') println('\n\n\nparse_files() nr_files=$paths.len')
println(paths) println(paths)
@ -194,6 +197,7 @@ pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, g
println('all done') println('all done')
return q.parsed_ast_files return q.parsed_ast_files
} }
*/
} }
if false { if false {
// TODO: remove this; it just prevents warnings about unused time and runtime // TODO: remove this; it just prevents warnings about unused time and runtime

View File

@ -247,3 +247,13 @@ fn new_animal() Animal {
fn new_animal2() Animal { fn new_animal2() Animal {
return new_animal() return new_animal()
} }
/*
fn animal_match(a Animal) {
match a {
Dog { println('(dog)') }
Cat { println('(cat)') }
else {}
}
}
*/