//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); } }
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); }
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); } }
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); }
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); }
/* * * * 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); }
//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); }
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); }
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); }
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); }
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); }