public Option <InterpreterResult> TryRun() { Guard.IsNotNull(Source, nameof(Source)); using MemoryOwner <Brainf_ckOperation>?operations = Brainf_ckParser.TryParse <Brainf_ckOperation>(Source.Value.Span, out SyntaxValidationResult validationResult); if (!validationResult.IsSuccess) { return(Option <InterpreterResult> .From(validationResult)); } if (InitialState is TuringMachineState initialState) { Guard.IsNull(MemorySize, nameof(MemorySize)); Guard.IsNull(OverflowMode, nameof(OverflowMode)); initialState = (TuringMachineState)initialState.Clone(); } else { int size = MemorySize ?? Specs.DefaultMemorySize; Guard.IsBetweenOrEqualTo(size, Specs.MinimumMemorySize, Specs.MaximumMemorySize, nameof(MemorySize)); initialState = new TuringMachineState(size, OverflowMode ?? Specs.DefaultOverflowMode); } InterpreterResult result = Brainf_ckInterpreter.Release.Run( operations !.Span, Stdin.GetValueOrDefault().Span, initialState, ExecutionToken); return(Option <InterpreterResult> .From(validationResult, result)); }
/// <summary> /// Creates a new <see cref="InterpreterSession"/> with the specified parameters /// </summary> /// <param name="opcodes">The sequence of parsed opcodes to execute</param> /// <param name="breakpoints">The table of breakpoints for the current executable</param> /// <param name="jumpTable">The jump table for loops and function declarations</param> /// <param name="functions">The mapping of functions for the current execution</param> /// <param name="definitions">The lookup table to check which functions are defined</param> /// <param name="stackFrames">The sequence of stack frames for the current execution</param> /// <param name="stdin">The input <see cref="ReadOnlyMemory{T}"/> to read characters from</param> /// <param name="machineState">The target machine state to use to run the script</param> /// <param name="executionToken">A <see cref="CancellationToken"/> that can be used to halt the execution</param> /// <param name="debugToken">A <see cref="CancellationToken"/> that is used to ignore/respect existing breakpoints</param> internal InterpreterSession( MemoryOwner <Brainf_ckOperator> opcodes, MemoryOwner <bool> breakpoints, MemoryOwner <int> jumpTable, MemoryOwner <Range> functions, MemoryOwner <ushort> definitions, MemoryOwner <StackFrame> stackFrames, ReadOnlyMemory <char> stdin, TuringMachineState machineState, CancellationToken executionToken, CancellationToken debugToken) { Opcodes = opcodes; Breakpoints = breakpoints; JumpTable = jumpTable; Functions = functions; Definitions = definitions; StackFrames = stackFrames; MachineState = machineState; StdinBuffer = new StdinBuffer(stdin); StdoutBuffer = StdoutBuffer.Allocate(); ExecutionToken = executionToken; DebugToken = debugToken; Stopwatch = new Stopwatch(); SourceCode = Brainf_ckParser.ExtractSource(opcodes.Span); }
// Tests a valid script private static void AssertIsValid(string script) { SyntaxValidationResult result = Brainf_ckParser.ValidateSyntax(script); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(result.ErrorOffset, -1); Assert.AreEqual(result.ErrorType, SyntaxError.None); }
// Tests an invalid script private static void AssertIsInvalid(string script, int position, SyntaxError error) { SyntaxValidationResult result = Brainf_ckParser.ValidateSyntax(script); Assert.IsFalse(result.IsSuccess); Assert.AreEqual(result.ErrorOffset, position); Assert.AreEqual(result.ErrorType, error); }
// Tests a sequence of characters private static void AssertIsOperator(string characters, bool result) { foreach (char c in characters) { bool isOperator = Brainf_ckParser.IsOperator(c); Assert.AreEqual(isOperator, result); } }
public void EmptyStackTrace() { using MemoryOwner <Brainf_ckOperator>?operators = Brainf_ckParser.TryParse <Brainf_ckOperator>("++[>++>-]>+", out _); Assert.IsNotNull(operators); using MemoryOwner <StackFrame> stackFrames = MemoryOwner <StackFrame> .Allocate(512); stackFrames.DangerousGetReference() = new StackFrame(new Range(0, operators !.Length), 10); HaltedExecutionInfo?exceptionInfo = Brainf_ckInterpreter.LoadDebugInfo(operators.Span, stackFrames.Span, -1); Assert.IsNull(exceptionInfo); }
public void ValidateReleaseCompression() { Span <Brainf_ckOperation> operations = stackalloc[] { new Brainf_ckOperation(Operators.Plus, 5), new Brainf_ckOperation(Operators.Minus, 4), new Brainf_ckOperation(Operators.ForwardPtr, 7), new Brainf_ckOperation(Operators.BackwardPtr, 3), new Brainf_ckOperation(Operators.ForwardPtr, 1), new Brainf_ckOperation(Operators.BackwardPtr, 1), new Brainf_ckOperation(Operators.ForwardPtr, 2), new Brainf_ckOperation(Operators.FunctionStart, 1), new Brainf_ckOperation(Operators.Plus, 5), new Brainf_ckOperation(Operators.FunctionEnd, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.LoopStart, 1), new Brainf_ckOperation(Operators.LoopStart, 1), new Brainf_ckOperation(Operators.Plus, 5), new Brainf_ckOperation(Operators.LoopEnd, 1), new Brainf_ckOperation(Operators.LoopEnd, 1), new Brainf_ckOperation(Operators.FunctionCall, 1), new Brainf_ckOperation(Operators.Plus, 15), new Brainf_ckOperation(Operators.Minus, 15), new Brainf_ckOperation(Operators.PrintChar, 1), new Brainf_ckOperation(Operators.PrintChar, 1), new Brainf_ckOperation(Operators.ReadChar, 1), new Brainf_ckOperation(Operators.ReadChar, 1), }; string script = Brainf_ckParser.ExtractSource(operations); using MemoryOwner <Brainf_ckOperation>?buffer = Brainf_ckParser.TryParse <Brainf_ckOperation>(script, out SyntaxValidationResult result); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(result.ErrorType, SyntaxError.None); Assert.AreEqual(result.ErrorOffset, -1); Assert.AreEqual(result.OperatorsCount, script.Length); CollectionAssert.AreEqual(operations.ToArray(), buffer !.Span.ToArray()); }
public void RootBreakpoint() { using MemoryOwner <Brainf_ckOperator>?operators = Brainf_ckParser.TryParse <Brainf_ckOperator>("++[>++>-]>+", out _); Assert.IsNotNull(operators); using MemoryOwner <StackFrame> stackFrames = MemoryOwner <StackFrame> .Allocate(512); stackFrames.DangerousGetReference() = new StackFrame(new Range(0, operators !.Length), 7); HaltedExecutionInfo?exceptionInfo = Brainf_ckInterpreter.LoadDebugInfo(operators.Span, stackFrames.Span, 0); Assert.IsNotNull(exceptionInfo); Assert.AreEqual(exceptionInfo !.StackTrace.Count, 1); Assert.AreEqual(exceptionInfo.StackTrace[0], "++[>++>-"); Assert.AreEqual(exceptionInfo.HaltingOperator, '-'); Assert.AreEqual(exceptionInfo.HaltingOffset, 7); }
public void TryParseInReleaseMode() { const string script = "[\n\tTest script\n]\n+++++[\n\t>++ 5 x 2 = 10\n\t<- Loop decrement\n]\n> Move to cell 1"; using MemoryOwner <Brainf_ckOperation>?operations = Brainf_ckParser.TryParse <Brainf_ckOperation>(script, out SyntaxValidationResult result); Assert.IsTrue(result.IsSuccess); Assert.AreEqual(result.ErrorType, SyntaxError.None); Assert.AreEqual(result.ErrorOffset, -1); Assert.AreEqual(result.OperatorsCount, 15); Assert.IsNotNull(operations); Assert.AreEqual(operations !.Length, 10); string source = Brainf_ckParser.ExtractSource(operations.Span); Assert.IsNotNull(source); Assert.AreEqual(source, "[]+++++[>++<-]>"); }
public static bool HaveSameColor(char first, char second) { if (first == second) { return(true); } // Always have the lowest character in first position if (second > first) { (first, second) = (second, first); } return (!Brainf_ckParser.IsOperator(first) && !Brainf_ckParser.IsOperator(second) || first == Characters.BackwardPtr && second == Characters.ForwardPtr || first == Characters.Plus && second == Characters.Minus || first == Characters.LoopStart && second == Characters.LoopEnd || first == Characters.FunctionStart && second == Characters.FunctionEnd); }
public void FunctionCallBreakpoint() { using MemoryOwner <Brainf_ckOperator>?operators = Brainf_ckParser.TryParse <Brainf_ckOperator>("(+>):+", out _); Assert.IsNotNull(operators); using MemoryOwner <StackFrame> stackFrames = MemoryOwner <StackFrame> .Allocate(512); stackFrames.Span[0] = new StackFrame(new Range(0, operators !.Length), 5); stackFrames.Span[1] = new StackFrame(new Range(1, 3), 2); HaltedExecutionInfo?exceptionInfo = Brainf_ckInterpreter.LoadDebugInfo(operators.Span, stackFrames.Span, 1); Assert.IsNotNull(exceptionInfo); Assert.AreEqual(exceptionInfo !.StackTrace.Count, 2); Assert.AreEqual(exceptionInfo.StackTrace[0], "+>"); Assert.AreEqual(exceptionInfo.StackTrace[1], "(+>):"); Assert.AreEqual(exceptionInfo.HaltingOperator, '>'); Assert.AreEqual(exceptionInfo.HaltingOffset, 2); }
public void ExtractSource() { Span <Brainf_ckOperator> operators = stackalloc Brainf_ckOperator[] { Operators.Plus, Operators.Minus, Operators.ForwardPtr, Operators.BackwardPtr, Operators.PrintChar, Operators.ReadChar, Operators.LoopStart, Operators.LoopEnd, Operators.FunctionStart, Operators.FunctionEnd, Operators.FunctionCall }; string source = Brainf_ckParser.ExtractSource(operators); Assert.IsNotNull(source); Assert.AreEqual(source, "+-><.,[]():"); }
protected override void OnTextChanged(ReadOnlyMemory <char> text) { ValidationResult = Brainf_ckParser.ValidateSyntax(text.Span); Column = text.Length + 1; }