Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

very simple cosole debuger written in c# #44

Merged
merged 4 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions CSharpWithDebug/DebugRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Text;

namespace petooh;

public class DebugRunner : IRunner
{
private readonly StringBuilder _out = new();

private void PrintStructured(IEnumerable<string> lexemes, int pc)
{
int counter = 0;
int shift = 0;
var split = "";
foreach (var lexeme in lexemes)
{
var print = lexeme;
if (counter == pc)
print = $"|{lexeme}|";
if (lexeme == Language.OP_JMP)
shift++;
if (lexeme == Language.OP_RET)
shift--;
if (lexeme is Language.OP_RET or Language.OP_JMP)
{
print = $"\n{print}\n";
if (lexeme == Language.OP_RET)
print += "\n";
Console.Write(print + new string(' ', shift * 2));
split = "";
}
else
{
Console.Write(split + print);
split = " ";
}

counter++;
}
Console.WriteLine();
}

private void PrintDebug(Interpreter interpreter)
{
var dbg = "nop";
if (interpreter.ProgramPointer < interpreter.Lexemes.Length)
dbg = interpreter.Lexemes[interpreter.ProgramPointer];

Console.Clear();

PrintStructured(interpreter.Lexemes, interpreter.ProgramPointer);

Console.WriteLine($"\noutput: {_out}");
Console.WriteLine("pc = " + interpreter.ProgramPointer + " |" + dbg +"|");
Console.WriteLine("mem ptr = " + interpreter.MemoryPointer);
Console.Write("memory:");
for (int i = 0; i < interpreter.Memory.Count; i++)
{
Console.Write(i == interpreter.MemoryPointer ? $" |{interpreter.Memory[i]}|" : $" {interpreter.Memory[i]}");
}

if (interpreter.ProgramPointer >= interpreter.Lexemes.Length)
Console.WriteLine("\nProgram finished. Press any key to exit...");
else
Console.WriteLine("\npress any key to next step...");

Console.ReadKey();
}

private void Output(string str)
{
_out.Append(str);
}

public void Run(Interpreter interpreter)
{
do
{
PrintDebug(interpreter);
} while (interpreter.Next(Output));

PrintDebug(interpreter);
}
}
6 changes: 6 additions & 0 deletions CSharpWithDebug/IRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using petooh;

public interface IRunner
{
void Run(Interpreter interpreter);
}
72 changes: 72 additions & 0 deletions CSharpWithDebug/Interpreter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace petooh;

public class Interpreter
{
private readonly List<byte> _memory = new(new byte[16]);
public IReadOnlyList<byte> Memory => _memory;
public int MemoryPointer { get; private set; }
public int ProgramPointer { get; private set; }
public string[] Lexemes { get; private set; } = Array.Empty<string>();

public void Load(string code)
{
Lexemes = Parser.ToLexemes(code);
}

void IncMemPtr()
{
if (MemoryPointer == _memory.Count - 1)
_memory.AddRange(new byte[16]);
MemoryPointer++;
}

void DecMemPtr()
{
MemoryPointer--;
}

public bool Next(Action<string> output)
{
if (ProgramPointer >= Lexemes.Length)
return false;

switch (Lexemes[ProgramPointer])
{
case Language.OP_INC:_memory[MemoryPointer]++; break;
case Language.OP_DEC:_memory[MemoryPointer]--; break;
case Language.OP_INCPTR: IncMemPtr(); break;
case Language.OP_DECPTR: DecMemPtr(); break;
case Language.OP_OUT: output(((char)_memory[MemoryPointer]).ToString()); break;
case Language.OP_JMP:
if (_memory[MemoryPointer] == 0)
{
var count = 1;
do
{
ProgramPointer++;
if (Lexemes[ProgramPointer] == Language.OP_JMP) count++;
if (Lexemes[ProgramPointer] == Language.OP_RET) count--;
} while (count > 0);
}
break;
case Language.OP_RET:
if (_memory[MemoryPointer] != 0)
{
var count = 0;
do
{
if (Lexemes[ProgramPointer] == Language.OP_JMP) count++;
if (Lexemes[ProgramPointer] == Language.OP_RET) count--;
ProgramPointer--;
} while (count < 0);

ProgramPointer += 1;
}
break;
}

ProgramPointer++;

return ProgramPointer < Lexemes.Length;
}
}
12 changes: 12 additions & 0 deletions CSharpWithDebug/Language.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace petooh;

public static class Language
{
public const string OP_INC = "Ko";
public const string OP_DEC = "kO";
public const string OP_OUT = "Kukarek";
public const string OP_INCPTR = "Kudah";
public const string OP_DECPTR = "kudah";
public const string OP_JMP = "Kud";
public const string OP_RET = "kud";
}
11 changes: 11 additions & 0 deletions CSharpWithDebug/NormalRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using petooh;

public class NormalRunner : IRunner
{
public void Run(Interpreter interpreter)
{
while (interpreter.Next(Console.Write))
{
}
}
}
64 changes: 64 additions & 0 deletions CSharpWithDebug/Parser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
namespace petooh;

public static class Parser
{
public static string[] ToLexemes(string text)
{
text += " ";
var validChars = new HashSet<char>(
Language.OP_DECPTR.ToCharArray()
.Union(Language.OP_INCPTR.ToCharArray())
.Union(Language.OP_INC.ToCharArray())
.Union(Language.OP_DEC.ToCharArray())
.Union(Language.OP_OUT.ToCharArray())
.Union(Language.OP_JMP.ToCharArray())
.Union(Language.OP_RET.ToCharArray()));

var lexemes = new List<string>();
string buf = "";
bool wait = false;
foreach (var ch in text)
{
if (wait && ch != 'a')
{
lexemes.Add(buf);
buf = "";
wait = false;
}
else
{
wait = false;
}

if (!validChars.Contains(ch))
continue;

var cmd = buf + ch;
if (cmd is Language.OP_INC
or Language.OP_DEC
or Language.OP_OUT
or Language.OP_INCPTR
or Language.OP_DECPTR
or Language.OP_JMP
or Language.OP_RET)
{
if (cmd is Language.OP_JMP or Language.OP_RET)
{
wait = true;
buf += ch;
}
else
{
lexemes.Add(cmd);
buf = "";
}
}
else
{
buf += ch;
}
}

return lexemes.ToArray();
}
}
21 changes: 21 additions & 0 deletions CSharpWithDebug/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using petooh;

if (args.Length > 0)
{
try
{
var interpreter = new Interpreter();
interpreter.Load(File.ReadAllText(args[0]));
IRunner runner = args.Contains("-d") ? new DebugRunner() : new NormalRunner();
runner.Run(interpreter);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
else
{
Console.WriteLine(" USAGE: dotnet petooh.dll /path/to/file.koko [-d]");
Console.WriteLine(" -d add this option to debug");
}
29 changes: 29 additions & 0 deletions CSharpWithDebug/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
### USAGE

#### Prerequisites
install [dotnet 8 sdk](https://dotnet.microsoft.com/en-us/download)

#### Simple use
```
dotnet run ../test.koko -d
```
Here and in the following sections use ```-d``` option to start debug session (can be omitted to just run interpreter)

#### Build and Use
##### Simple build and use
```
dotnet build
```

```
dotnet ./bin/Debug/net8.0/petooh.dll ../test.koko -d
```

##### Optimized build and use
```
dotnet build -c Release
```

```
dotnet ./bin/Release/net8.0/petooh.dll ../test.koko -d
```
10 changes: 10 additions & 0 deletions CSharpWithDebug/petooh.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Loading