public override void Compile(Assembly assembly, Scope scope, Register target) { throw new CompileError("Comparisons in general expressions are not implemented"); //Evaluate in reverse in case both need to go on the stack var secondTarget = scope.FindFreeRegister(); if (Scope.IsRegister((Register)secondTarget)) scope.UseRegister(secondTarget); (ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)secondTarget); if (AsString == "==" || AsString == "!=") { (ChildNodes[0] as CompilableNode).Compile(assembly, scope, Register.STACK); if (target == Register.STACK) { assembly.Add("SET", Scope.TempRegister, "0x0", "Equality onto stack"); assembly.Add((AsString == "==" ? "IFE" : "IFN"), "POP", Scope.GetRegisterLabelSecond(secondTarget)); assembly.Add("SET", Scope.TempRegister, "0x1"); assembly.Add("SET", "PUSH", Scope.TempRegister); } else { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "0x0", "Equality into register"); assembly.Add((AsString == "==" ? "IFE" : "IFN"), "POP", Scope.GetRegisterLabelSecond(secondTarget)); assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "0x1"); } } if (secondTarget == (int)Register.STACK) scope.stackDepth -= 1; else scope.FreeRegister(secondTarget); }
public static void CompileRoot(FunctionDeclarationNode root, Assembly assembly, Action<string> onError) { DCPUC.Scope.Reset(); var scope = new DCPUC.Scope(); var end_of_program = new Variable(); end_of_program.location = Register.STATIC; end_of_program.name = "__endofprogram"; end_of_program.staticLabel = "ENDOFPROGRAM"; end_of_program.emitBrackets = false; scope.variables.Add(end_of_program); var library = new List<String>(System.IO.File.ReadAllLines("libdcpuc.txt")); //root.InsertLibrary(library); try { root.CompileFunction(assembly, scope); foreach (var dataItem in DCPUC.Scope.dataElements) { var datString = ""; foreach (var item in dataItem.Item2) { datString += item; datString += ", "; } assembly.Add(":" + dataItem.Item1, "DAT", datString.Substring(0, datString.Length - 2)); } assembly.Add(":ENDOFPROGRAM", "", ""); } catch (DCPUC.CompileError c) { onError(c.Message); return; } }
public override void Compile(Assembly assembly, Scope scope, Register target) { var topLabel = Scope.GetLabel() + "BEGIN_WHILE"; assembly.Add(":" + topLabel, "", ""); var clauseOrder = CompileConditional(assembly, scope, ChildNodes[0] as CompilableNode); if (clauseOrder == ClauseOrder.ConstantPass) { CompileBlock(assembly, scope, ChildNodes[1] as CompilableNode); assembly.Add("SET", "PC", topLabel); } else if (clauseOrder == ClauseOrder.ConstantFail) { } else if (clauseOrder == ClauseOrder.PassFirst) { var endLabel = Scope.GetLabel() + "END"; assembly.Add("SET", "PC", endLabel); CompileBlock(assembly, scope, ChildNodes[1] as CompilableNode); assembly.Add("SET", "PC", topLabel); assembly.Add(":" + endLabel, "", ""); } else if (clauseOrder == ClauseOrder.FailFirst) { var elseLabel = Scope.GetLabel() + "ELSE"; var endLabel = Scope.GetLabel() + "END"; assembly.Add("SET", "PC", elseLabel); assembly.Add("SET", "PC", endLabel); assembly.Add(":" + elseLabel, "", ""); CompileBlock(assembly, scope, ChildNodes[1] as CompilableNode); assembly.Add("SET", "PC", topLabel); assembly.Add(":" + endLabel, "", ""); } }
public override void Compile(Assembly assembly, Scope scope, Register target) { var lines = AsString.Split(new String[2]{"\n", "\r"}, StringSplitOptions.RemoveEmptyEntries); assembly.Barrier(); foreach (var str in lines) assembly.Add(str + " ;", "", ""); }
public override void Compile(Assembly assembly, Scope scope, Register target) { var variable = scope.FindVariable(AsString); if (variable == null) throw new CompileError("Could not find variable " + AsString); if (variable.location == Register.CONST) { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), variable.staticLabel); } else if (variable.location == Register.STATIC) { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "[" + variable.staticLabel + "]"); } else if (variable.location == Register.STACK) { if (scope.stackDepth - variable.stackOffset > 1) { assembly.Add("SET", Scope.TempRegister, "SP"); assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "[" + hex(scope.stackDepth - variable.stackOffset - 1) + "+" + Scope.TempRegister + "]", "Fetching variable"); } else assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "PEEK", "Fetching variable"); } else { if (target == variable.location) return; assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), Scope.GetRegisterLabelSecond((int)variable.location), "Fetching variable"); } if (target == Register.STACK) scope.stackDepth += 1; }
public static void CompileBlock(Assembly assembly, Scope scope, CompilableNode block) { var blockScope = BeginBlock(scope); assembly.Barrier(); block.Compile(assembly, blockScope, Register.DISCARD); assembly.Barrier(); EndBlock(assembly, blockScope); }
public override void Compile(Assembly assembly, Scope scope, Register target) { foreach (var child in ChildNodes) { assembly.Barrier(); (child as CompilableNode).Compile(assembly, scope, Register.DISCARD); } }
public override void CompileFunction(Assembly assembly, Scope topscope) { //if (references == 0) return; foreach (var line in code) { assembly.Barrier(); assembly.Add(line, "", ""); } }
public override void Compile(Assembly assembly, Scope scope, Register target) { var reg = scope.FindAndUseFreeRegister(); (ChildNodes[0] as CompilableNode).Compile(assembly, scope, (Register)reg); if (reg != (int)Register.A) assembly.Add("SET", "A", Scope.GetRegisterLabelSecond(reg)); scope.FreeMaybeRegister(reg); if (reg == (int)Register.STACK) scope.stackDepth -= 1; if (scope.activeFunction != null) scope.activeFunction.CompileReturn(assembly, scope); else assembly.Add("BRK", "", ""); }
public override void Compile(Assembly assembly, Scope scope, Register target) { //if (data.Count == 1) // assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), hex(data[0])); //else //{ assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), dataLabel); Scope.AddData(dataLabel, data); //} if (target == Register.STACK) scope.stackDepth += 1; }
public override void Compile(Assembly assembly, Scope scope, Register target) { int secondTarget = (int)Register.STACK; var secondConstant = (ChildNodes[1] as CompilableNode).IsConstant(); var firstConstant = (ChildNodes[0] as CompilableNode).IsConstant(); if (firstConstant && secondConstant) { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), hex(GetConstantValue())); if (target == Register.STACK) scope.stackDepth += 1; return; } if (!secondConstant) { secondTarget = scope.FindAndUseFreeRegister(); (ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)secondTarget); } if (!firstConstant) (ChildNodes[0] as CompilableNode).Compile(assembly, scope, target); if (target == Register.STACK) { assembly.Add("SET", Scope.TempRegister, firstConstant ? hex((ChildNodes[0] as CompilableNode).GetConstantValue()) : "POP"); assembly.Add(opcodes[AsString], Scope.TempRegister, secondConstant ? hex((ChildNodes[1] as CompilableNode).GetConstantValue()) : Scope.GetRegisterLabelSecond(secondTarget)); assembly.Add("SET", "PUSH", Scope.TempRegister); } else { if (firstConstant) assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), hex((ChildNodes[0] as CompilableNode).GetConstantValue())); assembly.Add(opcodes[AsString], Scope.GetRegisterLabelFirst((int)target), secondConstant ? hex((ChildNodes[1] as CompilableNode).GetConstantValue()) : Scope.GetRegisterLabelSecond(secondTarget)); } if (secondTarget == (int)Register.STACK && !secondConstant) scope.stackDepth -= 1; else scope.FreeMaybeRegister(secondTarget); }
public virtual void CompileFunction(Assembly assembly, Scope topscope) { Scope lScope; if (localScope != null) { foreach (var variable in topscope.variables) if (variable.location == Register.STATIC) localScope.variables.Add(variable); lScope = localScope.Push(new Scope()); assembly.Add(":" + label, "", ""); } else lScope = topscope; assembly.Barrier(); if (localScope != null) lScope.stackDepth += 1; //account for return address (ChildNodes[0] as CompilableNode).Compile(assembly, lScope, Register.DISCARD); if (localScope != null) CompileReturn(assembly, lScope); else assembly.Add("BRK", "", ""); assembly.Barrier(); //Should leave the return value, if any, in A. foreach (var function in lScope.pendingFunctions) function.CompileFunction(assembly, topscope); }
public override void Compile(Assembly assembly, Scope scope, Register target) { var destRegister = target == Register.STACK ? scope.FindAndUseFreeRegister() : (int)target; (ChildNodes[0] as CompilableNode).Compile(assembly, scope, (Register)destRegister); if (target == Register.STACK) { if (destRegister == (int)Register.STACK) assembly.Add("SET", "PEEK", "[PEEK]"); else { assembly.Add("SET", "PUSH", "[" + Scope.GetRegisterLabelSecond(destRegister) + "]"); scope.stackDepth += 1; scope.FreeMaybeRegister(destRegister); } } else { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), "[" + Scope.GetRegisterLabelSecond(destRegister) + "]"); if (destRegister == (int)Register.STACK) scope.stackDepth -= 1; else if (destRegister != (int)target) scope.FreeMaybeRegister(destRegister); } }
internal void CompileReturn(Assembly assembly, Scope lScope) { if (lScope.stackDepth - localScope.stackDepth > 1) assembly.Add("ADD", "SP", hex(lScope.stackDepth - localScope.stackDepth - 1), "Cleanup stack"); assembly.Add("SET", "PC", "POP", "Return"); }
public override void Compile(Assembly assembly, Scope scope, Register target) { scope.pendingFunctions.Add(this); }
public virtual void Compile(Assembly assembly, Scope scope, Register target) { throw new NotImplementedException(); }
public static void EndBlock(Assembly assembly, Scope scope) { if (scope.stackDepth - scope.parentDepth > 0) assembly.Add("ADD", "SP", hex(scope.stackDepth - scope.parentDepth), "End block"); }
public override void Compile(Assembly assembly, Scope scope, Register target) { var newVariable = new Variable(); newVariable.name = AsString; newVariable.scope = scope; newVariable.stackOffset = scope.stackDepth; if (declLabel == "var") { newVariable.location = (Register)scope.FindAndUseFreeRegister(); if (newVariable.location == Register.I) newVariable.location = Register.STACK; if (ChildNodes[0] is BlockLiteralNode) { var size = Child(0).GetConstantValue(); scope.stackDepth += size; assembly.Add("SUB", "SP", hex(size)); assembly.Add("SET", Scope.GetRegisterLabelFirst((int)newVariable.location), "SP"); if (newVariable.location == Register.STACK) scope.stackDepth += 1; } else (ChildNodes[0] as CompilableNode).Compile(assembly, scope, newVariable.location); } else if (declLabel == "static") { newVariable.location = Register.STATIC; if (Child(0) is BlockLiteralNode) { newVariable.staticLabel = Scope.GetLabel() + "_STATIC_" + AsString; var datLabel = Scope.GetLabel() + "_STATIC_" + AsString + "_DATA"; Scope.AddData(datLabel, (ChildNodes[0] as BlockLiteralNode).MakeData()); Scope.AddData(newVariable.staticLabel, datLabel); } else if ((ChildNodes[0] as CompilableNode).IsConstant()) { newVariable.staticLabel = Scope.GetLabel() + "_STATIC_" + AsString; Scope.AddData(newVariable.staticLabel, new List<ushort>(new ushort[] { (ChildNodes[0] as CompilableNode).GetConstantValue() })); } else if (ChildNodes[0] is DataLiteralNode) { newVariable.staticLabel = Scope.GetLabel() + "_STATIC_" + AsString; var datLabel = Scope.GetLabel() + "_STATIC_" + AsString + "_DATA"; Scope.AddData(datLabel, (ChildNodes[0] as DataLiteralNode).data); Scope.AddData(newVariable.staticLabel, datLabel); } else throw new CompileError("Statics must be initialized to a constant value"); } else if (declLabel == "const") { newVariable.location = Register.CONST; if (Child(0) is BlockLiteralNode) { newVariable.staticLabel = Scope.GetLabel() + "_STATIC_" + AsString; Scope.AddData(newVariable.staticLabel, (ChildNodes[0] as BlockLiteralNode).MakeData()); } else if ((ChildNodes[0] as CompilableNode).IsConstant()) { //throw new CompileError("Initializing const to integrals is not supported yet"); newVariable.staticLabel = (ChildNodes[0] as CompilableNode).GetConstantToken(); //Scope.AddData(newVariable.staticLabel, (ChildNodes[0] as CompilableNode).GetConstantToken()); } else if (ChildNodes[0] is DataLiteralNode) { newVariable.staticLabel = Scope.GetLabel() + "_STATIC_" + AsString; Scope.AddData(newVariable.staticLabel, (ChildNodes[0] as DataLiteralNode).data); } } scope.variables.Add(newVariable); //scope.stackDepth += 1; }
public override void Compile(Assembly assembly, Scope scope, Register target) { throw new CompileError("Should never reach this."); }
private static void PushRegister(Assembly assembly, Scope scope, Register r) { assembly.Add("SET", "PUSH", Scope.GetRegisterLabelSecond((int)r), "Saving register"); scope.FreeRegister(0); scope.stackDepth += 1; }
public override void Compile(Assembly assembly, Scope scope, Register target) { if (ChildNodes[0] is VariableNameNode) { var variable = scope.FindVariable(ChildNodes[0].AsString); if (variable == null) throw new CompileError("Could not find variable " + ChildNodes[0].AsString); if (variable.location == Register.STACK) { var register = scope.FindAndUseFreeRegister(); (ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)register); scope.FreeMaybeRegister(register); if (scope.stackDepth - variable.stackOffset > 1) { assembly.Add("SET", Scope.TempRegister, "SP"); assembly.Add("SET", "[" + hex(scope.stackDepth - variable.stackOffset - 1) + "+" + Scope.TempRegister + "]", Scope.GetRegisterLabelSecond(register), "Fetching variable"); } else assembly.Add("SET", "PEEK", Scope.GetRegisterLabelSecond(register), "Fetching variable"); if (register == (int)Register.STACK) scope.stackDepth -= 1; } else if (variable.location == Register.STATIC) { //if (!variable.emitBrackets) throw new CompileError("Can't assign to data pointers!"); var register = scope.FindAndUseFreeRegister(); (ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)register); scope.FreeMaybeRegister(register); assembly.Add("SET", "[" + variable.staticLabel + "]", Scope.GetRegisterLabelSecond(register)); if (register == (int)Register.STACK) scope.stackDepth -= 1; } else if (variable.location == Register.CONST) { throw new CompileError("Can't assign to const"); } else (ChildNodes[1] as CompilableNode).Compile(assembly, scope, variable.location); } else if (ChildNodes[0] is DereferenceNode) { bool firstConstant = false; int firstRegister = (int)Register.STACK; if ((ChildNodes[0].ChildNodes[0] as CompilableNode).IsConstant()) firstConstant = true; else { firstRegister = scope.FindAndUseFreeRegister(); (ChildNodes[0].ChildNodes[0] as CompilableNode).Compile(assembly, scope, (Register)firstRegister); } var secondRegister = scope.FindAndUseFreeRegister(); (ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)secondRegister); if (firstConstant) { assembly.Add("SET", "[" + hex((ChildNodes[0].ChildNodes[0] as CompilableNode).GetConstantValue()) + "]", Scope.GetRegisterLabelSecond(secondRegister)); if (secondRegister == (int)Register.STACK) scope.stackDepth -= 1; else scope.FreeMaybeRegister(secondRegister); } else { if (firstRegister == (int)Register.STACK && secondRegister == (int)Register.STACK) { assembly.Add("SET", Scope.TempRegister, "POP"); assembly.Add("SET", "[" + Scope.TempRegister + "]", "POP"); scope.stackDepth -= 2; } else if (secondRegister == (int)Register.STACK) { assembly.Add("SET", "[" + Scope.GetRegisterLabelFirst(firstRegister) + "]", "POP"); scope.stackDepth -= 1; scope.FreeMaybeRegister(firstRegister); return; } else if (firstRegister == (int)Register.STACK) { throw new CompileError("Impossible situation entered"); } else { assembly.Add("SET", "[" + Scope.GetRegisterLabelFirst(firstRegister) + "]", Scope.GetRegisterLabelSecond(secondRegister)); scope.FreeMaybeRegister(firstRegister); scope.FreeMaybeRegister(secondRegister); } } } }
public override void Compile(Assembly assembly, Scope scope, Register target) { var func = findFunction(this, AsString); if (func == null) throw new CompileError("Can't find function - " + AsString); if (func.parameterCount != ChildNodes.Count) throw new CompileError("Incorrect number of arguments - " + AsString); func.references += 1; //Marshall registers var startingRegisterState = scope.SaveRegisterState(); for (int i = 0; i < 3; ++i) { if (startingRegisterState[i] == RegisterState.Used) { PushRegister(assembly, scope, (Register)i); if (scope.activeFunction != null && scope.activeFunction.parameterCount > i) { scope.activeFunction.localScope.variables[i].location = Register.STACK; scope.activeFunction.localScope.variables[i].stackOffset = scope.stackDepth - 1; } } if (func.parameterCount > i) { scope.UseRegister(i); (ChildNodes[i] as CompilableNode).Compile(assembly, scope, (Register)i); } } for (int i = 3; i < 7; ++i) if (startingRegisterState[i] == RegisterState.Used) PushRegister(assembly, scope, (Register)i); if (func.parameterCount > 3) for (int i = 3; i < func.parameterCount; ++i) (ChildNodes[i] as CompilableNode).Compile(assembly, scope, Register.STACK); assembly.Add("JSR", func.label, "", "Calling function"); if (func.parameterCount > 3) //Need to remove parameters from stack { assembly.Add("ADD", "SP", hex(func.parameterCount - 3), "Remove parameters"); scope.stackDepth -= (func.parameterCount - 3); } if (scope.activeFunction != null) for (int i = 0; i < 3 && i < scope.activeFunction.parameterCount; ++i) scope.activeFunction.localScope.variables[i].location = (Register)i; var saveA = startingRegisterState[0] == RegisterState.Used; if (saveA && target != Register.DISCARD) assembly.Add("SET", Scope.TempRegister, "A", "Save return value from being overwritten by stored register"); for (int i = 6; i >= 0; --i) { if (startingRegisterState[i] == RegisterState.Used) { assembly.Add("SET", Scope.GetRegisterLabelFirst(i), "POP", "Restoring register"); scope.UseRegister(i); scope.stackDepth -= 1; } } if (target == Register.A && !saveA) return; else if (Scope.IsRegister(target)) assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), saveA ? Scope.TempRegister : "A"); else if (target == Register.STACK) { assembly.Add("SET", "PUSH", saveA ? Scope.TempRegister : "A", "Put return value on stack"); scope.stackDepth += 1; } }
public override void Compile(Assembly assembly, Scope scope, Register target) { assembly.Add("SET", Scope.GetRegisterLabelFirst((int)target), hex(Value)); if (target == Register.STACK) scope.stackDepth += 1; }
public static ClauseOrder CompileConditional(Assembly assembly, Scope scope, CompilableNode conditionNode) { if (!(conditionNode is ComparisonNode)) { var condTarget = scope.FindAndUseFreeRegister(); conditionNode.Compile(assembly, scope, (Register)condTarget); assembly.Add("IFE", Scope.GetRegisterLabelSecond(condTarget), "0x0", "If from expression"); scope.FreeMaybeRegister(condTarget); return ClauseOrder.PassFirst; } else { var op = conditionNode.AsString; ushort firstConstantValue = 0, secondConstantValue = 0; var firstIsConstant = (conditionNode.ChildNodes[0] as CompilableNode).IsConstant(); var secondIsConstant = (conditionNode.ChildNodes[1] as CompilableNode).IsConstant(); int firstRegister = (int)Register.STACK; int secondRegister = (int)Register.STACK; if (secondIsConstant) secondConstantValue = (conditionNode.ChildNodes[1] as CompilableNode).GetConstantValue(); else { secondRegister = scope.FindAndUseFreeRegister(); (conditionNode.ChildNodes[1] as CompilableNode).Compile(assembly, scope, (Register)secondRegister); } if (firstIsConstant) firstConstantValue = (conditionNode.ChildNodes[0] as CompilableNode).GetConstantValue(); else { firstRegister = scope.FindAndUseFreeRegister(); (conditionNode.ChildNodes[0] as CompilableNode).Compile(assembly, scope, (Register)firstRegister); } if (op == "==") { if (firstIsConstant && secondIsConstant) { if (firstConstantValue == secondConstantValue) { return ClauseOrder.ConstantPass; } else { return ClauseOrder.ConstantFail; } } else if (firstIsConstant) { assembly.Add("IFE", (conditionNode.ChildNodes[0] as CompilableNode).GetConstantToken(), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } else if (secondIsConstant) { assembly.Add("IFE", Scope.GetRegisterLabelSecond(firstRegister), hex(secondConstantValue)); releaseRegister(scope, firstRegister); return ClauseOrder.FailFirst; } else { assembly.Add("IFE", Scope.GetRegisterLabelSecond(firstRegister), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, firstRegister); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } } else if (op == "!=") { if (firstIsConstant && secondIsConstant) { if (firstConstantValue != secondConstantValue) { return ClauseOrder.ConstantPass; } else { return ClauseOrder.ConstantFail; } } else if (firstIsConstant) { assembly.Add("IFN", hex(firstConstantValue), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } else if (secondIsConstant) { assembly.Add("IFN", Scope.GetRegisterLabelSecond(firstRegister), hex(secondConstantValue)); releaseRegister(scope, firstRegister); return ClauseOrder.FailFirst; } else { assembly.Add("IFN", Scope.GetRegisterLabelSecond(firstRegister), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, firstRegister); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } } else if (op == ">") { if (firstIsConstant && secondIsConstant) { if (firstConstantValue > secondConstantValue) { return ClauseOrder.ConstantPass; } else { return ClauseOrder.ConstantFail; } } else if (firstIsConstant) { assembly.Add("IFG", hex(firstConstantValue), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } else if (secondIsConstant) { assembly.Add("IFG", Scope.GetRegisterLabelSecond(firstRegister), hex(secondConstantValue)); releaseRegister(scope, firstRegister); return ClauseOrder.FailFirst; } else { assembly.Add("IFG", Scope.GetRegisterLabelSecond(firstRegister), Scope.GetRegisterLabelSecond(secondRegister)); releaseRegister(scope, firstRegister); releaseRegister(scope, secondRegister); return ClauseOrder.FailFirst; } } } throw new CompileError("Impossible situation reached"); }