HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Interpreting Brainfuck code to C#, then compiling to a .exe

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
exeinterpretingcodecompilingthenbrainfuck

Problem

This is a C# programme to convert Brainfuck to C#, then convert that C# to a .exe. So basically, it's a Brainfuck to Windows exe file converter/compiler.

This requires any of:

  • .NET 2.0 in C:\Windows\Microsoft.NET\Framework\v2.0.50727



  • .NET 3.5 in C:\Windows\Microsoft.NET\Framework\v3.5



  • .NET 4.0 in C:\Windows\Microsoft.NET\Framework\v4.0.30319



Just specify 2.0, 3.5, or 4.0 at the appropriate prompt.

Do note that this uses classes from my Framework library. If you wish to run it you'll need to download the Evbpc.Framework project there and compile it. (Or remove all of the ConsolePrompt, ConsoleLogger, and IPrompt stuff.)

It's also on GitHub.

```
class Program
{
static string AddExtension(string data, string extension)
{
if (data.IndexOf('.') == -1)
{
data += extension;
}

return data;
}

static void AcquireInput(ILogger logger, out string sourceFile, out string programName, out string destinationFile, out string executableFile, out int bufferSize, out string dotNetVersion)
{
ConsolePrompt prompt = new ConsolePrompt(new EmptyLogger());
logger.LogVerbose("Prompting for input...");
sourceFile = AddExtension(prompt.Prompt("Enter the source filename (.bf)", PromptOptions.Required), ".bf");
programName = sourceFile.Substring(0, sourceFile.LastIndexOf('.'));
destinationFile = AddExtension(prompt.Prompt("Enter the destination filename (.cs)", PromptOptions.Optional, programName + ".cs"), ".cs");
executableFile = AddExtension(prompt.Prompt("Enter the destination executable (.exe)", PromptOptions.Optional, programName + ".exe"), ".exe");
bufferSize = prompt.Prompt("Enter buffer size", PromptOptions.Optional, 2048);
dotNetVersion = prompt.Prompt("Enter .NET version to compile with", PromptOptions.Optional, "4.0", "Version can be any of: 2.0, 3.5, 4.0", x => _dotNetFolders.ContainsKey(x));
logger.LogVerbose("Input acqu

Solution

Dayum, there's some static around here.

Why not make it an instance class?

What you have here is a workflow, where methods have a specific order. This is clearly seen in your Main method. The workflow usually have a state, and static stuff is supposed to be stateless. So I really think an instance class would be good!

Doing this would also mean you wouldn't need all those dirty out parameters, nobody loves them anyway! You could keep these ->

string sourceFile = string.Empty;
string programName = string.Empty;
string destinationFile = string.Empty;
string executableFile = string.Empty;
string dotNetVersion = string.Empty;


as class members, which would make sense. This would also let you inject the dependancies of your logger at one place, instead of having it as a parameter for each of your methods.

You didn't specify your access modifier, you should. It's always easier if they're there, this way you don't have to wonder "Did I forget to make it [internal,private,public] or was private intended?"

Your static Dictionary should be at the top of your class, in order to follow conventions about the file template!

Finally, you've made a method for every step of your "workflow" except for the one where you replace your placeholders with actual values. You could argue 2-3 lines of code don't deserve a method, but I think they do!

In the best case scenario, you should have something like this in your Main method (which, btw, would be named something else if it was in an instance class)

//All the initialization that was here is now in the constructor

AcquireInput();
string brainfuck = LoadBrainfuckCode();
string result = AcquireTemplate("CompiledTemplate.cs");
string brainfuckCode = InterpretBrainfuck(brainfuck);
result = ReplacePlaceHolders(result,brainfuckCode);

WriteToCsFile(_logger, _destinationFile, result);
CompileCsFile(_logger, _dotNetFolders[dotNetVersion], _destinationFile, _executableFile);

_logger.LogInformation("Launching programme...");
Process.Start(_executableFile);
_logger.LogInformation("Programme launched.");

Console.WriteLine("Press enter key to exit...");
Console.ReadLine();


By retyping this, I realized you have a constant in your code that isn't a.. const. You should really extract it, so it's clear does "CompiledTemplate.cs" means.

I figured I didn't need to retype all the methods as you probably get my point, but if there's something not clear about the workflow process and you'd like me to write it all, I'll do it!

Code Snippets

string sourceFile = string.Empty;
string programName = string.Empty;
string destinationFile = string.Empty;
string executableFile = string.Empty;
string dotNetVersion = string.Empty;
//All the initialization that was here is now in the constructor

AcquireInput();
string brainfuck = LoadBrainfuckCode();
string result = AcquireTemplate("CompiledTemplate.cs");
string brainfuckCode = InterpretBrainfuck(brainfuck);
result = ReplacePlaceHolders(result,brainfuckCode);

WriteToCsFile(_logger, _destinationFile, result);
CompileCsFile(_logger, _dotNetFolders[dotNetVersion], _destinationFile, _executableFile);

_logger.LogInformation("Launching programme...");
Process.Start(_executableFile);
_logger.LogInformation("Programme launched.");

Console.WriteLine("Press enter key to exit...");
Console.ReadLine();

Context

StackExchange Code Review Q#107713, answer score: 11

Revisions (0)

No revisions yet.