|
|
@@ -0,0 +1,186 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+
|
|
|
+namespace D19._1
|
|
|
+{
|
|
|
+ public class Computer
|
|
|
+ {
|
|
|
+ protected ProcessUnit CPU { get; private set; }
|
|
|
+
|
|
|
+ uint Ip = 0;
|
|
|
+ List<(uint op, uint[] param)> Program;
|
|
|
+
|
|
|
+ Parser InstrParser = new Parser();
|
|
|
+
|
|
|
+ public Computer() => CPU = new ProcessUnit();
|
|
|
+
|
|
|
+ public bool ExecInstruction()
|
|
|
+ {
|
|
|
+ CPU.Registers[CPU.IpRegister] = Ip;
|
|
|
+
|
|
|
+ var instr = Program[(int)Ip];
|
|
|
+ CPU.OpCodes[instr.op](instr.param[0], instr.param[1], instr.param[2]);
|
|
|
+
|
|
|
+ Ip = CPU.Registers[CPU.IpRegister];
|
|
|
+ Ip++;
|
|
|
+ return Ip < Program.Count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void LoadProgram(StreamReader program)
|
|
|
+ {
|
|
|
+ (uint ip, List<(uint, uint[])> p) = InstrParser.Parse(program);
|
|
|
+ Program = p;
|
|
|
+ CPU.IpRegister = ip;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void DumpRegisters()
|
|
|
+ {
|
|
|
+ Console.WriteLine($"[ { string.Join(", ", CPU.Registers.Select(r => r.Value)) } ]");
|
|
|
+ }
|
|
|
+
|
|
|
+ protected internal class Parser
|
|
|
+ {
|
|
|
+ Dictionary<string, uint> OpCodes = new Dictionary<string, uint>
|
|
|
+ {
|
|
|
+ { "addr", 0 },
|
|
|
+ { "addi", 1 },
|
|
|
+ { "mulr", 2 },
|
|
|
+ { "muli", 3 },
|
|
|
+ { "banr", 4 },
|
|
|
+ { "bani", 5 },
|
|
|
+ { "borr", 6 },
|
|
|
+ { "bori", 7 },
|
|
|
+ { "setr", 8 },
|
|
|
+ { "seti", 9 },
|
|
|
+ { "gtir", 10 },
|
|
|
+ { "gtri", 11 },
|
|
|
+ { "gtrr", 12 },
|
|
|
+ { "eqir", 13 },
|
|
|
+ { "eqri", 14 },
|
|
|
+ { "eqrr", 15 },
|
|
|
+ };
|
|
|
+
|
|
|
+ protected internal (uint, List<(uint, uint[])>) Parse(StreamReader file)
|
|
|
+ {
|
|
|
+ var result = new List<(uint, uint[])>();
|
|
|
+ uint ip = 0;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ var line = file.ReadLine();
|
|
|
+ if (line == null) break;
|
|
|
+
|
|
|
+ if (line == string.Empty) continue;
|
|
|
+ if (line.StartsWith("#ip "))
|
|
|
+ {
|
|
|
+ ip = uint.Parse(line.Substring(4));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ result.Add(ParseLine(line));
|
|
|
+ } while (true);
|
|
|
+
|
|
|
+ return (ip, result);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected (uint, uint[]) ParseLine(string line)
|
|
|
+ {
|
|
|
+ var all = line.Split(" ");
|
|
|
+
|
|
|
+ var opcode = all[0];
|
|
|
+ var opParams = all.Skip(1).Select(s => uint.Parse(s)).ToArray();
|
|
|
+
|
|
|
+ var op = OpCodes[opcode];
|
|
|
+
|
|
|
+ return (op, opParams);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ProcessUnit
|
|
|
+ {
|
|
|
+ public uint IpRegister { get; internal protected set; }
|
|
|
+ public delegate void OpCode(uint a, uint b, uint c);
|
|
|
+
|
|
|
+ public Register[] Registers = new Register[6] { 0, 0, 0, 0, 0, 0 };
|
|
|
+
|
|
|
+ public OpCode[] OpCodes;
|
|
|
+
|
|
|
+ public void SetRegisters(uint[] registers)
|
|
|
+ {
|
|
|
+ for (var i = 0; i < Registers.Length; ++i)
|
|
|
+ Registers[i] = registers[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ public ProcessUnit()
|
|
|
+ {
|
|
|
+ OpCodes = new OpCode[]
|
|
|
+ {
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] + Registers[b]; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] + b; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] * Registers[b]; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] * b; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] & Registers[b]; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] & b; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] | Registers[b]; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] | b; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a]; },
|
|
|
+ (a, b, c) => { Registers[c] = a; },
|
|
|
+ (a, b, c) => { Registers[c] = a > Registers[b] ? 1 : 0; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] > b ? 1 : 0; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] > Registers[b] ? 1 : 0; },
|
|
|
+ (a, b, c) => { Registers[c] = a == Registers[b] ? 1 : 0; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] == b ? 1 : 0; },
|
|
|
+ (a, b, c) => { Registers[c] = Registers[a] == Registers[b] ? 1 : 0; },
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public class Register
|
|
|
+ {
|
|
|
+ public uint Value { get; private set; }
|
|
|
+
|
|
|
+ public Register() { }
|
|
|
+ public Register(uint value) => Value = value;
|
|
|
+
|
|
|
+ public static implicit operator Register(uint a) => new Register { Value = a };
|
|
|
+ public static implicit operator uint(Register a) => a.Value;
|
|
|
+ public static implicit operator Register(int a) => new Register { Value = (uint)a };
|
|
|
+ public static bool operator >(Register a, Register b) => a.Value > b.Value;
|
|
|
+ public static bool operator <(Register a, Register b) => a.Value < b.Value;
|
|
|
+ public static bool operator ==(Register a, Register b) => a.Value == b.Value;
|
|
|
+ public static bool operator !=(Register a, Register b) => a.Value != b.Value;
|
|
|
+
|
|
|
+ public override bool Equals(object obj)
|
|
|
+ {
|
|
|
+ var register = obj as Register;
|
|
|
+ return register is null == false &&
|
|
|
+ Value == register.Value;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override int GetHashCode() => HashCode.Combine(Value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class Program
|
|
|
+ {
|
|
|
+ static void Main(string[] args)
|
|
|
+ {
|
|
|
+ if (args.Length < 1) return;
|
|
|
+ if (File.Exists(args[0]) == false) return;
|
|
|
+
|
|
|
+ var pc = new Computer();
|
|
|
+ var file = File.OpenText(args[0]);
|
|
|
+ pc.LoadProgram(file);
|
|
|
+ file.Close();
|
|
|
+
|
|
|
+ pc.DumpRegisters();
|
|
|
+ Console.WriteLine("==== EXECUTING PROGRAM ===");
|
|
|
+
|
|
|
+ while (pc.ExecInstruction());
|
|
|
+
|
|
|
+ Console.WriteLine("====== PROGRAM ENDED =====");
|
|
|
+ pc.DumpRegisters();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|