diff --git a/.gitignore b/.gitignore
index 9a18cb0..ef96fea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,5 @@
.vs/
# Compilation Files
-BrRun/bin/
-BrRun/obj/
+*/bin/
+*/obj/
diff --git a/BrRun.sln b/BfRun.sln
similarity index 60%
rename from BrRun.sln
rename to BfRun.sln
index 5ba05bd..efb7766 100644
--- a/BrRun.sln
+++ b/BfRun.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BrRun", "BrRun\BrRun.csproj", "{2F98A27C-2F74-4377-BC63-88E1DF52558D}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BfRun", "BfRun\BfRun.csproj", "{5FDEA610-020B-4D09-8950-491E551DA9A6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {2F98A27C-2F74-4377-BC63-88E1DF52558D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2F98A27C-2F74-4377-BC63-88E1DF52558D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2F98A27C-2F74-4377-BC63-88E1DF52558D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2F98A27C-2F74-4377-BC63-88E1DF52558D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5FDEA610-020B-4D09-8950-491E551DA9A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5FDEA610-020B-4D09-8950-491E551DA9A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5FDEA610-020B-4D09-8950-491E551DA9A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5FDEA610-020B-4D09-8950-491E551DA9A6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {777E29D0-1222-4B40-BCB3-BD0489E5F38D}
+ SolutionGuid = {22B5EFF7-3B38-4012-A9E7-ABD601F01ADC}
EndGlobalSection
EndGlobal
diff --git a/BrRun/BrRun.csproj b/BfRun/BfRun.csproj
similarity index 70%
rename from BrRun/BrRun.csproj
rename to BfRun/BfRun.csproj
index 0f7d180..2150e37 100644
--- a/BrRun/BrRun.csproj
+++ b/BfRun/BfRun.csproj
@@ -3,9 +3,8 @@
Exe
net8.0
- disable
+ enable
enable
- bfrun
diff --git a/BfRun/Program.cs b/BfRun/Program.cs
new file mode 100644
index 0000000..6b56f5f
--- /dev/null
+++ b/BfRun/Program.cs
@@ -0,0 +1,10 @@
+namespace BfRun
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello, World!");
+ }
+ }
+}
diff --git a/BrRun/BrInterpretContext.cs b/BrRun/BrInterpretContext.cs
deleted file mode 100644
index 832b173..0000000
--- a/BrRun/BrInterpretContext.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace BrRun;
-
-public class BrInterpretContext
-{
- public required string filePath;
- public required bool stepFlag;
- public required bool usefulFlag;
- public required InterpretMode mode;
-
- internal BrInterpretContext() { }
-}
diff --git a/BrRun/BrInterpreterBase.cs b/BrRun/BrInterpreterBase.cs
deleted file mode 100644
index 031a1d4..0000000
--- a/BrRun/BrInterpreterBase.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace BrRun;
-
-public abstract class BrInterpreterBase
-{
- public BrInterpretContext Context { get; set; }
- public string FilePath { get; set; }
-
- public BrInterpreterBase(string filePath, BrInterpretContext context)
- {
- FilePath = filePath;
- Context = context;
- }
-
- public abstract void Interpret();
-}
diff --git a/BrRun/InterpretMode.cs b/BrRun/InterpretMode.cs
deleted file mode 100644
index f3a5782..0000000
--- a/BrRun/InterpretMode.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace BrRun;
-
-public enum InterpretMode
-{
- StandardBr,
- BrPlusPlus,
- UsefulBr,
-}
diff --git a/BrRun/Interpreters/StandardBrInterpreter.cs b/BrRun/Interpreters/StandardBrInterpreter.cs
deleted file mode 100644
index 6b2bb23..0000000
--- a/BrRun/Interpreters/StandardBrInterpreter.cs
+++ /dev/null
@@ -1,325 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-
-namespace BrRun.Interpreters;
-
-public class StandardBrInterpreter : BrInterpreterBase
-{
- // Can technically be changed, but it should remain the same to match convention.
- public static readonly short TapeMinValue = 0, TapeMaxValue = 255;
- public static readonly int TapeLength = 30_000;
-
- protected FileStream? reader;
- protected readonly short[] tape;
-
- protected int dataPointer;
- protected Stack stack;
- protected Stack<(int, int)> debugOpeningStack;
-
- private int lineNumber;
- private int charNumber;
- private char curChar;
- private int awakeTop = 0;
-
- public StandardBrInterpreter(string filePath, BrInterpretContext context) : base(filePath, context)
- {
- reader = null;
- tape = new short[TapeLength];
- dataPointer = 0;
- stack = [];
- debugOpeningStack = [];
-
- lineNumber = 1;
- charNumber = 0;
- }
-
- public override void Interpret()
- {
- awakeTop = Console.CursorTop;
- if (Context.stepFlag)
- {
- for (int i = 0; i < 10; i++) Console.WriteLine();
- awakeTop = Console.CursorTop - 10;
- }
- reader = new(FilePath, FileMode.Open);
-
- IntentionKind intent;
- while ((intent = StepProgram()) != IntentionKind.EndOfFile)
- {
- if (Context.stepFlag) ShowDebugScreen(intent);
- HandleIntent(intent);
- }
-
- reader.Close();
- Console.CursorVisible = true;
- }
-
- protected void HandleIntent(IntentionKind intent)
- {
- switch (intent)
- {
- case IntentionKind.IncrementPointer:
- dataPointer++;
- if (dataPointer >= TapeLength)
- {
- Console.WriteLine($"warn L{lineNumber} C{charNumber}: data pointer has overflowed! (length {TapeLength})");
- dataPointer = 0;
- }
- break;
-
- case IntentionKind.DecrementPointer:
- dataPointer--;
- if (dataPointer < 0)
- {
- Console.WriteLine($"warn L{lineNumber} C{charNumber}: data pointer has underflowed! (length {TapeLength})");
- dataPointer = TapeLength - 1;
- }
- break;
-
- case IntentionKind.IncrementValue:
- if (tape[dataPointer] == TapeMaxValue) tape[dataPointer] = TapeMinValue;
- else tape[dataPointer]++;
- break;
-
- case IntentionKind.DecrementValue:
- if (tape[dataPointer] == TapeMinValue) tape[dataPointer] = TapeMaxValue;
- else tape[dataPointer]--;
- break;
-
- case IntentionKind.OutputValue:
- Console.Write((char)tape[dataPointer]);
- break;
-
- case IntentionKind.InputValue:
- Console.CursorVisible = true;
- tape[dataPointer] = (byte)Console.ReadKey().KeyChar;
- break;
-
- case IntentionKind.BeginGroup:
- if (reader is null) Console.WriteLine($"error L{lineNumber} C{charNumber}: file hasn't been opened yet! how did this happen?");
- else
- {
- stack.Push(reader.Position);
- debugOpeningStack.Push((lineNumber, charNumber));
- if (tape[dataPointer] == 0)
- {
- // Look for closing brace.
- IntentionKind newIntent;
- while ((newIntent = StepProgram()) != IntentionKind.EndOfFile)
- {
- if (newIntent == IntentionKind.EndGroup) break; // Found closing bracket.
- }
- if (newIntent == IntentionKind.EndOfFile)
- {
- Console.WriteLine($"error L{lineNumber} C{charNumber}: no closing bracket to match opening bracket.");
- return;
- }
- }
- }
- break;
-
- case IntentionKind.EndGroup:
- if (stack.Count == 0)
- {
- Console.WriteLine($"error L{lineNumber} C{charNumber}: no opening bracket to match closing bracket.");
- return;
- }
-
- if (tape[dataPointer] == 0)
- {
- // Exit loop.
- stack.Pop();
- debugOpeningStack.Pop();
- }
- else
- {
- // Restart.
- if (reader is null) Console.WriteLine($"error L{lineNumber} C{charNumber}: file hasn't been opened yet! how did this happen?");
- else reader.Seek(stack.Peek(), SeekOrigin.Begin);
-
- (int newL, int newC) = debugOpeningStack.Peek();
- lineNumber = newL;
- charNumber = newC;
- }
- break;
-
- default:
- Console.WriteLine($"warn L{lineNumber} C{charNumber}: unknown intent! how did this happen?");
- break;
- }
- }
-
- private int remainingSkips = 0;
- protected void ShowDebugScreen(IntentionKind currentIntent)
- {
- const int numSpace = 3;
-
- Console.CursorVisible = false;
- int initialTop = Console.CursorTop, initialLeft = Console.CursorLeft;
- int totalCanFit = (Console.WindowWidth - 1) / (numSpace + 3);
-
- int startIndex = int.Max(0, (int)(dataPointer - totalCanFit * 0.5)),
- endIndex = int.Min(startIndex + totalCanFit - 1, TapeLength - 1);
-
- int consolePos = 0;
- for (int i = startIndex; i <= endIndex; i++)
- {
- Console.SetCursorPosition(consolePos, awakeTop + 1);
- Console.Write($" {i,numSpace + 2}");
-
- Console.SetCursorPosition(consolePos, awakeTop + 2);
- if (i == startIndex) Console.Write("╔═════");
- else Console.Write("╦═════");
-
- Console.SetCursorPosition(consolePos, awakeTop + 3);
- Console.Write($"║ {tape[i],numSpace} ");
-
- Console.SetCursorPosition(consolePos, awakeTop + 4);
- if (i == startIndex) Console.Write("╚═════");
- else Console.Write("╩═════");
-
- Console.SetCursorPosition(consolePos, awakeTop + 5);
- if (i == dataPointer) Console.Write(" ^ ");
- else Console.Write(" ");
-
- Console.SetCursorPosition(consolePos, awakeTop + 9);
- Console.Write($"──────");
-
- consolePos += numSpace + 3;
- }
- Console.SetCursorPosition(consolePos, awakeTop + 2);
- Console.Write('╗');
- Console.SetCursorPosition(consolePos, awakeTop + 3);
- Console.Write('║');
- Console.SetCursorPosition(consolePos, awakeTop + 4);
- Console.Write('╝');
- Console.SetCursorPosition(consolePos, awakeTop + 9);
- Console.Write('─');
-
- Console.SetCursorPosition(0, awakeTop + numSpace + 3);
- string message = $"L{lineNumber} C{charNumber}: {curChar} {GetDebugDescriptionOfOperator(currentIntent)} ";
- Console.Write(message + new string(' ', int.Max(Console.WindowWidth - message.Length - 1, 0)));
-
- if (remainingSkips < int.MaxValue - 1) remainingSkips--;
- if (remainingSkips == int.MaxValue - 1 && currentIntent == IntentionKind.EndGroup && tape[dataPointer] == 0) remainingSkips = 0;
-
- Console.SetCursorPosition(0, awakeTop + 7);
- if (currentIntent == IntentionKind.InputValue)
- {
- Console.Write("Enter one character to step the program." + new string(' ', 70));
- }
- else
- {
- if (remainingSkips > 0)
- {
- string message2;
- if (remainingSkips == int.MaxValue) message2 = $"Continuing program to completion...";
- else if (remainingSkips == int.MaxValue - 1) message2 = $"Waiting for loop exit...";
- else message2 = $"Skipping {remainingSkips} steps...";
- Console.Write(message2 + new string(' ', 110 - message2.Length));
- }
- else
- {
- Console.Write("Press space to step the system. D = +5 steps, F = +25 steps, G = +100 steps, J = until loop ends, K = continuous");
-
- _readKey:
- ConsoleKeyInfo stepKey = Console.ReadKey(true);
- switch (stepKey.Key)
- {
- case ConsoleKey.Spacebar:
- remainingSkips++;
- break;
- case ConsoleKey.D:
- remainingSkips += 5;
- break;
- case ConsoleKey.F:
- remainingSkips += 25;
- break;
- case ConsoleKey.G:
- remainingSkips += 100;
- break;
- case ConsoleKey.J:
- remainingSkips = int.MaxValue - 1;
- break;
- case ConsoleKey.K:
- remainingSkips = int.MaxValue;
- break;
- default: goto _readKey;
- }
- }
- }
-
- Console.SetCursorPosition(initialLeft, initialTop);
- }
- private string GetDebugDescriptionOfOperator(IntentionKind intent) => intent switch
- {
- IntentionKind.IncrementPointer => $"Move pointer to right ({dataPointer} -> {dataPointer + 1})",
- IntentionKind.DecrementPointer => $"Move pointer to left ({dataPointer} -> {dataPointer - 1})",
- IntentionKind.IncrementValue => $"Increase value at position {dataPointer} ({tape[dataPointer]} -> {tape[dataPointer] + 1})",
- IntentionKind.DecrementValue => $"Decrease value at position {dataPointer} ({tape[dataPointer]} -> {tape[dataPointer] - 1})",
- IntentionKind.OutputValue => $"Print out current value as character (value {tape[dataPointer]})",
- IntentionKind.InputValue => $"Input next character input into position {dataPointer}",
- IntentionKind.BeginGroup => tape[dataPointer] == 0
- ? "Skipping loop. Moving execution forward to closing bracket."
- : "Beginning a loop",
- IntentionKind.EndGroup => tape[dataPointer] == 0
- ? $"Breaking out of a loop"
- : $"Moving execution back to L{debugOpeningStack.Peek().Item1} C{debugOpeningStack.Peek().Item2} until value at position {dataPointer} is zero (currently {tape[dataPointer]})",
- _ => "?? unknown intent ??"
- };
-
- protected IntentionKind StepProgram()
- {
- if (reader is null)
- {
- if (reader is null) Console.WriteLine("error: file hasn't been opened yet! how did this happen?");
- return IntentionKind.EndOfFile;
- }
-
- int cI = reader.ReadByte();
- if (cI == -1) return IntentionKind.EndOfFile;
-
- char c = (char)cI;
- if (c == '\n')
- {
- lineNumber++;
- charNumber = 0;
- }
- else if (c != '\r') charNumber++;
-
-
- curChar = c;
- switch (c)
- {
- case '\r' or '\n' or ' ' or '\t': return StepProgram(); // Skip newlines.
- case '#':
- Console.WriteLine("error: comments are not supported in standard brainfuck.");
- return StepProgram();
- case '>': return IntentionKind.IncrementPointer;
- case '<': return IntentionKind.DecrementPointer;
- case '+': return IntentionKind.IncrementValue;
- case '-': return IntentionKind.DecrementValue;
- case '.': return IntentionKind.OutputValue;
- case ',': return IntentionKind.InputValue;
- case '[': return IntentionKind.BeginGroup;
- case ']': return IntentionKind.EndGroup;
- default:
- Console.WriteLine($"error: unsupported operator {c}");
- return StepProgram();
- }
- }
-
- protected enum IntentionKind
- {
- EndOfFile,
- IncrementPointer,
- DecrementPointer,
- IncrementValue,
- DecrementValue,
- OutputValue,
- InputValue,
- BeginGroup,
- EndGroup
- }
-}
diff --git a/BrRun/Program.cs b/BrRun/Program.cs
deleted file mode 100644
index f152f4f..0000000
--- a/BrRun/Program.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using BrRun.Interpreters;
-using System;
-using System.IO;
-
-namespace BrRun;
-
-public static class Program
-{
- public static void Main(string[] args)
- {
- if (args.Length == 0)
- {
- Console.WriteLine("fatal: no file provided.");
- return;
- }
-
- string path = args[0];
- bool stepFlag = false, usefulFlag = false;
- for (int i = 1; i < args.Length; i++)
- {
- switch (args[i])
- {
- case "--step":
- if (stepFlag) Console.WriteLine("warn: duplicate --step flag.");
- stepFlag = true;
- break;
-
- case "--useful":
- if (usefulFlag) Console.WriteLine("warn: duplicate --useful flag.");
- usefulFlag = true;
- break;
-
- default:
- Console.WriteLine($"warn: unknown {args[i]} argument.");
- break;
- }
- }
-
- if (!File.Exists(path))
- {
- Console.WriteLine($"fatal: file does not exist at {path}");
- return;
- }
-
- InterpretMode mode;
- if (path.EndsWith(".bf") || path.EndsWith(".br") || path.EndsWith(".b"))
- {
- mode = InterpretMode.StandardBr;
- if (usefulFlag) Console.WriteLine("warn: --useful flag is not applicable to standard brainfuck.");
- }
- else if (path.EndsWith(".bpp") || path.EndsWith(".b++") || path.EndsWith(".bfpp") ||
- path.EndsWith(".bf++") || path.EndsWith(".brpp") || path.EndsWith(".br++"))
- {
- mode = InterpretMode.BrPlusPlus;
- if (usefulFlag) mode = InterpretMode.UsefulBr;
- }
- else
- {
- Console.WriteLine($"fatal: unsupported file type {path[path.LastIndexOf('.')..]}.");
- return;
- }
-
- BrInterpretContext context = new()
- {
- filePath = path,
- stepFlag = stepFlag,
- usefulFlag = usefulFlag,
- mode = mode
- };
-
- BrInterpreterBase interpreter;
- switch (mode)
- {
- case InterpretMode.StandardBr:
- interpreter = new StandardBrInterpreter(path, context);
- break;
-
- default:
- Console.WriteLine("fatal: unknown interpreter mode. how did this happen?");
- return;
- }
-
- interpreter.Interpret();
- }
-}