コード例 #1
0
ファイル: ComparisonNode.cs プロジェクト: colinvh/DCPUC
        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);
        }
コード例 #2
0
ファイル: Scope.cs プロジェクト: colinvh/DCPUC
        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;
            }
        }
コード例 #3
0
ファイル: WhileStatementNode.cs プロジェクト: colinvh/DCPUC
        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, "", "");
            }
        }
コード例 #4
0
ファイル: InlineASMNode.cs プロジェクト: colinvh/DCPUC
 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 + " ;", "", "");
 }
コード例 #5
0
ファイル: VariableNameNode.cs プロジェクト: colinvh/DCPUC
        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;
        }
コード例 #6
0
ファイル: BranchStatementNode.cs プロジェクト: colinvh/DCPUC
 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);
 }
コード例 #7
0
ファイル: BlockNode.cs プロジェクト: colinvh/DCPUC
 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);
     }
 }
コード例 #8
0
ファイル: LibraryFunctionNode.cs プロジェクト: colinvh/DCPUC
 public override void CompileFunction(Assembly assembly, Scope topscope)
 {
     //if (references == 0) return;
     foreach (var line in code)
     {
         assembly.Barrier();
         assembly.Add(line, "", "");
     }
 }
コード例 #9
0
ファイル: ReturnStatementNode.cs プロジェクト: colinvh/DCPUC
 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", "", "");
 }
コード例 #10
0
ファイル: DataLiteralNode.cs プロジェクト: colinvh/DCPUC
 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;
 }
コード例 #11
0
ファイル: BinaryOperationNode.cs プロジェクト: colinvh/DCPUC
        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);
        }
コード例 #12
0
 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);
 }
コード例 #13
0
ファイル: DereferenceNode.cs プロジェクト: colinvh/DCPUC
 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);
     }
 }
コード例 #14
0
 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");
 }
コード例 #15
0
 public override void Compile(Assembly assembly, Scope scope, Register target)
 {
     scope.pendingFunctions.Add(this);
 }
コード例 #16
0
ファイル: CompilableNode.cs プロジェクト: colinvh/DCPUC
 public virtual void Compile(Assembly assembly, Scope scope, Register target)
 {
     throw new NotImplementedException();
 }
コード例 #17
0
ファイル: CompilableNode.cs プロジェクト: colinvh/DCPUC
 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");
 }
コード例 #18
0
        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;
        }
コード例 #19
0
ファイル: DataLiteralNode.cs プロジェクト: colinvh/DCPUC
 public override void Compile(Assembly assembly, Scope scope, Register target)
 {
     throw new CompileError("Should never reach this.");
 }
コード例 #20
0
ファイル: FunctionCallNode.cs プロジェクト: colinvh/DCPUC
 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;
 }
コード例 #21
0
ファイル: AssignmentNode.cs プロジェクト: colinvh/DCPUC
        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);
                    }
                }
            }
        }
コード例 #22
0
ファイル: FunctionCallNode.cs プロジェクト: colinvh/DCPUC
        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;
            }
        }
コード例 #23
0
ファイル: NumberLiteralNode.cs プロジェクト: colinvh/DCPUC
 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;
 }
コード例 #24
0
ファイル: BranchStatementNode.cs プロジェクト: colinvh/DCPUC
        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");
        }