Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define USE_INSTRUCTION_COMPRESSION
- // NPSF3000 Simple Brainfuck Interpreter V0.01
- // Free for Educational/Personal Use, Attribution required.
- // Work In progress. Meant to be simple learning experiment hence lack of comments.
- // Tested and works with non-trivial BF.
- // Contact, NPSF3001 Gmail.com
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Diagnostics;
- using System.Windows.Forms;
- class Program
- {
- const byte END_OF_LINE = 10;
- enum COMMANDS : byte { Left, Right, Add, Subtract, Input, Output, LoopStart, LoopEnd };
- [STAThread]
- static void Main(string[] args)
- {
- byte[] program;
- print("Use clipboard y/n?");
- if (Console.ReadKey(true).KeyChar.ToString().ToLower() == "y")
- {
- print(Clipboard.GetText());
- program = CleanProgram(Clipboard.GetText());
- }
- else
- {
- print("Enter line of code");
- program = CleanProgram(Console.ReadLine());
- }
- #if USE_INSTRUCTION_COMPRESSION
- program = CompressProgram(program);
- #endif
- ushort[] LLU = new ushort[program.Length];
- foreach (var keyPair in ParseLoops(program))
- {
- LLU[keyPair.Value] = keyPair.Key;
- LLU[keyPair.Key] = keyPair.Value;
- }
- while (true)
- {
- ushort sPointer = 0, pPointer = 0;
- byte[] stack = new byte[ushort.MaxValue + 1];
- print("Starting Program");
- Stopwatch sw = new Stopwatch();
- sw.Start();
- while (pPointer < program.Length)
- {
- switch (program[pPointer])
- {
- #if USE_INSTRUCTION_COMPRESSION
- case (byte)COMMANDS.Right: pPointer++; sPointer += program[pPointer]; break;
- case (byte)COMMANDS.Left: pPointer++; sPointer -= program[pPointer]; break;
- case (byte)COMMANDS.Add: pPointer++; stack[sPointer] += (byte)program[pPointer]; break;
- case (byte)COMMANDS.Subtract: pPointer++; stack[sPointer] -= (byte)program[pPointer]; break;
- #else
- case (byte)COMMANDS.Right: sPointer++; break;
- case (byte)COMMANDS.Left: sPointer--; break;
- case (byte)COMMANDS.Add: stack[sPointer]++; break;
- case (byte)COMMANDS.Subtract: stack[sPointer]--; break;
- #endif
- case (byte)COMMANDS.Output: Output(stack[sPointer]); break;
- case (byte)COMMANDS.Input: stack[sPointer] = Input(); break;
- case (byte)COMMANDS.LoopStart:
- if (stack[sPointer] == 0)
- {
- pPointer = LLU[pPointer];//FindLoopEnd[pPointer];
- } break;
- case (byte)COMMANDS.LoopEnd:
- if (stack[sPointer] == 0) break;
- pPointer = LLU[pPointer]; //FindLoopStart[pPointer];
- break;
- }
- pPointer++;
- }
- sw.Stop();
- stack = null;
- GC.Collect();
- while (Console.KeyAvailable) Console.ReadKey();
- print("");
- print("Program finished in " + sw.ElapsedMilliseconds.ToString() + "ms");
- Console.ReadKey();
- }
- }
- static Dictionary<ushort, ushort> ParseLoops(byte[] program)
- {
- var result = new Dictionary<ushort, ushort>();
- for (ushort i = 0; i < program.Length; i++)
- {
- var command = program[i];
- if (IsCompressedCommand(command))
- {
- i++; //Skip next instruction (which is part of the command);
- continue;
- }
- if (command != (byte)(COMMANDS.LoopStart)) continue;
- ushort searchPos = i;
- byte brackets = 1;
- while (brackets != 0)
- {
- // Skip to matching ']'
- searchPos++;
- byte searchCommand = program[searchPos];
- if (IsCompressedCommand(searchCommand))
- {
- searchPos++; //Skip next instruction (which is part of the command);
- continue;
- }
- switch (searchCommand)
- {
- case (byte)(COMMANDS.LoopStart): brackets++; break;
- case (byte)(COMMANDS.LoopEnd): brackets--; break;
- }
- }
- result.Add(i, searchPos);
- }
- return result;
- }
- static bool IsCompressedCommand(byte command)
- {
- #if USE_INSTRUCTION_COMPRESSION
- return ((command == (byte)COMMANDS.Add) || (command == (byte)COMMANDS.Subtract) || (command == (byte)COMMANDS.Left) || (command == (byte)COMMANDS.Right));
- #endif
- }
- static void print(string line)
- {
- Console.WriteLine(line);
- }
- static byte Input()
- {
- //var input = (byte)Console.ReadKey(false).KeyChar.;
- var input = Encoding.ASCII.GetBytes(Console.ReadKey(false).KeyChar.ToString())[0];
- if (input == 13) input = END_OF_LINE;
- return input;
- }
- static void Output(byte value)
- {
- if (value == END_OF_LINE) Console.WriteLine("");
- else Console.Write(Encoding.ASCII.GetString(new[] { value }));
- }
- static byte[] CompressProgram(byte[] wastefulProgram)
- {
- List<byte> program = new List<byte>(wastefulProgram.Count());
- for (int i = 0; i < wastefulProgram.Count(); i++)
- {
- byte command = wastefulProgram[i];
- if (IsCompressedCommand(command))
- {
- program.Add(command);
- byte compressedValue = 1;
- while (i+1 < wastefulProgram.Count() && command == wastefulProgram[i + 1])
- {
- i++;
- compressedValue++;
- if (compressedValue == byte.MaxValue) break;
- }
- program.Add(compressedValue);
- }
- else
- {
- program.Add(command);
- }
- }
- return program.ToArray();
- }
- static byte[] CleanProgram(string dirtyProgram)
- {
- List<byte> program = new List<byte>(short.MaxValue);
- foreach (var command in dirtyProgram)
- {
- switch (command)
- {
- case '>': program.Add((byte)COMMANDS.Right); break;
- case '<': program.Add((byte)COMMANDS.Left); break;
- case '+': program.Add((byte)COMMANDS.Add); break;
- case '-': program.Add((byte)COMMANDS.Subtract); break;
- case '.': program.Add((byte)COMMANDS.Output); break;
- case ',': program.Add((byte)COMMANDS.Input); break;
- case '[': program.Add((byte)COMMANDS.LoopStart); break;
- case ']': program.Add((byte)COMMANDS.LoopEnd); break;
- }
- }
- return program.ToArray();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement