public abstract void Parse(Exp_Node node);
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); } }