diff options
| -rw-r--r-- | .DS_Store | bin | 8196 -> 10244 bytes | |||
| -rw-r--r-- | .fleet/run.json | 11 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/.gitignore | 13 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/ANTLRv4ToolGrammarProperties.xml | 42 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/encodings.xml | 4 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/indexLayout.xml | 8 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/misc.xml | 10 | ||||
| -rw-r--r-- | .idea/.idea.Q1/.idea/vcs.xml | 6 | ||||
| -rw-r--r-- | Assembler/Assembler.cs | 328 | ||||
| -rw-r--r-- | Assembler/Assembler.csproj | 19 | ||||
| -rw-r--r-- | Assembler/Extensions.cs | 15 | ||||
| -rw-r--r-- | Assembler/GlobalUsings.cs (renamed from GlobalUsings.cs) | 0 | ||||
| -rw-r--r-- | Assembler/Options.cs | 12 | ||||
| -rw-r--r-- | Assembler/Program.cs | 38 | ||||
| -rw-r--r-- | Compiler/CCompilerVisitor.cs | 172 | ||||
| -rw-r--r-- | Compiler/CGrammar.g4 | 50 | ||||
| -rw-r--r-- | Compiler/Compiler.csproj | 20 | ||||
| -rw-r--r-- | Compiler/CompilerException.cs | 4 | ||||
| -rw-r--r-- | Compiler/Options.cs | 12 | ||||
| -rw-r--r-- | Compiler/Program.cs | 31 | ||||
| -rw-r--r-- | Compiler/gen/CGrammar.interp | 70 | ||||
| -rw-r--r-- | Compiler/gen/CGrammar.tokens | 52 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarBaseVisitor.cs | 299 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarLexer.cs | 149 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarLexer.interp | 98 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarLexer.tokens | 52 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarParser.cs | 1006 | ||||
| -rw-r--r-- | Compiler/gen/CGrammarVisitor.cs | 200 | ||||
| -rw-r--r-- | Emulator/.DS_Store | bin | 0 -> 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.cs | 13 | ||||
| -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.cs | 12 | ||||
| -rw-r--r-- | Emulator/Icon.bmp (renamed from Icon.bmp) | bin | 262282 -> 262282 bytes | |||
| -rw-r--r-- | Emulator/Icon.ico (renamed from Icon.ico) | bin | 147541 -> 147541 bytes | |||
| -rw-r--r-- | Emulator/Make.cs (renamed from Make.cs) | 6 | ||||
| -rw-r--r-- | Emulator/Options.cs | 7 | ||||
| -rw-r--r-- | Emulator/Program.cs | 82 | ||||
| -rw-r--r-- | Program.cs | 106 | ||||
| -rw-r--r-- | Q1.sln | 28 | ||||
| -rw-r--r-- | Q1.sln.DotSettings.user (renamed from Chip8Emu2.sln.DotSettings.user) | 2 | ||||
| -rw-r--r-- | Q1Emu.sln | 16 | ||||
| -rw-r--r-- | Q1Emu.sln.DotSettings.user | 4 | ||||
| -rw-r--r-- | ROMs/.DS_Store | bin | 6148 -> 6148 bytes | |||
| -rw-r--r-- | ROMs/font copy.bin | bin | 32768 -> 0 bytes | |||
| -rw-r--r-- | ROMs/font.bin | bin | 32768 -> 2048 bytes | |||
| -rw-r--r-- | ROMs/hello_c.asm | 7 | ||||
| -rw-r--r-- | ROMs/hello_c.c | 4 | ||||
| -rw-r--r-- | ROMs/hello_c.q1 | bin | 0 -> 22 bytes | |||
| -rw-r--r-- | ROMs/hello_world.asm (renamed from ROMs/hello_world.dat) | 15 | ||||
| -rw-r--r-- | ROMs/hello_world.q1 | bin | 32842 -> 2151 bytes | |||
| -rw-r--r-- | ROMs/write_display_direct.asm (renamed from ROMs/write_display_direct.dat) | 0 | ||||
| -rw-r--r-- | app.manifest | 43 |
63 files changed, 2863 insertions, 446 deletions
| 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 Binary files differnew file mode 100644 index 0000000..0bebabf --- /dev/null +++ b/Emulator/.DS_Store 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 Binary files differindex 2b48165..2b48165 100644 --- a/Icon.bmp +++ b/Emulator/Icon.bmp diff --git a/Icon.ico b/Emulator/Icon.ico Binary files differindex 7d9dec1..7d9dec1 100644 --- a/Icon.ico +++ b/Emulator/Icon.ico 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 @@ -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 Binary files differindex 523af33..775e323 100644 --- a/ROMs/.DS_Store +++ b/ROMs/.DS_Store diff --git a/ROMs/font copy.bin b/ROMs/font copy.bin Binary files differdeleted file mode 100644 index 88e4a93..0000000 --- a/ROMs/font copy.bin +++ /dev/null diff --git a/ROMs/font.bin b/ROMs/font.bin Binary files differindex 88e4a93..89f2af5 100644 --- a/ROMs/font.bin +++ b/ROMs/font.bin 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 Binary files differnew file mode 100644 index 0000000..deffc80 --- /dev/null +++ b/ROMs/hello_c.q1 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 Binary files differindex 4c1b1cd..fd66ffe 100644 --- a/ROMs/hello_world.q1 +++ b/ROMs/hello_world.q1 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> |
