Skip to content

Commit 4b9758e

Browse files
committed
Refactor to a more functional API
1 parent 039be32 commit 4b9758e

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

act/statemachine.go

+30-11
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ type StateMachine[D any] struct {
6969
// Type alias for MessageHandler callbacks.
7070
// D is the type of the data associated with the StateMachine.
7171
// M is the type of the message this handler accepts.
72-
type StateMessageHandler[D any, M any] func(*StateMachine[D], M) error
72+
type StateMessageHandler[D any, M any] func(gen.Atom, D, M, gen.Process) (gen.Atom, D, error)
7373

7474
// Type alias for CallHandler callbacks.
7575
// D is the type of the data associated with the StateMachine.
7676
// M is the type of the message this handler accepts.
7777
// R is the type of the result value.
78-
type StateCallHandler[D any, M any, R any] func(*StateMachine[D], M) (R, error)
78+
type StateCallHandler[D any, M any, R any] func(gen.Atom, D, M, gen.Process) (gen.Atom, D, R, error)
7979

8080
type StateMachineSpec[D any] struct {
8181
initialState gen.Atom
@@ -347,14 +347,26 @@ func (sm *StateMachine[D]) lookupMessageHandler(messageType string) (any, bool)
347347

348348
func (sm *StateMachine[D]) invokeMessageHandler(handler any, message *gen.MailboxMessage) error {
349349
callbackValue := reflect.ValueOf(handler)
350-
smValue := reflect.ValueOf(sm)
350+
stateValue := reflect.ValueOf(sm.currentState)
351+
dataValue := reflect.ValueOf(sm.Data())
351352
msgValue := reflect.ValueOf(message.Message)
353+
procValue := reflect.ValueOf(sm)
352354

353-
results := callbackValue.Call([]reflect.Value{smValue, msgValue})
355+
results := callbackValue.Call([]reflect.Value{stateValue, dataValue, msgValue, procValue})
354356

355-
if len(results) > 0 && !results[0].IsNil() {
356-
return results[0].Interface().(error)
357+
if len(results) != 3 {
358+
sm.Log().Panic("StateMachine terminated. Panic reason: unexpected "+
359+
"error when invoking call handler for %v", typeName(message))
357360
}
361+
if !results[2].IsNil() {
362+
return results[2].Interface().(error)
363+
}
364+
//TODO: panic if new state or new data is not provided
365+
setCurrentStateMethod := reflect.ValueOf(sm).MethodByName("SetCurrentState")
366+
setCurrentStateMethod.Call([]reflect.Value{results[0]})
367+
setDataMethod := reflect.ValueOf(sm).MethodByName("SetData")
368+
setDataMethod.Call([]reflect.Value{results[1]})
369+
358370
return nil
359371
}
360372

@@ -369,21 +381,28 @@ func (sm *StateMachine[D]) lookupCallHandler(messageType string) (any, bool) {
369381

370382
func (sm *StateMachine[D]) invokeCallHandler(handler any, message *gen.MailboxMessage) (any, error) {
371383
callbackValue := reflect.ValueOf(handler)
372-
smValue := reflect.ValueOf(sm)
384+
stateValue := reflect.ValueOf(sm.currentState)
385+
dataValue := reflect.ValueOf(sm.Data())
373386
msgValue := reflect.ValueOf(message.Message)
387+
procValue := reflect.ValueOf(sm)
374388

375-
results := callbackValue.Call([]reflect.Value{smValue, msgValue})
389+
results := callbackValue.Call([]reflect.Value{stateValue, dataValue, msgValue, procValue})
376390

377-
if len(results) != 2 {
391+
if len(results) != 4 {
378392
sm.Log().Panic("StateMachine terminated. Panic reason: unexpected "+
379393
"error when invoking call handler for %v", typeName(message))
380394
}
381395

382-
if !results[1].IsNil() {
396+
if !results[3].IsNil() {
383397
err := results[1].Interface().(error)
384398
return nil, err
385399
}
400+
//TODO: panic if new state or new data is not provided
401+
setCurrentStateMethod := reflect.ValueOf(sm).MethodByName("SetCurrentState")
402+
setCurrentStateMethod.Call([]reflect.Value{results[0]})
403+
setDataMethod := reflect.ValueOf(sm).MethodByName("SetData")
404+
setDataMethod.Call([]reflect.Value{results[1]})
386405

387-
result := results[0].Interface()
406+
result := results[2].Interface()
388407
return result, nil
389408
}

tests/001_local/t018_statemachine_test.go

+4-10
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,14 @@ func (sm *t18statemachine) Init(args ...any) (act.StateMachineSpec[t18data], err
7878
return spec, nil
7979
}
8080

81-
func state1to2(sm *act.StateMachine[t18data], message t18transitionState1toState2) error {
82-
sm.SetCurrentState(gen.Atom("state2"))
83-
data := sm.Data()
81+
func state1to2(state gen.Atom, data t18data, message t18transitionState1toState2, proc gen.Process) (gen.Atom, t18data, error) {
8482
data.count++
85-
sm.SetData(data)
86-
return nil
83+
return gen.Atom("state2"), data, nil
8784
}
8885

89-
func state2to1(sm *act.StateMachine[t18data], message t18transitionState2toState1) (int, error) {
90-
sm.SetCurrentState(gen.Atom("state1"))
91-
data := sm.Data()
86+
func state2to1(state gen.Atom, data t18data, message t18transitionState2toState1, proc gen.Process) (gen.Atom, t18data, int, error) {
9287
data.count++
93-
sm.SetData(data)
94-
return data.count, nil
88+
return gen.Atom("state1"), data, data.count, nil
9589
}
9690

9791
func (t *t18) TestStateMachine(input any) {

0 commit comments

Comments
 (0)