Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use co-dependent types with each other that implement a common interface #120

Open
kettek opened this issue Mar 17, 2022 · 1 comment

Comments

@kettek
Copy link

kettek commented Mar 17, 2022

The following code produces cannot use <*main.SceneB> as <main.Scene> in argument to switchTo:

package main

import (
        "github.com/cosmos72/gomacro/fast"
)

func main() {
        interp := fast.New()

        interp.Eval(`
                import "fmt"

                type Scene interface {
                        Init()
                        Destroy()
                }
                var globalScene Scene

                func switchTo(s Scene) {
                        if globalScene != nil {
                                globalScene.Destroy()
                        }
                        globalScene = s
                        s.Init()
                }

                type SceneA struct {
                }
                func (s *SceneA) Init() {
                        fmt.Println("Init")
                        switchTo(&SceneB{})
                }
                func (s *SceneA) Destroy() {
                        fmt.Println("Destroy")
                }

                type SceneB struct {
                }
                func (s *SceneB) Init() {
                        fmt.Println("Init")
                        switchTo(&SceneA{})
                }
                func (s *SceneB) Destroy() {
                        fmt.Println("Destroy")
                }

                switchTo(&SceneA{})
        `)
}

In the actual code I'm using, where this problem cropped up, the switchTo function isn't called in the global scope, but rather by an interpreter function that is invoked by the host-side. Same problem in that context.

This deviates from expected Go behavior, as the evaluated code compiles and runs under standard Go.

@cosmos72
Copy link
Owner

Hello @kettek,
your code really pushes the interpreter to its limits, for several reasons:

  1. support for out-of-order code, i.e. code that refers to declarations appearing later, was added as an after-thought and has some limitations.
  2. interpreted interfaces are emulated, because there is no reflect.InterfaceOf function
  3. mutually recursive types are emulated too, because reflect.StructOf does not support them. In this case, only methods of the two types mutually reference the each other, but the first call to switchTo(Scene) appears before the type SceneB and its methods are declared, thus I suspect gomacro will not recognize that *SceneB implements Scene at the call site switchTo(&SceneB{})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants