summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelodi <62381002+Melodi17@users.noreply.github.com>2025-08-06 22:36:34 +1000
committerMelodi <62381002+Melodi17@users.noreply.github.com>2025-08-06 22:36:34 +1000
commit7a8d2bcd75d88a5429937bf551878c55e1dcf0fd (patch)
tree81bc1f259fb8678513aa8b214df4ef72720bb585
parent16f3cb74564cf7c19da6e13666c98aca36094716 (diff)
moved everything to seperate projects, and started compiler work + push and pop instructions added
-rw-r--r--.DS_Storebin8196 -> 10244 bytes
-rw-r--r--.fleet/run.json11
-rw-r--r--.idea/.idea.Q1/.idea/.gitignore13
-rw-r--r--.idea/.idea.Q1/.idea/ANTLRv4ToolGrammarProperties.xml42
-rw-r--r--.idea/.idea.Q1/.idea/encodings.xml4
-rw-r--r--.idea/.idea.Q1/.idea/indexLayout.xml8
-rw-r--r--.idea/.idea.Q1/.idea/misc.xml10
-rw-r--r--.idea/.idea.Q1/.idea/vcs.xml6
-rw-r--r--Assembler/Assembler.cs328
-rw-r--r--Assembler/Assembler.csproj19
-rw-r--r--Assembler/Extensions.cs15
-rw-r--r--Assembler/GlobalUsings.cs (renamed from GlobalUsings.cs)0
-rw-r--r--Assembler/Options.cs12
-rw-r--r--Assembler/Program.cs38
-rw-r--r--Compiler/CCompilerVisitor.cs172
-rw-r--r--Compiler/CGrammar.g450
-rw-r--r--Compiler/Compiler.csproj20
-rw-r--r--Compiler/CompilerException.cs4
-rw-r--r--Compiler/Options.cs12
-rw-r--r--Compiler/Program.cs31
-rw-r--r--Compiler/gen/CGrammar.interp70
-rw-r--r--Compiler/gen/CGrammar.tokens52
-rw-r--r--Compiler/gen/CGrammarBaseVisitor.cs299
-rw-r--r--Compiler/gen/CGrammarLexer.cs149
-rw-r--r--Compiler/gen/CGrammarLexer.interp98
-rw-r--r--Compiler/gen/CGrammarLexer.tokens52
-rw-r--r--Compiler/gen/CGrammarParser.cs1006
-rw-r--r--Compiler/gen/CGrammarVisitor.cs200
-rw-r--r--Emulator/.DS_Storebin0 -> 6148 bytes
-rw-r--r--Emulator/Assembler/Disassembler.cs (renamed from Assembler/Disassembler.cs)10
-rw-r--r--Emulator/Chip/Bus.cs (renamed from Chip/Bus.cs)6
-rw-r--r--Emulator/Chip/BusDevice.cs (renamed from Chip/BusDevice.cs)9
-rw-r--r--Emulator/Chip/DebugDevice.cs13
-rw-r--r--Emulator/Chip/DisplayDevice.cs (renamed from Chip/DisplayDevice.cs)10
-rw-r--r--Emulator/Chip/Q1Cpu.cs (renamed from Chip/Q1Cpu.cs)57
-rw-r--r--Emulator/Chip/Q1CpuAddressingModes.cs (renamed from Chip/Q1CpuAddressingModes.cs)5
-rw-r--r--Emulator/Chip/Q1CpuInstructions.cs (renamed from Chip/Q1CpuInstructions.cs)94
-rw-r--r--Emulator/Chip/RamDevice.cs (renamed from Chip/RamDevice.cs)5
-rw-r--r--Emulator/Content/Content.mgcb (renamed from Content/Content.mgcb)0
-rw-r--r--Emulator/DisplayEngine.cs (renamed from DisplayEngine.cs)38
-rw-r--r--Emulator/Emulator.csproj (renamed from Q1Emu.csproj)7
-rw-r--r--Emulator/Extensions.cs (renamed from Extensions.cs)2
-rw-r--r--Emulator/GlobalUsings.cs12
-rw-r--r--Emulator/Icon.bmp (renamed from Icon.bmp)bin262282 -> 262282 bytes
-rw-r--r--Emulator/Icon.ico (renamed from Icon.ico)bin147541 -> 147541 bytes
-rw-r--r--Emulator/Make.cs (renamed from Make.cs)6
-rw-r--r--Emulator/Options.cs7
-rw-r--r--Emulator/Program.cs82
-rw-r--r--Program.cs106
-rw-r--r--Q1.sln28
-rw-r--r--Q1.sln.DotSettings.user (renamed from Chip8Emu2.sln.DotSettings.user)2
-rw-r--r--Q1Emu.sln16
-rw-r--r--Q1Emu.sln.DotSettings.user4
-rw-r--r--ROMs/.DS_Storebin6148 -> 6148 bytes
-rw-r--r--ROMs/font copy.binbin32768 -> 0 bytes
-rw-r--r--ROMs/font.binbin32768 -> 2048 bytes
-rw-r--r--ROMs/hello_c.asm7
-rw-r--r--ROMs/hello_c.c4
-rw-r--r--ROMs/hello_c.q1bin0 -> 22 bytes
-rw-r--r--ROMs/hello_world.asm (renamed from ROMs/hello_world.dat)15
-rw-r--r--ROMs/hello_world.q1bin32842 -> 2151 bytes
-rw-r--r--ROMs/write_display_direct.asm (renamed from ROMs/write_display_direct.dat)0
-rw-r--r--app.manifest43
63 files changed, 2863 insertions, 446 deletions
diff --git a/.DS_Store b/.DS_Store
index b56fb2b..a997d4b 100644
--- a/.DS_Store
+++ b/.DS_Store
Binary files differ
diff --git a/.fleet/run.json b/.fleet/run.json
deleted file mode 100644
index 5ae6c96..0000000
--- a/.fleet/run.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "configurations": [
- {
- "type": "dotnet",
- "name": "Dotnet configuration",
- "projectPath": "$PROJECT_DIR$",
- "solutionPath": "$PROJECT_DIR$",
- "args": []
- }
- ]
-} \ No newline at end of file
diff --git a/.idea/.idea.Q1/.idea/.gitignore b/.idea/.idea.Q1/.idea/.gitignore
new file mode 100644
index 0000000..842bf41
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/contentModel.xml
+/projectSettingsUpdater.xml
+/.idea.Q1.iml
+/modules.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.Q1/.idea/ANTLRv4ToolGrammarProperties.xml b/.idea/.idea.Q1/.idea/ANTLRv4ToolGrammarProperties.xml
new file mode 100644
index 0000000..bb8d49b
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/ANTLRv4ToolGrammarProperties.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ANTLRv4ToolGrammarProperties">
+ <option name="perGrammarGenerationSettings">
+ <list>
+ <PerGrammarGenerationSettings>
+ <option name="fileName" value="$PROJECT_DIR$/Assembler/cgrammar.g4" />
+ <option name="autoGen" value="true" />
+ <option name="outputDir" value="" />
+ <option name="libDir" value="" />
+ <option name="encoding" value="" />
+ <option name="pkg" value="" />
+ <option name="language" value="CSharp" />
+ <option name="generateListener" value="false" />
+ <option name="generateVisitor" value="true" />
+ </PerGrammarGenerationSettings>
+ <PerGrammarGenerationSettings>
+ <option name="fileName" value="$PROJECT_DIR$/Assembler/CGrammar.g4" />
+ <option name="autoGen" value="true" />
+ <option name="outputDir" value="" />
+ <option name="libDir" value="" />
+ <option name="encoding" value="" />
+ <option name="pkg" value="" />
+ <option name="language" value="CSharp" />
+ <option name="generateListener" value="false" />
+ <option name="generateVisitor" value="true" />
+ </PerGrammarGenerationSettings>
+ <PerGrammarGenerationSettings>
+ <option name="fileName" value="$PROJECT_DIR$/Compiler/CGrammar.g4" />
+ <option name="autoGen" value="true" />
+ <option name="outputDir" value="" />
+ <option name="libDir" value="" />
+ <option name="encoding" value="" />
+ <option name="pkg" value="" />
+ <option name="language" value="CSharp" />
+ <option name="generateListener" value="false" />
+ <option name="generateVisitor" value="true" />
+ </PerGrammarGenerationSettings>
+ </list>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/.idea.Q1/.idea/encodings.xml b/.idea/.idea.Q1/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
+</project> \ No newline at end of file
diff --git a/.idea/.idea.Q1/.idea/indexLayout.xml b/.idea/.idea.Q1/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="UserContentModel">
+ <attachedFolders />
+ <explicitIncludes />
+ <explicitExcludes />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/.idea.Q1/.idea/misc.xml b/.idea/.idea.Q1/.idea/misc.xml
new file mode 100644
index 0000000..5207dea
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/misc.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="MaterialThemeProjectNewConfig">
+ <option name="metadata">
+ <MTProjectMetadataState>
+ <option name="userId" value="2ed817c6:198067820d1:-7fff" />
+ </MTProjectMetadataState>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/.idea.Q1/.idea/vcs.xml b/.idea/.idea.Q1/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/.idea.Q1/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Git" />
+ </component>
+</project> \ No newline at end of file
diff --git a/Assembler/Assembler.cs b/Assembler/Assembler.cs
index 09ac30e..7c172e7 100644
--- a/Assembler/Assembler.cs
+++ b/Assembler/Assembler.cs
@@ -1,21 +1,11 @@
-namespace Q1Emu.Assembler;
+namespace Q1.Assembler;
-using System;
-using System.Collections.Generic;
using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using Chip;
+using Emulator;
+using Emulator.Chip;
public class Assembler
{
- public readonly BinaryWriter Writer;
- public readonly StringReader Reader;
-
- private Dictionary<string, u16> _labels = new();
- private Dictionary<u16, string> _unloadedLabels = new();
- private u16 _addressOffset = 0;
-
public static Dictionary<u16, string> RegisterLookup = new()
{
{ 0x40, "AX" },
@@ -26,30 +16,31 @@ public class Assembler
{ 0x45, "DL" },
{ 0x46, "LX" },
{ 0x50, "PC" },
- { 0x51, "SP" },
+ { 0x51, "SP" }
};
+ private readonly string[] InputLines;
+
+ private readonly Dictionary<string, u16> _labels = new();
- public Assembler(StringReader reader, BinaryWriter writer)
+ public Assembler(string[] inputLines)
{
- this.Reader = reader;
- this.Writer = writer;
+ this.InputLines = inputLines;
}
- public void Assemble()
+ private void ResolveLabels()
{
- int lineNumber = 0;
- while (this.Reader.ReadLine() is { } line)
+ int offset = 0;
+ int pos = 0;
+ foreach (string line in this.InputLines)
{
- lineNumber++;
- string trimmedLine = line.Split(";")[0].Trim(); // Remove comments
+ string trimmedLine = line.Split(";")[0].Trim();
if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(';'))
continue;
if (trimmedLine.StartsWith(".org"))
{
- // Handle .org directive
string orgValue = trimmedLine[5..].Trim();
- this._addressOffset = this.GetConstant(orgValue);
+ offset = this.GetConstant(orgValue);
}
else if (trimmedLine.StartsWith(".ascii"))
@@ -61,6 +52,7 @@ public class Assembler
{
char c = asciiValue[i];
if (c == '\\')
+ {
c = asciiValue[++i] switch
{
'n' => '\n',
@@ -68,90 +60,173 @@ public class Assembler
'\\' => '\\',
'\'' => '\'',
'"' => '"',
- _ => throw new AssemblerException($"Unknown escape sequence: \\{asciiValue[i]}"),
+ _ => throw new AssemblerException($"Unknown escape sequence: \\{asciiValue[i]}")
};
+ }
- this.Write((u8) c);
+ pos++;
}
}
else if (trimmedLine.StartsWith(".raw"))
{
string[] values = trimmedLine[5..].Split(',');
- foreach (string value in values)
- this.Write(GetConstant(value.Trim()));
+ pos += values.Length * 2; // Each value is 2 bytes
}
-
+
else if (trimmedLine.StartsWith(".include"))
{
string includeFile = trimmedLine[9..].Trim()[1..^1];
if (!File.Exists(includeFile))
- {
- WriteError(line, lineNumber, $"Include file '{includeFile}' not found");
- return;
- }
+ throw new AssemblerException($"Include file '{includeFile}' not found");
- foreach (byte b in File.ReadAllBytes(includeFile))
- this.Writer.Write(b);
+ pos += File.ReadAllBytes(includeFile).Length;
}
else if (trimmedLine.EndsWith(":"))
- this._labels[trimmedLine[..^1]] = (u16) (this.Writer.BaseStream.Position + this._addressOffset);
+ {
+ string label = trimmedLine[..^1].Trim();
+ if (this._labels.ContainsKey(label))
+ throw new AssemblerException($"Label '{label}' already defined");
+ this._labels[label] = (u16) (pos + offset);
+ }
else
+ pos += this.GetInstructionLength(trimmedLine);
+ }
+ }
+
+ public IEnumerable<byte> Assemble()
+ {
+ this.ResolveLabels();
+
+ foreach (string line in this.InputLines)
+ {
+ string trimmedLine = line.Split(";")[0].Trim(); // Remove comments
+ if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(';'))
+ continue;
+
+ if (trimmedLine.StartsWith(".org"))
+ {
+ // Already handled in ResolveLabels
+ }
+
+ else if (trimmedLine.StartsWith(".ascii"))
{
- try
+ string asciiValue = trimmedLine[7..].Trim()
+ [1..^1]; // Remove quotes
+
+ for (int i = 0; i < asciiValue.Length; i++)
{
- this.ParseInstruction(trimmedLine);
+ char c = asciiValue[i];
+ if (c == '\\')
+ {
+ c = asciiValue[++i] switch
+ {
+ 'n' => '\n',
+ 't' => '\t',
+ '\\' => '\\',
+ '\'' => '\'',
+ '"' => '"',
+ _ => throw new AssemblerException($"Unknown escape sequence: \\{asciiValue[i]}")
+ };
+ }
+
+ yield return (byte) c;
}
- catch (AssemblerException ex)
+ }
+
+ else if (trimmedLine.StartsWith(".raw"))
+ {
+ string[] values = trimmedLine[5..].Split(',');
+ foreach (string value in values)
{
- WriteError(line, lineNumber, ex.Message);
- return;
+ u16 c = this.GetConstant(value.Trim());
+
+ yield return c.High();
+ yield return c.Low();
}
}
- }
- foreach ((u16 key, string value) in this._unloadedLabels)
- {
- if (this._labels.TryGetValue(value, out u16 address))
+ else if (trimmedLine.StartsWith(".include"))
{
- Console.WriteLine($"Resolving label '{value}' at address {address:X4} for key {key:X4}");
- this.Writer.BaseStream.Seek(key, SeekOrigin.Begin);
- this.Write(address);
+ string includeFile = trimmedLine[9..].Trim()[1..^1];
+ if (!File.Exists(includeFile))
+ throw new AssemblerException($"Include file '{includeFile}' not found");
+
+ foreach (byte b in File.ReadAllBytes(includeFile))
+ yield return b;
}
- else
+
+ else if (trimmedLine.EndsWith(":"))
{
- WriteError($"", 0, "Label not defined");
+ // Handled in ResolveLabels
}
+
+ else
+ foreach (byte b in this.GetInstructionBytes(trimmedLine))
+ yield return b;
}
}
- private void WriteError(string line, int lineNumber, string message)
+ private int GetInstructionLength(string instruction)
{
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine($"Error on line {lineNumber}: {message}");
- Console.WriteLine($" --> {line}");
- Console.ResetColor();
+ string[] parts = instruction.Split(' ', 2);
+ string opcode = parts[0].ToUpperInvariant();
+
+ parts = parts.Length > 1 ? parts[1].Split(',') : [];
+ if (parts.Length > 2)
+ throw new AssemblerException("Invalid instruction format");
+
+ u8 opcodeValue = this.ResolveOpcode(opcode, parts.Length, out u8 addressingIndex);
+ (u8 m1, u8 m2) = this.ResolveAddressingModes(addressingIndex, parts);
+
+ int length = 2; // Opcode + mode byte
+
+ if (parts.Length > 0)
+ length += this.GetModeLength(m1);
+
+ if (parts.Length > 1)
+ length += this.GetModeLength(m2);
+
+ return length;
}
- private void ParseInstruction(string instruction)
+ private IEnumerable<byte> GetInstructionBytes(string instruction)
{
string[] parts = instruction.Split(' ', 2);
string opcode = parts[0].ToUpperInvariant();
parts = parts.Length > 1 ? parts[1].Split(',') : [];
if (parts.Length > 2)
- throw new AssemblerException($"Invalid instruction format");
+ throw new AssemblerException("Invalid instruction format");
+
+ u8 opcodeValue = this.ResolveOpcode(opcode, parts.Length, out u8 addressingIndex);
+ (u8 m1, u8 m2) = this.ResolveAddressingModes(addressingIndex, parts);
+
+ yield return opcodeValue;
+ yield return (u8) ((m1 << 4) | m2); // Combine m1 and m2 into a single byte
- u8 opcodeValue = this.ParseOpcode(opcode, parts.Length, out u8 addressingIndex);
+ if (parts.Length > 0)
+ {
+ foreach (byte b in this.GetModeBytes(m1, parts[0]))
+ yield return b;
+ }
+ if (parts.Length > 1)
+ {
+ foreach (byte b in this.GetModeBytes(m2, parts[1]))
+ yield return b;
+ }
+ }
+ private (u8 m1, u8 m2) ResolveAddressingModes(u8 addressingIndex, string[] parts)
+ {
u8 m1, m2;
switch (addressingIndex)
{
case 0: // Implicit
if (parts.Length > 0)
- throw new AssemblerException($"Implicit instruction should not have operands");
+ throw new AssemblerException("Implicit instruction should not have operands");
m1 = 0x00;
m2 = 0x00;
@@ -159,17 +234,17 @@ public class Assembler
case 1: // Simple addressing mode
if (parts.Length > 2)
- throw new AssemblerException($"Simple addressing mode should have at most one operand");
+ throw new AssemblerException("Simple addressing mode should have at most one operand");
if (parts.Length == 0)
- throw new AssemblerException($"Simple addressing mode requires an operand");
+ throw new AssemblerException("Simple addressing mode requires an operand");
- m1 = this.ParseMode(parts[0]);
+ m1 = this.ResolveMode(parts[0]);
m2 = 0x00;
break;
case 2: // Extended implicit
if (parts.Length > 0)
- throw new AssemblerException($"Extended implicit instruction should not have operands");
+ throw new AssemblerException("Extended implicit instruction should not have operands");
m1 = 0x00;
m2 = 0x01;
@@ -177,25 +252,19 @@ public class Assembler
case 3: // Dual addressing mode
if (parts.Length != 2)
- throw new AssemblerException($"Dual addressing mode requires exactly two operands");
+ throw new AssemblerException("Dual addressing mode requires exactly two operands");
- m1 = this.ParseMode(parts[0]);
- m2 = this.ParseMode(parts[1]);
+ m1 = this.ResolveMode(parts[0]);
+ m2 = this.ResolveMode(parts[1]);
break;
default:
throw new UnreachableException("Invalid addressing index: " + addressingIndex);
}
-
- this.WriteInstruction(opcodeValue, m1, m2);
-
- if (parts.Length > 0)
- this.WriteMode(m1, parts[0]);
- if (parts.Length > 1)
- this.WriteMode(m2, parts[1]);
+ return (m1, m2);
}
- private u8 ParseOpcode(string opcode, int parts, out u8 addressingIndex)
+ private u8 ResolveOpcode(string opcode, int parts, out u8 addressingIndex)
{
List<int> addressingIndices = new();
u8? opCode = null;
@@ -231,7 +300,7 @@ public class Assembler
return opCode.Value;
}
- private u8 ParseMode(string mode)
+ private u8 ResolveMode(string mode)
{
mode = mode.Trim();
@@ -244,14 +313,10 @@ public class Assembler
}
if (this._labels.ContainsKey(mode))
- {
return 0x01; // Immediate
- }
if (mode.StartsWith("@"))
- {
return 0x03; // Indirect
- }
if (mode.StartsWith("[") && mode.EndsWith("]"))
{
@@ -271,13 +336,7 @@ public class Assembler
return 0x01; // Immediate
}
- private void WriteInstruction(u8 opcode, u8 m1, u8 m2)
- {
- Write(opcode);
- Write((u8) (m1 << 4 | m2)); // Combine m1 and m2 into a single byte
- }
-
- private void WriteMode(u8 mode, string operand)
+ private byte[] GetModeBytes(u8 mode, string operand)
{
operand = operand.Trim();
@@ -285,53 +344,66 @@ public class Assembler
{
case 0x00: // Implicit
// No additional data needed
- break;
+ return [];
case 0x01: // Immediate
u16 immediateValue = this.GetConstant(operand);
- this.Write(immediateValue);
- break;
+ return [immediateValue.High(), immediateValue.Low()];
case 0x02: // Direct
u16 directAddress = this.GetConstant(operand); // Remove brackets
- this.Write(directAddress);
- break;
+ return [directAddress.High(), directAddress.Low()];
case 0x03: // Indirect
u16 indirectAddress = this.GetConstant(operand); // Remove brackets and @
- this.Write(indirectAddress);
- break;
+ return [indirectAddress.High(), indirectAddress.Low()];
case 0x04: // Relative
- i16 relativeOffset = this.GetSignedConstant(operand);
- Write(relativeOffset);
- break;
+ u16 relativeOffset = this.GetConstant(operand);
+ return [relativeOffset.High(), relativeOffset.Low()];
case 0x05: // Register
u8 regIndex = this.GetRegisterIndex(operand);
- Write(regIndex);
- break;
+ return [regIndex];
case 0x06: // Register Indirect
u8 indirectRegIndex = this.GetRegisterIndex(operand); // Remove brackets
- Write(indirectRegIndex);
- break;
+ return [indirectRegIndex];
case 0x07: // Register Indirect with Offset
u8 offsetRegIndex = this.GetRegisterIndex(operand[1..^1].Split('+')[0].Trim());
- i16 offsetValue = this.GetSignedConstant(operand[1..^1].Split('+')[1].Trim());
- Write(offsetRegIndex);
- Write(offsetValue);
- break;
+ u16 offsetValue = this.GetConstant(operand[1..^1].Split('+')[1].Trim());
+ return [offsetRegIndex, offsetValue.High(), offsetValue.Low()];
+
+ default:
+ throw new AssemblerException($"Unknown addressing mode: {mode:X2}");
}
}
+
+ private int GetModeLength(u8 mode)
+ {
+ return mode switch
+ {
+ 0x00 => 0, // Implicit
+ 0x01 => 2, // Immediate
+ 0x02 => 2, // Direct
+ 0x03 => 2, // Indirect
+ 0x04 => 2, // Relative
+ 0x05 => 1, // Register
+ 0x06 => 1, // Register indirect
+ 0x07 => 3, // Register indirect with offset
+ _ => throw new AssemblerException($"Unknown addressing mode: {mode:X2}")
+ };
+ }
private u8 GetRegisterIndex(string reg)
{
reg = this.Clean(reg);
if (reg.StartsWith("V"))
+ {
if (u8.TryParse(reg[1..], out u8 index) && index < 0x3F)
return index;
+ }
if (Assembler.RegisterLookup.ContainsValue(reg))
{
@@ -351,32 +423,15 @@ public class Assembler
u16 x = Convert.ToUInt16(value[1..], 16);
return x;
}
- else if (u16.TryParse(value, out u16 result))
+ if (u16.TryParse(value, out u16 result))
// Decimal constant
return result;
- else
- {
- this._unloadedLabels[(u16) this.Writer.BaseStream.Position] = value;
- return 0;
- }
- }
- private i16 GetSignedConstant(string value)
- {
- value = this.Clean(value);
-
- if (value.StartsWith("$"))
- {
- // Hexadecimal offset
- return Convert.ToInt16(value[1..], 16);
- }
- else if (i16.TryParse(value, out i16 result))
- // Decimal offset
- return result;
- else
- {
- this._unloadedLabels[(u16) this.Writer.BaseStream.Position] = value;
- return 0;
- }
+
+ if (this._labels.TryGetValue(value, out u16 labelAddress))
+ // Label reference
+ return labelAddress;
+
+ return 0;
}
private string Clean(string value)
@@ -389,23 +444,6 @@ public class Assembler
return value.Trim();
}
-
- private void Write(u16 value)
- {
- u16 swappedValue = (u16) ((value >> 8) | (value << 8));
- this.Writer.Write(swappedValue);
- }
-
- private void Write(u8 value)
- {
- this.Writer.Write(value);
- }
-
- private void Write(i16 value)
- {
- u16 swappedValue = (u16) ((value >> 8) | (value << 8));
- this.Writer.Write(swappedValue);
- }
}
public class AssemblerException(string message)
diff --git a/Assembler/Assembler.csproj b/Assembler/Assembler.csproj
new file mode 100644
index 0000000..fd4f4fa
--- /dev/null
+++ b/Assembler/Assembler.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net9.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <RootNamespace>Q1.Assembler</RootNamespace>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\Emulator\Emulator.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="CommandLineParser" Version="2.9.1" />
+ </ItemGroup>
+
+</Project>
diff --git a/Assembler/Extensions.cs b/Assembler/Extensions.cs
new file mode 100644
index 0000000..fd4ea1f
--- /dev/null
+++ b/Assembler/Extensions.cs
@@ -0,0 +1,15 @@
+namespace Q1.Assembler;
+
+public static class Extensions
+{
+
+ public static u8 High(this u16 value)
+ {
+ return (u8)(value >> 8);
+ }
+
+ public static u8 Low(this u16 value)
+ {
+ return (u8)(value & 0xFF);
+ }
+} \ No newline at end of file
diff --git a/GlobalUsings.cs b/Assembler/GlobalUsings.cs
index ff38a75..ff38a75 100644
--- a/GlobalUsings.cs
+++ b/Assembler/GlobalUsings.cs
diff --git a/Assembler/Options.cs b/Assembler/Options.cs
new file mode 100644
index 0000000..dc4efc2
--- /dev/null
+++ b/Assembler/Options.cs
@@ -0,0 +1,12 @@
+namespace Q1.Assembler;
+
+using CommandLine;
+
+public class Options
+{
+ [Option('i', "input", Required = true, HelpText = "Input file to assemble.")]
+ public string InputFile { get; set; }
+
+ [Option('o', "output", Required = true, HelpText = "Output file to write the assembled code.")]
+ public string OutputFile { get; set; }
+} \ No newline at end of file
diff --git a/Assembler/Program.cs b/Assembler/Program.cs
new file mode 100644
index 0000000..b30df1e
--- /dev/null
+++ b/Assembler/Program.cs
@@ -0,0 +1,38 @@
+namespace Q1.Assembler;
+
+using CommandLine;
+
+public class Program
+{
+ static void Main(string[] args)
+ {
+ Parser.Default.ParseArguments<Options>(args).WithParsed(Program.Main);
+ }
+
+ static void Main(Options options)
+ {
+ Environment.CurrentDirectory = Path.GetDirectoryName(options.InputFile) ?? Environment.CurrentDirectory;
+ options.InputFile = Path.GetFileName(options.InputFile);
+
+ string[] input = File.ReadAllLines(options.InputFile);
+
+ try
+ {
+ Assembler assembler = new(input);
+ byte[] bin = assembler.Assemble().ToArray();
+ if (bin.Length > 8 * 1024)
+ throw new AssemblerException("Assembled binary exceeds maximum size of 8KB.");
+
+ File.WriteAllBytes(options.OutputFile, bin);
+
+ Console.WriteLine($"Assembled {options.InputFile} to {options.OutputFile} ({bin.Length} bytes)");
+ }
+ catch (AssemblerException ex)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.Error.WriteLine($"Error: {ex.Message}");
+ Console.ResetColor();
+ Environment.Exit(1);
+ }
+ }
+} \ No newline at end of file
diff --git a/Compiler/CCompilerVisitor.cs b/Compiler/CCompilerVisitor.cs
new file mode 100644
index 0000000..cee69f4
--- /dev/null
+++ b/Compiler/CCompilerVisitor.cs
@@ -0,0 +1,172 @@
+namespace Q1.Compiler;
+
+public class CCompilerVisitor : CGrammarBaseVisitor<string?>
+{
+ private List<string> Instructions = new();
+ public IEnumerable<string> Compile(CGrammarParser.ProgramContext program)
+ {
+ this.Visit(program);
+ return this.Instructions;
+ }
+
+ public override string? VisitFunction(CGrammarParser.FunctionContext context)
+ {
+ string functionName = context.ID().GetText();
+ Instructions.Add($"_{functionName}:");
+ this.VisitChildren(context);
+ this.Instructions.Add("");
+
+ return null;
+ }
+ public override string? VisitParenthesizedExpression(CGrammarParser.ParenthesizedExpressionContext context)
+ {
+ return this.Visit(context.expression());
+ }
+ public override string? VisitReturnStatement(CGrammarParser.ReturnStatementContext context)
+ {
+ if (context.expression() != null)
+ {
+ string? expression = this.Visit(context.expression());
+ if (expression != null)
+ {
+ this.Instructions.Add($"MOV {expression}, V0");
+ Instructions.Add($"RET");
+ }
+ else
+ throw new CompilerException("Return value was not an expression.");
+ }
+ else
+ Instructions.Add("RET");
+
+ return null;
+ }
+ public override string? VisitIntConstant(CGrammarParser.IntConstantContext context)
+ {
+ string valueString = context.INT().GetText();
+ if (int.TryParse(valueString, out int value))
+ return $"{value}";
+ else
+ throw new CompilerException($"Invalid integer value: {valueString}");
+ }
+
+ public override string? VisitNotExpression(CGrammarParser.NotExpressionContext context)
+ {
+ string? value = this.Visit(context.expression());
+ if (value == null)
+ throw new CompilerException("Value for negating was not an expression.");
+
+ this.Instructions.Add($"NOT {value}");
+ return "LX";
+ }
+
+ public override string? VisitInvertExpression(CGrammarParser.InvertExpressionContext context)
+ {
+ string? value = this.Visit(context.expression());
+ if (value == null)
+ throw new CompilerException("Value for inversion was not an expression.");
+
+ this.Instructions.Add($"INV {value}");
+ return "DX";
+ }
+
+ public override string? VisitAddExpression(CGrammarParser.AddExpressionContext context)
+ {
+ string? left = this.Visit(context.left);
+ string? right = this.Visit(context.right);
+
+ if (left == null || right == null)
+ throw new CompilerException("Left or right operand for addition was not an expression.");
+
+ this.Instructions.Add($"ADD {left}, {right}");
+ return "AX";
+ }
+ public override string? VisitSubtractExpression(CGrammarParser.SubtractExpressionContext context)
+ {
+ string? left = this.Visit(context.left);
+ string? right = this.Visit(context.right);
+
+ if (left == null || right == null)
+ throw new CompilerException("Left or right operand for subtraction was not an expression.");
+
+ this.Instructions.Add($"SUB {left}, {right}");
+ return "AX";
+ }
+ public override string? VisitMultiplyExpression(CGrammarParser.MultiplyExpressionContext context)
+ {
+ string? left = this.Visit(context.left);
+ string? right = this.Visit(context.right);
+
+ if (left == null || right == null)
+ throw new CompilerException("Left or right operand for multiplication was not an expression.");
+
+ this.Instructions.Add($"MUL {left}, {right}");
+ return "AX";
+ }
+ public override string? VisitDivideExpression(CGrammarParser.DivideExpressionContext context)
+ {
+ string? left = this.Visit(context.left);
+ string? right = this.Visit(context.right);
+
+ if (left == null || right == null)
+ throw new CompilerException("Left or right operand for division was not an expression.");
+
+ this.Instructions.Add($"DIV {left}, {right}");
+ return "AX";
+ }
+ public override string? VisitModulusExpression(CGrammarParser.ModulusExpressionContext context)
+ {
+ string? left = this.Visit(context.left);
+ string? right = this.Visit(context.right);
+
+ if (left == null || right == null)
+ throw new CompilerException("Left or right operand for modulus was not an expression.");
+
+ this.Instructions.Add($"MOD {left}, {right}");
+ return "AX";
+ }
+
+ public override string? VisitBitwiseXorExpression(CGrammarParser.BitwiseXorExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitLessThanOrEqualExpression(CGrammarParser.LessThanOrEqualExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitNotEqualExpression(CGrammarParser.NotEqualExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitGreaterThanExpression(CGrammarParser.GreaterThanExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitLogicalOrExpression(CGrammarParser.LogicalOrExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitGreaterThanOrEqualExpression(CGrammarParser.GreaterThanOrEqualExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitBitwiseOrExpression(CGrammarParser.BitwiseOrExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitBitwiseAndExpression(CGrammarParser.BitwiseAndExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitLessThanExpression(CGrammarParser.LessThanExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitLogicalAndExpression(CGrammarParser.LogicalAndExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+ public override string? VisitEqualExpression(CGrammarParser.EqualExpressionContext context)
+ {
+ throw new NotImplementedException();
+ }
+} \ No newline at end of file
diff --git a/Compiler/CGrammar.g4 b/Compiler/CGrammar.g4
new file mode 100644
index 0000000..69b2c0a
--- /dev/null
+++ b/Compiler/CGrammar.g4
@@ -0,0 +1,50 @@
+grammar CGrammar;
+
+ID: [a-zA-Z_][a-zA-Z0-9_]*;
+INT: [0-9]+;
+
+program
+ : function EOF
+ ;
+
+function
+ : 'int' ID '(' ')' '{' statement* '}'
+ ;
+
+statement
+ : 'return' expression ';' #returnStatement
+ ;
+
+expression
+ : '(' expression ')' #parenthesizedExpression
+
+ | '!' expression #notExpression
+ | '~' expression #invertExpression
+
+ | left=expression '*' right=expression #multiplyExpression
+ | left=expression '/' right=expression #divideExpression
+ | left=expression '%' right=expression #modulusExpression
+
+ | left=expression '+' right=expression #addExpression
+ | left=expression '-' right=expression #subtractExpression
+
+ | left=expression '<' right=expression #lessThanExpression
+ | left=expression '>' right=expression #greaterThanExpression
+ | left=expression '<=' right=expression #lessThanOrEqualExpression
+ | left=expression '>=' right=expression #greaterThanOrEqualExpression
+ | left=expression '==' right=expression #equalExpression
+ | left=expression '!=' right=expression #notEqualExpression
+
+ | left=expression '&' right=expression #bitwiseAndExpression
+ | left=expression '|' right=expression #bitwiseOrExpression
+ | left=expression '^' right=expression #bitwiseXorExpression
+
+ | left=expression '&&' right=expression #logicalAndExpression
+ | left=expression '||' right=expression #logicalOrExpression
+
+ | constant #constantExpression
+ ;
+
+constant
+ : INT # intConstant
+ ; \ No newline at end of file
diff --git a/Compiler/Compiler.csproj b/Compiler/Compiler.csproj
new file mode 100644
index 0000000..042331e
--- /dev/null
+++ b/Compiler/Compiler.csproj
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net9.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <RootNamespace>Q1.Compiler</RootNamespace>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Antlr4.Runtime.Standard" Version="4.13.1" />
+ <PackageReference Include="CommandLineParser" Version="2.9.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Folder Include="gen\" />
+ </ItemGroup>
+
+</Project>
diff --git a/Compiler/CompilerException.cs b/Compiler/CompilerException.cs
new file mode 100644
index 0000000..f5a78f1
--- /dev/null
+++ b/Compiler/CompilerException.cs
@@ -0,0 +1,4 @@
+namespace Q1.Compiler;
+
+public class CompilerException(string message)
+ : Exception(message); \ No newline at end of file
diff --git a/Compiler/Options.cs b/Compiler/Options.cs
new file mode 100644
index 0000000..c12a4c6
--- /dev/null
+++ b/Compiler/Options.cs
@@ -0,0 +1,12 @@
+namespace Q1.Compiler;
+
+using CommandLine;
+
+public class Options
+{
+ [Option('i', "input", Required = true, HelpText = "Input file to compile.")]
+ public string InputFile { get; set; }
+
+ [Option('o', "output", Required = true, HelpText = "Output file to write the compiled code.")]
+ public string OutputFile { get; set; }
+} \ No newline at end of file
diff --git a/Compiler/Program.cs b/Compiler/Program.cs
new file mode 100644
index 0000000..b832a53
--- /dev/null
+++ b/Compiler/Program.cs
@@ -0,0 +1,31 @@
+namespace Q1.Compiler;
+
+using Antlr4.Runtime;
+using CommandLine;
+using Parser = CommandLine.Parser;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Parser.Default.ParseArguments<Options>(args).WithParsed(Program.Main);
+ }
+
+ static void Main(Options options)
+ {
+ Environment.CurrentDirectory = Path.GetDirectoryName(options.InputFile) ?? Environment.CurrentDirectory;
+ options.InputFile = Path.GetFileName(options.InputFile);
+
+ AntlrFileStream inputStream = new(options.InputFile);
+ CGrammarLexer lexer = new(inputStream);
+ lexer.RemoveErrorListeners();
+
+ CommonTokenStream tokenStream = new(lexer);
+ CGrammarParser parser = new(tokenStream);
+ parser.RemoveErrorListeners();
+
+ CCompilerVisitor compiler = new();
+ var result = compiler.Compile(parser.program());
+ File.WriteAllLines(options.OutputFile, result);
+ }
+} \ No newline at end of file
diff --git a/Compiler/gen/CGrammar.interp b/Compiler/gen/CGrammar.interp
new file mode 100644
index 0000000..d5453b2
--- /dev/null
+++ b/Compiler/gen/CGrammar.interp
@@ -0,0 +1,70 @@
+token literal names:
+null
+'int'
+'('
+')'
+'{'
+'}'
+'return'
+';'
+'!'
+'~'
+'*'
+'/'
+'%'
+'+'
+'-'
+'<'
+'>'
+'<='
+'>='
+'=='
+'!='
+'&'
+'|'
+'^'
+'&&'
+'||'
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+ID
+INT
+
+rule names:
+program
+function
+statement
+expression
+constant
+
+
+atn:
+[4, 1, 27, 98, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 20, 8, 1, 10, 1, 12, 1, 23, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 41, 8, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 91, 8, 3, 10, 3, 12, 3, 94, 9, 3, 1, 4, 1, 4, 1, 4, 0, 1, 6, 5, 0, 2, 4, 6, 8, 0, 0, 112, 0, 10, 1, 0, 0, 0, 2, 13, 1, 0, 0, 0, 4, 26, 1, 0, 0, 0, 6, 40, 1, 0, 0, 0, 8, 95, 1, 0, 0, 0, 10, 11, 3, 2, 1, 0, 11, 12, 5, 0, 0, 1, 12, 1, 1, 0, 0, 0, 13, 14, 5, 1, 0, 0, 14, 15, 5, 26, 0, 0, 15, 16, 5, 2, 0, 0, 16, 17, 5, 3, 0, 0, 17, 21, 5, 4, 0, 0, 18, 20, 3, 4, 2, 0, 19, 18, 1, 0, 0, 0, 20, 23, 1, 0, 0, 0, 21, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 24, 1, 0, 0, 0, 23, 21, 1, 0, 0, 0, 24, 25, 5, 5, 0, 0, 25, 3, 1, 0, 0, 0, 26, 27, 5, 6, 0, 0, 27, 28, 3, 6, 3, 0, 28, 29, 5, 7, 0, 0, 29, 5, 1, 0, 0, 0, 30, 31, 6, 3, -1, 0, 31, 32, 5, 2, 0, 0, 32, 33, 3, 6, 3, 0, 33, 34, 5, 3, 0, 0, 34, 41, 1, 0, 0, 0, 35, 36, 5, 8, 0, 0, 36, 41, 3, 6, 3, 19, 37, 38, 5, 9, 0, 0, 38, 41, 3, 6, 3, 18, 39, 41, 3, 8, 4, 0, 40, 30, 1, 0, 0, 0, 40, 35, 1, 0, 0, 0, 40, 37, 1, 0, 0, 0, 40, 39, 1, 0, 0, 0, 41, 92, 1, 0, 0, 0, 42, 43, 10, 17, 0, 0, 43, 44, 5, 10, 0, 0, 44, 91, 3, 6, 3, 18, 45, 46, 10, 16, 0, 0, 46, 47, 5, 11, 0, 0, 47, 91, 3, 6, 3, 17, 48, 49, 10, 15, 0, 0, 49, 50, 5, 12, 0, 0, 50, 91, 3, 6, 3, 16, 51, 52, 10, 14, 0, 0, 52, 53, 5, 13, 0, 0, 53, 91, 3, 6, 3, 15, 54, 55, 10, 13, 0, 0, 55, 56, 5, 14, 0, 0, 56, 91, 3, 6, 3, 14, 57, 58, 10, 12, 0, 0, 58, 59, 5, 15, 0, 0, 59, 91, 3, 6, 3, 13, 60, 61, 10, 11, 0, 0, 61, 62, 5, 16, 0, 0, 62, 91, 3, 6, 3, 12, 63, 64, 10, 10, 0, 0, 64, 65, 5, 17, 0, 0, 65, 91, 3, 6, 3, 11, 66, 67, 10, 9, 0, 0, 67, 68, 5, 18, 0, 0, 68, 91, 3, 6, 3, 10, 69, 70, 10, 8, 0, 0, 70, 71, 5, 19, 0, 0, 71, 91, 3, 6, 3, 9, 72, 73, 10, 7, 0, 0, 73, 74, 5, 20, 0, 0, 74, 91, 3, 6, 3, 8, 75, 76, 10, 6, 0, 0, 76, 77, 5, 21, 0, 0, 77, 91, 3, 6, 3, 7, 78, 79, 10, 5, 0, 0, 79, 80, 5, 22, 0, 0, 80, 91, 3, 6, 3, 6, 81, 82, 10, 4, 0, 0, 82, 83, 5, 23, 0, 0, 83, 91, 3, 6, 3, 5, 84, 85, 10, 3, 0, 0, 85, 86, 5, 24, 0, 0, 86, 91, 3, 6, 3, 4, 87, 88, 10, 2, 0, 0, 88, 89, 5, 25, 0, 0, 89, 91, 3, 6, 3, 3, 90, 42, 1, 0, 0, 0, 90, 45, 1, 0, 0, 0, 90, 48, 1, 0, 0, 0, 90, 51, 1, 0, 0, 0, 90, 54, 1, 0, 0, 0, 90, 57, 1, 0, 0, 0, 90, 60, 1, 0, 0, 0, 90, 63, 1, 0, 0, 0, 90, 66, 1, 0, 0, 0, 90, 69, 1, 0, 0, 0, 90, 72, 1, 0, 0, 0, 90, 75, 1, 0, 0, 0, 90, 78, 1, 0, 0, 0, 90, 81, 1, 0, 0, 0, 90, 84, 1, 0, 0, 0, 90, 87, 1, 0, 0, 0, 91, 94, 1, 0, 0, 0, 92, 90, 1, 0, 0, 0, 92, 93, 1, 0, 0, 0, 93, 7, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 95, 96, 5, 27, 0, 0, 96, 9, 1, 0, 0, 0, 4, 21, 40, 90, 92] \ No newline at end of file
diff --git a/Compiler/gen/CGrammar.tokens b/Compiler/gen/CGrammar.tokens
new file mode 100644
index 0000000..fc1a392
--- /dev/null
+++ b/Compiler/gen/CGrammar.tokens
@@ -0,0 +1,52 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+T__22=23
+T__23=24
+T__24=25
+ID=26
+INT=27
+'int'=1
+'('=2
+')'=3
+'{'=4
+'}'=5
+'return'=6
+';'=7
+'!'=8
+'~'=9
+'*'=10
+'/'=11
+'%'=12
+'+'=13
+'-'=14
+'<'=15
+'>'=16
+'<='=17
+'>='=18
+'=='=19
+'!='=20
+'&'=21
+'|'=22
+'^'=23
+'&&'=24
+'||'=25
diff --git a/Compiler/gen/CGrammarBaseVisitor.cs b/Compiler/gen/CGrammarBaseVisitor.cs
new file mode 100644
index 0000000..1f864c3
--- /dev/null
+++ b/Compiler/gen/CGrammarBaseVisitor.cs
@@ -0,0 +1,299 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// ANTLR Version: 4.13.2
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+// Generated from /Users/melodidey/Source/csharp/Q1/Compiler/CGrammar.g4 by ANTLR 4.13.2
+
+// Unreachable code detected
+#pragma warning disable 0162
+// The variable '...' is assigned but its value is never used
+#pragma warning disable 0219
+// Missing XML comment for publicly visible type or member '...'
+#pragma warning disable 1591
+// Ambiguous reference in cref attribute
+#pragma warning disable 419
+
+using Antlr4.Runtime.Misc;
+using Antlr4.Runtime.Tree;
+using IToken = Antlr4.Runtime.IToken;
+using ParserRuleContext = Antlr4.Runtime.ParserRuleContext;
+
+/// <summary>
+/// This class provides an empty implementation of <see cref="ICGrammarVisitor{Result}"/>,
+/// which can be extended to create a visitor which only needs to handle a subset
+/// of the available methods.
+/// </summary>
+/// <typeparam name="Result">The return type of the visit operation.</typeparam>
+[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.13.2")]
+[System.Diagnostics.DebuggerNonUserCode]
+[System.CLSCompliant(false)]
+public partial class CGrammarBaseVisitor<Result> : AbstractParseTreeVisitor<Result>, ICGrammarVisitor<Result> {
+ /// <summary>
+ /// Visit a parse tree produced by <see cref="CGrammarParser.program"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitProgram([NotNull] CGrammarParser.ProgramContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by <see cref="CGrammarParser.function"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitFunction([NotNull] CGrammarParser.FunctionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>returnStatement</c>
+ /// labeled alternative in <see cref="CGrammarParser.statement"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitReturnStatement([NotNull] CGrammarParser.ReturnStatementContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseXorExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitBitwiseXorExpression([NotNull] CGrammarParser.BitwiseXorExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>constantExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitConstantExpression([NotNull] CGrammarParser.ConstantExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>lessThanOrEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitLessThanOrEqualExpression([NotNull] CGrammarParser.LessThanOrEqualExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>modulusExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitModulusExpression([NotNull] CGrammarParser.ModulusExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>notExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitNotExpression([NotNull] CGrammarParser.NotExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>notEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitNotEqualExpression([NotNull] CGrammarParser.NotEqualExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>multiplyExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitMultiplyExpression([NotNull] CGrammarParser.MultiplyExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>greaterThanExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitGreaterThanExpression([NotNull] CGrammarParser.GreaterThanExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>logicalOrExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitLogicalOrExpression([NotNull] CGrammarParser.LogicalOrExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>greaterThanOrEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitGreaterThanOrEqualExpression([NotNull] CGrammarParser.GreaterThanOrEqualExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>divideExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitDivideExpression([NotNull] CGrammarParser.DivideExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseOrExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitBitwiseOrExpression([NotNull] CGrammarParser.BitwiseOrExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>parenthesizedExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitParenthesizedExpression([NotNull] CGrammarParser.ParenthesizedExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>addExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitAddExpression([NotNull] CGrammarParser.AddExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>subtractExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitSubtractExpression([NotNull] CGrammarParser.SubtractExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseAndExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitBitwiseAndExpression([NotNull] CGrammarParser.BitwiseAndExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>lessThanExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitLessThanExpression([NotNull] CGrammarParser.LessThanExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>logicalAndExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitLogicalAndExpression([NotNull] CGrammarParser.LogicalAndExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>invertExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitInvertExpression([NotNull] CGrammarParser.InvertExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>equalExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitEqualExpression([NotNull] CGrammarParser.EqualExpressionContext context) { return VisitChildren(context); }
+ /// <summary>
+ /// Visit a parse tree produced by the <c>intConstant</c>
+ /// labeled alternative in <see cref="CGrammarParser.constant"/>.
+ /// <para>
+ /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
+ /// on <paramref name="context"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ public virtual Result VisitIntConstant([NotNull] CGrammarParser.IntConstantContext context) { return VisitChildren(context); }
+}
diff --git a/Compiler/gen/CGrammarLexer.cs b/Compiler/gen/CGrammarLexer.cs
new file mode 100644
index 0000000..3bb49f2
--- /dev/null
+++ b/Compiler/gen/CGrammarLexer.cs
@@ -0,0 +1,149 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// ANTLR Version: 4.13.2
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+// Generated from /Users/melodidey/Source/csharp/Q1/Compiler/CGrammar.g4 by ANTLR 4.13.2
+
+// Unreachable code detected
+#pragma warning disable 0162
+// The variable '...' is assigned but its value is never used
+#pragma warning disable 0219
+// Missing XML comment for publicly visible type or member '...'
+#pragma warning disable 1591
+// Ambiguous reference in cref attribute
+#pragma warning disable 419
+
+using System;
+using System.IO;
+using System.Text;
+using Antlr4.Runtime;
+using Antlr4.Runtime.Atn;
+using Antlr4.Runtime.Misc;
+using DFA = Antlr4.Runtime.Dfa.DFA;
+
+[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.13.2")]
+[System.CLSCompliant(false)]
+public partial class CGrammarLexer : Lexer {
+ protected static DFA[] decisionToDFA;
+ protected static PredictionContextCache sharedContextCache = new PredictionContextCache();
+ public const int
+ T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9,
+ T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17,
+ T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24,
+ T__24=25, ID=26, INT=27;
+ public static string[] channelNames = {
+ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
+ };
+
+ public static string[] modeNames = {
+ "DEFAULT_MODE"
+ };
+
+ public static readonly string[] ruleNames = {
+ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8",
+ "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16",
+ "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24",
+ "ID", "INT"
+ };
+
+
+ public CGrammarLexer(ICharStream input)
+ : this(input, Console.Out, Console.Error) { }
+
+ public CGrammarLexer(ICharStream input, TextWriter output, TextWriter errorOutput)
+ : base(input, output, errorOutput)
+ {
+ Interpreter = new LexerATNSimulator(this, _ATN, decisionToDFA, sharedContextCache);
+ }
+
+ private static readonly string[] _LiteralNames = {
+ null, "'int'", "'('", "')'", "'{'", "'}'", "'return'", "';'", "'!'", "'~'",
+ "'*'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'<='", "'>='", "'=='",
+ "'!='", "'&'", "'|'", "'^'", "'&&'", "'||'"
+ };
+ private static readonly string[] _SymbolicNames = {
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, "ID", "INT"
+ };
+ public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames);
+
+ [NotNull]
+ public override IVocabulary Vocabulary
+ {
+ get
+ {
+ return DefaultVocabulary;
+ }
+ }
+
+ public override string GrammarFileName { get { return "CGrammar.g4"; } }
+
+ public override string[] RuleNames { get { return ruleNames; } }
+
+ public override string[] ChannelNames { get { return channelNames; } }
+
+ public override string[] ModeNames { get { return modeNames; } }
+
+ public override int[] SerializedAtn { get { return _serializedATN; } }
+
+ static CGrammarLexer() {
+ decisionToDFA = new DFA[_ATN.NumberOfDecisions];
+ for (int i = 0; i < _ATN.NumberOfDecisions; i++) {
+ decisionToDFA[i] = new DFA(_ATN.GetDecisionState(i), i);
+ }
+ }
+ private static int[] _serializedATN = {
+ 4,0,27,130,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
+ 6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,
+ 7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,
+ 7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,1,0,1,0,1,0,1,0,
+ 1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,
+ 7,1,7,1,8,1,8,1,9,1,9,1,10,1,10,1,11,1,11,1,12,1,12,1,13,1,13,1,14,1,14,
+ 1,15,1,15,1,16,1,16,1,16,1,17,1,17,1,17,1,18,1,18,1,18,1,19,1,19,1,19,
+ 1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,1,24,1,24,1,24,1,25,1,25,
+ 5,25,121,8,25,10,25,12,25,124,9,25,1,26,4,26,127,8,26,11,26,12,26,128,
+ 0,0,27,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,
+ 27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,
+ 51,26,53,27,1,0,3,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,
+ 1,0,48,57,131,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,
+ 0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,
+ 21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,
+ 0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,
+ 0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,
+ 1,0,0,0,1,55,1,0,0,0,3,59,1,0,0,0,5,61,1,0,0,0,7,63,1,0,0,0,9,65,1,0,0,
+ 0,11,67,1,0,0,0,13,74,1,0,0,0,15,76,1,0,0,0,17,78,1,0,0,0,19,80,1,0,0,
+ 0,21,82,1,0,0,0,23,84,1,0,0,0,25,86,1,0,0,0,27,88,1,0,0,0,29,90,1,0,0,
+ 0,31,92,1,0,0,0,33,94,1,0,0,0,35,97,1,0,0,0,37,100,1,0,0,0,39,103,1,0,
+ 0,0,41,106,1,0,0,0,43,108,1,0,0,0,45,110,1,0,0,0,47,112,1,0,0,0,49,115,
+ 1,0,0,0,51,118,1,0,0,0,53,126,1,0,0,0,55,56,5,105,0,0,56,57,5,110,0,0,
+ 57,58,5,116,0,0,58,2,1,0,0,0,59,60,5,40,0,0,60,4,1,0,0,0,61,62,5,41,0,
+ 0,62,6,1,0,0,0,63,64,5,123,0,0,64,8,1,0,0,0,65,66,5,125,0,0,66,10,1,0,
+ 0,0,67,68,5,114,0,0,68,69,5,101,0,0,69,70,5,116,0,0,70,71,5,117,0,0,71,
+ 72,5,114,0,0,72,73,5,110,0,0,73,12,1,0,0,0,74,75,5,59,0,0,75,14,1,0,0,
+ 0,76,77,5,33,0,0,77,16,1,0,0,0,78,79,5,126,0,0,79,18,1,0,0,0,80,81,5,42,
+ 0,0,81,20,1,0,0,0,82,83,5,47,0,0,83,22,1,0,0,0,84,85,5,37,0,0,85,24,1,
+ 0,0,0,86,87,5,43,0,0,87,26,1,0,0,0,88,89,5,45,0,0,89,28,1,0,0,0,90,91,
+ 5,60,0,0,91,30,1,0,0,0,92,93,5,62,0,0,93,32,1,0,0,0,94,95,5,60,0,0,95,
+ 96,5,61,0,0,96,34,1,0,0,0,97,98,5,62,0,0,98,99,5,61,0,0,99,36,1,0,0,0,
+ 100,101,5,61,0,0,101,102,5,61,0,0,102,38,1,0,0,0,103,104,5,33,0,0,104,
+ 105,5,61,0,0,105,40,1,0,0,0,106,107,5,38,0,0,107,42,1,0,0,0,108,109,5,
+ 124,0,0,109,44,1,0,0,0,110,111,5,94,0,0,111,46,1,0,0,0,112,113,5,38,0,
+ 0,113,114,5,38,0,0,114,48,1,0,0,0,115,116,5,124,0,0,116,117,5,124,0,0,
+ 117,50,1,0,0,0,118,122,7,0,0,0,119,121,7,1,0,0,120,119,1,0,0,0,121,124,
+ 1,0,0,0,122,120,1,0,0,0,122,123,1,0,0,0,123,52,1,0,0,0,124,122,1,0,0,0,
+ 125,127,7,2,0,0,126,125,1,0,0,0,127,128,1,0,0,0,128,126,1,0,0,0,128,129,
+ 1,0,0,0,129,54,1,0,0,0,3,0,122,128,0
+ };
+
+ public static readonly ATN _ATN =
+ new ATNDeserializer().Deserialize(_serializedATN);
+
+
+}
diff --git a/Compiler/gen/CGrammarLexer.interp b/Compiler/gen/CGrammarLexer.interp
new file mode 100644
index 0000000..d041f13
--- /dev/null
+++ b/Compiler/gen/CGrammarLexer.interp
@@ -0,0 +1,98 @@
+token literal names:
+null
+'int'
+'('
+')'
+'{'
+'}'
+'return'
+';'
+'!'
+'~'
+'*'
+'/'
+'%'
+'+'
+'-'
+'<'
+'>'
+'<='
+'>='
+'=='
+'!='
+'&'
+'|'
+'^'
+'&&'
+'||'
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+ID
+INT
+
+rule names:
+T__0
+T__1
+T__2
+T__3
+T__4
+T__5
+T__6
+T__7
+T__8
+T__9
+T__10
+T__11
+T__12
+T__13
+T__14
+T__15
+T__16
+T__17
+T__18
+T__19
+T__20
+T__21
+T__22
+T__23
+T__24
+ID
+INT
+
+channel names:
+DEFAULT_TOKEN_CHANNEL
+HIDDEN
+
+mode names:
+DEFAULT_MODE
+
+atn:
+[4, 0, 27, 130, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 5, 25, 121, 8, 25, 10, 25, 12, 25, 124, 9, 25, 1, 26, 4, 26, 127, 8, 26, 11, 26, 12, 26, 128, 0, 0, 27, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 1, 0, 3, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 1, 0, 48, 57, 131, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 1, 55, 1, 0, 0, 0, 3, 59, 1, 0, 0, 0, 5, 61, 1, 0, 0, 0, 7, 63, 1, 0, 0, 0, 9, 65, 1, 0, 0, 0, 11, 67, 1, 0, 0, 0, 13, 74, 1, 0, 0, 0, 15, 76, 1, 0, 0, 0, 17, 78, 1, 0, 0, 0, 19, 80, 1, 0, 0, 0, 21, 82, 1, 0, 0, 0, 23, 84, 1, 0, 0, 0, 25, 86, 1, 0, 0, 0, 27, 88, 1, 0, 0, 0, 29, 90, 1, 0, 0, 0, 31, 92, 1, 0, 0, 0, 33, 94, 1, 0, 0, 0, 35, 97, 1, 0, 0, 0, 37, 100, 1, 0, 0, 0, 39, 103, 1, 0, 0, 0, 41, 106, 1, 0, 0, 0, 43, 108, 1, 0, 0, 0, 45, 110, 1, 0, 0, 0, 47, 112, 1, 0, 0, 0, 49, 115, 1, 0, 0, 0, 51, 118, 1, 0, 0, 0, 53, 126, 1, 0, 0, 0, 55, 56, 5, 105, 0, 0, 56, 57, 5, 110, 0, 0, 57, 58, 5, 116, 0, 0, 58, 2, 1, 0, 0, 0, 59, 60, 5, 40, 0, 0, 60, 4, 1, 0, 0, 0, 61, 62, 5, 41, 0, 0, 62, 6, 1, 0, 0, 0, 63, 64, 5, 123, 0, 0, 64, 8, 1, 0, 0, 0, 65, 66, 5, 125, 0, 0, 66, 10, 1, 0, 0, 0, 67, 68, 5, 114, 0, 0, 68, 69, 5, 101, 0, 0, 69, 70, 5, 116, 0, 0, 70, 71, 5, 117, 0, 0, 71, 72, 5, 114, 0, 0, 72, 73, 5, 110, 0, 0, 73, 12, 1, 0, 0, 0, 74, 75, 5, 59, 0, 0, 75, 14, 1, 0, 0, 0, 76, 77, 5, 33, 0, 0, 77, 16, 1, 0, 0, 0, 78, 79, 5, 126, 0, 0, 79, 18, 1, 0, 0, 0, 80, 81, 5, 42, 0, 0, 81, 20, 1, 0, 0, 0, 82, 83, 5, 47, 0, 0, 83, 22, 1, 0, 0, 0, 84, 85, 5, 37, 0, 0, 85, 24, 1, 0, 0, 0, 86, 87, 5, 43, 0, 0, 87, 26, 1, 0, 0, 0, 88, 89, 5, 45, 0, 0, 89, 28, 1, 0, 0, 0, 90, 91, 5, 60, 0, 0, 91, 30, 1, 0, 0, 0, 92, 93, 5, 62, 0, 0, 93, 32, 1, 0, 0, 0, 94, 95, 5, 60, 0, 0, 95, 96, 5, 61, 0, 0, 96, 34, 1, 0, 0, 0, 97, 98, 5, 62, 0, 0, 98, 99, 5, 61, 0, 0, 99, 36, 1, 0, 0, 0, 100, 101, 5, 61, 0, 0, 101, 102, 5, 61, 0, 0, 102, 38, 1, 0, 0, 0, 103, 104, 5, 33, 0, 0, 104, 105, 5, 61, 0, 0, 105, 40, 1, 0, 0, 0, 106, 107, 5, 38, 0, 0, 107, 42, 1, 0, 0, 0, 108, 109, 5, 124, 0, 0, 109, 44, 1, 0, 0, 0, 110, 111, 5, 94, 0, 0, 111, 46, 1, 0, 0, 0, 112, 113, 5, 38, 0, 0, 113, 114, 5, 38, 0, 0, 114, 48, 1, 0, 0, 0, 115, 116, 5, 124, 0, 0, 116, 117, 5, 124, 0, 0, 117, 50, 1, 0, 0, 0, 118, 122, 7, 0, 0, 0, 119, 121, 7, 1, 0, 0, 120, 119, 1, 0, 0, 0, 121, 124, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 52, 1, 0, 0, 0, 124, 122, 1, 0, 0, 0, 125, 127, 7, 2, 0, 0, 126, 125, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 54, 1, 0, 0, 0, 3, 0, 122, 128, 0] \ No newline at end of file
diff --git a/Compiler/gen/CGrammarLexer.tokens b/Compiler/gen/CGrammarLexer.tokens
new file mode 100644
index 0000000..fc1a392
--- /dev/null
+++ b/Compiler/gen/CGrammarLexer.tokens
@@ -0,0 +1,52 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+T__22=23
+T__23=24
+T__24=25
+ID=26
+INT=27
+'int'=1
+'('=2
+')'=3
+'{'=4
+'}'=5
+'return'=6
+';'=7
+'!'=8
+'~'=9
+'*'=10
+'/'=11
+'%'=12
+'+'=13
+'-'=14
+'<'=15
+'>'=16
+'<='=17
+'>='=18
+'=='=19
+'!='=20
+'&'=21
+'|'=22
+'^'=23
+'&&'=24
+'||'=25
diff --git a/Compiler/gen/CGrammarParser.cs b/Compiler/gen/CGrammarParser.cs
new file mode 100644
index 0000000..88f1740
--- /dev/null
+++ b/Compiler/gen/CGrammarParser.cs
@@ -0,0 +1,1006 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// ANTLR Version: 4.13.2
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+// Generated from /Users/melodidey/Source/csharp/Q1/Compiler/CGrammar.g4 by ANTLR 4.13.2
+
+// Unreachable code detected
+#pragma warning disable 0162
+// The variable '...' is assigned but its value is never used
+#pragma warning disable 0219
+// Missing XML comment for publicly visible type or member '...'
+#pragma warning disable 1591
+// Ambiguous reference in cref attribute
+#pragma warning disable 419
+
+using System;
+using System.IO;
+using System.Text;
+using System.Diagnostics;
+using System.Collections.Generic;
+using Antlr4.Runtime;
+using Antlr4.Runtime.Atn;
+using Antlr4.Runtime.Misc;
+using Antlr4.Runtime.Tree;
+using DFA = Antlr4.Runtime.Dfa.DFA;
+
+[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.13.2")]
+[System.CLSCompliant(false)]
+public partial class CGrammarParser : Parser {
+ protected static DFA[] decisionToDFA;
+ protected static PredictionContextCache sharedContextCache = new PredictionContextCache();
+ public const int
+ T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9,
+ T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17,
+ T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24,
+ T__24=25, ID=26, INT=27;
+ public const int
+ RULE_program = 0, RULE_function = 1, RULE_statement = 2, RULE_expression = 3,
+ RULE_constant = 4;
+ public static readonly string[] ruleNames = {
+ "program", "function", "statement", "expression", "constant"
+ };
+
+ private static readonly string[] _LiteralNames = {
+ null, "'int'", "'('", "')'", "'{'", "'}'", "'return'", "';'", "'!'", "'~'",
+ "'*'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'<='", "'>='", "'=='",
+ "'!='", "'&'", "'|'", "'^'", "'&&'", "'||'"
+ };
+ private static readonly string[] _SymbolicNames = {
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, "ID", "INT"
+ };
+ public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames);
+
+ [NotNull]
+ public override IVocabulary Vocabulary
+ {
+ get
+ {
+ return DefaultVocabulary;
+ }
+ }
+
+ public override string GrammarFileName { get { return "CGrammar.g4"; } }
+
+ public override string[] RuleNames { get { return ruleNames; } }
+
+ public override int[] SerializedAtn { get { return _serializedATN; } }
+
+ static CGrammarParser() {
+ decisionToDFA = new DFA[_ATN.NumberOfDecisions];
+ for (int i = 0; i < _ATN.NumberOfDecisions; i++) {
+ decisionToDFA[i] = new DFA(_ATN.GetDecisionState(i), i);
+ }
+ }
+
+ public CGrammarParser(ITokenStream input) : this(input, Console.Out, Console.Error) { }
+
+ public CGrammarParser(ITokenStream input, TextWriter output, TextWriter errorOutput)
+ : base(input, output, errorOutput)
+ {
+ Interpreter = new ParserATNSimulator(this, _ATN, decisionToDFA, sharedContextCache);
+ }
+
+ public partial class ProgramContext : ParserRuleContext {
+ [System.Diagnostics.DebuggerNonUserCode] public FunctionContext function() {
+ return GetRuleContext<FunctionContext>(0);
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ITerminalNode Eof() { return GetToken(CGrammarParser.Eof, 0); }
+ public ProgramContext(ParserRuleContext parent, int invokingState)
+ : base(parent, invokingState)
+ {
+ }
+ public override int RuleIndex { get { return RULE_program; } }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitProgram(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+
+ [RuleVersion(0)]
+ public ProgramContext program() {
+ ProgramContext _localctx = new ProgramContext(Context, State);
+ EnterRule(_localctx, 0, RULE_program);
+ try {
+ EnterOuterAlt(_localctx, 1);
+ {
+ State = 10;
+ function();
+ State = 11;
+ Match(Eof);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ ErrorHandler.ReportError(this, re);
+ ErrorHandler.Recover(this, re);
+ }
+ finally {
+ ExitRule();
+ }
+ return _localctx;
+ }
+
+ public partial class FunctionContext : ParserRuleContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ITerminalNode ID() { return GetToken(CGrammarParser.ID, 0); }
+ [System.Diagnostics.DebuggerNonUserCode] public StatementContext[] statement() {
+ return GetRuleContexts<StatementContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public StatementContext statement(int i) {
+ return GetRuleContext<StatementContext>(i);
+ }
+ public FunctionContext(ParserRuleContext parent, int invokingState)
+ : base(parent, invokingState)
+ {
+ }
+ public override int RuleIndex { get { return RULE_function; } }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitFunction(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+
+ [RuleVersion(0)]
+ public FunctionContext function() {
+ FunctionContext _localctx = new FunctionContext(Context, State);
+ EnterRule(_localctx, 2, RULE_function);
+ int _la;
+ try {
+ EnterOuterAlt(_localctx, 1);
+ {
+ State = 13;
+ Match(T__0);
+ State = 14;
+ Match(ID);
+ State = 15;
+ Match(T__1);
+ State = 16;
+ Match(T__2);
+ State = 17;
+ Match(T__3);
+ State = 21;
+ ErrorHandler.Sync(this);
+ _la = TokenStream.LA(1);
+ while (_la==T__5) {
+ {
+ {
+ State = 18;
+ statement();
+ }
+ }
+ State = 23;
+ ErrorHandler.Sync(this);
+ _la = TokenStream.LA(1);
+ }
+ State = 24;
+ Match(T__4);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ ErrorHandler.ReportError(this, re);
+ ErrorHandler.Recover(this, re);
+ }
+ finally {
+ ExitRule();
+ }
+ return _localctx;
+ }
+
+ public partial class StatementContext : ParserRuleContext {
+ public StatementContext(ParserRuleContext parent, int invokingState)
+ : base(parent, invokingState)
+ {
+ }
+ public override int RuleIndex { get { return RULE_statement; } }
+
+ public StatementContext() { }
+ public virtual void CopyFrom(StatementContext context) {
+ base.CopyFrom(context);
+ }
+ }
+ public partial class ReturnStatementContext : StatementContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression() {
+ return GetRuleContext<ExpressionContext>(0);
+ }
+ public ReturnStatementContext(StatementContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitReturnStatement(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+
+ [RuleVersion(0)]
+ public StatementContext statement() {
+ StatementContext _localctx = new StatementContext(Context, State);
+ EnterRule(_localctx, 4, RULE_statement);
+ try {
+ _localctx = new ReturnStatementContext(_localctx);
+ EnterOuterAlt(_localctx, 1);
+ {
+ State = 26;
+ Match(T__5);
+ State = 27;
+ expression(0);
+ State = 28;
+ Match(T__6);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ ErrorHandler.ReportError(this, re);
+ ErrorHandler.Recover(this, re);
+ }
+ finally {
+ ExitRule();
+ }
+ return _localctx;
+ }
+
+ public partial class ExpressionContext : ParserRuleContext {
+ public ExpressionContext(ParserRuleContext parent, int invokingState)
+ : base(parent, invokingState)
+ {
+ }
+ public override int RuleIndex { get { return RULE_expression; } }
+
+ public ExpressionContext() { }
+ public virtual void CopyFrom(ExpressionContext context) {
+ base.CopyFrom(context);
+ }
+ }
+ public partial class BitwiseXorExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public BitwiseXorExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitBitwiseXorExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class ConstantExpressionContext : ExpressionContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ConstantContext constant() {
+ return GetRuleContext<ConstantContext>(0);
+ }
+ public ConstantExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitConstantExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class LessThanOrEqualExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public LessThanOrEqualExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitLessThanOrEqualExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class ModulusExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public ModulusExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitModulusExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class NotExpressionContext : ExpressionContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression() {
+ return GetRuleContext<ExpressionContext>(0);
+ }
+ public NotExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitNotExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class NotEqualExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public NotEqualExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitNotEqualExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class MultiplyExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public MultiplyExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitMultiplyExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class GreaterThanExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public GreaterThanExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitGreaterThanExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class LogicalOrExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public LogicalOrExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitLogicalOrExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class GreaterThanOrEqualExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public GreaterThanOrEqualExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitGreaterThanOrEqualExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class DivideExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public DivideExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitDivideExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class BitwiseOrExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public BitwiseOrExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitBitwiseOrExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class ParenthesizedExpressionContext : ExpressionContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression() {
+ return GetRuleContext<ExpressionContext>(0);
+ }
+ public ParenthesizedExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitParenthesizedExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class AddExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public AddExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitAddExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class SubtractExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public SubtractExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitSubtractExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class BitwiseAndExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public BitwiseAndExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitBitwiseAndExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class LessThanExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public LessThanExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitLessThanExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class LogicalAndExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public LogicalAndExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitLogicalAndExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class InvertExpressionContext : ExpressionContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression() {
+ return GetRuleContext<ExpressionContext>(0);
+ }
+ public InvertExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitInvertExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+ public partial class EqualExpressionContext : ExpressionContext {
+ public ExpressionContext left;
+ public ExpressionContext right;
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext[] expression() {
+ return GetRuleContexts<ExpressionContext>();
+ }
+ [System.Diagnostics.DebuggerNonUserCode] public ExpressionContext expression(int i) {
+ return GetRuleContext<ExpressionContext>(i);
+ }
+ public EqualExpressionContext(ExpressionContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitEqualExpression(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+
+ [RuleVersion(0)]
+ public ExpressionContext expression() {
+ return expression(0);
+ }
+
+ private ExpressionContext expression(int _p) {
+ ParserRuleContext _parentctx = Context;
+ int _parentState = State;
+ ExpressionContext _localctx = new ExpressionContext(Context, _parentState);
+ ExpressionContext _prevctx = _localctx;
+ int _startState = 6;
+ EnterRecursionRule(_localctx, 6, RULE_expression, _p);
+ try {
+ int _alt;
+ EnterOuterAlt(_localctx, 1);
+ {
+ State = 40;
+ ErrorHandler.Sync(this);
+ switch (TokenStream.LA(1)) {
+ case T__1:
+ {
+ _localctx = new ParenthesizedExpressionContext(_localctx);
+ Context = _localctx;
+ _prevctx = _localctx;
+
+ State = 31;
+ Match(T__1);
+ State = 32;
+ expression(0);
+ State = 33;
+ Match(T__2);
+ }
+ break;
+ case T__7:
+ {
+ _localctx = new NotExpressionContext(_localctx);
+ Context = _localctx;
+ _prevctx = _localctx;
+ State = 35;
+ Match(T__7);
+ State = 36;
+ expression(19);
+ }
+ break;
+ case T__8:
+ {
+ _localctx = new InvertExpressionContext(_localctx);
+ Context = _localctx;
+ _prevctx = _localctx;
+ State = 37;
+ Match(T__8);
+ State = 38;
+ expression(18);
+ }
+ break;
+ case INT:
+ {
+ _localctx = new ConstantExpressionContext(_localctx);
+ Context = _localctx;
+ _prevctx = _localctx;
+ State = 39;
+ constant();
+ }
+ break;
+ default:
+ throw new NoViableAltException(this);
+ }
+ Context.Stop = TokenStream.LT(-1);
+ State = 92;
+ ErrorHandler.Sync(this);
+ _alt = Interpreter.AdaptivePredict(TokenStream,3,Context);
+ while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) {
+ if ( _alt==1 ) {
+ if ( ParseListeners!=null )
+ TriggerExitRuleEvent();
+ _prevctx = _localctx;
+ {
+ State = 90;
+ ErrorHandler.Sync(this);
+ switch ( Interpreter.AdaptivePredict(TokenStream,2,Context) ) {
+ case 1:
+ {
+ _localctx = new MultiplyExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((MultiplyExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 42;
+ if (!(Precpred(Context, 17))) throw new FailedPredicateException(this, "Precpred(Context, 17)");
+ State = 43;
+ Match(T__9);
+ State = 44;
+ ((MultiplyExpressionContext)_localctx).right = expression(18);
+ }
+ break;
+ case 2:
+ {
+ _localctx = new DivideExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((DivideExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 45;
+ if (!(Precpred(Context, 16))) throw new FailedPredicateException(this, "Precpred(Context, 16)");
+ State = 46;
+ Match(T__10);
+ State = 47;
+ ((DivideExpressionContext)_localctx).right = expression(17);
+ }
+ break;
+ case 3:
+ {
+ _localctx = new ModulusExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((ModulusExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 48;
+ if (!(Precpred(Context, 15))) throw new FailedPredicateException(this, "Precpred(Context, 15)");
+ State = 49;
+ Match(T__11);
+ State = 50;
+ ((ModulusExpressionContext)_localctx).right = expression(16);
+ }
+ break;
+ case 4:
+ {
+ _localctx = new AddExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((AddExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 51;
+ if (!(Precpred(Context, 14))) throw new FailedPredicateException(this, "Precpred(Context, 14)");
+ State = 52;
+ Match(T__12);
+ State = 53;
+ ((AddExpressionContext)_localctx).right = expression(15);
+ }
+ break;
+ case 5:
+ {
+ _localctx = new SubtractExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((SubtractExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 54;
+ if (!(Precpred(Context, 13))) throw new FailedPredicateException(this, "Precpred(Context, 13)");
+ State = 55;
+ Match(T__13);
+ State = 56;
+ ((SubtractExpressionContext)_localctx).right = expression(14);
+ }
+ break;
+ case 6:
+ {
+ _localctx = new LessThanExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((LessThanExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 57;
+ if (!(Precpred(Context, 12))) throw new FailedPredicateException(this, "Precpred(Context, 12)");
+ State = 58;
+ Match(T__14);
+ State = 59;
+ ((LessThanExpressionContext)_localctx).right = expression(13);
+ }
+ break;
+ case 7:
+ {
+ _localctx = new GreaterThanExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((GreaterThanExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 60;
+ if (!(Precpred(Context, 11))) throw new FailedPredicateException(this, "Precpred(Context, 11)");
+ State = 61;
+ Match(T__15);
+ State = 62;
+ ((GreaterThanExpressionContext)_localctx).right = expression(12);
+ }
+ break;
+ case 8:
+ {
+ _localctx = new LessThanOrEqualExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((LessThanOrEqualExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 63;
+ if (!(Precpred(Context, 10))) throw new FailedPredicateException(this, "Precpred(Context, 10)");
+ State = 64;
+ Match(T__16);
+ State = 65;
+ ((LessThanOrEqualExpressionContext)_localctx).right = expression(11);
+ }
+ break;
+ case 9:
+ {
+ _localctx = new GreaterThanOrEqualExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((GreaterThanOrEqualExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 66;
+ if (!(Precpred(Context, 9))) throw new FailedPredicateException(this, "Precpred(Context, 9)");
+ State = 67;
+ Match(T__17);
+ State = 68;
+ ((GreaterThanOrEqualExpressionContext)_localctx).right = expression(10);
+ }
+ break;
+ case 10:
+ {
+ _localctx = new EqualExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((EqualExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 69;
+ if (!(Precpred(Context, 8))) throw new FailedPredicateException(this, "Precpred(Context, 8)");
+ State = 70;
+ Match(T__18);
+ State = 71;
+ ((EqualExpressionContext)_localctx).right = expression(9);
+ }
+ break;
+ case 11:
+ {
+ _localctx = new NotEqualExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((NotEqualExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 72;
+ if (!(Precpred(Context, 7))) throw new FailedPredicateException(this, "Precpred(Context, 7)");
+ State = 73;
+ Match(T__19);
+ State = 74;
+ ((NotEqualExpressionContext)_localctx).right = expression(8);
+ }
+ break;
+ case 12:
+ {
+ _localctx = new BitwiseAndExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((BitwiseAndExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 75;
+ if (!(Precpred(Context, 6))) throw new FailedPredicateException(this, "Precpred(Context, 6)");
+ State = 76;
+ Match(T__20);
+ State = 77;
+ ((BitwiseAndExpressionContext)_localctx).right = expression(7);
+ }
+ break;
+ case 13:
+ {
+ _localctx = new BitwiseOrExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((BitwiseOrExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 78;
+ if (!(Precpred(Context, 5))) throw new FailedPredicateException(this, "Precpred(Context, 5)");
+ State = 79;
+ Match(T__21);
+ State = 80;
+ ((BitwiseOrExpressionContext)_localctx).right = expression(6);
+ }
+ break;
+ case 14:
+ {
+ _localctx = new BitwiseXorExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((BitwiseXorExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 81;
+ if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)");
+ State = 82;
+ Match(T__22);
+ State = 83;
+ ((BitwiseXorExpressionContext)_localctx).right = expression(5);
+ }
+ break;
+ case 15:
+ {
+ _localctx = new LogicalAndExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((LogicalAndExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 84;
+ if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)");
+ State = 85;
+ Match(T__23);
+ State = 86;
+ ((LogicalAndExpressionContext)_localctx).right = expression(4);
+ }
+ break;
+ case 16:
+ {
+ _localctx = new LogicalOrExpressionContext(new ExpressionContext(_parentctx, _parentState));
+ ((LogicalOrExpressionContext)_localctx).left = _prevctx;
+ PushNewRecursionContext(_localctx, _startState, RULE_expression);
+ State = 87;
+ if (!(Precpred(Context, 2))) throw new FailedPredicateException(this, "Precpred(Context, 2)");
+ State = 88;
+ Match(T__24);
+ State = 89;
+ ((LogicalOrExpressionContext)_localctx).right = expression(3);
+ }
+ break;
+ }
+ }
+ }
+ State = 94;
+ ErrorHandler.Sync(this);
+ _alt = Interpreter.AdaptivePredict(TokenStream,3,Context);
+ }
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ ErrorHandler.ReportError(this, re);
+ ErrorHandler.Recover(this, re);
+ }
+ finally {
+ UnrollRecursionContexts(_parentctx);
+ }
+ return _localctx;
+ }
+
+ public partial class ConstantContext : ParserRuleContext {
+ public ConstantContext(ParserRuleContext parent, int invokingState)
+ : base(parent, invokingState)
+ {
+ }
+ public override int RuleIndex { get { return RULE_constant; } }
+
+ public ConstantContext() { }
+ public virtual void CopyFrom(ConstantContext context) {
+ base.CopyFrom(context);
+ }
+ }
+ public partial class IntConstantContext : ConstantContext {
+ [System.Diagnostics.DebuggerNonUserCode] public ITerminalNode INT() { return GetToken(CGrammarParser.INT, 0); }
+ public IntConstantContext(ConstantContext context) { CopyFrom(context); }
+ [System.Diagnostics.DebuggerNonUserCode]
+ public override TResult Accept<TResult>(IParseTreeVisitor<TResult> visitor) {
+ ICGrammarVisitor<TResult> typedVisitor = visitor as ICGrammarVisitor<TResult>;
+ if (typedVisitor != null) return typedVisitor.VisitIntConstant(this);
+ else return visitor.VisitChildren(this);
+ }
+ }
+
+ [RuleVersion(0)]
+ public ConstantContext constant() {
+ ConstantContext _localctx = new ConstantContext(Context, State);
+ EnterRule(_localctx, 8, RULE_constant);
+ try {
+ _localctx = new IntConstantContext(_localctx);
+ EnterOuterAlt(_localctx, 1);
+ {
+ State = 95;
+ Match(INT);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ ErrorHandler.ReportError(this, re);
+ ErrorHandler.Recover(this, re);
+ }
+ finally {
+ ExitRule();
+ }
+ return _localctx;
+ }
+
+ public override bool Sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
+ switch (ruleIndex) {
+ case 3: return expression_sempred((ExpressionContext)_localctx, predIndex);
+ }
+ return true;
+ }
+ private bool expression_sempred(ExpressionContext _localctx, int predIndex) {
+ switch (predIndex) {
+ case 0: return Precpred(Context, 17);
+ case 1: return Precpred(Context, 16);
+ case 2: return Precpred(Context, 15);
+ case 3: return Precpred(Context, 14);
+ case 4: return Precpred(Context, 13);
+ case 5: return Precpred(Context, 12);
+ case 6: return Precpred(Context, 11);
+ case 7: return Precpred(Context, 10);
+ case 8: return Precpred(Context, 9);
+ case 9: return Precpred(Context, 8);
+ case 10: return Precpred(Context, 7);
+ case 11: return Precpred(Context, 6);
+ case 12: return Precpred(Context, 5);
+ case 13: return Precpred(Context, 4);
+ case 14: return Precpred(Context, 3);
+ case 15: return Precpred(Context, 2);
+ }
+ return true;
+ }
+
+ private static int[] _serializedATN = {
+ 4,1,27,98,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,1,0,1,0,1,0,1,1,1,1,
+ 1,1,1,1,1,1,1,1,5,1,20,8,1,10,1,12,1,23,9,1,1,1,1,1,1,2,1,2,1,2,1,2,1,
+ 3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,3,3,41,8,3,1,3,1,3,1,3,1,3,1,3,1,
+ 3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,
+ 1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,
+ 3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,5,3,91,8,3,10,3,12,3,94,9,3,1,4,1,4,1,4,
+ 0,1,6,5,0,2,4,6,8,0,0,112,0,10,1,0,0,0,2,13,1,0,0,0,4,26,1,0,0,0,6,40,
+ 1,0,0,0,8,95,1,0,0,0,10,11,3,2,1,0,11,12,5,0,0,1,12,1,1,0,0,0,13,14,5,
+ 1,0,0,14,15,5,26,0,0,15,16,5,2,0,0,16,17,5,3,0,0,17,21,5,4,0,0,18,20,3,
+ 4,2,0,19,18,1,0,0,0,20,23,1,0,0,0,21,19,1,0,0,0,21,22,1,0,0,0,22,24,1,
+ 0,0,0,23,21,1,0,0,0,24,25,5,5,0,0,25,3,1,0,0,0,26,27,5,6,0,0,27,28,3,6,
+ 3,0,28,29,5,7,0,0,29,5,1,0,0,0,30,31,6,3,-1,0,31,32,5,2,0,0,32,33,3,6,
+ 3,0,33,34,5,3,0,0,34,41,1,0,0,0,35,36,5,8,0,0,36,41,3,6,3,19,37,38,5,9,
+ 0,0,38,41,3,6,3,18,39,41,3,8,4,0,40,30,1,0,0,0,40,35,1,0,0,0,40,37,1,0,
+ 0,0,40,39,1,0,0,0,41,92,1,0,0,0,42,43,10,17,0,0,43,44,5,10,0,0,44,91,3,
+ 6,3,18,45,46,10,16,0,0,46,47,5,11,0,0,47,91,3,6,3,17,48,49,10,15,0,0,49,
+ 50,5,12,0,0,50,91,3,6,3,16,51,52,10,14,0,0,52,53,5,13,0,0,53,91,3,6,3,
+ 15,54,55,10,13,0,0,55,56,5,14,0,0,56,91,3,6,3,14,57,58,10,12,0,0,58,59,
+ 5,15,0,0,59,91,3,6,3,13,60,61,10,11,0,0,61,62,5,16,0,0,62,91,3,6,3,12,
+ 63,64,10,10,0,0,64,65,5,17,0,0,65,91,3,6,3,11,66,67,10,9,0,0,67,68,5,18,
+ 0,0,68,91,3,6,3,10,69,70,10,8,0,0,70,71,5,19,0,0,71,91,3,6,3,9,72,73,10,
+ 7,0,0,73,74,5,20,0,0,74,91,3,6,3,8,75,76,10,6,0,0,76,77,5,21,0,0,77,91,
+ 3,6,3,7,78,79,10,5,0,0,79,80,5,22,0,0,80,91,3,6,3,6,81,82,10,4,0,0,82,
+ 83,5,23,0,0,83,91,3,6,3,5,84,85,10,3,0,0,85,86,5,24,0,0,86,91,3,6,3,4,
+ 87,88,10,2,0,0,88,89,5,25,0,0,89,91,3,6,3,3,90,42,1,0,0,0,90,45,1,0,0,
+ 0,90,48,1,0,0,0,90,51,1,0,0,0,90,54,1,0,0,0,90,57,1,0,0,0,90,60,1,0,0,
+ 0,90,63,1,0,0,0,90,66,1,0,0,0,90,69,1,0,0,0,90,72,1,0,0,0,90,75,1,0,0,
+ 0,90,78,1,0,0,0,90,81,1,0,0,0,90,84,1,0,0,0,90,87,1,0,0,0,91,94,1,0,0,
+ 0,92,90,1,0,0,0,92,93,1,0,0,0,93,7,1,0,0,0,94,92,1,0,0,0,95,96,5,27,0,
+ 0,96,9,1,0,0,0,4,21,40,90,92
+ };
+
+ public static readonly ATN _ATN =
+ new ATNDeserializer().Deserialize(_serializedATN);
+
+
+}
diff --git a/Compiler/gen/CGrammarVisitor.cs b/Compiler/gen/CGrammarVisitor.cs
new file mode 100644
index 0000000..1f9691a
--- /dev/null
+++ b/Compiler/gen/CGrammarVisitor.cs
@@ -0,0 +1,200 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// ANTLR Version: 4.13.2
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+// Generated from /Users/melodidey/Source/csharp/Q1/Compiler/CGrammar.g4 by ANTLR 4.13.2
+
+// Unreachable code detected
+#pragma warning disable 0162
+// The variable '...' is assigned but its value is never used
+#pragma warning disable 0219
+// Missing XML comment for publicly visible type or member '...'
+#pragma warning disable 1591
+// Ambiguous reference in cref attribute
+#pragma warning disable 419
+
+using Antlr4.Runtime.Misc;
+using Antlr4.Runtime.Tree;
+using IToken = Antlr4.Runtime.IToken;
+
+/// <summary>
+/// This interface defines a complete generic visitor for a parse tree produced
+/// by <see cref="CGrammarParser"/>.
+/// </summary>
+/// <typeparam name="Result">The return type of the visit operation.</typeparam>
+[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.13.2")]
+[System.CLSCompliant(false)]
+public interface ICGrammarVisitor<Result> : IParseTreeVisitor<Result> {
+ /// <summary>
+ /// Visit a parse tree produced by <see cref="CGrammarParser.program"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitProgram([NotNull] CGrammarParser.ProgramContext context);
+ /// <summary>
+ /// Visit a parse tree produced by <see cref="CGrammarParser.function"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitFunction([NotNull] CGrammarParser.FunctionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>returnStatement</c>
+ /// labeled alternative in <see cref="CGrammarParser.statement"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitReturnStatement([NotNull] CGrammarParser.ReturnStatementContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseXorExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitBitwiseXorExpression([NotNull] CGrammarParser.BitwiseXorExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>constantExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitConstantExpression([NotNull] CGrammarParser.ConstantExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>lessThanOrEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitLessThanOrEqualExpression([NotNull] CGrammarParser.LessThanOrEqualExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>modulusExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitModulusExpression([NotNull] CGrammarParser.ModulusExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>notExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitNotExpression([NotNull] CGrammarParser.NotExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>notEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitNotEqualExpression([NotNull] CGrammarParser.NotEqualExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>multiplyExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitMultiplyExpression([NotNull] CGrammarParser.MultiplyExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>greaterThanExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitGreaterThanExpression([NotNull] CGrammarParser.GreaterThanExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>logicalOrExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitLogicalOrExpression([NotNull] CGrammarParser.LogicalOrExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>greaterThanOrEqualExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitGreaterThanOrEqualExpression([NotNull] CGrammarParser.GreaterThanOrEqualExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>divideExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitDivideExpression([NotNull] CGrammarParser.DivideExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseOrExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitBitwiseOrExpression([NotNull] CGrammarParser.BitwiseOrExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>parenthesizedExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitParenthesizedExpression([NotNull] CGrammarParser.ParenthesizedExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>addExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitAddExpression([NotNull] CGrammarParser.AddExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>subtractExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitSubtractExpression([NotNull] CGrammarParser.SubtractExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>bitwiseAndExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitBitwiseAndExpression([NotNull] CGrammarParser.BitwiseAndExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>lessThanExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitLessThanExpression([NotNull] CGrammarParser.LessThanExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>logicalAndExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitLogicalAndExpression([NotNull] CGrammarParser.LogicalAndExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>invertExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitInvertExpression([NotNull] CGrammarParser.InvertExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>equalExpression</c>
+ /// labeled alternative in <see cref="CGrammarParser.expression"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitEqualExpression([NotNull] CGrammarParser.EqualExpressionContext context);
+ /// <summary>
+ /// Visit a parse tree produced by the <c>intConstant</c>
+ /// labeled alternative in <see cref="CGrammarParser.constant"/>.
+ /// </summary>
+ /// <param name="context">The parse tree.</param>
+ /// <return>The visitor result.</return>
+ Result VisitIntConstant([NotNull] CGrammarParser.IntConstantContext context);
+}
diff --git a/Emulator/.DS_Store b/Emulator/.DS_Store
new file mode 100644
index 0000000..0bebabf
--- /dev/null
+++ b/Emulator/.DS_Store
Binary files differ
diff --git a/Assembler/Disassembler.cs b/Emulator/Assembler/Disassembler.cs
index 816ddbc..d49d2eb 100644
--- a/Assembler/Disassembler.cs
+++ b/Emulator/Assembler/Disassembler.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu.Assembler;
+namespace Q1.Emulator.Assembler;
using System;
using System.Collections.Generic;
@@ -42,16 +42,16 @@ public class Disassembler
_ => 3 // Extended addressing mode
};
- string opcodeName = GetOpcodeName(op, i);
+ string opcodeName = Disassembler.GetOpcodeName(op, i);
if (i == 0 || i == 2)
return opcodeName;
if (i == 1)
- return $"{opcodeName} {GetModeName(m1)}";
+ return $"{opcodeName} {Disassembler.GetModeName(m1)}";
if (i == 3)
- return $"{opcodeName} {GetModeName(m1)}, {GetModeName(m2)}";
+ return $"{opcodeName} {Disassembler.GetModeName(m1)}, {Disassembler.GetModeName(m2)}";
throw new InvalidOperationException($"Unknown instruction format for opcode {op:X2} with modes {m1:X2}, {m2:X2}");
}
@@ -66,7 +66,7 @@ public class Disassembler
private static string GetModeName(u8 mode)
{
- if (ModeLookup.TryGetValue(mode, out string? modeName))
+ if (Disassembler.ModeLookup.TryGetValue(mode, out string? modeName))
return modeName;
return $"[{mode:X2}]"; // Fallback for unknown modes
diff --git a/Chip/Bus.cs b/Emulator/Chip/Bus.cs
index 3578ad6..0907f61 100644
--- a/Chip/Bus.cs
+++ b/Emulator/Chip/Bus.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu.Chip;
+namespace Q1.Emulator.Chip;
using System.Collections.Generic;
using System.Linq;
@@ -19,7 +19,7 @@ public class Bus : BusDevice
public override u8 Read(u16 address)
{
- BusDevice? device = GetDevice(address);
+ BusDevice? device = this.GetDevice(address);
if (device == null)
return 0;
@@ -28,7 +28,7 @@ public class Bus : BusDevice
public override void Write(u16 address, u8 value)
{
- BusDevice? device = GetDevice(address);
+ BusDevice? device = this.GetDevice(address);
if (device == null)
return;
diff --git a/Chip/BusDevice.cs b/Emulator/Chip/BusDevice.cs
index 8b677c5..1e1e972 100644
--- a/Chip/BusDevice.cs
+++ b/Emulator/Chip/BusDevice.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu.Chip;
+namespace Q1.Emulator.Chip;
using System.Runtime.CompilerServices;
@@ -29,13 +29,6 @@ public abstract class BusDevice
this.Write((u16) (address + 1), data[1]);
}
- public i16 ReadSignedWord(u16 address)
- {
- u8 high = this.Read(address);
- u8 low = this.Read((u16) (address + 1));
- return Make.i16(high, low);
- }
-
public virtual void Clock() { }
public virtual void Reset() { }
diff --git a/Emulator/Chip/DebugDevice.cs b/Emulator/Chip/DebugDevice.cs
new file mode 100644
index 0000000..4e869bb
--- /dev/null
+++ b/Emulator/Chip/DebugDevice.cs
@@ -0,0 +1,13 @@
+namespace Q1.Emulator.Chip;
+
+using System;
+
+public class DebugDevice(u16 addressPoint)
+ : BusDevice(addressPoint, (u16) (addressPoint + 2))
+{
+ public override u8 Read(u16 address) => throw new Exception("DebugDevice.Read not permitted");
+ public override void Write(u16 address, u8 value)
+ {
+ Console.WriteLine($"DebugDevice.Write: x{value:X4} b{value:b8}");
+ }
+} \ No newline at end of file
diff --git a/Chip/DisplayDevice.cs b/Emulator/Chip/DisplayDevice.cs
index 1bf4f14..a18dbd4 100644
--- a/Chip/DisplayDevice.cs
+++ b/Emulator/Chip/DisplayDevice.cs
@@ -1,8 +1,6 @@
-namespace Q1Emu.Chip;
+namespace Q1.Emulator.Chip;
using System;
-using System.Collections.Generic;
-using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@@ -33,14 +31,14 @@ public class DisplayDevice : RamDevice
Color[] palette = this.ReadPalette();
ref8 pixelData = this.Memory.AsSpan((u16) (this._paletteSize * 3), (u16) (this._displayWidth * this._displayHeight));
// Console.WriteLine($"DisplayDevice.Clock: @{(this.AddressableStart + this._paletteSize * 3):X4} palette size={this._paletteSize} display size={this._displayWidth}x{this._displayHeight}");
- for (u16 i = 0; i < textureData.Length; i++)
+ for (u16 i = 0; i < this.textureData.Length; i++)
{
u8 pixelValue = pixelData[i];
- textureData[i] = palette[pixelValue % this._paletteSize];
+ this.textureData[i] = palette[pixelValue % this._paletteSize];
}
if (this.OutputTexture != null)
- this.OutputTexture.SetData(textureData);
+ this.OutputTexture.SetData(this.textureData);
}
private Color[] ReadPalette()
diff --git a/Chip/Q1Cpu.cs b/Emulator/Chip/Q1Cpu.cs
index eefc61c..16e1e14 100644
--- a/Chip/Q1Cpu.cs
+++ b/Emulator/Chip/Q1Cpu.cs
@@ -1,8 +1,6 @@
-using System;
+namespace Q1.Emulator.Chip;
-namespace Q1Emu.Chip;
-
-using System.Collections.Generic;
+using System;
using Assembler;
public partial class Q1Cpu
@@ -23,20 +21,22 @@ public partial class Q1Cpu
public u16 I { get; set; } // Index register
public u16 Cycles { get; set; } // Number of cycles
- public Bus Bus { get; set; }
+ public Bus Bus { get; set; }
+ public bool AbortRequested = false;
public Q1Cpu()
{
this.LoadInstructionLookup();
-
- this.Reset();
}
public void Reset()
{
+ this.AbortRequested = false;
+
this.V = new u16[16];
- this.SP = StackStart;
+ this.SP = Q1Cpu.StackStart;
+ this.PushStack(0xFFFF);
this.I = 0;
}
@@ -44,9 +44,15 @@ public partial class Q1Cpu
public void Clock()
{
var pc = this.PC;
+ if (pc == 0xFFFF)
+ {
+ this.AbortRequested = true;
+ return;
+ }
+
u16 instruction = this.FetchInstruction(out u8 op, out u8 m1, out u8 m2, out _);
- Console.WriteLine($"CPU.Clock: {pc:X4} | {Disassembler.ParseInstruction(instruction)}");
- // Console.WriteLine($"{V[0]:X4} {V[1]:X4} {V[2]:X4} {V[3]:X4} {V[4]:X4} {V[5]:X4} {V[6]:X4} {V[7]:X4}");
+ if (instruction != 0x0101)
+ Console.WriteLine($"CPU.Clock: {pc:X4} | {Disassembler.ParseInstruction(instruction)}");
bool ex = m2 > 0;
switch (m1, ex)
@@ -82,7 +88,7 @@ public partial class Q1Cpu
private void PushStack(u16 value)
{
- if (this.SP + 2 >= StackStart + StackLength)
+ if (this.SP + 2 >= Q1Cpu.StackStart + Q1Cpu.StackLength)
throw new InvalidOperationException("Stack overflow");
this.Bus.WriteWord(this.SP, value);
@@ -91,7 +97,7 @@ public partial class Q1Cpu
private u16 PopStack()
{
- if (this.SP - 2 < StackStart)
+ if (this.SP - 2 < Q1Cpu.StackStart)
throw new InvalidOperationException("Stack underflow");
this.SP -= 2;
@@ -129,25 +135,34 @@ public partial class Q1Cpu
break;
case 0x40:
- this.AX = value; break;
+ this.AX = value;
+ break;
case 0x41:
- this.AX = (u16) ((this.AX & 0x00FF) | (value << 8)); break; // Set high byte
+ this.AX = (u16) ((this.AX & 0x00FF) | (value << 8));
+ break; // Set high byte
case 0x42:
- this.AX = (u16) ((this.AX & 0xFF00) | (value & 0x00FF)); break; // Set low byte
+ this.AX = (u16) ((this.AX & 0xFF00) | (value & 0x00FF));
+ break; // Set low byte
case 0x43:
- this.DX = value; break;
+ this.DX = value;
+ break;
case 0x44:
- this.DX = (u16) ((this.DX & 0x00FF) | (value << 8)); break; // Set high byte
+ this.DX = (u16) ((this.DX & 0x00FF) | (value << 8));
+ break; // Set high byte
case 0x45:
- this.DX = (u16) ((this.DX & 0xFF00) | (value & 0x00FF)); break; // Set low byte
+ this.DX = (u16) ((this.DX & 0xFF00) | (value & 0x00FF));
+ break; // Set low byte
case 0x46:
- this.LX = value; break;
+ this.LX = value;
+ break;
case 0x50:
- this.PC = value; break;
+ this.PC = value;
+ break;
case 0x51:
- this.SP = value; break;
+ this.SP = value;
+ break;
default:
throw new InvalidOperationException($"Unknown register index: {regIndex:X2}");
diff --git a/Chip/Q1CpuAddressingModes.cs b/Emulator/Chip/Q1CpuAddressingModes.cs
index 2b79db7..40020f1 100644
--- a/Chip/Q1CpuAddressingModes.cs
+++ b/Emulator/Chip/Q1CpuAddressingModes.cs
@@ -1,7 +1,6 @@
-namespace Q1Emu.Chip;
+namespace Q1.Emulator.Chip;
using System;
-using System.Collections.Generic;
public partial class Q1Cpu
{
@@ -161,7 +160,7 @@ public partial class Q1Cpu
u8 regIndex = this.Bus.Read(this.PC);
this.PC += 1;
- i16 offset = this.Bus.ReadSignedWord(this.PC);
+ u16 offset = this.Bus.ReadWord(this.PC);
this.PC += 2;
u16 Read()
diff --git a/Chip/Q1CpuInstructions.cs b/Emulator/Chip/Q1CpuInstructions.cs
index b31a102..2da8969 100644
--- a/Chip/Q1CpuInstructions.cs
+++ b/Emulator/Chip/Q1CpuInstructions.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu.Chip;
+namespace Q1.Emulator.Chip;
using System;
using System.Collections.Generic;
@@ -10,6 +10,8 @@ public partial class Q1Cpu
{ 0x00, ["NOP", "JMP", "HALT", "MOV"] },
{ 0x01, ["RET", "CALL", "SUS", "MOVB"] },
{ 0x02, ["BZ", "BZ", "BR", "NOP"] },
+ { 0x03, ["NOP", "PUSH", "NOP", "NOP"] },
+ { 0x04, ["NOP", "POP", "NOP", "NOP"] },
{ 0x10, ["INV", "INV", "NOP", "AND"] },
{ 0x11, ["SHL", "SHL", "NOP", "OR"] },
@@ -25,7 +27,7 @@ public partial class Q1Cpu
{ 0x33, ["NOP", "NOP", "NOP", "MUL"] },
{ 0x34, ["NOP", "NOP", "NOP", "MOD"] },
};
-
+
public Dictionary<u8, (Action, Action<u8>, Action, Action<u8, u8>)> InstructionLookup;
private void LoadInstructionLookup()
{
@@ -34,11 +36,13 @@ public partial class Q1Cpu
{ 0x00, (this.Instruction_NOP, this.Instruction_JMP, this.Instruction_HALT, this.Instruction_MOV) },
{ 0x01, (this.Instruction_RET, this.Instruction_CALL, this.Instruction_SUS, this.Instruction_MOVB) },
{ 0x02, (this.Instruction_BZ_LX, this.Instruction_BZ, this.Instruction_BR, this.Instruction_NOP) },
+ { 0x03, (this.Instruction_NOP, this.Instruction_PUSH, this.Instruction_NOP, this.Instruction_NOP) },
+ { 0x04, (this.Instruction_NOP, this.Instruction_POP, this.Instruction_NOP, this.Instruction_NOP) },
{ 0x10, (this.Instruction_INV_DX, this.Instruction_INV, this.Instruction_NOP, this.Instruction_AND) },
{ 0x11, (this.Instruction_SHL_DX, this.Instruction_SHL, this.Instruction_NOP, this.Instruction_OR) },
{ 0x12, (this.Instruction_SHR_DX, this.Instruction_SHR, this.Instruction_NOP, this.Instruction_XOR) },
-
+
{ 0x20, (this.Instruction_NOT_LX, this.Instruction_NOT, this.Instruction_NOP, this.Instruction_CMP) },
{ 0x21, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_LT) },
{ 0x22, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_GT) },
@@ -54,7 +58,7 @@ public partial class Q1Cpu
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
+
u16 result = (u16) (v1 + v2);
this.AX = result;
}
@@ -62,15 +66,15 @@ public partial class Q1Cpu
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- u16 result = (u16)(v1 - v2);
+
+ u16 result = (u16) (v1 - v2);
this.AX = result;
}
private void Instruction_MUL(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
+
u16 result = (u16) (v1 * v2);
this.AX = result;
}
@@ -78,124 +82,124 @@ public partial class Q1Cpu
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
+
if (v2 == 0)
throw new DivideByZeroException("Cannot perform division by zero.");
- u16 result = (u16)(v1 / v2);
+ u16 result = (u16) (v1 / v2);
this.AX = result;
}
private void Instruction_MOD(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
+
if (v2 == 0)
throw new DivideByZeroException("Cannot perform modulo operation with divisor zero.");
- u16 result = (u16)(v1 % v2);
+ u16 result = (u16) (v1 % v2);
this.AX = result;
}
private void Instruction_INC(u8 obj)
{
var address = this.Address(obj);
u16 value = address.read();
- address.write((u16)(value + 1));
+ address.write((u16) (value + 1));
}
private void Instruction_DEC(u8 obj)
{
var address = this.Address(obj);
u16 value = address.read();
- address.write((u16)(value - 1));
+ address.write((u16) (value - 1));
}
private void Instruction_INC_AX()
{
- this.AX = (u16)(this.AX + 1);
+ this.AX = (u16) (this.AX + 1);
}
private void Instruction_DEC_AX()
{
- this.AX = (u16)(this.AX - 1);
+ this.AX = (u16) (this.AX - 1);
}
private void Instruction_SHL(u8 obj)
{
var address = this.Address(obj);
u16 value = address.read();
- u16 result = (u16)(value << 1);
+ u16 result = (u16) (value << 1);
address.write(result);
}
private void Instruction_SHR(u8 obj)
{
var address = this.Address(obj);
u16 value = address.read();
- u16 result = (u16)(value >> 1);
+ u16 result = (u16) (value >> 1);
address.write(result);
}
private void Instruction_SHL_DX()
{
- this.DX = (u16)(this.DX << 1);
+ this.DX = (u16) (this.DX << 1);
}
private void Instruction_SHR_DX()
{
- this.DX = (u16)(this.DX >> 1);
+ this.DX = (u16) (this.DX >> 1);
}
private void Instruction_XOR(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- u16 result = (u16)(v1 ^ v2);
+
+ u16 result = (u16) (v1 ^ v2);
this.DX = result;
}
private void Instruction_OR(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- u16 result = (u16)(v1 | v2);
+
+ u16 result = (u16) (v1 | v2);
this.DX = result;
}
private void Instruction_INV(u8 obj)
{
var address = this.Address(obj);
u16 value = address.read();
- u16 result = (u16)~value;
- address.write(result);
+ u16 result = (u16) ~value;
+ this.DX = result;
}
private void Instruction_INV_DX()
{
- this.DX = (u16)~this.DX;
+ this.DX = (u16) ~this.DX;
}
private void Instruction_AND(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- u16 result = (u16)(v1 & v2);
+
+ u16 result = (u16) (v1 & v2);
this.DX = result;
}
private void Instruction_NOT(u8 obj)
{
u16 value = this.Address(obj).read();
- u16 result = value == 0 ? (u16)1 : (u16)0;
+ u16 result = value == 0 ? (u16) 1 : (u16) 0;
this.LX = result;
}
private void Instruction_NOT_LX()
{
- this.LX = this.LX == 0 ? (u16)1 : (u16)0;
+ this.LX = this.LX == 0 ? (u16) 1 : (u16) 0;
}
private void Instruction_GT(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- this.LX = (u16)(v1 > v2 ? 1 : 0);
+
+ this.LX = (u16) (v1 > v2 ? 1 : 0);
}
private void Instruction_LT(u8 m1, u8 m2)
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
- this.LX = (u16)(v1 < v2 ? 1 : 0);
+
+ this.LX = (u16) (v1 < v2 ? 1 : 0);
}
-
+
private void Instruction_BR()
{
this.FetchInstruction(out _, out _, out _, out u8 length);
@@ -216,16 +220,16 @@ public partial class Q1Cpu
{
u16 v1 = this.Address(m1).read();
u16 v2 = this.Address(m2).read();
-
+
// Set LX based on comparison
- this.LX = (u16)(v1 == v2 ? 1 : 0);
+ this.LX = (u16) (v1 == v2 ? 1 : 0);
}
private void Instruction_MOV(u8 m1, u8 m2)
{
u16 value = this.Address(m1).read();
this.Address(m2).write(value);
}
-
+
private void Instruction_MOVB(u8 m1, u8 m2)
{
u16 value = this.Address(m1).read();
@@ -256,11 +260,23 @@ public partial class Q1Cpu
public void Instruction_HALT()
{
- throw new NotImplementedException("Halt instruction not implemented yet.");
+ this.AbortRequested = true;
}
public void Instruction_SUS()
{
this.PC -= 2;
}
+
+ public void Instruction_PUSH(u8 m1)
+ {
+ u16 value = this.Address(m1).read();
+ this.PushStack(value);
+ }
+
+ public void Instruction_POP(u8 m1)
+ {
+ u16 value = this.PopStack();
+ this.Address(m1).write(value);
+ }
} \ No newline at end of file
diff --git a/Chip/RamDevice.cs b/Emulator/Chip/RamDevice.cs
index 509a2df..8d5b051 100644
--- a/Chip/RamDevice.cs
+++ b/Emulator/Chip/RamDevice.cs
@@ -1,7 +1,4 @@
-namespace Q1Emu.Chip;
-
-using System;
-using System.Runtime.CompilerServices;
+namespace Q1.Emulator.Chip;
public class RamDevice : BusDevice
{
diff --git a/Content/Content.mgcb b/Emulator/Content/Content.mgcb
index ddc4c36..ddc4c36 100644
--- a/Content/Content.mgcb
+++ b/Emulator/Content/Content.mgcb
diff --git a/DisplayEngine.cs b/Emulator/DisplayEngine.cs
index 3f67bed..beb2bba 100644
--- a/DisplayEngine.cs
+++ b/Emulator/DisplayEngine.cs
@@ -1,16 +1,15 @@
-using System;
-using System.Collections.Generic;
-using Q1Emu.Chip;
+namespace Q1.Emulator;
+
+using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
-namespace Q1Emu;
-
public class DisplayEngine : Game
{
private readonly Action<Texture2D> _onScreenTextureLoaded;
private readonly Action _requestUpdate;
+ private readonly Func<bool> _checkAbort;
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
@@ -19,42 +18,43 @@ public class DisplayEngine : Game
public int Width { get; }
public int Height { get; }
- public DisplayEngine(int width, int height, int scaling, Action<Texture2D> onScreenTextureLoaded, Action requestUpdate)
+ public DisplayEngine(int width, int height, int scaling, Action<Texture2D> onScreenTextureLoaded, Action requestUpdate, Func<bool> checkAbort)
{
this.Width = width;
this.Height = height;
this.Scaling = scaling;
this._onScreenTextureLoaded = onScreenTextureLoaded;
this._requestUpdate = requestUpdate;
+ this._checkAbort = checkAbort;
- _graphics = new GraphicsDeviceManager(this);
- Content.RootDirectory = "Content";
- IsMouseVisible = true;
+ this._graphics = new GraphicsDeviceManager(this);
+ this.Content.RootDirectory = "Content";
+ this.IsMouseVisible = true;
}
protected override void Initialize()
{
- this._texture = new Texture2D(GraphicsDevice, Width, Height);
+ this._texture = new Texture2D(this.GraphicsDevice, this.Width, this.Height);
this._onScreenTextureLoaded?.Invoke(this._texture);
// set window size
- _graphics.PreferredBackBufferWidth = Width * Scaling;
- _graphics.PreferredBackBufferHeight = Height * Scaling;
- _graphics.ApplyChanges();
+ this._graphics.PreferredBackBufferWidth = this.Width * this.Scaling;
+ this._graphics.PreferredBackBufferHeight = this.Height * this.Scaling;
+ this._graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
- _spriteBatch = new SpriteBatch(GraphicsDevice);
+ this._spriteBatch = new SpriteBatch(this.GraphicsDevice);
}
protected override void Update(GameTime gameTime)
{
var state = Keyboard.GetState();
- if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || state.IsKeyDown(Keys.Escape))
- Exit();
+ if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || state.IsKeyDown(Keys.Escape) || this._checkAbort())
+ this.Exit();
base.Update(gameTime);
}
@@ -65,11 +65,11 @@ public class DisplayEngine : Game
this._requestUpdate();
- _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone);
+ this._spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone);
// Draw the texture to the screen
- _spriteBatch.Draw(_texture, new Rectangle(0, 0, Width * Scaling, Height * Scaling), Color.White);
+ this._spriteBatch.Draw(this._texture, new Rectangle(0, 0, this.Width * this.Scaling, this.Height * this.Scaling), Color.White);
- _spriteBatch.End();
+ this._spriteBatch.End();
base.Draw(gameTime);
}
diff --git a/Q1Emu.csproj b/Emulator/Emulator.csproj
index 035139a..8cb327c 100644
--- a/Q1Emu.csproj
+++ b/Emulator/Emulator.csproj
@@ -5,13 +5,9 @@
<RollForward>Major</RollForward>
<PublishReadyToRun>false</PublishReadyToRun>
<TieredCompilation>false</TieredCompilation>
- <RootNamespace>Chip8Emu2</RootNamespace>
+ <RootNamespace>Q1.Emulator</RootNamespace>
<Nullable>enable</Nullable>
</PropertyGroup>
- <PropertyGroup>
- <ApplicationManifest>app.manifest</ApplicationManifest>
- <ApplicationIcon>Icon.ico</ApplicationIcon>
- </PropertyGroup>
<ItemGroup>
<None Remove="Icon.ico"/>
<None Remove="Icon.bmp"/>
@@ -25,6 +21,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
+ <PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105"/>
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.2.1105"/>
</ItemGroup>
diff --git a/Extensions.cs b/Emulator/Extensions.cs
index 6303c8c..3cc980d 100644
--- a/Extensions.cs
+++ b/Emulator/Extensions.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu;
+namespace Q1.Emulator;
using System.Collections.Generic;
diff --git a/Emulator/GlobalUsings.cs b/Emulator/GlobalUsings.cs
new file mode 100644
index 0000000..ff38a75
--- /dev/null
+++ b/Emulator/GlobalUsings.cs
@@ -0,0 +1,12 @@
+// Integer type aliases
+global using i8 = sbyte; // -128 to 127
+global using u8 = byte; // 0 to 255
+global using i16 = short; // -32,768 to 32,767
+global using u16 = ushort; // 0 to 65,535
+global using i32 = int; // -2,147,483,648 to 2,147,483,647
+global using u32 = uint; // 0 to 4,294,967,295
+global using i64 = long; // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
+global using u64 = ulong; // 0 to 18,446,744,073,709,551,615
+
+global using ref8 = System.Span<byte>;
+global using data8 = byte[];
diff --git a/Icon.bmp b/Emulator/Icon.bmp
index 2b48165..2b48165 100644
--- a/Icon.bmp
+++ b/Emulator/Icon.bmp
Binary files differ
diff --git a/Icon.ico b/Emulator/Icon.ico
index 7d9dec1..7d9dec1 100644
--- a/Icon.ico
+++ b/Emulator/Icon.ico
Binary files differ
diff --git a/Make.cs b/Emulator/Make.cs
index 24f3ac2..aad9644 100644
--- a/Make.cs
+++ b/Emulator/Make.cs
@@ -1,4 +1,4 @@
-namespace Q1Emu;
+namespace Q1.Emulator;
using System;
using System.Buffers.Binary;
@@ -15,7 +15,7 @@ public static class Make
if (data.Length < 2)
throw new ArgumentException("Data must contain at least 2 bytes to form a u16.");
- return u16(data[0], data[1]);
+ return Make.u16(data[0], data[1]);
}
public static u32 u32(u8 b1, u8 b2, u8 b3, u8 b4)
@@ -28,7 +28,7 @@ public static class Make
if (data.Length < 4)
throw new ArgumentException("Data must contain at least 4 bytes to form a u32.");
- return u32(data[0], data[1], data[2], data[3]);
+ return Make.u32(data[0], data[1], data[2], data[3]);
}
public static ref8 ref8(u16 value)
diff --git a/Emulator/Options.cs b/Emulator/Options.cs
new file mode 100644
index 0000000..a42b560
--- /dev/null
+++ b/Emulator/Options.cs
@@ -0,0 +1,7 @@
+namespace Q1.Emulator;
+
+public class Options
+{
+ [CommandLine.Option('i', "input", Required = true, HelpText = "Input file to run.")]
+ public string InputFile { get; set; }
+} \ No newline at end of file
diff --git a/Emulator/Program.cs b/Emulator/Program.cs
new file mode 100644
index 0000000..cd6a8c0
--- /dev/null
+++ b/Emulator/Program.cs
@@ -0,0 +1,82 @@
+namespace Q1.Emulator;
+
+using System;
+using System.IO;
+using System.Threading;
+using Chip;
+using CommandLine;
+using Microsoft.Xna.Framework;
+
+internal class Program
+{
+ public static void Main(string[] args)
+ {
+ Parser.Default.ParseArguments<Options>(args).WithParsed(Program.Main);
+ }
+
+ static void Main(Options options)
+ {
+ Q1Cpu cpu = new();
+ Bus bus = new(u16.MinValue, u16.MaxValue);
+ RamDevice ram = new(0x1FFF, 1024 * 8);
+ File.ReadAllBytes(options.InputFile).CopyTo(ram.Memory, 0);
+
+ cpu.PC = ram.AddressableStart;
+
+ DisplayDevice display = new(16, 64, 32, 0x3FFF);
+ display.SetPalette([
+ Color.Red,
+ Color.Green,
+ Color.Blue,
+ Color.Yellow,
+ Color.Cyan,
+ Color.Magenta,
+ Color.White,
+ Color.Black,
+ Color.Gray,
+ Color.Orange,
+ Color.Purple,
+ Color.Brown,
+ Color.LightGray,
+ Color.DarkGray,
+ Color.LightBlue,
+ Color.LightGreen
+ ]);
+
+ DebugDevice debug = new(0xEFFF);
+
+ cpu.Bus = bus;
+ ram.AttachToBus(bus);
+ display.AttachToBus(bus);
+ debug.AttachToBus(bus);
+
+ Thread t = new(() =>
+ {
+ cpu.Reset();
+ while (!cpu.AbortRequested)
+ {
+ for (int i = 0; i < 64; i++)
+ cpu.Clock();
+
+ Thread.Sleep(1);
+ //
+ // cpu.Clock();
+ // Thread.Sleep(1000);
+ }
+ Console.WriteLine($"Exit code: 0x{cpu.V[0]:X4}");
+ });
+ t.IsBackground = true;
+ t.Start();
+
+ using DisplayEngine game = new(64, 32, 10,
+ tex =>
+ {
+ display.OutputTexture = tex;
+ Console.WriteLine("Display surface initialized.");
+ }, () => display.Clock(), () => cpu.AbortRequested);
+ game.Run();
+
+ Console.WriteLine("Display surface closed. Waiting for CPU thread to finish...");
+ t.Join();
+ }
+} \ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100644
index 016e557..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using Microsoft.Xna.Framework;
-using Q1Emu.Chip;
-using Q1Emu;
-using Q1Emu.Assembler;
-
-internal class Program
-{
- public static void Main(string[] args)
- {
- if (args.Length > 0)
- {
- string filePath = args[0];
-
- Environment.CurrentDirectory = Path.GetDirectoryName(filePath) ?? Environment.CurrentDirectory;
- filePath = Path.GetFileName(filePath);
-
- if (filePath.EndsWith(".q1"))
- {
- Run(filePath);
- }
- else
- {
- Program.AssembleAndRun(filePath);
- }
- }
- else
- {
- Console.WriteLine("Usage: Q1Emu <file.q1|file.asm>");
- Console.WriteLine("Example: Q1Emu game.q1");
- Console.WriteLine("Example: Q1Emu game.asm");
- }
- }
- private static void AssembleAndRun(string filePath)
- {
- StringReader reader = new(File.ReadAllText(filePath));
- BinaryWriter writer = new(File.Create(Path.ChangeExtension(filePath, ".q1")));
-
- Assembler assembler = new(reader, writer);
- assembler.Assemble();
- writer.Close();
- Console.WriteLine($"Assembled {filePath} to {Path.ChangeExtension(filePath, ".q1")}");
- Run(Path.ChangeExtension(filePath, ".q1"));
- }
- private static void Run(string filePath)
- {
- Q1Cpu cpu = new();
- Bus bus = new(u16.MinValue, u16.MaxValue);
- RamDevice ram = new(0x1FFF, 1024 * 8);
- File.ReadAllBytes(filePath).CopyTo(ram.Memory, 0);
-
- cpu.PC = ram.AddressableStart;
-
- DisplayDevice display = new(16, 64, 32, 0x3FFF);
- display.SetPalette([
- Color.Red,
- Color.Green,
- Color.Blue,
- Color.Yellow,
- Color.Cyan,
- Color.Magenta,
- Color.White,
- Color.Black,
- Color.Gray,
- Color.Orange,
- Color.Purple,
- Color.Brown,
- Color.LightGray,
- Color.DarkGray,
- Color.LightBlue,
- Color.LightGreen
- ]);
-
- cpu.Bus = bus;
- ram.AttachToBus(bus);
- display.AttachToBus(bus);
-
- Thread t = new(() =>
- {
- while (true)
- {
- for (int i = 0; i < 64; i++)
- {
- cpu.Clock();
- }
- Thread.Sleep(1);
- //
- // cpu.Clock();
- // Thread.Sleep(1000);
- }
- });
- t.IsBackground = true;
- t.Start();
-
- using DisplayEngine game = new(64, 32, 10,
- tex =>
- {
- display.OutputTexture = tex;
- Console.WriteLine("Display texture initialized.");
- }, () => display.Clock());
- game.Run();
- }
-} \ No newline at end of file
diff --git a/Q1.sln b/Q1.sln
new file mode 100644
index 0000000..97d648f
--- /dev/null
+++ b/Q1.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emulator", "Emulator\Emulator.csproj", "{04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compiler", "Compiler\Compiler.csproj", "{F3A482AD-855E-49B2-9E62-A7C68AB6250D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembler", "Assembler\Assembler.csproj", "{330B7F43-7267-4A2C-8EB0-257458231B7E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F3A482AD-855E-49B2-9E62-A7C68AB6250D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F3A482AD-855E-49B2-9E62-A7C68AB6250D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F3A482AD-855E-49B2-9E62-A7C68AB6250D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F3A482AD-855E-49B2-9E62-A7C68AB6250D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {330B7F43-7267-4A2C-8EB0-257458231B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {330B7F43-7267-4A2C-8EB0-257458231B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {330B7F43-7267-4A2C-8EB0-257458231B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {330B7F43-7267-4A2C-8EB0-257458231B7E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Chip8Emu2.sln.DotSettings.user b/Q1.sln.DotSettings.user
index d66483f..a489bb0 100644
--- a/Chip8Emu2.sln.DotSettings.user
+++ b/Q1.sln.DotSettings.user
@@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
- <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc06673f4846f4984af370f3a7898b653d83800_003F85_003F06ad3dad_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> \ No newline at end of file
+ <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABinaryWriter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fb5ea9bfdffa3204580857642ef06a8c5c8bf9e1e0cba3035b23ebccbdf92_003FBinaryWriter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> \ No newline at end of file
diff --git a/Q1Emu.sln b/Q1Emu.sln
deleted file mode 100644
index 801cf19..0000000
--- a/Q1Emu.sln
+++ /dev/null
@@ -1,16 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Q1Emu", "Q1Emu.csproj", "{04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {04CE77A9-E0DC-4CAB-9382-5F84B4275B6B}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/Q1Emu.sln.DotSettings.user b/Q1Emu.sln.DotSettings.user
deleted file mode 100644
index e3f7764..0000000
--- a/Q1Emu.sln.DotSettings.user
+++ /dev/null
@@ -1,4 +0,0 @@
-<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
- <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABinaryWriter_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fb5ea9bfdffa3204580857642ef06a8c5c8bf9e1e0cba3035b23ebccbdf92_003FBinaryWriter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
- <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConvert_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F68661b21b92f5da34c8d2e71bca89037a38df2db50765d2a8c0ccd638188e7c_003FConvert_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
- <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGame_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F49bab08708434a08802510b75a8ea3691b3400_003F26_003F86c71a55_003FGame_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> \ No newline at end of file
diff --git a/ROMs/.DS_Store b/ROMs/.DS_Store
index 523af33..775e323 100644
--- a/ROMs/.DS_Store
+++ b/ROMs/.DS_Store
Binary files differ
diff --git a/ROMs/font copy.bin b/ROMs/font copy.bin
deleted file mode 100644
index 88e4a93..0000000
--- a/ROMs/font copy.bin
+++ /dev/null
Binary files differ
diff --git a/ROMs/font.bin b/ROMs/font.bin
index 88e4a93..89f2af5 100644
--- a/ROMs/font.bin
+++ b/ROMs/font.bin
Binary files differ
diff --git a/ROMs/hello_c.asm b/ROMs/hello_c.asm
new file mode 100644
index 0000000..292b99a
--- /dev/null
+++ b/ROMs/hello_c.asm
@@ -0,0 +1,7 @@
+_main:
+ADD 1, 2
+SUB 4, 1
+MUL AX, AX
+MOV AX, V0
+RET
+
diff --git a/ROMs/hello_c.c b/ROMs/hello_c.c
new file mode 100644
index 0000000..46eab8d
--- /dev/null
+++ b/ROMs/hello_c.c
@@ -0,0 +1,4 @@
+int main()
+{
+ return (1 + 2) * (4 - 1);
+} \ No newline at end of file
diff --git a/ROMs/hello_c.q1 b/ROMs/hello_c.q1
new file mode 100644
index 0000000..deffc80
--- /dev/null
+++ b/ROMs/hello_c.q1
Binary files differ
diff --git a/ROMs/hello_world.dat b/ROMs/hello_world.asm
index 6cdacff..1d812fb 100644
--- a/ROMs/hello_world.dat
+++ b/ROMs/hello_world.asm
@@ -5,7 +5,7 @@ font:
.include "font.bin"
program:
- MOV 13, V0 ; Load character #12
+ MOV 0, V0 ; Load character #12
MOV 0, V1 ; X position
MOV 0, V2 ; Y position
MOV 1, V3 ; Color (1 = white)
@@ -26,8 +26,17 @@ write_char:
ADD AX, V1
MOV AX, V4 ; V4 = X position + Y position * 64 (screen index)
- MOV [V0 + $1FFF], V5 ; Read character
+ MOV V4, [$EFFF] ; Debug
+
+ MOV [V0 + $2003], V5 ; Read character (1FFF + 4 since jump address is 1FFF)
+ MOV V5, [$EFFF] ; Debug
+ AND V5, $01 ; Mask to get first bit (color)
+ MOV DX, V5
+ MOV V5, [$EFFF] ; Debug
MUL V5, V3 ; V5 = Character * Color (color index)
MOV AX, V5 ; Store result into V5
- MOV V5, [V4 + $3FFF] ; Write character to screen memory
+
+ MOV V5, [$EFFF] ; Debug
+
+ MOVB V5, [V4 + $402F] ; Write character to screen memory
RET \ No newline at end of file
diff --git a/ROMs/hello_world.q1 b/ROMs/hello_world.q1
index 4c1b1cd..fd66ffe 100644
--- a/ROMs/hello_world.q1
+++ b/ROMs/hello_world.q1
Binary files differ
diff --git a/ROMs/write_display_direct.dat b/ROMs/write_display_direct.asm
index 9fde417..9fde417 100644
--- a/ROMs/write_display_direct.dat
+++ b/ROMs/write_display_direct.asm
diff --git a/app.manifest b/app.manifest
deleted file mode 100644
index d9c2d8d..0000000
--- a/app.manifest
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
- <assemblyIdentity version="1.0.0.0" name="Chip8Emu2"/>
- <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
- <security>
- <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
- <requestedExecutionLevel level="asInvoker" uiAccess="false" />
- </requestedPrivileges>
- </security>
- </trustInfo>
-
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
- <application>
- <!-- A list of the Windows versions that this application has been tested on and is
- is designed to work with. Uncomment the appropriate elements and Windows will
- automatically selected the most compatible environment. -->
-
- <!-- Windows Vista -->
- <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
-
- <!-- Windows 7 -->
- <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
-
- <!-- Windows 8 -->
- <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
-
- <!-- Windows 8.1 -->
- <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
-
- <!-- Windows 10 -->
- <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
-
- </application>
- </compatibility>
-
- <application xmlns="urn:schemas-microsoft-com:asm.v3">
- <windowsSettings>
- <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
- <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
- </windowsSettings>
- </application>
-
-</assembly>