private void AddIncrement(StringMatchData matchData) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.VR, new object[] { 1 }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RPlus, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RR, sourcePosition: matchData.StartIndex)); }
private void AddNot(FragmentMatchData matchData) { foreach (StringMatchData not in matchData.Parts) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RNot, sourcePosition: not.StartIndex)); } }
private void AddIfElseBlock(FragmentMatchData matchData) { List <int> cbes = new List <int>(); foreach (FragmentMatchData partMatchData in matchData.Parts) { switch (partMatchData.Name) { case "IfStatement": cbes.Add(AddIfStatement(partMatchData)); break; case "ElseIfStatement": cbes.Add(AddElseIfStatement(partMatchData)); break; case "ElseStatement": AddElseStatement(partMatchData); break; } } int endBlockIndex = _instructions.Count; foreach (int cbe in cbes) { _instructions[cbe] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.CSE, new IComparable[] { endBlockIndex }, sourcePosition : matchData.StartIndex + matchData.Length); } }
private void AddDecrement(FragmentMatchData matchData) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.VR, new object[] { 1 }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RSubtract, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RR, sourcePosition: matchData.StartIndex)); }
private void AddWhileBlock(FragmentMatchData matchData) { FragmentMatchData condition = (FragmentMatchData)matchData.Parts[0]; FragmentMatchData block = (FragmentMatchData)matchData.Parts[1]; int origActionStackLocation = _action.ActionStackLocation; _action.BlockDepth++; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.B, sourcePosition: matchData.StartIndex)); int lbIndex = _instructions.Count; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.L, sourcePosition: matchData.StartIndex, interruptable: true)); AddItem(condition); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: matchData.Parts[1].StartIndex)); int lbcIndex = _instructions.Count; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.NC, sourcePosition: matchData.Parts[1].StartIndex)); AddItem(block); int lbeIndex = _instructions.Count; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.LE, new object[] { lbIndex }, sourcePosition: matchData.StartIndex + matchData.Length)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.BE, sourcePosition: matchData.StartIndex + matchData.Length)); _action.BlockDepth--; ProcessFlowControls(lbIndex, lbcIndex, lbeIndex); _action.ActionStackLocation = origActionStackLocation; }
private void ProcessFlowControls(int lbIndex, int lbcIndex, int lbeIndex) { _instructions[lbcIndex] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.NC, new object[] { lbeIndex + 1 }, sourcePosition : _instructions[lbcIndex].SourcePosition); if (_reprocessRequiredIndexes.TryGetValue(InstructionCode.J, out List <int> reprocessIndexes)) { foreach (int instructionIndex in reprocessIndexes) { Instruction <GroupState> instruction = _instructions[instructionIndex]; if ((string)instruction.Payload[0] == "break") { _instructions[instructionIndex - 1] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.US, new object[] { lbIndex }, sourcePosition : instruction.SourcePosition, interruptable : instruction.Interruptable); _instructions[instructionIndex] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.J, new object[] { lbeIndex + 1 }, sourcePosition : instruction.SourcePosition); } else if ((string)instruction.Payload[0] == "continue") { _instructions[instructionIndex - 1] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.US, new object[] { lbIndex }, sourcePosition : instruction.SourcePosition, interruptable : instruction.Interruptable); _instructions[instructionIndex] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.J, new object[] { lbIndex }, sourcePosition : instruction.SourcePosition); } } } _reprocessRequiredIndexes.Remove(InstructionCode.J); }
private bool OptimizeAssignmentInstructions() { bool optimized = false; Instruction <G> instruction1 = _oldInstructions[_currentIndex]; Instruction <G> instruction2 = _oldInstructions.ElementAtOrDefault(_currentIndex + 1); Instruction <G> instruction3 = _oldInstructions.ElementAtOrDefault(_currentIndex + 2); Instruction <G> instruction4 = _oldInstructions.ElementAtOrDefault(_currentIndex + 3); if (IsPushCode(instruction2.Code) && instruction4.Code == InstructionCode.RR && IsCreateOrGetPointerCode(instruction1.Code) && IsGetPointerOrValueCode(instruction3.Code)) { if (Enum.TryParse(instruction3.Code.ToString().Replace("R", "") + instruction1.Code.ToString().Replace("R", ""), out InstructionCode newCode)) { object[] payload = instruction3.Payload.Concat(instruction1.Payload).ToArray(); int? sourcePosition = instruction1.SourcePosition ?? instruction2.SourcePosition ?? instruction3.SourcePosition ?? instruction4.SourcePosition; bool interruptable = instruction1.Interruptable || instruction2.Interruptable || instruction3.Interruptable || instruction4.Interruptable; Instruction <G> newInstruction = InstructionProvider <G> .GetInstruction(newCode, payload, sourcePosition, interruptable); _newInstructions.Add(newInstruction); AddInstructionOffset(-3); optimized = true; } } return(optimized); }
private void AddOperatedBooleanValuable(FragmentMatchData matchData) { AddItem(matchData.Parts.First(part => part.Name != "Nots")); foreach (IMatchData not in ((FragmentMatchData)matchData.Parts.FirstOrDefault(part => part.Name == "Nots")).Parts ?? Enumerable.Empty <IMatchData>()) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RNot, sourcePosition: not.StartIndex)); } }
private void AddValuedIndex(FragmentMatchData matchData) { FragmentMatchData evaluable = (FragmentMatchData)matchData.Parts[0]; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); AddItem(evaluable); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RVK, new object[] { _isAssignmentTarget }, sourcePosition: matchData.StartIndex)); }
private void AddItemReturn(FragmentMatchData matchData) { if (matchData.Parts.ElementAtOrDefault(0) is FragmentMatchData item) { AddItem(item, true); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RLR, new object[] { 1 }, sourcePosition: matchData.StartIndex)); } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.AE, sourcePosition: matchData.StartIndex, interruptable: matchData.Parts.Count > 0)); }
private void AddDeclarationAssignment(FragmentMatchData matchData) { FragmentMatchData target = (FragmentMatchData)matchData.Parts[0]; FragmentMatchData evaluable = (FragmentMatchData)matchData.Parts[1]; AddNewStackVariable(target); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: target.StartIndex)); AddItem(evaluable); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RR, sourcePosition: target.StartIndex)); }
private void AddGetStackVariable(string name, int startIndex, bool interruptable) { if (_action.GetVariableOrDefault(name) is VariableInfo actionVariable) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.SPR, new object[] { _action.ActionStackLocation - actionVariable.StackLocation - 1 }, sourcePosition: startIndex, interruptable: interruptable)); } else { throw new LanguageConstraintException($"Variable '{name}' is not declared.", startIndex); } }
public async void ShouldReadAllInstructions() { // Arrange var provider = new InstructionProvider("TestData/input.txt"); // Act var instructions = await provider.ReadInstructions(); // Assert instructions.Count.Should().Be(779); instructions[0].Should().Be("S3"); instructions[^ 1].Should().Be("F51");
private void AddNumber(FragmentMatchData matchData) { string numberStr = matchData.Parts.Last().ToString(); if (matchData.Parts.Count > 1) { numberStr = $"-{numberStr}"; } object numberObj = int.TryParse(numberStr, out int numberInt) ? numberInt : (object)double.Parse(numberStr); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.VR, new object[] { numberObj }, sourcePosition: matchData.StartIndex)); }
public void BinaryConverter_ToBinary_ToInstructions(bool withDebugInto) { InstructionProvider <G> instructionProvider = new InstructionProvider <G>(); instructionProvider.SpecialInstructionMap.Add("SPECIAL", (executor, executionState, payload, stackRegister, stackPointers) => { }); List <Instruction <G> > input = new List <Instruction <G> > { instructionProvider.GetSpecialInstruction(new object[] { "SPECIAL", "other" }, 20, true), InstructionProvider <G> .GetInstruction(InstructionCode.J, new object[] { 8 }, 20, true), InstructionProvider <G> .GetInstruction(InstructionCode.RAR, new object[] { "name" }, 20, false), InstructionProvider <G> .GetInstruction(InstructionCode.RGAR, new object[] { null }, 20, true), InstructionProvider <G> .GetInstruction(InstructionCode.RGDPR, new object[] { "loc", null }, default, true),
private void AddAction(FragmentMatchData matchData, FragmentMatchData functionParameters, FragmentMatchData body) { // Start the declaration of the function _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.A, new object[] { false }, sourcePosition: functionParameters.StartIndex)); AddFunctionParameters(functionParameters); // Add instructions for the body of the function AddItem(body); // End the function declaration _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.AE, sourcePosition: matchData.StartIndex + matchData.Length)); }
private void AddNewStackVariable(string name, int startIndex, bool interruptable) { if (_action.Variables.ContainsKey(name)) { throw new LanguageConstraintException($"Variable '{name}' is already declared.", startIndex); } _action.Variables[name] = new VariableInfo { Name = name, StackLocation = _action.ActionStackLocation++, Depth = _action.BlockDepth }; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CSP, new object[] { name }, sourcePosition: startIndex, interruptable: interruptable)); }
private void AddNewArray(FragmentMatchData matchData) { FragmentMatchData arrayInitializer = (FragmentMatchData)matchData.Parts[0]; if (arrayInitializer.Parts.ElementAtOrDefault(0) is FragmentMatchData evaluable) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); AddItem(evaluable); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CVR, new object[] { true, null }, sourcePosition: matchData.StartIndex)); } else { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CVR, new object[] { false, null }, sourcePosition: matchData.StartIndex)); } }
private void AddBlock(FragmentMatchData matchData) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.B, sourcePosition: matchData.StartIndex, interruptable: true)); int origActionStackLocation = _action.ActionStackLocation; _action.BlockDepth++; foreach (IMatchData partMatchData in matchData.Parts) { AddItem(partMatchData, true); } _action.Variables.Where(pair => pair.Value.Depth >= _action.BlockDepth).Select(pair => pair.Key).ToList().ForEach(key => _action.Variables.Remove(key)); _action.ActionStackLocation = origActionStackLocation; _action.BlockDepth--; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.BE, sourcePosition: matchData.StartIndex + matchData.Length, interruptable: true)); }
private void AddArgumentValues(FragmentMatchData matchData) { if (matchData.Parts.Count > 0) { bool first = true; foreach (FragmentMatchData partMatchData in matchData.Parts) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: partMatchData.StartIndex)); AddItem(partMatchData, first); first = false; } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RLR, new object[] { matchData.Parts.Count }, sourcePosition: matchData.StartIndex)); } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RCE, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.LRR, new object[] { 1, false }, sourcePosition: matchData.StartIndex)); }
private bool OptimizeMultipleGetPointersInstructions() { bool optimized = false; if (IsMultipleGetPointersInstructions(out bool hasPushFirst)) { int offset = hasPushFirst ? 0 : -1; int count = 0; int? sourcePosition = null; bool interruptable = false; List <object> newPayload = new List <object> { _currentIndex > 0 ? offset : 0, null }; while (true) { Instruction <G> instruction = _oldInstructions.ElementAtOrDefault(_currentIndex + count + offset + 1); if (!IsGetPointerOrValueCode(instruction.Code)) { break; } offset++; newPayload.Add(instruction.Code); newPayload.AddRange(instruction.Payload); sourcePosition = sourcePosition ?? instruction.SourcePosition; interruptable |= instruction.Interruptable; count++; instruction = _oldInstructions.ElementAtOrDefault(_currentIndex + count + offset); if (!IsPushCode(instruction.Code)) { break; } } newPayload[1] = count; offset = count + offset - 1; _newInstructions.Add(InstructionProvider <G> .GetInstruction(InstructionCode.CPR, payload: newPayload.ToArray(), sourcePosition: sourcePosition, interruptable: interruptable)); AddInstructionOffset(-offset); optimized = true; } return(optimized); }
private void AddFunctionParameters(FragmentMatchData matchData) { string[] names = matchData.Parts.Select(part => GetIdentifierText((FragmentMatchData)part)).ToArray(); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.LRR, new object[] { names.Length, false }, sourcePosition: matchData.StartIndex)); List <object> payload = new List <object> { names.Length }; foreach (string name in names) { payload.Add(InstructionCode.CSP); payload.Add(name); AddParameterVariable(name); } if (matchData.Parts.Count > 0) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RCP, payload.ToArray(), sourcePosition: matchData.StartIndex)); } }
private int AddIfStatement(FragmentMatchData matchData) { FragmentMatchData condition = (FragmentMatchData)matchData.Parts[0]; FragmentMatchData body = (FragmentMatchData)matchData.Parts[1]; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CS, sourcePosition: matchData.StartIndex, interruptable: true)); AddItem(condition); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: condition.StartIndex)); int cbcIndex = _instructions.Count; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.NC, sourcePosition: condition.StartIndex)); AddItem(body); int endBlockNeededIndex = _instructions.Count; _instructions[cbcIndex] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.NC, new object[] { endBlockNeededIndex + 1 }, sourcePosition : matchData.Parts[1].StartIndex); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CSE, new object[] { "endif" }, sourcePosition: matchData.StartIndex + matchData.Length)); return(endBlockNeededIndex); }
private void AddAnonymousFunction(FragmentMatchData matchData) { FragmentMatchData functionParameters = (FragmentMatchData)matchData.Parts[0]; FragmentMatchData body = (FragmentMatchData)matchData.Parts[1]; ActionInfo outerAction = _action; ActionInfo innerAction = new ActionInfo { Parent = outerAction }; _action = innerAction; _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.J, payload: new object[] { "endaction" }, sourcePosition: matchData.StartIndex)); int actionStartIndex = _instructions.Count; AddAction(matchData, functionParameters, body); _action = outerAction; _instructions[actionStartIndex - 1] = InstructionProvider <GroupState> .GetInstruction(InstructionCode.J, payload : new object[] { _instructions.Count }, sourcePosition : matchData.StartIndex); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.AR, payload: new object[] { actionStartIndex }, sourcePosition: matchData.StartIndex)); if (innerAction.OrderedVariablesFromParent.Count > 0) { foreach (string name in innerAction.OrderedVariablesFromParent.Select(variable => variable.Name).Reverse()) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); AddGetStackVariable(name, matchData.StartIndex, false); } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RLR, new object[] { innerAction.OrderedVariablesFromParent.Count }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.LRAS, new object[] { innerAction.OrderedVariablesFromParent.Count }, sourcePosition: matchData.StartIndex)); } if (_reprocessRequiredIndexes.Count > 0) { throw new LanguageConstraintException("Invalid operation", _reprocessRequiredIndexes.Values.FirstOrDefault()?.FirstOrDefault()); } }
private bool OptimizeCopyPushInstructions() { bool optimized = false; Instruction <G> instruction1 = _oldInstructions[_currentIndex]; if (IsGetPointerOrValueCode(instruction1.Code)) { Instruction <G> instruction2 = _oldInstructions.ElementAtOrDefault(_currentIndex + 1); Instruction <G> instruction3 = _oldInstructions.ElementAtOrDefault(_currentIndex + 2); if (instruction2.Code == InstructionCode.PHR && instruction3.Code == instruction1.Code && Enumerable.SequenceEqual(instruction1.Payload, instruction3.Payload)) { _newInstructions.Add(instruction1); _newInstructions.Add(InstructionProvider <G> .GetInstruction(InstructionCode.CPHR, sourcePosition: instruction3.SourcePosition)); optimized = true; AddInstructionOffset(-1, 2); } } return(optimized); }
private void AddValuablePrefix(FragmentMatchData matchData) { if (matchData.Parts.ElementAtOrDefault(0) is IMatchData partMatchData) { switch (partMatchData.Name) { case "Not": AddNot((FragmentMatchData)partMatchData); break; case "Increment": _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: matchData.StartIndex)); AddIncrement((StringMatchData)partMatchData); break; case "Decrement": _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: matchData.StartIndex)); AddDecrement((FragmentMatchData)partMatchData); break; } } }
private void AddValuableSuffix(FragmentMatchData matchData) { if (matchData.Parts.ElementAtOrDefault(0) is IMatchData partMatchData) { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.VR, new object[] { null }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RM, new object[] { 1 }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RR, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RM, new object[] { 1 }, sourcePosition: matchData.StartIndex)); _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: matchData.StartIndex)); switch (partMatchData.Name) { case "Increment": AddIncrement((StringMatchData)partMatchData); break; case "Decrement": AddDecrement((FragmentMatchData)partMatchData); break; } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PLR, sourcePosition: matchData.StartIndex)); } }
private void AddAssignment(FragmentMatchData matchData) { _isAssignmentTarget = true; FragmentMatchData target = (FragmentMatchData)matchData.Parts[0]; StringMatchData assignmentEqual = (StringMatchData)matchData.Parts[1]; FragmentMatchData evaluable = (FragmentMatchData)matchData.Parts[2]; AddItem(target, true); _isAssignmentTarget = false; if (_instructions.Last().Code == InstructionCode.LRR) { throw new LanguageConstraintException($"Cannot assign to the return of a function.", target.StartIndex + target.Length); } if (assignmentEqual.Name != "Equal") { _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.CPHR, sourcePosition: target.StartIndex)); } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.PHR, sourcePosition: target.StartIndex)); AddItem(evaluable); switch (assignmentEqual.Name) { case "MinusEqual": _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RSubtract, sourcePosition: target.StartIndex)); break; case "PlusEqual": _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RPlus, sourcePosition: target.StartIndex)); break; } _instructions.Add(InstructionProvider <GroupState> .GetInstruction(InstructionCode.RR, sourcePosition: target.StartIndex)); }
private static async Task <List <string> > ReadInstruction() { var provider = new InstructionProvider("Input/input.txt"); return(await provider.ReadInstructions()); }
public new static Instruction <G> GetInstruction(InstructionCode code, object[] payload, int?sourcePosition, bool interruptable, InstructionExecutionBody <G> executionBody) { return(InstructionProvider <G> .GetInstruction(code, payload, sourcePosition, interruptable, executionBody ?? ((executor, executionState, _, stackRegister, stackPointers) => { }))); }