예제 #1
0
 public abstract void Parse(Exp_Node node);
예제 #2
0
        public override void Parse(Exp_Node node)
        {
            if (node.exp_Type == Exp_Type.Operator)
            {
                if (node.left == null && node.right != null)
                {
                    //It is a prefix
                    if (node.exp_Data == "return")
                    {
                        if (functionData.returnValue.DataType.GetName() == "void")
                        {
                            throw new AST_BadFormatException(
                                      "A void function " + functionData.name + " can\'t have return statements", -1);
                        }
                        if (node.right.exp_Type == Exp_Type.Constant)
                        {
                            //A simple return value
                            Result += "\tmov  \teax,\t" + node.right.exp_Data + AST_Program.separator_line;
                        }
                        else if (node.right.exp_Type == Exp_Type.Operator)
                        {
                            node.right.Accept(this);
                            string right = functionData.ret.Pop();
                            if (SetDimentions(right, 32) != "eax")
                            {
                                Result += "\tmov  \teax,\t" + right + AST_Program.separator_line;
                                ClearReg(SetDimentions(right, 32), true);
                            }
                        }
                        else
                        {
                            throw new NotImplementedException("This node is not supported in a return statement");
                        }
                        Result += functionData.ending;
                    }
                    else
                    {
                        throw new NotImplementedException("Not supported suffix operator " + node.exp_Data);
                    }
                }
                else if (node.left != null && node.right == null)
                {
                    throw new NotImplementedException("Not supported prefix operator " + node.exp_Data);
                }
                else if (node.left != null && node.right != null)
                {
                    bool   popAx = false;
                    string left  = "";
                    string right = "";
                    //TODO - use stack for variable declaration
                    Stack <Exp_Node> stack = new Stack <Exp_Node>();

                    //Process left node
                    if (node.left.exp_Type == Exp_Type.Function)
                    {
                        if (functionData.axUsed)
                        {
                            Result += "\tpush \teax" + AST_Program.separator_line;
                            popAx   = true;
                            functionData.axUsed = false;
                        }

                        node.left.Accept(this);
                        if (functionData.ret.Pop() != "eax")
                        {
                            throw new AST_BadFormatException(
                                      "Return stack corrupted from function " + node.left.exp_Data, -1);
                        }

                        if (functionData.axUsed)
                        {
                            //We have a return value
                            //TODO - we shouldn't always have a return value
                            //TODO - we don't have to always move return value to something else
                            right = ToReg("eax");
                            if (popAx)
                            {
                                Result += "\tpop  \teax" + AST_Program.separator_line;
                            }
                        }
                    }
                    else if (node.left.exp_Type == Exp_Type.Operator)
                    {
                        node.left.Accept(this);
                        left = functionData.ret.Pop();
                    }
                    else if (node.left.exp_Type == Exp_Type.Constant)
                    {
                        left = ToReg(node.left.exp_Data);
                        //left = node.left.exp_Data;
                    }
                    else if (node.left.exp_Type == Exp_Type.Variable)
                    {
                        int indParam = functionData.parameters.FindIndex(a => a.Item1.Data == node.left.exp_Data);
                        int indLocal = functionData.locals.FindIndex(a => a.Item1.Data == node.left.exp_Data);
                        if (indLocal != -1)
                        {
                            //This variable exists as a local
                            left = functionData.locals[indParam].Item3;
                        }
                        else if (indParam != -1)
                        {
                            //This variable exists as a parameter
                            left = functionData.parameters[indParam].Item3;
                        }
                        else
                        {
                            throw new AST_BadFormatException("Unknown variable " + node.left.exp_Data, -1);
                        }
                    }
                    else
                    {
                        throw new AST_BadFormatException("Not supported node " + node.left.exp_Type.ToString(), -1);
                    }

                    //Process right node
                    if (node.right.exp_Type == Exp_Type.Function)
                    {
                        if (functionData.axUsed)
                        {
                            Result += "\tpush \teax" + AST_Program.separator_line;
                            popAx   = true;
                            functionData.axUsed = false;
                        }

                        node.right.Accept(this);
                        if (functionData.ret.Pop() != "eax")
                        {
                            throw new AST_BadFormatException(
                                      "Return stack corrupted from function " + node.right.exp_Data, -1);
                        }

                        if (functionData.axUsed)
                        {
                            //We have a return value
                            //TODO - we shouldn't always have a return value
                            //TODO - we don't have to always move return value to something else
                            right = ToReg("eax");
                            if (popAx)
                            {
                                Result += "\tpop  \teax" + AST_Program.separator_line;
                            }
                        }
                    }
                    else if (node.right.exp_Type == Exp_Type.Operator)
                    {
                        //TODO - actually handle recurent operations
                        node.right.Accept(this);
                        right = functionData.ret.Pop();
                    }
                    else if (node.right.exp_Type == Exp_Type.Constant)
                    {
                        right = node.right.exp_Data;
                    }
                    else if (node.right.exp_Type == Exp_Type.Variable)
                    {
                        int indParam = functionData.parameters.FindIndex(a => a.Item1.Data == node.right.exp_Data);
                        int indLocal = functionData.locals.FindIndex(a => a.Item1.Data == node.right.exp_Data);
                        if (indLocal != -1)
                        {
                            //This variable exists as a local
                            right = functionData.locals[indParam].Item3;
                        }
                        else if (indParam != -1)
                        {
                            //This variable exists as a parameter
                            right = functionData.parameters[indParam].Item3;
                        }
                        else
                        {
                            throw new AST_BadFormatException("Unknown variable " + node.right.exp_Data, -1);
                        }
                    }
                    else
                    {
                        throw new AST_BadFormatException(
                                  "Not supported node of type " + node.right.exp_Type.ToString(), -1);
                    }

                    if (node.exp_Data == "+")
                    {
                        if (!IsReg(left))
                        {
                            left = ToReg(left);
                        }
                        if (convertTo32)
                        {
                            if (!IsReg(right) && GetDimentions(right) != 32)
                            {
                                right = ToReg(right);
                            }
                        }
                        if (GetDimentions(left) != GetDimentions(right))
                        {
                            left = SetDimentions(left, GetDimentions(right));
                        }
                        Result += "\tadd  \t" + left + ",\t" + right + AST_Program.separator_line;
                        if (IsReg(right))
                        {
                            ClearReg(SetDimentions(right, 32), true);
                        }
                        if (!convertTo32 && IsReg(left) && GetDimentions(left) != 32)
                        {
                            Result += "\tmovsx\t" + SetDimentions(left, 32) + ",\t" + left + AST_Program.separator_line;
                        }
                        functionData.ret.Push(left);
                    }
                    else if (node.exp_Data == "-")
                    {
                        if (!IsReg(left))
                        {
                            left = ToReg(left);
                        }
                        if (convertTo32)
                        {
                            if (!IsReg(right) && GetDimentions(right) != 32)
                            {
                                right = ToReg(right);
                            }
                        }
                        if (GetDimentions(left) != GetDimentions(right))
                        {
                            left = SetDimentions(left, GetDimentions(right));
                        }
                        Result += "\tsub  \t" + left + ",\t" + right + AST_Program.separator_line;
                        if (IsReg(right))
                        {
                            ClearReg(SetDimentions(right, 32), true);
                        }
                        if (!convertTo32 && IsReg(left) && GetDimentions(left) != 32)
                        {
                            Result += "\tmovsx\t" + SetDimentions(left, 32) + ",\t" + left + AST_Program.separator_line;
                        }
                        functionData.ret.Push(left);
                    }
                    else
                    {
                        throw new NotImplementedException("Operation " + node.exp_Data + " is not supported");
                    }
                }
                //TODO - check if it is an empty return statement or something
                else
                {
                    throw new AST_BadFormatException("Operation " + node.exp_Data + " is not supported", -1);
                }
            }
            else if (node.exp_Type == Exp_Type.Bracket)
            {
                node.left.Accept(this);
                throw new AST_BadFormatException("Bracket nodes are not supported and should be simplified", -1);
            }
            else
            {
                throw new AST_BadFormatException("Not supported node of type " + node.exp_Type.ToString(), -1);
            }
        }