checker/cgen: interface match
parent
c4241f90e6
commit
f87e872fa2
|
@ -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 {
|
||||||
|
@ -657,7 +658,7 @@ pub:
|
||||||
pub struct ArrayInit {
|
pub struct ArrayInit {
|
||||||
pub:
|
pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
elem_type_pos token.Position
|
elem_type_pos token.Position
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
is_fixed bool
|
is_fixed bool
|
||||||
has_val bool
|
has_val bool
|
||||||
|
|
|
@ -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)
|
||||||
// TODO:
|
} else {
|
||||||
if typ_sym.kind == .sum_type {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.stmts(branch.stmts)
|
c.stmts(branch.stmts)
|
||||||
|
|
|
@ -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)
|
||||||
g.write('.typ == ')
|
sym := g.table.get_type_symbol(node.cond_type)
|
||||||
// g.write('${tmp}.typ == ')
|
// branch_sym := g.table.get_type_symbol(branch.typ)
|
||||||
// sum_type_str
|
if sym.kind == .sum_type {
|
||||||
|
g.write('.typ == ')
|
||||||
|
} else if sym.kind == .interface_ {
|
||||||
|
// 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(')
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue