예제 #1
0
        //called after initVirtualIds(...)
        private void initLetStatements(Expression expression, Dictionary <Expression, int> registers, Stack <LetStatement> stack)
        {
            LetStatement letStatement = new LetStatement();

            letStatement.Variable = "_" + registers[expression];

            if (expression is VariableExpression || expression is NumericExpression)
            {
                letStatement.Value = expression;
                stack.Push(letStatement);
            }
            else
            {
                BinaryOperationExpression binExp = (BinaryOperationExpression)expression;

                BinaryOperationExpression value   = new BinaryOperationExpression();
                VariableExpression        varExp1 = new VariableExpression();
                VariableExpression        varExp2 = new VariableExpression();
                value.Operator     = binExp.Operator;
                varExp1.Name       = "_" + registers[binExp.Operand1];
                varExp2.Name       = "_" + registers[binExp.Operand2];
                value.Operand1     = varExp1;
                value.Operand2     = varExp2;
                letStatement.Value = value;
                stack.Push(letStatement);
                initLetStatements(binExp.Operand1, registers, stack);
                initLetStatements(binExp.Operand2, registers, stack);
            }
        }
예제 #2
0
        private void SplitTheExp(ref List <AssignmentStatement> l, BinaryOperationExpression binaryOp)
        {
            string replaceLeft = "", replaceRight = "";

            if (binaryOp.Operand1 is BinaryOperationExpression)
            {
                SplitTheExp(ref l, (BinaryOperationExpression)binaryOp.Operand1);
                replaceLeft = ((AssignmentStatement)l.Last()).Variable.Name;
            }
            if (binaryOp.Operand2 is BinaryOperationExpression)
            {
                SplitTheExp(ref l, (BinaryOperationExpression)binaryOp.Operand2);
                replaceRight = ((AssignmentStatement)l.Last()).Variable.Name;
            }
            tempLocals++;
            string             s   = "_" + tempLocals;
            VariableExpression var = new VariableExpression();

            var.Name = s;
            AssignmentStatement toAdd = new AssignmentStatement();

            toAdd.Variable = var;
            if (replaceLeft == "" && replaceRight == "")
            {
                toAdd.Value = binaryOp;
            }
            else
            {
                BinaryOperationExpression change = new BinaryOperationExpression();
                change.Operator = binaryOp.Operator;
                if (replaceLeft != "")
                {
                    VariableExpression var2 = new VariableExpression();
                    var2.Name       = replaceLeft;
                    change.Operand1 = var2;
                }
                else
                {
                    change.Operand1 = binaryOp.Operand1;
                }
                if (replaceRight != "")
                {
                    VariableExpression var2 = new VariableExpression();
                    var2.Name       = replaceRight;
                    change.Operand2 = var2;
                }
                else
                {
                    change.Operand2 = binaryOp.Operand1;
                }
                toAdd.Value = change;
            }
            l.Add(toAdd);
        }
예제 #3
0
 private void initVirtualIds(Expression expression, Dictionary <Expression, int> registers)
 {
     if (!(expression is BinaryOperationExpression))
     {
         numVirtualVars++;
         registers.Add(expression, numVirtualVars);
     }
     else
     {
         numVirtualVars++;
         registers.Add(expression, numVirtualVars);
         BinaryOperationExpression binaryExpression = (BinaryOperationExpression)expression;
         initVirtualIds(binaryExpression.Operand1, registers);
         initVirtualIds(binaryExpression.Operand2, registers);
     }
 }
예제 #4
0
 private int ComputeExpression(Expression exp, Dictionary <string, int> dValues)
 {
     if (exp.ToString() == "((x2 + x3) - (x2 - 7))")
     {
         string s = "stop for debug here";
     }
     if (exp is NumericExpression)
     {
         return(((NumericExpression)exp).Value);
     }
     if (exp is VariableExpression)
     {
         return(dValues[((VariableExpression)exp).Name]);
     }
     if (exp is BinaryOperationExpression)
     {
         BinaryOperationExpression be = (BinaryOperationExpression)exp;
         int iOperand1 = ComputeExpression(be.Operand1, dValues);
         int iOperand2 = ComputeExpression(be.Operand2, dValues);
         if (be.Operator == "+")
         {
             return(iOperand1 + iOperand2);
         }
         if (be.Operator == "-")
         {
             return(iOperand1 - iOperand2);
         }
         if (be.Operator == "&")
         {
             return(iOperand1 & iOperand2);
         }
         if (be.Operator == "|")
         {
             return(iOperand1 | iOperand2);
         }
         if (be.Operator == "*")
         {
             return(iOperand1 * iOperand2);
         }
         if (be.Operator == "/")
         {
             return(iOperand1 / iOperand2);
         }
     }
     return(0);
 }
예제 #5
0
        private bool CheckThatAllVariablesWereDeclared(Expression expression, List <string> varNames)
        {
            bool output = true;

            if (expression is VariableExpression)
            {
                output = varNames.Contains(expression.ToString());
            }
            else if (expression is BinaryOperationExpression)
            {
                BinaryOperationExpression binExp = (BinaryOperationExpression)expression;
                output = ((CheckThatAllVariablesWereDeclared(binExp.Operand1, varNames)) && (CheckThatAllVariablesWereDeclared(binExp.Operand2, varNames)));
            }
            if (!output)
            {
                throw new SyntaxErrorException("the variable " + expression + " was never declared", new Token());
            }
            return(true);
        }
예제 #6
0
/*
 *
 *
 * Impelementtt!!!!
 */


        public List <string> GenerateCode(LetStatement aSimple, Dictionary <string, int> dSymbolTable)
        {
            List <string> lAssembly = new List <string>();

            ///////////////NumericExpression
            if (aSimple.Value is NumericExpression)
            {
                int exp = aSimple.Value;

                lAssembly.Add("@" + exp);

                lAssembly.Add("D=A");

                lAssembly.Add("@RESULT");

                lAssembly.Add("M=D");

                lAssembly.AddRange(ResultTOtable(aSimple.Variable, dSymbolTable));
            }
//////////////////VariableExpression
            if (aSimple.Value is VariableExpression)
            {
                int exp = ComputeExpression(aSimple.Value, dSymbolTable);

                lAssembly.AddRange(VariableAddressToADDRESS(dSymbolTable.ElementAt(exp).Key, dSymbolTable));

                lAssembly.Add("@ADDRESS");

                lAssembly.Add("A=M");

                lAssembly.Add("D=M");

                lAssembly.Add("@RESULT");

                lAssembly.Add("M=D");

                lAssembly.AddRange(ResultTOtable(aSimple.Variable, dSymbolTable));
            }
///////////////////BinaryOperationExpression
            if (aSimple.Value is BinaryOperationExpression)
            {
                int exp = ComputeExpression(aSimple.Value, dSymbolTable);
                BinaryOperationExpression be = (BinaryOperationExpression)aSimple.Value;
                if (be.Operand1 is NumericExpression)
                {
                    lAssembly.Add("@" + be.Operand1);

                    lAssembly.Add("D=A");

                    lAssembly.Add("@OPERAND1");

                    lAssembly.Add("M=D");
                }
                if (be.Operand1 is VariableExpression)
                {
                    lAssembly.AddRange(VariableAddressToADDRESS(be.Operand1.ToString(), dSymbolTable));

                    lAssembly.Add("@ADDRESS");

                    lAssembly.Add("A=M");

                    lAssembly.Add("D=M");

                    lAssembly.Add("@OPERAND1");

                    lAssembly.Add("M=D");
                }
                if (be.Operand2 is NumericExpression)
                {
                    lAssembly.Add("@" + be.Operand2);

                    lAssembly.Add("D=A");

                    lAssembly.Add("@OPERAND2");

                    lAssembly.Add("M=D");
                }
                if (be.Operand2 is VariableExpression)
                {
                    lAssembly.AddRange(VariableAddressToADDRESS(be.Operand2.ToString(), dSymbolTable));

                    lAssembly.Add("@ADDRESS");

                    lAssembly.Add("A=M");

                    lAssembly.Add("D=M");

                    lAssembly.Add("@OPERAND2");

                    lAssembly.Add("M=D");
                }

                lAssembly.Add("@OPERAND1");

                lAssembly.Add("D=M");

                lAssembly.Add("@OPERAND2");

                lAssembly.Add("D=D" + be.Operator + "M");

                lAssembly.Add("@RESULT");

                lAssembly.Add("M=D");

                lAssembly.AddRange(ResultTOtable(aSimple.Variable, dSymbolTable));
            }
            return(lAssembly);
        }
예제 #7
0
        //Generates assembly code for a simple assignment statement. Can accept only the following:
        //let <var> = <number>; e.g. let x = 5;
        //let <var> = <var>; e.g. let x = y;
        //let <var> = (<operator> <operand1> <operand2>); where operand1 and operand2 can only by either numbers or variables, but not nested expressions. e.g. let x = (- y 5);
        public List <string> GenerateCode(AssignmentStatement aSimple)
        {
            List <string> AssemblyList = new List <string>();

            if (aSimple.Value is NumericExpression)
            {
                AssemblyList = isNumaricAssigment(AssemblyList, aSimple);
            }
            else if (aSimple.Value is VariableExpression)
            {
                VariableExpression var = (VariableExpression)aSimple.Value;
                if (!symbolTable.ContainsKey(var.Name))
                {
                    throw new SyntaxErrorException("Undefined variable, please define the variable " + var.Name + " first.", new Token());
                }
                else
                {
                    AssemblyList = isVariableAssigment(AssemblyList, aSimple);
                }
            }
            else
            {
                BinaryOperationExpression temp = new BinaryOperationExpression();
                temp = (BinaryOperationExpression)aSimple.Value;
                if (temp.Operand1 is NumericExpression)
                {
                    AssemblyList.Add("@" + ((NumericExpression)temp.Operand1).Value);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@OPERAND1");
                    AssemblyList.Add(" M = D");
                }
                else
                {
                    AssemblyList.Add("@" + symbolTable[((VariableExpression)temp.Operand1).Name]);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@LOCAL");
                    AssemblyList.Add("D = D + M");
                    AssemblyList.Add("A = D");
                    AssemblyList.Add("D = M");
                    AssemblyList.Add("@OPERAND1");
                    AssemblyList.Add("M = D");
                }
                if (temp.Operand2 is NumericExpression)
                {
                    AssemblyList.Add("@" + ((NumericExpression)temp.Operand2).Value);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@OPERAND2");
                    AssemblyList.Add("M = D");
                }
                else
                {
                    AssemblyList.Add("@" + symbolTable[((VariableExpression)temp.Operand2).Name]);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@LOCAL");
                    AssemblyList.Add("D = D + M");
                    AssemblyList.Add("A = D");
                    AssemblyList.Add("D = M");
                    AssemblyList.Add("@OPERAND2");
                    AssemblyList.Add("M = D");
                }
                AssemblyList.Add("@OPERAND1");
                AssemblyList.Add(" D = M");
                AssemblyList.Add("@OPERAND2");
                if (temp.Operator == "+")
                {
                    AssemblyList.Add("D = D + M");
                }
                else
                {
                    AssemblyList.Add("D = D - M");
                }
                AssemblyList.Add("@RESULT");
                AssemblyList.Add("M = D");

                computeVariabletoR0(AssemblyList, aSimple.Variable.Name);
                updateDestinationWithResult(AssemblyList);
            }


            return(AssemblyList);
        }
예제 #8
0
 private Expression BinaryExpressionCreate(BinaryOperationExpression exp, ref Stack <Token> sTokens)
 {
     if (sTokens.Peek().Name == "-" || sTokens.Peek().Name == "+")
     {
         exp.Operator = sTokens.Pop().Name;
     }
     else
     {
         throw new SyntaxErrorException("Operator '+' or '-' expected", sTokens.Pop());
     }
     if (sTokens.Peek().Name == "(")
     {
         sTokens.Pop();
         exp.Operand1 = BinaryExpressionCreate(new BinaryOperationExpression(), ref sTokens);
         if (sTokens.Pop().Name != ")")
         {
             throw new SyntaxErrorException("Missing ')' symbol", sTokens.Pop());
         }
     }
     else
     {
         if (Char.IsDigit(sTokens.Peek().Name, 0))
         {
             bool success          = false;
             NumericExpression num = new NumericExpression();
             success = Int32.TryParse(sTokens.Pop().Name, out num.Value);
             if (!success)
             {
                 throw new SyntaxErrorException("Invalid number", sTokens.Pop());
             }
             exp.Operand1 = num;
         }
         else if (Char.IsLetter(sTokens.Peek().Name, 0))
         {
             VariableExpression var2 = new VariableExpression();
             var2.Name    = sTokens.Pop().Name;
             exp.Operand1 = var2;
         }
         else
         {
             throw new SyntaxErrorException("Invalid variable or const", sTokens.Pop());
         }
     }
     if (sTokens.Peek().Name == "(")
     {
         sTokens.Pop();
         exp.Operand2 = BinaryExpressionCreate(new BinaryOperationExpression(), ref sTokens);
         if (sTokens.Pop().Name != ")")
         {
             throw new SyntaxErrorException("Missing ')' symbol", sTokens.Pop());
         }
     }
     else
     {
         if (Char.IsDigit(sTokens.Peek().Name, 0))
         {
             bool success          = false;
             NumericExpression num = new NumericExpression();
             success = Int32.TryParse(sTokens.Pop().Name, out num.Value);
             if (!success)
             {
                 throw new SyntaxErrorException("Invalid number", sTokens.Pop());
             }
             exp.Operand2 = num;
         }
         else if (Char.IsLetter(sTokens.Peek().Name, 0))
         {
             VariableExpression var2 = new VariableExpression();
             var2.Name    = sTokens.Pop().Name;
             exp.Operand2 = var2;
         }
         else
         {
             throw new SyntaxErrorException("Invalid variable or const", sTokens.Pop());
         }
     }
     return(exp);
 }
예제 #9
0
        private Expression SimplifyExpressions(
            Expression expression,
            List <LetStatement> newLetStatements,
            List <VarDeclaration> lVars,
            bool isFirst
            )
        {
            Expression simplifiedExpression;
            var        binaryOperationExpression = expression as BinaryOperationExpression;

            if (binaryOperationExpression == null)
            {
                simplifiedExpression = expression;
            }
            else
            {
                var tempSimplifiedExpression = new BinaryOperationExpression
                {
                    Operator = binaryOperationExpression.Operator,

                    Operand1 = SimplifyExpressions(
                        binaryOperationExpression.Operand1,
                        newLetStatements,
                        lVars,
                        false
                        ),
                    Operand2 = SimplifyExpressions(
                        binaryOperationExpression.Operand2,
                        newLetStatements,
                        lVars,
                        false
                        )
                };

                if (tempSimplifiedExpression.Operand1 == binaryOperationExpression.Operand1 &&
                    tempSimplifiedExpression.Operand2 == binaryOperationExpression.Operand2)
                {
                    simplifiedExpression = binaryOperationExpression;
                }
                else
                {
                    simplifiedExpression = tempSimplifiedExpression;
                }

                if (!isFirst)
                {
                    string artificialVarName = $"_{m_cLocals}";
                    m_cLocals++;
                    lVars.Add(new VarDeclaration("int", artificialVarName));
                    newLetStatements.Add(new LetStatement
                    {
                        Variable = artificialVarName,
                        Value    = simplifiedExpression
                    });
                    simplifiedExpression = new VariableExpression
                    {
                        Name = artificialVarName
                    };
                }
            }

            return(simplifiedExpression);
        }
예제 #10
0
        public List <LetStatement> SimplifyExpressions(LetStatement s, List <VarDeclaration> lVars)
        {
            //add here code to simply expressins in a statement.
            //add var declarations for artificial variables.
            //check that all vars appear in vardeclarations
            List <LetStatement> output = new List <LetStatement>();
            //first check that all vars in expression were declared;
            List <string> varNames = new List <string>();

            foreach (VarDeclaration varDec in lVars)
            {
                varNames.Add(varDec.Name);
            }
            if (!varNames.Contains(s.Variable))
            {
                throw new SyntaxErrorException(" the variable " + s.Variable + " was never defined in expression " + s, new Token());
            }
            CheckThatAllVariablesWereDeclared(s.Value, varNames);

            if (s.Value is BinaryOperationExpression)
            {
                //init data
                numVirtualVars = 0;
                Dictionary <Expression, int> registers = new Dictionary <Expression, int>();
                initVirtualIds(s.Value, registers);
                Stack <LetStatement> lets = new Stack <LetStatement>();
                initLetStatements(s.Value, registers, lets);


                BinaryOperationExpression binExp = (BinaryOperationExpression)(s.Value);
                BinaryOperationExpression binVal = new BinaryOperationExpression();

                // let OPERATOR1 = _xxx
                VariableExpression var1 = makeVariable("_" + registers[binExp.Operand1]);
                binVal.Operand1 = var1;
                LetStatement letOP1 = makeLetStatement(OPERAND1, var1);

                // let OPERATOR2 = _yyy
                VariableExpression var2 = makeVariable("_" + registers[binExp.Operand2]);
                binVal.Operand2 = var2;
                LetStatement letOP2 = makeLetStatement(OPERAND2, var2);

                // let RESULT= _1 and variable=RESULT
                LetStatement letResult = makeLetStatement(RESULT, makeVariable("_" + registers[s.Value]));
                LetStatement letVar    = makeLetStatement(s.Variable, makeVariable(RESULT));



                while (lets.Count > 0)
                {
                    output.Add(lets.Pop());
                }

                output.Add(letOP1);
                output.Add(letOP2);
                output.Add(letResult);
                output.Add(letVar);
            }
            else
            {
                //need to put in RESULT???
                output.Add(s);
            }

            return(output);
        }
예제 #11
0
        public List <string> GenerateCode(LetStatement aSimple, Dictionary <string, int> dSymbolTable)
        {
            List <string> lAssembly = new List <string>();

            lAssembly.Add("//generation started" + aSimple);

            //add here code for computing a single let statement containing only a simple expression
            Expression value    = aSimple.Value;
            string     variable = aSimple.Variable;

            if (value is NumericExpression | value is VariableExpression)
            {
                lAssembly.AddRange(GenerateCodeForUnaryAssignment(aSimple, dSymbolTable));
            }
            else if (value is BinaryOperationExpression)
            {
                lAssembly.Add("//Binary Expression" + aSimple);
                //
                //Example: a = b <op> c
                //first let a=b
                //next  let a=a <op> c
                //
                BinaryOperationExpression binExp = (BinaryOperationExpression)value;
                Expression   operand1            = binExp.Operand1;
                Expression   operand2            = binExp.Operand2;
                LetStatement letAEqualB          = makeLetStatement(variable, operand1);

                //let a=b
                lAssembly.AddRange(GenerateCodeForUnaryAssignment(letAEqualB, dSymbolTable));
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("D=M");
                lAssembly.Add("@" + OPERAND1);
                lAssembly.Add("M=D");


                //let a = a <op> c
                if (operand2 is NumericExpression)
                {
                    lAssembly.Add("//Opearand 2 is Numeric " + aSimple);

                    NumericExpression num = (NumericExpression)operand2;
                    lAssembly.Add("@" + num.Value);
                    lAssembly.Add("D=A");
                    lAssembly.Add("@_a");
                    lAssembly.Add("M=M" + binExp.Operator + "D");
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + RESULT);
                    lAssembly.Add("M=D");
                }
                else if (operand2 is VariableExpression)
                {
                    lAssembly.Add("//Opearand 2 is a Variable " + aSimple);

                    VariableExpression c = (VariableExpression)operand2;
                    lAssembly.Add("@LCL");
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + dSymbolTable[c.Name]);
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + dSymbolTable[variable]);
                    lAssembly.Add("M=M" + binExp.Operator + "D");
                    lAssembly.Add("D=M");

                    lAssembly.Add("@" + RESULT);
                    lAssembly.Add("M=D");
                }
            }


            return(lAssembly);
        }