x) Add whatFile for fast cached lookup of filenames from a path
x) Debug renames
x) Add default OnChanged handler that does nothing
x) Cleanups to the FSM stuff
This commit is contained in:
Marc Hernandez 2024-04-21 23:31:47 -07:00
parent 959b9aac05
commit a3e79e83b4
3 changed files with 103 additions and 53 deletions

View File

@ -1,6 +1,8 @@
 
using System; using System;
using System.Runtime.CompilerServices;
using Optional;
@ -13,25 +15,25 @@ public record class Context : imm.Recorded<Context>
} }
public record class State<T, CTX>( CTX Context ) : imm.Recorded<State<T, CTX>> public record class State<TSUB, CTX>( CTX Context ) : imm.Recorded<TSUB>
where T : State<T, CTX> where TSUB : State<TSUB, CTX>
where CTX : Context where CTX : Context
{ {
virtual public (CTX, T) onEnter(CTX ctx, State<T, CTX> oldState) virtual public (CTX, TSUB) onEnter(CTX ctx, State<TSUB, CTX> oldState)
{ {
return (ctx, (T)this); return (ctx, (TSUB)this);
} }
virtual public (CTX, T) onExit(CTX ctx, State<T, CTX> newState) virtual public (CTX, TSUB) onExit(CTX ctx, State<TSUB, CTX> newState)
{ {
return (ctx, (T)this); return (ctx, (TSUB)this);
} }
} }
public record class FSM<T, ST, CTX> : imm.Recorded<FSM<T, ST, CTX>> public record class FSM<TSUB, ST, CTX> : imm.Recorded<TSUB>
where T : FSM<T, ST, CTX> where TSUB : FSM<TSUB, ST, CTX>
where ST : State<ST, CTX> where ST : State<ST, CTX>
where CTX : Context where CTX : Context
{ {
@ -44,37 +46,54 @@ public record class FSM<T, ST, CTX> : imm.Recorded<FSM<T, ST, CTX>>
State = stStart; State = stStart;
} }
public FSM<T, ST, CTX> Transition(ST newState) 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 origState = State;
var (newOldCTX, oldState) = State.onExit(Context, newState); var (newCtx, oldState) = State.onExit(Context, newState);
var (newCTX, storeState) = newState.onEnter(newOldCTX, oldState); var (newCTX, storeState) = newState.onEnter(newCtx, oldState);
var newFSM = this.Process( this with var newFSM = this.Process( (v) => (this as TSUB) with
{ {
Context = newCTX, Context = newCTX,
State = storeState, State = storeState,
}, $"Trans: {origState.GetType().Name} to {newState.GetType().Name}" ); }, $"{reason}" );
return newFSM; return newFSM;
} }
public FSM<T, ST, CTX> Process( Func<ST, ST> fn, string reason ) /*
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 ); var newState = fn( State );
if( object.ReferenceEquals( newState, State ) ) return this; if( object.ReferenceEquals( newState, State ) ) return (TSUB)this;
FSM<T, ST, CTX> newFSM = this.Process( this with TSUB newFSM = this.Process( this with
{ {
Context = Context, Context = Context,
State = newState, State = newState,
}, $"Processing: {newState.GetType().Name} for {reason}" ); }, $"Processing: {newState.GetType().Name} for {reason}",
member, file, line, expression );
return newFSM; return (TSUB)newFSM;
} }
*/
} }

View File

@ -14,23 +14,23 @@ static public class Util
{ {
//This can handle both Timed and Recorded //This can handle both Timed and Recorded
static public T Process<T>( ref T obj, Func<T, T> fn, string reason = "", static public T Process<T>( ref T obj, Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string expression = default ) string dbgExp = default )
where T : Recorded<T> where T : Recorded<T>
{ {
obj = obj.Process( fn, reason, memberName, filePath, lineNumber, expression ); obj = obj.Process( fn, reason, dbgName, dbgPath, lineNumber, dbgExp );
return obj; return obj;
} }
static public T LightProcess<T>( ref T obj, Func<T, T> fn, string reason = "", static public T LightProcess<T>( ref T obj, Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string expression = default ) string dbgExp = default )
where T : Versioned<T> where T : Versioned<T>
{ {
obj = obj.Process( fn, reason ); obj = obj.Process( fn, reason );
@ -61,7 +61,7 @@ public record class Versioned<T>
public MetaData Meta => MetaStorage; public MetaData Meta => MetaStorage;
public ChangeDelegate OnChange; public ChangeDelegate OnChange = (x, y) => {};
public T Process( Func<T, T> fn, string reason = "" ) public T Process( Func<T, T> fn, string reason = "" )
{ {
@ -88,7 +88,7 @@ public record class Recorded<T> : Versioned<T>
public string Expression { get; internal set; } = ""; public string Expression { get; internal set; } = "";
public string MemberName { get; internal set; } = ""; public string MemberName { get; internal set; } = "";
public string FilePath { get; internal set; } = ""; public string FilePath { get; internal set; } = "";
public int LineNumber { get; internal set; } = -1; public int LineNumber { get; internal set; } = -1;
public MetaData() { } public MetaData() { }
} }
@ -105,29 +105,29 @@ public record class Recorded<T> : Versioned<T>
virtual public T Record( string reason = "", virtual public T Record( string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0 ) [CallerLineNumber] int lineNumber = 0 )
{ {
return Process( t => t, reason, memberName, filePath, lineNumber ); return Process( t => t, reason, dbgName, dbgPath, lineNumber );
} }
virtual public T Process( T next, string reason = "", virtual public T Process( T next, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string expression = default ) string dbgExp = default )
{ {
return Process( ( old ) => next, reason, memberName, filePath, lineNumber, expression ); return Process( ( old ) => next, reason, dbgName, dbgPath, lineNumber, dbgExp );
} }
virtual public T Process( Func<T, T> fn, string reason = "", virtual public T Process( Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string expression = default ) string dbgExp = default )
{ {
var orig = ( T )this; var orig = ( T )this;
@ -142,8 +142,8 @@ public record class Recorded<T> : Versioned<T>
Reason = reason, Reason = reason,
ZZOld = orig, ZZOld = orig,
MemberName = memberName, MemberName = dbgName,
FilePath = filePath, FilePath = dbgPath,
LineNumber = lineNumber, LineNumber = lineNumber,
} }
}; };
@ -178,30 +178,31 @@ public record class Timed<T> : Recorded<T>
override public T Record( string reason = "", override public T Record( string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0 ) [CallerLineNumber] int lineNumber = 0 )
{ {
return Process( t => t, reason, memberName, filePath, lineNumber ); return Process( t => t, reason, dbgName, dbgPath, lineNumber );
} }
override public T Process( T next, string reason = "", override public T Process( T next, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int lineNumber = 0,
[CallerArgumentExpression("next")] [CallerArgumentExpression("next")]
string expression = default ) string dbgExp = default )
{ {
return Process( ( old ) => next, reason, memberName, filePath, lineNumber, expression ); return Process( ( old ) => next, reason, dbgName, dbgPath, lineNumber, dbgExp );
} }
override public T Process( Func<T, T> fn, string reason = "", override public T Process( Func<T, T> fn, string reason = "",
[CallerMemberName] string memberName = "", [CallerMemberName] string dbgName = "",
[CallerFilePath] string filePath = "", [CallerFilePath] string dbgPath = "",
[CallerLineNumber] int lineNumber = 0, [CallerLineNumber] int dbgLine = 0,
[CallerArgumentExpression("fn")] [CallerArgumentExpression("fn")]
string expression = default ) string dbgExp = default
)
{ {
var orig = ( T )this; var orig = ( T )this;
@ -216,9 +217,9 @@ public record class Timed<T> : Recorded<T>
Reason = reason, Reason = reason,
//Recorded //Recorded
MemberName = memberName, MemberName = dbgName,
FilePath = filePath, FilePath = dbgPath,
LineNumber = lineNumber, LineNumber = dbgLine,
ZZOld = orig, ZZOld = orig,
//Timed //Timed

View File

@ -9,6 +9,7 @@ using System.Reflection;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Security.Cryptography.X509Certificates;
//using System.Threading.Tasks; //using System.Threading.Tasks;
static public class log static public class log
@ -99,6 +100,35 @@ static public class log
public delegate void Log_delegate( LogEvent evt ); public delegate void Log_delegate( LogEvent evt );
static ImmutableDictionary<int, string> s_files = ImmutableDictionary<int, string>.Empty;
static public string whatFile(string path)
{
var file = "";
var pathHash = path.GetHashCode();
if (s_files.TryGetValue(pathHash, out var autoCat))
{
file = autoCat;
}
else
{
var pathPieces = path.Split('\\');
if (pathPieces.Length < 2)
{
pathPieces = path.Split('/');
}
var lastDir = pathPieces[pathPieces.Length - 1];
ImmutableInterlocked.AddOrUpdate(ref s_files, pathHash, lastDir, (key, value) => { return lastDir; });
file = lastDir;
}
return file;
}