0xE111 / cat-400

Game framework for nim programming language. Modular and extensible
Mozilla Public License 2.0
90 stars 5 forks source link

State management - in-place changing and dynamic dispatch #1

Closed 0xE111 closed 6 years ago

0xE111 commented 6 years ago

Current c4 implementation heavily uses method dispatching. I want to have state module usage as simple as possible, so I would like to change states by calling

# passing `instance` to `switch` is optional but usually helpful
instance.state.switch(new(ref Loading), instance=instance)

Here switch internally changes instance.state, so you don't need to write

instance.state = instance.state.switch(...)

This is achieved by using var ref State and assigning self = newState.

method switch*(self: var ref State, newState: ref Running, instance: ref Server) =
  if self of ref Loading:  # <-- ugly
    self = newState  # actually swich current state to Running
    echo("Hello world")

However, now we have to check initial state manually and write ugly if self of ref Loading. I wish one could write smth like this and make dynamic dispatch do all the job:

method switch*(self: var ref None, newState: ref Running, instance: ref Server) =
  # this method will be called only when switching from None to Running state
  self = newState  # <-- oops

However, this doesn't work cause self is of type ref None and newState is of type ref Running, so assigning is forbidden. Of course we know that self is a ref State (because it's a ref to subtype), and newState is also a ref State for the same reason. But the assignment is still a problem.

0xE111 commented 6 years ago

Fixed by 0314c3c2d1d3024324624610811889786ff70e07