Esempio n. 1
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Multiplicative expression");

            ((ICodeEmitter)Tokens[0]).Emit(context);

            var t1ExpressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            if (Tokens.Count > 1)
            {
                TypeChecking.CheckExpressionTypeIsNumeric(t1ExpressionType);
            }

            for (int i = 1; i < Tokens.Count; i += 2)
            {
                ((ICodeEmitter)Tokens[i + 1]).Emit(context);

                var t2ExpressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context);

                TypeChecking.CheckExpressionTypeIsNumeric(t2ExpressionType);
                TypeChecking.CheckExpressionTypesMatch(t1ExpressionType, t2ExpressionType);

                t1ExpressionType = t2ExpressionType;

                string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value;

                context.EmitInstruction(new IRPop()
                {
                    To = "ebx"
                });
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                switch (op)
                {
                case "*":
                    context.EmitInstruction(new IRMult()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    break;

                case "/":
                    context.EmitInstruction(new IRDiv()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    break;
                }

                context.EmitInstruction(new IRPushRegister()
                {
                    From = "ecx"
                });
            }
        }
Esempio n. 2
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Boolean expression");

            ((ICodeEmitter)Tokens[0]).Emit(context);

            var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            if (Tokens.Count > 1)
            {
                TypeChecking.CheckExpressionTypeIsBoolean(expressionType);
            }

            for (int i = 1; i < Tokens.Count; i += 2)
            {
                string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value;

                ((ICodeEmitter)Tokens[i + 1]).Emit(context);

                expressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context);

                TypeChecking.CheckExpressionTypeIsBoolean(expressionType);

                context.EmitInstruction(new IRPop()
                {
                    To = "ebx"
                });
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                var trueLabel = new LabelAddressValue(context.CreateNewLabel());

                switch (op)
                {
                case "&&":
                    context.EmitInstruction(new IRAnd()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    context.EmitInstruction(new IRCompareImmediate()
                    {
                        Left = "ecx", Right = new ImmediateValue(0)
                    });
                    context.EmitInstruction(new IRJumpNE()
                    {
                        Address = trueLabel
                    });
                    break;

                case "||":
                    context.EmitInstruction(new IROr()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    context.EmitInstruction(new IRCompareImmediate()
                    {
                        Left = "ecx", Right = new ImmediateValue(0)
                    });
                    context.EmitInstruction(new IRJumpNE()
                    {
                        Address = trueLabel
                    });
                    break;
                }

                var skipTrueLabel = new LabelAddressValue(context.CreateNewLabel());

                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(0)
                });
                context.EmitInstruction(new IRJumpImmediate()
                {
                    Address = skipTrueLabel
                });
                context.EmitLabel(trueLabel.Value);
                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(1)
                });
                context.EmitLabel(skipTrueLabel.Value);
            }
        }
Esempio n. 3
0
        public override void CaseADelegateInvokeExp(ADelegateInvokeExp node)
        {
            //Build a list of the possible methods
            AASourceFile       currentFile    = Util.GetAncestor <AASourceFile>(node);
            List <AMethodDecl> methods        = new List <AMethodDecl>();
            ANamedType         type           = (ANamedType)finalTrans.data.ExpTypes[node.GetReceiver()];
            AMethodDecl        delegateMethod = finalTrans.data.DelegateTypeLinks[type];

            foreach (KeyValuePair <ADelegateExp, AMethodDecl> delegateCreationPair in finalTrans.data.DelegateCreationMethod)
            {
                if (TypeChecking.Assignable(delegateCreationPair.Key.GetType(), type))
                {
                    if (!methods.Contains(delegateCreationPair.Value))
                    {
                        methods.Add(delegateCreationPair.Value);
                    }
                }
            }
            MoveMethodDeclsOut mover;

            if (methods.Count == 0)
            {
                //Can only remove it if the return value is unused
                if (!(node.Parent() is AExpStm))
                {
                    finalTrans.errors.Add(new ErrorCollection.Error(node.GetToken(),
                                                                    currentFile,
                                                                    "No possible methods found for delegate invoke."));
                    throw new ParserException(node.GetToken(), "Delegates.OutADelegateInvokeExp");
                }

                mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data);
                foreach (Node arg in node.GetArgs())
                {
                    arg.Apply(mover);
                }
                node.Parent().Parent().RemoveChild(node.Parent());
                foreach (PStm stm in mover.NewStatements)
                {
                    stm.Apply(this);
                }
                return;
            }
            if (methods.Count == 1)
            {
                ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList());
                while (node.GetArgs().Count > 0)
                {
                    invoke.GetArgs().Add(node.GetArgs()[0]);
                }

                //If we have a struct method, add the pointer from the delegate
                if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(methods[0])))
                {
                    AStructDecl      targetStr        = finalTrans.data.StructMethods.First(str => str.Value.Contains(methods[0])).Key;
                    AMethodDecl      getPointerDecl   = GetPointerMethod(targetStr.GetDimention() != null);
                    ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList()
                    {
                        node.GetReceiver()
                    });
                    invoke.GetArgs().Add(getPointerInvoke);

                    finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl;
                    finalTrans.data.ExpTypes[getPointerInvoke]          = getPointerDecl.GetReturnType();
                }

                finalTrans.data.SimpleMethodLinks[invoke] = methods[0];
                finalTrans.data.ExpTypes[invoke]          = methods[0].GetReturnType();
                node.ReplaceBy(invoke);
                return;
            }
            //Multiple methods. Make

            /*
             * <Methods moved out from reciever>
             * string delegate = GetMethodPart(<reciever>);
             * if (delegate == "...")
             * {
             *    Foo(...);
             * }
             * else if (delegate == "...")
             * {
             *    Bar(..., GetPointerPart(<reciever>);
             * }
             * else if(...)
             * ...
             * else
             * {
             *     UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("[<file>:<line>]: No methods matched delegate."));
             *     int i = 1/0;
             *     return;
             * }
             *
             */
            AABlock block = new AABlock(new ArrayList(), new TRBrace("}"));

            mover = new MoveMethodDeclsOut("delegateVar", finalTrans.data);
            node.GetReceiver().Apply(mover);
            AMethodDecl      methodPartMethod = GetMethodMethod();
            ASimpleInvokeExp methodPartInvoke = new ASimpleInvokeExp(new TIdentifier("GetMethodPart"),
                                                                     new ArrayList()
            {
                Util.MakeClone(node.GetReceiver(),
                               finalTrans.data)
            });

            finalTrans.data.SimpleMethodLinks[methodPartInvoke] = methodPartMethod;
            finalTrans.data.ExpTypes[methodPartInvoke]          = methodPartMethod.GetReturnType();
            AALocalDecl methodPartDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                         new ANamedType(new TIdentifier("string"), null),
                                                         new TIdentifier("methodPart"), methodPartInvoke);

            block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), methodPartDecl));
            //If the invoke's return value is used, get the lvalue
            PLvalue leftSide;

            if (node.Parent() is AALocalDecl)
            {
                leftSide = new ALocalLvalue(new TIdentifier("renameMe"));
                finalTrans.data.LocalLinks[(ALocalLvalue)leftSide] = (AALocalDecl)node.Parent();
                finalTrans.data.LvalueTypes[leftSide] = new ANamedType(new TIdentifier("string"), null);
                PStm    pStm   = Util.GetAncestor <PStm>(node);
                AABlock pBlock = (AABlock)pStm.Parent();
                pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + 1, new ABlockStm(new TLBrace("{"), block));
                node.Parent().RemoveChild(node);
            }
            else if (node.Parent() is AAssignmentExp)
            {
                AAssignmentExp assignExp = (AAssignmentExp)node.Parent();
                leftSide = assignExp.GetLvalue();
                leftSide.Apply(mover);

                PStm pStm = Util.GetAncestor <PStm>(node);
                pStm.ReplaceBy(new ABlockStm(new TLBrace("{"), block));
            }
            else if (node.Parent() is AExpStm)
            {
                //No assignments needed
                leftSide = null;
                node.Parent().ReplaceBy(new ABlockStm(new TLBrace("{"), block));
            }
            else
            {
                //Create a new local
                AALocalDecl leftSideDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                           Util.MakeClone(delegateMethod.GetReturnType(),
                                                                          finalTrans.data),
                                                           new TIdentifier("delegateVar"), null);
                ALocalLvalue leftSideLink    = new ALocalLvalue(new TIdentifier("delegateVar"));
                ALvalueExp   leftSideLinkExp = new ALvalueExp(leftSideLink);


                PStm    pStm   = Util.GetAncestor <PStm>(node);
                AABlock pBlock = (AABlock)pStm.Parent();
                pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), new ABlockStm(new TLBrace("{"), block));

                node.ReplaceBy(leftSideLinkExp);

                finalTrans.data.LocalLinks[leftSideLink]      = leftSideDecl;
                finalTrans.data.LvalueTypes[leftSideLink]     =
                    finalTrans.data.ExpTypes[leftSideLinkExp] = leftSideDecl.GetType();

                leftSide = leftSideLink;
                block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), leftSideDecl));
            }

            ABlockStm elseBranch;

            //Make final else branch

            /* {
             *     UIDisplayMessage(PlayerGroupAll(), c_messageAreaDebug, StringToText("<file>[<line>, <pos>]: No methods matched delegate."));
             *     IntToString(1/0);
             *     return;
             * }
             */
            {
                AABlock          innerBlock         = new AABlock(new ArrayList(), new TRBrace("}"));
                ASimpleInvokeExp playerGroupInvoke  = new ASimpleInvokeExp(new TIdentifier("PlayerGroupAll"), new ArrayList());
                AFieldLvalue     messageAreaLink    = new AFieldLvalue(new TIdentifier("c_messageAreaDebug"));
                ALvalueExp       messageAreaLinkExp = new ALvalueExp(messageAreaLink);
                AStringConstExp  stringConst        =
                    new AStringConstExp(
                        new TStringLiteral("\"" + currentFile.GetName().Text.Replace('\\', '/') + "[" +
                                           node.GetToken().Line + ", " + node.GetToken().Pos +
                                           "]: Got a null delegate.\""));
                ASimpleInvokeExp stringToTextInvoke = new ASimpleInvokeExp(new TIdentifier("StringToText"),
                                                                           new ArrayList()
                {
                    stringConst
                });
                ASimpleInvokeExp displayMessageInvoke = new ASimpleInvokeExp(new TIdentifier("UIDisplayMessage"),
                                                                             new ArrayList()
                {
                    playerGroupInvoke,
                    messageAreaLinkExp,
                    stringToTextInvoke
                });

                AIntConstExp     intConst1         = new AIntConstExp(new TIntegerLiteral("1"));
                AIntConstExp     intConst2         = new AIntConstExp(new TIntegerLiteral("0"));
                ABinopExp        binop             = new ABinopExp(intConst1, new ADivideBinop(new TDiv("/")), intConst2);
                ASimpleInvokeExp intToStringInvoke = new ASimpleInvokeExp(new TIdentifier("IntToString"),
                                                                          new ArrayList()
                {
                    binop
                });

                innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), displayMessageInvoke));
                innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), intToStringInvoke));
                //innerBlock.GetStatements().Add(new AVoidReturnStm(new TReturn("return")));

                elseBranch = new ABlockStm(new TLBrace("{"), innerBlock);


                finalTrans.data.SimpleMethodLinks[playerGroupInvoke] =
                    finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == playerGroupInvoke.GetName().Text);
                finalTrans.data.SimpleMethodLinks[stringToTextInvoke] =
                    finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == stringToTextInvoke.GetName().Text);
                finalTrans.data.SimpleMethodLinks[displayMessageInvoke] =
                    finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == displayMessageInvoke.GetName().Text);
                finalTrans.data.SimpleMethodLinks[intToStringInvoke] =
                    finalTrans.data.Libraries.Methods.First(m => m.GetName().Text == intToStringInvoke.GetName().Text);
                finalTrans.data.FieldLinks[messageAreaLink] =
                    finalTrans.data.Libraries.Fields.First(m => m.GetName().Text == messageAreaLink.GetName().Text);

                finalTrans.data.ExpTypes[playerGroupInvoke] =
                    finalTrans.data.SimpleMethodLinks[playerGroupInvoke].GetReturnType();
                finalTrans.data.LvalueTypes[messageAreaLink]     =
                    finalTrans.data.ExpTypes[messageAreaLinkExp] =
                        finalTrans.data.FieldLinks[messageAreaLink].GetType();
                finalTrans.data.ExpTypes[stringToTextInvoke] =
                    finalTrans.data.SimpleMethodLinks[stringToTextInvoke].GetReturnType();
                finalTrans.data.ExpTypes[stringConst]           =
                    finalTrans.data.ExpTypes[intToStringInvoke] = new ANamedType(new TIdentifier("string"), null);
                finalTrans.data.ExpTypes[displayMessageInvoke]  = new AVoidType();

                finalTrans.data.ExpTypes[intConst1]     =
                    finalTrans.data.ExpTypes[intConst2] =
                        finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("int"), null);
            }

            foreach (AMethodDecl method in methods)
            {
                /*  * if (delegate == "...")
                 * {
                 *    Foo(...);
                 * }
                 * else if (delegate == "...")
                 * {
                 *    Bar(..., GetPointerPart(<reciever>);
                 * }
                 * else if(...)
                 * ...
                 */
                AABlock          innerBlock = new AABlock(new ArrayList(), new TRBrace("}"));
                ASimpleInvokeExp invoke     = new ASimpleInvokeExp(new TIdentifier(method.GetName().Text), new ArrayList());
                for (int i = 0; i < node.GetArgs().Count; i++)
                {
                    PExp arg = (PExp)node.GetArgs()[i];
                    invoke.GetArgs().Add(Util.MakeClone(arg, finalTrans.data));
                }
                //If we have a struct method, add the pointer from the delegate
                if (finalTrans.data.StructMethods.Any(str => str.Value.Contains(method)))
                {
                    AStructDecl      targetStr        = finalTrans.data.StructMethods.First(str => str.Value.Contains(method)).Key;
                    AMethodDecl      getPointerDecl   = GetPointerMethod(targetStr.GetDimention() != null);
                    ASimpleInvokeExp getPointerInvoke = new ASimpleInvokeExp(new TIdentifier("renameMe"), new ArrayList()
                    {
                        Util.MakeClone(node.GetReceiver(), data)
                    });
                    invoke.GetArgs().Add(getPointerInvoke);

                    finalTrans.data.SimpleMethodLinks[getPointerInvoke] = getPointerDecl;
                    finalTrans.data.ExpTypes[getPointerInvoke]          = getPointerDecl.GetReturnType();
                }

                finalTrans.data.SimpleMethodLinks[invoke] = method;
                finalTrans.data.ExpTypes[invoke]          = method.GetReturnType();

                if (leftSide == null)
                {
                    innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), invoke));
                }
                else
                {
                    AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), Util.MakeClone(leftSide, finalTrans.data), invoke);
                    finalTrans.data.ExpTypes[assignment] = finalTrans.data.ExpTypes[invoke];
                    innerBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), assignment));
                }
                ALocalLvalue    methodPartLink    = new ALocalLvalue(new TIdentifier("methodPart"));
                ALvalueExp      methodPartLinkExp = new ALvalueExp(methodPartLink);
                AStringConstExp stringConst       = new AStringConstExp(new TStringLiteral("\"" + GetName(method) + "\""));
                finalTrans.data.LocalLinks[methodPartLink]      = methodPartDecl;
                finalTrans.data.LvalueTypes[methodPartLink]     =
                    finalTrans.data.ExpTypes[methodPartLinkExp] =
                        finalTrans.data.ExpTypes[stringConst]   = new ANamedType(new TIdentifier("string"), null);


                ABinopExp binop = new ABinopExp(methodPartLinkExp, new AEqBinop(new TEq("==")), stringConst);
                finalTrans.data.ExpTypes[binop] = new ANamedType(new TIdentifier("bool"), null);

                AIfThenElseStm ifThenElse = new AIfThenElseStm(new TLParen("("), binop, new ABlockStm(new TLBrace("{"), innerBlock), elseBranch);

                elseBranch = new ABlockStm(new TLBrace("{"), new AABlock(new ArrayList()
                {
                    ifThenElse
                }, new TRBrace("}")));
            }

            block.GetStatements().Add(elseBranch);
        }
Esempio n. 4
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Return statement");

            context.ReportReturnStatement();

            var returnExpressionType = new ExpressionType()
            {
                BaseType = new TypeDef()
                {
                    Name = "void", Size = 0
                }
            };

            if (Tokens.Count > 1)
            {
                returnExpressionType = ((IHasType)Tokens[1]).GetExpressionType(context);

                ((ICodeEmitter)Tokens[1]).Emit(context);

                //(Caller saves registers)

                if (returnExpressionType.GetSize() > 4)
                {
                    //Return value gets placed space allocated in caller's stack
                    throw new Exception("Large return values not supported");
                }
                else
                {
                    //Return value from function goes in eax
                    context.EmitInstruction(new IRPop()
                    {
                        To = "eax"
                    });
                }
            }

            int localVarsSize = context.GetFunctionLocalVarSize();

            //Reclaim local variables from stack space

            context.EmitInstruction(new IRMoveImmediate()
            {
                To = "ebx", Value = new ImmediateValue(localVarsSize)
            });
            context.EmitInstruction(new IRSub()
            {
                To = "sp", Left = "sp", Right = "ebx"
            });

            TypeChecking.CheckExpressionTypesMatch(context.GetCurrentFunctionReturnExpressionType(), returnExpressionType);

            if (context.IsEntryPointFunction)
            {
                //DONT WANT THIS. HALT JUST STOPS CPU COMPLETELY NOW
                //At this point the return value of the function is still in eax and we simple halt execution
                //as the exe has run to completion
                //context.EmitInstruction(new IRHalt());
            }
            else
            {
                //Pop return address off stack and jump
                context.EmitInstruction(new IRRet());
            }
        }
Esempio n. 5
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Function call");

            var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            if (!(expressionType.BaseType is FunctionTypeDef))
            {
                throw new Exception("Can't call expression type: " + expressionType + " as a function");
            }

            FunctionTypeDef functionType = (FunctionTypeDef)expressionType.BaseType;
            ExpressionType  returnType   = functionType.ReturnType;

            //List<ExpressionType> parameterTypes = functionType.ArgumentTypes;

            if (returnType.GetSize() > 4)
            {
                //Make space for return value in caller stack
                //context.EmitInstruction(new IRMoveImmediate() { To = "eax", Value = new ImmediateValue(function.ReturnType.GetSize()) });
                //context.EmitInstruction(new IRAdd() { Left = "sp", Right = "eax", To = "sp" });
                throw new LargeReturnValuesNotSupportedException();
            }

            //Push base pointer on stack
            context.EmitInstruction(new IRPushRegister()
            {
                From = "bp"
            });

            //Save registers (TODO: Not actually needed until we have smarter allocation that uses registers instead of stack)
            //context.EmitInstruction(new IRPushRegister() { From = "eax" });
            //context.EmitInstruction(new IRPushRegister() { From = "ebx" });
            //context.EmitInstruction(new IRPushRegister() { From = "ecx" });
            //context.EmitInstruction(new IRPushRegister() { From = "edx" });

            int argumentCount = Tokens.Count - 1;
            int argumentsSize = 0;

            if (argumentCount != functionType.ArgumentTypes.Count)
            {
                throw new ArgumentCountMismatchException(Tokens[0].ToString(), functionType.ArgumentTypes.Count, argumentCount);
            }

            if (Tokens.Count > 1)
            {
                //Push arguments on stack in reverse order
                for (int i = Tokens.Count - 1; i > 0; i--)
                {
                    var argExpressionType   = ((IHasType)Tokens[i]).GetExpressionType(context);
                    var paramExpressionType = functionType.ArgumentTypes[functionType.ArgumentTypes.Count - 1 - (Tokens.Count - 1 - i)];

                    TypeChecking.CheckExpressionTypesMatch(paramExpressionType, argExpressionType);

                    //Push argument value on stack
                    ((ICodeEmitter)Tokens[i]).Emit(context);

                    argumentCount++;
                    argumentsSize += argExpressionType.GetSize();
                }
            }

            var returnLabel = new LabelAddressValue(context.CreateNewLabel());

            //Address of function -> eax
            ((ICodeEmitter)Tokens[0]).Emit(context);
            context.EmitInstruction(new IRPop()
            {
                To = "eax"
            });

            //Set base pointer to be the top of current function's stack which will be the bottom
            //of the called function's stack
            context.EmitInstruction(new IRMoveRegister()
            {
                From = "sp", To = "bp"
            });

            //Push return address
            context.EmitInstruction(new IRPushImmediate()
            {
                Value = returnLabel
            });

            //Jump to function
            context.EmitInstruction(new IRJumpRegister()
            {
                Address = "eax"
            });

            //Resume here, reclaim space from arguments pushed on stack
            context.EmitLabel(returnLabel.Value);
            context.EmitInstruction(new IRMoveImmediate()
            {
                To = "ebx", Value = new ImmediateValue(argumentsSize)
            });
            context.EmitInstruction(new IRSub()
            {
                To = "sp", Left = "sp", Right = "ebx"
            });

            //Restore registers (TODO: Not actually needed until we have smarter allocation that uses registers instead of stack)
            //context.EmitInstruction(new IRPop() { To = "edx" });
            //context.EmitInstruction(new IRPop() { To = "ecx" });
            //context.EmitInstruction(new IRPop() { To = "ebx" });
            //context.EmitInstruction(new IRPop() { To = "eax" });

            //Reset base pointer
            context.EmitInstruction(new IRPop()
            {
                To = "bp"
            });

            if (returnType.GetSize() > 4)
            {
                //Return value is already on stack
                throw new LargeReturnValuesNotSupportedException();
            }
            else if (returnType.GetSize() > 0)
            {
                //Return value in eax, put on stack
                context.EmitInstruction(new IRPushRegister()
                {
                    From = "eax"
                });
            }
        }
Esempio n. 6
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Variable definition");

            var    type         = ((IHasType)Tokens[0]).GetExpressionType(context);
            string variableName = ((IdentifierToken)Tokens[1]).Name;

            if (type.IsArray && type.ArrayLength == -1)
            {
                throw new MissingArraySizeSpecifierException(variableName);
            }

            context.AddVariableSymbol(variableName, type, IsStatic, IsExported, IsExtern);

            if (!IsStatic && !context.InFunctionScope())
            {
                throw new Exception("Cannot define non static variable outside of function scope.");
            }

            if (Tokens.Count > 2)
            {
                var assignmentExpressionType = ((IHasType)Tokens[3]).GetExpressionType(context);

                var variable = context.GetVariable(variableName);

                if (variable.Type.GetSize() == 0)
                {
                    throw new VoidAssignmentException("to");
                }
                else if (assignmentExpressionType.GetSize() == 0)
                {
                    throw new VoidAssignmentException("from");
                }

                TypeChecking.CheckExpressionTypesMatch(variable.Type, assignmentExpressionType);

                //Special case for assignment of string literal to byte array:
                //  Don't emit string constant normally (which would add it as a string constant in the data section),
                //  instead copy the string to the memory occupied by tge byte array itself
                if (assignmentExpressionType.BaseType is StringLiteralTypeDef && variable.Type.IsArray)
                {
                    string stringLiteral = ((StringLiteralTypeDef)assignmentExpressionType.BaseType).Value;

                    if (assignmentExpressionType.ArrayLength > variable.Type.ArrayLength)
                    {
                        throw new Exception("The string '" + stringLiteral + "' is too large to be assigned by value to the left hand expression.");
                    }

                    //Put start address to copy string value to into eax
                    if (variable.Address is StackAddressValue)
                    {
                        context.EmitInstruction(new IRMoveImmediate()
                        {
                            To = "ebx", Value = new ImmediateValue(variable.Address.Value)
                        });
                        context.EmitInstruction(new IRAdd()
                        {
                            To = "ebx", Left = "bp", Right = "ebx"
                        });
                        context.EmitInstruction(new IRPushRegister()
                        {
                            From = "ebx"
                        });
                    }
                    else
                    {
                        context.EmitInstruction(new IRPushImmediate()
                        {
                            Value = variable.Address
                        });
                    }

                    context.EmitInstruction(new IRPop()
                    {
                        To = "eax"
                    });

                    for (int i = 0; i < assignmentExpressionType.ArrayLength; i++)
                    {
                        byte charValue = i < stringLiteral.Length ? (byte)stringLiteral[i] : (byte)0;

                        //Put char value into ebx
                        context.EmitInstruction(new IRMoveImmediate()
                        {
                            To = "ebx", Value = new ImmediateValue(charValue), OperandSize = 1
                        });
                        //Store char value into address [eax + char offset]
                        context.EmitInstruction(new IRStoreRegisterPlusImmediate()
                        {
                            To = "eax", Offset = new ImmediateValue(i), From = "ebx", OperandSize = 1
                        });
                    }
                }
                else
                {
                    if (assignmentExpressionType.GetSize() > 4)
                    {
                        //Memory copy

                        //Dest address -> eax
                        throw new Exception("TODO: Copy large values to stack variables");
                        //context.EmitInstruction(new IRMoveImmediate() { To = "eax", Value = variable.Address }); //STACK!!!!

                        //Source address -> ebx
                        //((IHasAddress)Tokens[3]).PushAddress(context);

                        //context.EmitInstruction(new IRPop() { To = "ebx" });

                        //context.EmitInstruction(new IRMemCopy() { From = "ebx", To = "eax", Length = new ImmediateValue(assignmentExpressionType.GetSize()) });
                    }
                    else
                    {
                        //Copy using register
                        ((ICodeEmitter)Tokens[3]).Emit(context);

                        context.EmitInstruction(new IRPop()
                        {
                            To = "eax"
                        });

                        if (variable.Address is StackAddressValue)
                        {
                            context.EmitInstruction(new IRStoreRegisterPlusImmediate()
                            {
                                From = "eax", To = "bp", Offset = new ImmediateValue(variable.Address.Value), OperandSize = assignmentExpressionType.GetSize()
                            });
                        }
                        else
                        {
                            context.EmitInstruction(new IRStoreImmediate()
                            {
                                From = "eax", To = variable.Address, OperandSize = assignmentExpressionType.GetSize()
                            });
                        }
                    }
                }
            }
        }
Esempio n. 7
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Assignment");

            var leftSideExpressionType  = ((IHasType)Tokens[0]).GetExpressionType(context);
            var rightSideExpressionType = ((IHasType)Tokens[2]).GetExpressionType(context);

            if (leftSideExpressionType.IsArray)
            {
                throw new TypeMismatchException(new ExpressionType()
                {
                    IsArray = true, BaseType = leftSideExpressionType.BaseType, ArrayLength = leftSideExpressionType.ArrayLength
                }, rightSideExpressionType);
            }

            if (leftSideExpressionType.GetSize() == 0)
            {
                throw new VoidAssignmentException("to");
            }
            else if (rightSideExpressionType.GetSize() == 0)
            {
                throw new VoidAssignmentException("from");
            }

            TypeChecking.CheckExpressionTypesMatch(leftSideExpressionType, rightSideExpressionType);

            //Special case for assignment of string literal to byte array:
            //  Don't emit string constant normally (which would add it as a string constant in the data section),
            //  instead copy the string to the memory occupied by tge byte array itself
            if (rightSideExpressionType.BaseType is StringLiteralTypeDef && leftSideExpressionType.IsArray)
            {
                string stringLiteral = ((StringLiteralTypeDef)rightSideExpressionType.BaseType).Value;

                if (rightSideExpressionType.ArrayLength > leftSideExpressionType.ArrayLength)
                {
                    throw new Exception("The string '" + stringLiteral + "' is too large to be assigned by value to the left hand expression.");
                }

                //Put start address to copy string value to into eax
                ((IHasAddress)Tokens[0]).PushAddress(context);
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                for (int i = 0; i < leftSideExpressionType.ArrayLength; i++)
                {
                    byte charValue = i < stringLiteral.Length ? (byte)stringLiteral[i] : (byte)0;

                    //Put char value into ebx
                    context.EmitInstruction(new IRMoveImmediate()
                    {
                        To = "ebx", Value = new ImmediateValue(charValue), OperandSize = 1
                    });
                    //Store char value into address [eax + char offset]
                    context.EmitInstruction(new IRStoreRegisterPlusImmediate()
                    {
                        To = "eax", Offset = new ImmediateValue(i), From = "ebx", OperandSize = 1
                    });
                }
            }
            else
            {
                //right hand side value -> stack
                ((ICodeEmitter)Tokens[2]).Emit(context);

                if (rightSideExpressionType.GetSize() > 4)
                {
                    //[sp] -> [destination]
                    //Dest address -> eax
                    ((IHasAddress)Tokens[0]).PushAddress(context);
                    context.EmitInstruction(new IRPop()
                    {
                        To = "eax"
                    });

                    //sp -= size of value
                    context.EmitInstruction(new IRMoveImmediate()
                    {
                        To = "ebx", Value = new ImmediateValue(rightSideExpressionType.GetSize())
                    });
                    context.EmitInstruction(new IRSub()
                    {
                        Left = "sp", Right = "ebx", To = "sp"
                    });

                    context.EmitInstruction(new IRMemCopy()
                    {
                        From = "sp", To = "eax", Length = new ImmediateValue(rightSideExpressionType.GetSize())
                    });
                }
                else
                {
                    //store ebx -> [destination]
                    ((IHasAddress)Tokens[0]).PushAddress(context);
                    context.EmitInstruction(new IRPop()
                    {
                        To = "eax"
                    });

                    //Store assign value in ebx
                    context.EmitInstruction(new IRPop()
                    {
                        To = "ebx"
                    });
                    context.EmitInstruction(new IRStoreRegister()
                    {
                        From = "ebx", To = "eax", OperandSize = rightSideExpressionType.GetSize()
                    });                                                                                                                           //MB!
                }
            }
        }
Esempio n. 8
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Bitwise expression");

            ((ICodeEmitter)Tokens[0]).Emit(context);

            var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            if (Tokens.Count > 1)
            {
                TypeChecking.CheckExpressionTypeIsNumeric(expressionType);
            }

            for (int i = 1; i < Tokens.Count; i += 2)
            {
                string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value;

                ((ICodeEmitter)Tokens[i + 1]).Emit(context);

                expressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context);

                TypeChecking.CheckExpressionTypeIsNumeric(expressionType);

                context.EmitInstruction(new IRPop()
                {
                    To = "ebx"
                });
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                switch (op)
                {
                case "&":
                    context.EmitInstruction(new IRAnd()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    break;

                case "|":
                    context.EmitInstruction(new IROr()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    break;

                case "^":
                    context.EmitInstruction(new IRXOr()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    break;
                }

                context.EmitInstruction(new IRPushRegister()
                {
                    From = "ecx"
                });
            }
        }
Esempio n. 9
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Equality expression");

            ((ICodeEmitter)Tokens[0]).Emit(context);

            var t1ExpressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            for (int i = 1; i < Tokens.Count; i += 2)
            {
                string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value;

                ((ICodeEmitter)Tokens[i + 1]).Emit(context);

                var t2ExpressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context);

                TypeChecking.CheckExpressionTypesMatch(t1ExpressionType, t2ExpressionType);
                t1ExpressionType = t2ExpressionType;

                context.EmitInstruction(new IRPop()
                {
                    To = "ebx"
                });
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                context.EmitInstruction(new IRCompareRegister()
                {
                    Left = "eax", Right = "ebx"
                });

                var trueLabel = new LabelAddressValue(context.CreateNewLabel());

                switch (op)
                {
                case "==":
                    context.EmitInstruction(new IRJumpEQ()
                    {
                        Address = trueLabel
                    });
                    break;

                case "!=":
                    context.EmitInstruction(new IRJumpNE()
                    {
                        Address = trueLabel
                    });
                    break;

                case ">":
                    context.EmitInstruction(new IRJumpGT()
                    {
                        Address = trueLabel
                    });
                    break;

                case "<":
                    context.EmitInstruction(new IRJumpLT()
                    {
                        Address = trueLabel
                    });
                    break;

                case ">=":
                    context.EmitInstruction(new IRJumpGE()
                    {
                        Address = trueLabel
                    });
                    break;

                case "<=":
                    context.EmitInstruction(new IRJumpLE()
                    {
                        Address = trueLabel
                    });
                    break;
                }

                var skipTrueLabel = new LabelAddressValue(context.CreateNewLabel());

                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(0)
                });
                context.EmitInstruction(new IRJumpImmediate()
                {
                    Address = skipTrueLabel
                });
                context.EmitLabel(trueLabel.Value);
                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(1)
                });
                context.EmitLabel(skipTrueLabel.Value);
            }
        }