turing-machine/Implementation/Core/Machine.cs

92 lines
2.6 KiB
C#

using System;
namespace TuringMachine.Core
{
public class Machine
{
public Tape Tape { get; }
public TransitionTable Transitions { get; }
public int HeadPosition { get; private set; }
public string CurrentState { get; private set; }
public bool IsHalted { get; private set; }
public string InitialState { get; set; } = "q0";
public event Action? OnStep;
public event Action? OnHalt;
public Machine()
{
Tape = new Tape();
Transitions = new TransitionTable();
CurrentState = InitialState;
}
public void ForceHeadPosition(int position)
{
HeadPosition = position;
}
public void Reset()
{
Tape.Clear();
HeadPosition = 0;
CurrentState = InitialState;
IsHalted = false;
OnStep?.Invoke();
}
public void LoadProgram(string initialState, IEnumerable<(string state, char read, string newState, char write, MoveDirection move, string comment)> transitions)
{
InitialState = initialState;
Transitions.Clear();
foreach (var t in transitions)
{
Transitions.Add(t.state, t.read, t.newState, t.write, t.move, t.comment);
}
Reset();
}
public bool Step()
{
if (IsHalted) return false;
char readSymbol = Tape[HeadPosition];
if (Transitions.TryGetTransition(CurrentState, readSymbol, out var result))
{
if (result == null)
{
// Should not simplify happen due to TryGetTransition semantics, but for safety
IsHalted = true;
OnHalt?.Invoke();
return false;
}
Tape[HeadPosition] = result.WriteSymbol;
CurrentState = result.NewState;
switch (result.MoveDirection)
{
case MoveDirection.Left:
HeadPosition--;
break;
case MoveDirection.Right:
HeadPosition++;
break;
}
OnStep?.Invoke();
return true;
}
else
{
// No transition defined = Halt
IsHalted = true;
OnHalt?.Invoke();
return false;
}
}
}
}