v: implement interface embedding (#9935)
parent
3363c3ef65
commit
4b818fa2be
|
@ -260,18 +260,31 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct InterfaceEmbedding {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
typ Type
|
||||||
|
pos token.Position
|
||||||
|
comments []Comment
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InterfaceDecl {
|
pub struct InterfaceDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
typ Type
|
||||||
name_pos token.Position
|
name_pos token.Position
|
||||||
language Language
|
language Language
|
||||||
field_names []string
|
field_names []string
|
||||||
is_pub bool
|
is_pub bool
|
||||||
methods []FnDecl
|
|
||||||
mut_pos int // mut:
|
mut_pos int // mut:
|
||||||
fields []StructField
|
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pre_comments []Comment
|
pre_comments []Comment
|
||||||
|
pub mut:
|
||||||
|
methods []FnDecl
|
||||||
|
fields []StructField
|
||||||
|
//
|
||||||
|
ifaces []InterfaceEmbedding
|
||||||
|
are_ifaces_expanded bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructInitField {
|
pub struct StructInitField {
|
||||||
|
@ -352,7 +365,6 @@ pub struct FnDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
mod string
|
mod string
|
||||||
params []Param
|
|
||||||
is_deprecated bool
|
is_deprecated bool
|
||||||
is_pub bool
|
is_pub bool
|
||||||
is_variadic bool
|
is_variadic bool
|
||||||
|
@ -379,6 +391,7 @@ pub:
|
||||||
attrs []Attr
|
attrs []Attr
|
||||||
skip_gen bool // this function doesn't need to be generated (for example [if foo])
|
skip_gen bool // this function doesn't need to be generated (for example [if foo])
|
||||||
pub mut:
|
pub mut:
|
||||||
|
params []Param
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
defer_stmts []DeferStmt
|
defer_stmts []DeferStmt
|
||||||
return_type Type
|
return_type Type
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub mut:
|
||||||
cflags []cflag.CFlag
|
cflags []cflag.CFlag
|
||||||
redefined_fns []string
|
redefined_fns []string
|
||||||
fn_generic_types map[string][][]Type // for generic functions
|
fn_generic_types map[string][][]Type // for generic functions
|
||||||
|
interfaces map[int]InterfaceDecl
|
||||||
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
||||||
is_fmt bool
|
is_fmt bool
|
||||||
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
||||||
|
@ -60,7 +61,6 @@ pub fn (t &Table) panic(message string) {
|
||||||
|
|
||||||
pub struct Fn {
|
pub struct Fn {
|
||||||
pub:
|
pub:
|
||||||
params []Param
|
|
||||||
return_type Type
|
return_type Type
|
||||||
is_variadic bool
|
is_variadic bool
|
||||||
language Language
|
language Language
|
||||||
|
@ -77,8 +77,12 @@ pub:
|
||||||
mod string
|
mod string
|
||||||
ctdefine string // compile time define. "myflag", when [if myflag] tag
|
ctdefine string // compile time define. "myflag", when [if myflag] tag
|
||||||
attrs []Attr
|
attrs []Attr
|
||||||
|
//
|
||||||
|
pos token.Position
|
||||||
|
return_type_pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
name string
|
name string
|
||||||
|
params []Param
|
||||||
source_fn voidptr // set in the checker, while processing fn declarations
|
source_fn voidptr // set in the checker, while processing fn declarations
|
||||||
usages int
|
usages int
|
||||||
}
|
}
|
||||||
|
@ -96,9 +100,24 @@ pub:
|
||||||
name string
|
name string
|
||||||
is_mut bool
|
is_mut bool
|
||||||
is_auto_rec bool
|
is_auto_rec bool
|
||||||
typ Type
|
|
||||||
type_pos token.Position
|
type_pos token.Position
|
||||||
is_hidden bool // interface first arg
|
is_hidden bool // interface first arg
|
||||||
|
pub mut:
|
||||||
|
typ Type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (f Fn) new_method_with_receiver_type(new_type Type) Fn {
|
||||||
|
mut new_method := f
|
||||||
|
new_method.params = f.params.clone()
|
||||||
|
new_method.params[0].typ = new_type
|
||||||
|
return new_method
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (f FnDecl) new_method_with_receiver_type(new_type Type) FnDecl {
|
||||||
|
mut new_method := f
|
||||||
|
new_method.params = f.params.clone()
|
||||||
|
new_method.params[0].typ = new_type
|
||||||
|
return new_method
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p &Param) equals(o &Param) bool {
|
fn (p &Param) equals(o &Param) bool {
|
||||||
|
@ -213,6 +232,10 @@ pub fn (mut t Table) register_fn(new_fn Fn) {
|
||||||
t.fns[new_fn.name] = new_fn
|
t.fns[new_fn.name] = new_fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut t Table) register_interface(idecl InterfaceDecl) {
|
||||||
|
t.interfaces[idecl.typ] = idecl
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut t TypeSymbol) register_method(new_fn Fn) int {
|
pub fn (mut t TypeSymbol) register_method(new_fn Fn) int {
|
||||||
// returns a method index, stored in the ast.FnDecl
|
// returns a method index, stored in the ast.FnDecl
|
||||||
// for faster lookup in the checker's fn_decl method
|
// for faster lookup in the checker's fn_decl method
|
||||||
|
|
|
@ -734,6 +734,7 @@ pub mut:
|
||||||
types []Type
|
types []Type
|
||||||
fields []StructField
|
fields []StructField
|
||||||
methods []Fn
|
methods []Fn
|
||||||
|
ifaces []Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Enum {
|
pub struct Enum {
|
||||||
|
|
|
@ -360,9 +360,130 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
|
pub fn (mut c Checker) expand_iface_embeds(idecl &ast.InterfaceDecl, level int, iface_embeds []ast.InterfaceEmbedding) []ast.InterfaceEmbedding {
|
||||||
|
// eprintln('> expand_iface_embeds: idecl.name: $idecl.name | level: $level | iface_embeds.len: $iface_embeds.len')
|
||||||
|
if level > 100 {
|
||||||
|
c.error('too many interface embedding levels: $level, for interface `$idecl.name`',
|
||||||
|
idecl.pos)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if iface_embeds.len == 0 {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
mut res := map[int]ast.InterfaceEmbedding{}
|
||||||
|
mut ares := []ast.InterfaceEmbedding{}
|
||||||
|
for ie in iface_embeds {
|
||||||
|
if iface_decl := c.table.interfaces[ie.typ] {
|
||||||
|
mut list := iface_decl.ifaces
|
||||||
|
if !iface_decl.are_ifaces_expanded {
|
||||||
|
list = c.expand_iface_embeds(idecl, level + 1, iface_decl.ifaces)
|
||||||
|
c.table.interfaces[ie.typ].ifaces = list
|
||||||
|
c.table.interfaces[ie.typ].are_ifaces_expanded = true
|
||||||
|
}
|
||||||
|
for partial in list {
|
||||||
|
res[partial.typ] = partial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res[ie.typ] = ie
|
||||||
|
}
|
||||||
|
for _, v in res {
|
||||||
|
ares << v
|
||||||
|
}
|
||||||
|
return ares
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut c Checker) interface_decl(mut decl ast.InterfaceDecl) {
|
||||||
c.check_valid_pascal_case(decl.name, 'interface name', decl.pos)
|
c.check_valid_pascal_case(decl.name, 'interface name', decl.pos)
|
||||||
for method in decl.methods {
|
mut decl_sym := c.table.get_type_symbol(decl.typ)
|
||||||
|
if mut decl_sym.info is ast.Interface {
|
||||||
|
if decl.ifaces.len > 0 {
|
||||||
|
all_ifaces := c.expand_iface_embeds(decl, 0, decl.ifaces)
|
||||||
|
// eprintln('> decl.name: $decl.name | decl.ifaces.len: $decl.ifaces.len | all_ifaces: $all_ifaces.len')
|
||||||
|
decl.ifaces = all_ifaces
|
||||||
|
mut emnames := map[string]int{}
|
||||||
|
mut emnames_ds := map[string]bool{}
|
||||||
|
mut emnames_ds_info := map[string]bool{}
|
||||||
|
mut efnames := map[string]int{}
|
||||||
|
mut efnames_ds_info := map[string]bool{}
|
||||||
|
for i, m in decl.methods {
|
||||||
|
emnames[m.name] = i
|
||||||
|
emnames_ds[m.name] = true
|
||||||
|
emnames_ds_info[m.name] = true
|
||||||
|
}
|
||||||
|
for i, f in decl.fields {
|
||||||
|
efnames[f.name] = i
|
||||||
|
efnames_ds_info[f.name] = true
|
||||||
|
}
|
||||||
|
//
|
||||||
|
for iface in all_ifaces {
|
||||||
|
isym := c.table.get_type_symbol(iface.typ)
|
||||||
|
if isym.kind != .interface_ {
|
||||||
|
c.error('interface `$decl.name` tries to embed `$isym.name`, but `$isym.name` is not an interface, but `$isym.kind`',
|
||||||
|
iface.pos)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for f in isym.info.fields {
|
||||||
|
if !efnames_ds_info[f.name] {
|
||||||
|
efnames_ds_info[f.name] = true
|
||||||
|
decl_sym.info.fields << f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for m in isym.info.methods {
|
||||||
|
if !emnames_ds_info[m.name] {
|
||||||
|
emnames_ds_info[m.name] = true
|
||||||
|
decl_sym.info.methods << m.new_method_with_receiver_type(decl.typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for m in isym.methods {
|
||||||
|
if !emnames_ds[m.name] {
|
||||||
|
emnames_ds[m.name] = true
|
||||||
|
decl_sym.methods << m.new_method_with_receiver_type(decl.typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if iface_decl := c.table.interfaces[iface.typ] {
|
||||||
|
for f in iface_decl.fields {
|
||||||
|
if f.name in efnames {
|
||||||
|
// already existing method name, check for conflicts
|
||||||
|
ifield := decl.fields[efnames[f.name]]
|
||||||
|
if field := c.table.find_field_with_embeds(isym, f.name) {
|
||||||
|
if ifield.typ != field.typ {
|
||||||
|
exp := c.table.type_to_str(ifield.typ)
|
||||||
|
got := c.table.type_to_str(field.typ)
|
||||||
|
c.error('embedded interface `$iface_decl.name` conflicts existing field: `$ifield.name`, expecting type: `$exp`, got type: `$got`',
|
||||||
|
ifield.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
efnames[f.name] = decl.fields.len
|
||||||
|
decl.fields << f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for m in iface_decl.methods {
|
||||||
|
if m.name in emnames {
|
||||||
|
// already existing field name, check for conflicts
|
||||||
|
imethod := decl.methods[emnames[m.name]]
|
||||||
|
if em_fn := decl_sym.find_method(imethod.name) {
|
||||||
|
if m_fn := isym.find_method(m.name) {
|
||||||
|
msg := c.table.is_same_method(m_fn, em_fn)
|
||||||
|
if msg.len > 0 {
|
||||||
|
em_sig := c.table.fn_signature(em_fn, skip_receiver: true)
|
||||||
|
m_sig := c.table.fn_signature(m_fn, skip_receiver: true)
|
||||||
|
c.error('embedded interface `$iface_decl.name` causes conflict: $msg, for interface method `$em_sig` vs `$m_sig`',
|
||||||
|
imethod.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emnames[m.name] = decl.methods.len
|
||||||
|
mut new_method := m.new_method_with_receiver_type(decl.typ)
|
||||||
|
new_method.pos = iface.pos
|
||||||
|
decl.methods << new_method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, method in decl.methods {
|
||||||
if decl.language == .v {
|
if decl.language == .v {
|
||||||
c.check_valid_snake_case(method.name, 'method name', method.pos)
|
c.check_valid_snake_case(method.name, 'method name', method.pos)
|
||||||
}
|
}
|
||||||
|
@ -370,6 +491,11 @@ pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
|
||||||
for param in method.params {
|
for param in method.params {
|
||||||
c.ensure_type_exists(param.typ, param.pos) or { return }
|
c.ensure_type_exists(param.typ, param.pos) or { return }
|
||||||
}
|
}
|
||||||
|
for j in 0 .. i {
|
||||||
|
if method.name == decl.methods[j].name {
|
||||||
|
c.error('duplicate method name `$method.name`', method.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for i, field in decl.fields {
|
for i, field in decl.fields {
|
||||||
if decl.language == .v {
|
if decl.language == .v {
|
||||||
|
@ -383,6 +509,7 @@ pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
|
pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
|
||||||
if decl.language == .v && !c.is_builtin_mod {
|
if decl.language == .v && !c.is_builtin_mod {
|
||||||
|
@ -3660,7 +3787,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.import_stmt(node)
|
c.import_stmt(node)
|
||||||
}
|
}
|
||||||
ast.InterfaceDecl {
|
ast.InterfaceDecl {
|
||||||
c.interface_decl(node)
|
c.interface_decl(mut node)
|
||||||
}
|
}
|
||||||
ast.Module {
|
ast.Module {
|
||||||
c.mod = node.name
|
c.mod = node.name
|
||||||
|
@ -6319,6 +6446,11 @@ pub fn (mut c Checker) warn(s string, pos token.Position) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) error(message string, pos token.Position) {
|
pub fn (mut c Checker) error(message string, pos token.Position) {
|
||||||
|
$if checker_exit_on_first_error ? {
|
||||||
|
eprintln('\n\n>> checker error: $message, pos: $pos')
|
||||||
|
print_backtrace()
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
if c.pref.translated && message.starts_with('mismatched types') {
|
if c.pref.translated && message.starts_with('mismatched types') {
|
||||||
// TODO move this
|
// TODO move this
|
||||||
return
|
return
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/interface_too_many_embedding_levels.vv:9:1: error: too many interface embedding levels: 101, for interface `I103`
|
||||||
|
7 | }
|
||||||
|
8 |
|
||||||
|
9 | interface I103 {
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
10 | I102
|
||||||
|
11 | }
|
|
@ -0,0 +1,431 @@
|
||||||
|
interface I1 {
|
||||||
|
I0
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I2 {
|
||||||
|
I1
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I103 {
|
||||||
|
I102
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I102 {
|
||||||
|
I101
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I101 {
|
||||||
|
I100
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I3 {
|
||||||
|
I2
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I4 {
|
||||||
|
I3
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I5 {
|
||||||
|
I4
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I6 {
|
||||||
|
I5
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I7 {
|
||||||
|
I6
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I8 {
|
||||||
|
I7
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I9 {
|
||||||
|
I8
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I10 {
|
||||||
|
I9
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I11 {
|
||||||
|
I10
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I12 {
|
||||||
|
I11
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I13 {
|
||||||
|
I12
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I14 {
|
||||||
|
I13
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I15 {
|
||||||
|
I14
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I16 {
|
||||||
|
I15
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I17 {
|
||||||
|
I16
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I18 {
|
||||||
|
I17
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I19 {
|
||||||
|
I18
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I20 {
|
||||||
|
I19
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I21 {
|
||||||
|
I20
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I22 {
|
||||||
|
I21
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I23 {
|
||||||
|
I22
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I24 {
|
||||||
|
I23
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I25 {
|
||||||
|
I24
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I26 {
|
||||||
|
I25
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I27 {
|
||||||
|
I26
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I28 {
|
||||||
|
I27
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I29 {
|
||||||
|
I28
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I30 {
|
||||||
|
I29
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I31 {
|
||||||
|
I30
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I32 {
|
||||||
|
I31
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I33 {
|
||||||
|
I32
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I34 {
|
||||||
|
I33
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I35 {
|
||||||
|
I34
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I36 {
|
||||||
|
I35
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I37 {
|
||||||
|
I36
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I38 {
|
||||||
|
I37
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I39 {
|
||||||
|
I38
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I40 {
|
||||||
|
I39
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I41 {
|
||||||
|
I40
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I42 {
|
||||||
|
I41
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I43 {
|
||||||
|
I42
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I44 {
|
||||||
|
I43
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I45 {
|
||||||
|
I44
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I46 {
|
||||||
|
I45
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I47 {
|
||||||
|
I46
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I48 {
|
||||||
|
I47
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I49 {
|
||||||
|
I48
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I50 {
|
||||||
|
I49
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I51 {
|
||||||
|
I50
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I52 {
|
||||||
|
I51
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I53 {
|
||||||
|
I52
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I54 {
|
||||||
|
I53
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I55 {
|
||||||
|
I54
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I56 {
|
||||||
|
I55
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I57 {
|
||||||
|
I56
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I58 {
|
||||||
|
I57
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I59 {
|
||||||
|
I58
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I60 {
|
||||||
|
I59
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I61 {
|
||||||
|
I60
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I62 {
|
||||||
|
I61
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I63 {
|
||||||
|
I62
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I64 {
|
||||||
|
I63
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I65 {
|
||||||
|
I64
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I66 {
|
||||||
|
I65
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I67 {
|
||||||
|
I66
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I68 {
|
||||||
|
I67
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I69 {
|
||||||
|
I68
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I70 {
|
||||||
|
I69
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I71 {
|
||||||
|
I70
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I72 {
|
||||||
|
I71
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I73 {
|
||||||
|
I72
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I74 {
|
||||||
|
I73
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I75 {
|
||||||
|
I74
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I76 {
|
||||||
|
I75
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I77 {
|
||||||
|
I76
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I78 {
|
||||||
|
I77
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I79 {
|
||||||
|
I78
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I80 {
|
||||||
|
I79
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I81 {
|
||||||
|
I80
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I82 {
|
||||||
|
I81
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I83 {
|
||||||
|
I82
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I84 {
|
||||||
|
I83
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I85 {
|
||||||
|
I84
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I86 {
|
||||||
|
I85
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I87 {
|
||||||
|
I86
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I88 {
|
||||||
|
I87
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I89 {
|
||||||
|
I88
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I90 {
|
||||||
|
I89
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I91 {
|
||||||
|
I90
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I92 {
|
||||||
|
I91
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I93 {
|
||||||
|
I92
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I94 {
|
||||||
|
I93
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I95 {
|
||||||
|
I94
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I96 {
|
||||||
|
I95
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I97 {
|
||||||
|
I96
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I98 {
|
||||||
|
I97
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I99 {
|
||||||
|
I98
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I100 {
|
||||||
|
I99
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I0 {
|
||||||
|
m999() int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
x int = 123
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s Abc) m999() int {
|
||||||
|
return 999
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
a := Abc{}
|
||||||
|
dump(a)
|
||||||
|
i := I103(a)
|
||||||
|
dump(i)
|
||||||
|
assert i.m999() == 999
|
||||||
|
}
|
|
@ -1180,6 +1180,11 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) {
|
||||||
f.writeln('')
|
f.writeln('')
|
||||||
}
|
}
|
||||||
f.comments_after_last_field(node.pre_comments)
|
f.comments_after_last_field(node.pre_comments)
|
||||||
|
for iface in node.ifaces {
|
||||||
|
f.write('\t$iface.name')
|
||||||
|
f.comments(iface.comments, inline: true, has_nl: false, level: .indent)
|
||||||
|
f.writeln('')
|
||||||
|
}
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
if i == node.mut_pos {
|
if i == node.mut_pos {
|
||||||
f.writeln('mut:')
|
f.writeln('mut:')
|
||||||
|
|
|
@ -6386,9 +6386,9 @@ $staticprefix inline $interface_name I_${cctype}_to_Interface_${interface_name}(
|
||||||
// .speak = Cat_speak
|
// .speak = Cat_speak
|
||||||
mut method_call := '${cctype}_$method.name'
|
mut method_call := '${cctype}_$method.name'
|
||||||
if !method.params[0].typ.is_ptr() {
|
if !method.params[0].typ.is_ptr() {
|
||||||
// inline void Cat_speak_method_wrapper(Cat c) { return Cat_speak(*c); }
|
// inline void Cat_speak_Interface_Animal_method_wrapper(Cat c) { return Cat_speak(*c); }
|
||||||
methods_wrapper.write_string('static inline ${g.typ(method.return_type)}')
|
iwpostfix := '_Interface_${interface_name}_method_wrapper'
|
||||||
methods_wrapper.write_string(' ${method_call}_method_wrapper(')
|
methods_wrapper.write_string('static inline ${g.typ(method.return_type)} $method_call${iwpostfix}(')
|
||||||
//
|
//
|
||||||
params_start_pos := g.out.len
|
params_start_pos := g.out.len
|
||||||
mut params := method.params.clone()
|
mut params := method.params.clone()
|
||||||
|
@ -6406,8 +6406,8 @@ $staticprefix inline $interface_name I_${cctype}_to_Interface_${interface_name}(
|
||||||
}
|
}
|
||||||
methods_wrapper.writeln('${method_call}(*${fargs.join(', ')});')
|
methods_wrapper.writeln('${method_call}(*${fargs.join(', ')});')
|
||||||
methods_wrapper.writeln('}')
|
methods_wrapper.writeln('}')
|
||||||
// .speak = Cat_speak_method_wrapper
|
// .speak = Cat_speak_Interface_Animal_method_wrapper
|
||||||
method_call += '_method_wrapper'
|
method_call += iwpostfix
|
||||||
}
|
}
|
||||||
if g.pref.build_mode != .build_module {
|
if g.pref.build_mode != .build_module {
|
||||||
methods_struct.writeln('\t\t._method_${c_name(method.name)} = (void*) $method_call,')
|
methods_struct.writeln('\t\t._method_${c_name(method.name)} = (void*) $method_call,')
|
||||||
|
|
|
@ -483,7 +483,24 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
mut methods := []ast.FnDecl{cap: 20}
|
mut methods := []ast.FnDecl{cap: 20}
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
mut mut_pos := -1
|
mut mut_pos := -1
|
||||||
|
mut ifaces := []ast.InterfaceEmbedding{}
|
||||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||||
|
if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital() {
|
||||||
|
iface_pos := p.tok.position()
|
||||||
|
iface_name := p.tok.lit
|
||||||
|
iface_type := p.parse_type()
|
||||||
|
comments := p.eat_comments({})
|
||||||
|
ifaces << ast.InterfaceEmbedding{
|
||||||
|
name: iface_name
|
||||||
|
typ: iface_type
|
||||||
|
pos: iface_pos
|
||||||
|
comments: comments
|
||||||
|
}
|
||||||
|
if p.tok.kind == .rcbr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
if is_mut {
|
if is_mut {
|
||||||
p.error_with_pos('redefinition of `mut` section', p.tok.position())
|
p.error_with_pos('redefinition of `mut` section', p.tok.position())
|
||||||
|
@ -498,6 +515,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
method_start_pos := p.tok.position()
|
method_start_pos := p.tok.position()
|
||||||
line_nr := p.tok.line_nr
|
line_nr := p.tok.line_nr
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
|
|
||||||
if name == 'type_name' {
|
if name == 'type_name' {
|
||||||
p.error_with_pos('cannot override built-in method `type_name`', method_start_pos)
|
p.error_with_pos('cannot override built-in method `type_name`', method_start_pos)
|
||||||
return ast.InterfaceDecl{}
|
return ast.InterfaceDecl{}
|
||||||
|
@ -545,6 +563,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
tmethod := ast.Fn{
|
tmethod := ast.Fn{
|
||||||
name: name
|
name: name
|
||||||
params: args
|
params: args
|
||||||
|
pos: method.pos
|
||||||
return_type: method.return_type
|
return_type: method.return_type
|
||||||
is_variadic: is_variadic
|
is_variadic: is_variadic
|
||||||
is_pub: true
|
is_pub: true
|
||||||
|
@ -581,19 +600,24 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
info.ifaces = ifaces.map(it.typ)
|
||||||
ts.info = info
|
ts.info = info
|
||||||
p.top_level_statement_end()
|
p.top_level_statement_end()
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
pos = pos.extend_with_last_line(p.prev_tok.position(), p.prev_tok.line_nr)
|
pos = pos.extend_with_last_line(p.prev_tok.position(), p.prev_tok.line_nr)
|
||||||
return ast.InterfaceDecl{
|
res := ast.InterfaceDecl{
|
||||||
name: interface_name
|
name: interface_name
|
||||||
language: language
|
language: language
|
||||||
|
typ: typ
|
||||||
fields: fields
|
fields: fields
|
||||||
methods: methods
|
methods: methods
|
||||||
|
ifaces: ifaces
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
pos: pos
|
pos: pos
|
||||||
pre_comments: pre_comments
|
pre_comments: pre_comments
|
||||||
mut_pos: mut_pos
|
mut_pos: mut_pos
|
||||||
name_pos: name_pos
|
name_pos: name_pos
|
||||||
}
|
}
|
||||||
|
p.table.register_interface(res)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []s
|
||||||
if prefs.backend != .js && !prefs.should_compile_asm(file) {
|
if prefs.backend != .js && !prefs.should_compile_asm(file) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if file.starts_with('.#') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if file.contains('_d_') {
|
if file.contains('_d_') {
|
||||||
if prefs.compile_defines_all.len == 0 {
|
if prefs.compile_defines_all.len == 0 {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -0,0 +1,415 @@
|
||||||
|
interface I99 {
|
||||||
|
I98
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I1 {
|
||||||
|
I0
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I2 {
|
||||||
|
I1
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I3 {
|
||||||
|
I2
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I4 {
|
||||||
|
I3
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I5 {
|
||||||
|
I4
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I6 {
|
||||||
|
I5
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I7 {
|
||||||
|
I6
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I8 {
|
||||||
|
I7
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I9 {
|
||||||
|
I8
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I10 {
|
||||||
|
I9
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I11 {
|
||||||
|
I10
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I12 {
|
||||||
|
I11
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I13 {
|
||||||
|
I12
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I14 {
|
||||||
|
I13
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I15 {
|
||||||
|
I14
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I16 {
|
||||||
|
I15
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I17 {
|
||||||
|
I16
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I18 {
|
||||||
|
I17
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I19 {
|
||||||
|
I18
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I20 {
|
||||||
|
I19
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I21 {
|
||||||
|
I20
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I22 {
|
||||||
|
I21
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I23 {
|
||||||
|
I22
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I24 {
|
||||||
|
I23
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I25 {
|
||||||
|
I24
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I26 {
|
||||||
|
I25
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I27 {
|
||||||
|
I26
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I28 {
|
||||||
|
I27
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I29 {
|
||||||
|
I28
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I30 {
|
||||||
|
I29
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I31 {
|
||||||
|
I30
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I32 {
|
||||||
|
I31
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I33 {
|
||||||
|
I32
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I34 {
|
||||||
|
I33
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I35 {
|
||||||
|
I34
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I36 {
|
||||||
|
I35
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I37 {
|
||||||
|
I36
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I38 {
|
||||||
|
I37
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I39 {
|
||||||
|
I38
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I40 {
|
||||||
|
I39
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I41 {
|
||||||
|
I40
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I42 {
|
||||||
|
I41
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I43 {
|
||||||
|
I42
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I44 {
|
||||||
|
I43
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I45 {
|
||||||
|
I44
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I46 {
|
||||||
|
I45
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I47 {
|
||||||
|
I46
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I48 {
|
||||||
|
I47
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I49 {
|
||||||
|
I48
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I50 {
|
||||||
|
I49
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I51 {
|
||||||
|
I50
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I52 {
|
||||||
|
I51
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I53 {
|
||||||
|
I52
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I54 {
|
||||||
|
I53
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I55 {
|
||||||
|
I54
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I56 {
|
||||||
|
I55
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I57 {
|
||||||
|
I56
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I58 {
|
||||||
|
I57
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I59 {
|
||||||
|
I58
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I60 {
|
||||||
|
I59
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I61 {
|
||||||
|
I60
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I62 {
|
||||||
|
I61
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I63 {
|
||||||
|
I62
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I64 {
|
||||||
|
I63
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I65 {
|
||||||
|
I64
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I66 {
|
||||||
|
I65
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I67 {
|
||||||
|
I66
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I68 {
|
||||||
|
I67
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I69 {
|
||||||
|
I68
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I70 {
|
||||||
|
I69
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I71 {
|
||||||
|
I70
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I72 {
|
||||||
|
I71
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I73 {
|
||||||
|
I72
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I74 {
|
||||||
|
I73
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I75 {
|
||||||
|
I74
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I76 {
|
||||||
|
I75
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I77 {
|
||||||
|
I76
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I78 {
|
||||||
|
I77
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I79 {
|
||||||
|
I78
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I80 {
|
||||||
|
I79
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I81 {
|
||||||
|
I80
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I82 {
|
||||||
|
I81
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I83 {
|
||||||
|
I82
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I84 {
|
||||||
|
I83
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I85 {
|
||||||
|
I84
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I86 {
|
||||||
|
I85
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I87 {
|
||||||
|
I86
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I88 {
|
||||||
|
I87
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I89 {
|
||||||
|
I88
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I90 {
|
||||||
|
I89
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I91 {
|
||||||
|
I90
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I92 {
|
||||||
|
I91
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I93 {
|
||||||
|
I92
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I94 {
|
||||||
|
I93
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I95 {
|
||||||
|
I94
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I96 {
|
||||||
|
I95
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I97 {
|
||||||
|
I96
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I98 {
|
||||||
|
I97
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I0 {
|
||||||
|
m999() int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
x int = 123
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s Abc) m999() int {
|
||||||
|
return 999
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_deep_nested_interface_embeddings() {
|
||||||
|
a := Abc{}
|
||||||
|
dump(a)
|
||||||
|
i := I99(a)
|
||||||
|
dump(i)
|
||||||
|
assert i.m999() == 999
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
// This test orders the interface definitions intentionally
|
||||||
|
// in such a way that interface `Re` is first, and `Fe` is
|
||||||
|
// last. The goal is testing that the embedding expansion
|
||||||
|
// works independently from the source order, and that both
|
||||||
|
// can be checked/compiled/used at the same time.
|
||||||
|
interface Re {
|
||||||
|
I1
|
||||||
|
I2
|
||||||
|
m_ie() int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I1 {
|
||||||
|
I0
|
||||||
|
m1() int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I2 {
|
||||||
|
I0
|
||||||
|
m2() int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I0 {
|
||||||
|
m0() int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Fe {
|
||||||
|
I1
|
||||||
|
I2
|
||||||
|
m_ie() int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StructIE {
|
||||||
|
x int = 456
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s StructIE) m0() int {
|
||||||
|
println(@METHOD)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s StructIE) m1() int {
|
||||||
|
println(@METHOD)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s StructIE) m2() int {
|
||||||
|
println(@METHOD)
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (s StructIE) m_ie() int {
|
||||||
|
println(@METHOD)
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_ie_recursive_forward() {
|
||||||
|
i := Fe(StructIE{})
|
||||||
|
eprintln(i)
|
||||||
|
assert 0 == i.m0()
|
||||||
|
assert 1 == i.m1()
|
||||||
|
assert 2 == i.m2()
|
||||||
|
assert 3 == i.m_ie()
|
||||||
|
if i is StructIE {
|
||||||
|
assert i.x == 456
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_ie_recursive_backward() {
|
||||||
|
i := Re(StructIE{})
|
||||||
|
eprintln(i)
|
||||||
|
assert 0 == i.m0()
|
||||||
|
assert 1 == i.m1()
|
||||||
|
assert 2 == i.m2()
|
||||||
|
assert 3 == i.m_ie()
|
||||||
|
if i is StructIE {
|
||||||
|
assert i.x == 456
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
interface WalkerTalker {
|
||||||
|
// Abc
|
||||||
|
Walker // adsas
|
||||||
|
// zxczxc
|
||||||
|
Talker // xyzdef
|
||||||
|
// asdasdas
|
||||||
|
nspeeches int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Talker {
|
||||||
|
nspeeches int
|
||||||
|
talk(msg string)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Walker {
|
||||||
|
nsteps int
|
||||||
|
walk(newx int, newy int)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
mut:
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
phrases []string
|
||||||
|
nsteps int = 1000
|
||||||
|
nspeeches int = 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut s Abc) talk(msg string) {
|
||||||
|
s.phrases << msg
|
||||||
|
s.nspeeches++
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut s Abc) walk(x int, y int) {
|
||||||
|
s.x = x
|
||||||
|
s.y = y
|
||||||
|
s.nsteps++
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_walker_talker() {
|
||||||
|
mut wt := WalkerTalker(Abc{
|
||||||
|
x: 1
|
||||||
|
y: 1
|
||||||
|
phrases: ['hi']
|
||||||
|
})
|
||||||
|
wt.talk('my name is Wally')
|
||||||
|
wt.walk(100, 100)
|
||||||
|
if mut wt is Abc {
|
||||||
|
dump(wt)
|
||||||
|
assert wt.x == 100
|
||||||
|
assert wt.y == 100
|
||||||
|
assert wt.phrases.last().ends_with('Wally')
|
||||||
|
assert wt.nspeeches == 1001
|
||||||
|
assert wt.nsteps == 1001
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue