sharplib/imm/FSM.cs
Marc Hernandez bea7080a5c Immutability and strip the / off the path
x) Better path substring
x) Add some interfaces for immutability
2024-04-30 12:19:56 -07:00

104 lines
2.2 KiB
C#

using System;
using System.Runtime.CompilerServices;
using Optional;
namespace imm;
public record class Context : imm.Recorded<Context>, Imm
{
Meta Imm.Meta => base.Meta;
}
public record class State<TSUB, CTX>( CTX Context ) : imm.Recorded<TSUB>, Imm
where TSUB : State<TSUB, CTX>
where CTX : Context
{
Meta Imm.Meta => base.Meta;
virtual public (CTX, TSUB) onEnter(CTX ctx, State<TSUB, CTX> oldState)
{
return (ctx, (TSUB)this);
}
virtual public (CTX, TSUB) onExit(CTX ctx, State<TSUB, CTX> newState)
{
return (ctx, (TSUB)this);
}
}
public record class FSM<TSUB, ST, CTX> : imm.Recorded<TSUB>, Imm
where TSUB : FSM<TSUB, ST, CTX>
where ST : State<ST, CTX>
where CTX : Context
{
Meta Imm.Meta => base.Meta;
public CTX Context { get; init; }
public ST State { get; init; }
public FSM( CTX context, ST stStart )
{
Context = context;
State = stStart;
}
public TSUB Transition(ST newState, string reason,
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")]
string expression = default
)
{
log.debug( $"Trans from {State.GetType().Name} to {newState.GetType().Name} for {reason}" );
var origState = State;
var (newCtx, oldState) = State.onExit(Context, newState);
var (newCTX, storeState) = newState.onEnter(newCtx, oldState);
var newFSM = this.Process( (v) => (this as TSUB) with
{
Context = newCTX,
State = storeState,
}, $"{reason}" );
return newFSM;
}
/*
public TSUB ( Func<ST, ST> fn, string reason,
[CallerMemberName] string member = "",
[CallerFilePath] string file = "",
[CallerLineNumber] int line = 0,
[CallerArgumentExpression("fn")]
string expression = default
)
{
var newState = fn( State );
if( object.ReferenceEquals( newState, State ) ) return (TSUB)this;
TSUB newFSM = this.Process( this with
{
Context = Context,
State = newState,
}, $"Processing: {newState.GetType().Name} for {reason}",
member, file, line, expression );
return (TSUB)newFSM;
}
*/
}