private void CheckPreorder(Node node, IList<Node> nodesPreOrder) { Assert.AreNotEqual(nodesPreOrder.Count, 0); Assert.AreEqual(nodesPreOrder[0], node); nodesPreOrder.RemoveAt(0); foreach (var child in node.Children) { CheckPreorder(child, nodesPreOrder); } }
public void AddChild(Node node) { Children.Add(node); }
private void TypeCheckVariableAssignment(Node assignmentNode, VariableDeclarationNode declarationNode) { var childType = assignmentNode.Children[0].NodeType(); // if type is error type, the error has already been reported if (declarationNode.Type != childType && childType != VariableType.ERROR_TYPE) { reporter.ReportError( Error.SEMANTIC_ERROR, "Expression has invalid type '" + childType.Name() + "' while variable has type '" + declarationNode.Type.Name() + "'", assignmentNode.Children[0].Line, assignmentNode.Children[0].Column); reporter.ReportError( Error.NOTE, "Variable was declared here", declarationNode.Line, declarationNode.Column); } }
private void ASTPreOrderMatches(Node node, IList<Node> nodesPreorder) { CheckPreorder(node, nodesPreorder); Assert.AreEqual(0, nodesPreorder.Count); }
private void ReportUnacceptableTypes(Node node, string op, IList<VariableType> acceptableOperandTypes) { var typeStr = BuildTypeErrorString(acceptableOperandTypes); reporter.ReportError( Error.SEMANTIC_ERROR, "Operator '" + op + "' expects operands to have " + typeStr, node.Line, node.Column); LeftRightTypeNote(node); }
private void ReportUndeclaredVariable(Node node, string name) { reporter.ReportError( Error.SEMANTIC_ERROR, "Variable '" + name + "' has not been declared at this point", node.Line, node.Column); }
private void LeftRightTypeNote(Node node) { reporter.ReportError( Error.NOTE, "Left side expression has type '" + node.Children[0].NodeType().Name() + "'", node.Children[0].Line, node.Children[0].Column); reporter.ReportError( Error.NOTE, "Right side expression has type '" + node.Children[1].NodeType().Name() + "'", node.Children[1].Line, node.Children[1].Column); }
private void BinaryOperator(Node node, string name, Func<VariableType> nodeType, IList<VariableType> acceptableOperandTypes) { if (node.Children.Count != 2) { throw new InternalCompilerError("Invalid child count for less-than-node"); } foreach (var child in node.Children) { child.Accept(this); } BinaryOperatorTypeChecks(node, name, nodeType, acceptableOperandTypes); }
private void CheckVariableAssignmentUsedInStartEndExpression(IdentifierNode loopVariable, Node startExpression, Node endExpression, Node loopBody) { var stack = new Stack<Node>(); stack.Push(endExpression); stack.Push(startExpression); var loopExpressionVariables = new Dictionary<IdentifierNode, IdentifierNode>(); while (stack.Count != 0) { var current = stack.Pop(); if (current is IdentifierNode && ((IdentifierNode)current).Name != loopVariable.Name) { var id = (IdentifierNode)current; if (!loopExpressionVariables.ContainsKey(id)) { loopExpressionVariables.Add(id, id); } } foreach (var child in current.Children) { stack.Push(child); } } stack.Push(loopBody); while (stack.Count != 0) { var current = stack.Pop(); if (current is VariableAssignmentNode && loopExpressionVariables.ContainsKey(new IdentifierNode(0, 0, ((VariableAssignmentNode)current).Name))) { reporter.ReportError( Error.WARNING, "Possibly incorrect or confusing assignment to a variable '" + ((VariableAssignmentNode)current).Name + "', used in loop expression,", current.Line, current.Column); var id = loopExpressionVariables[new IdentifierNode(0, 0, ((VariableAssignmentNode)current).Name)]; reporter.ReportError( Error.NOTE, "Previous usage here", id.Line, id.Column); reporter.ReportError( Error.NOTE_GENERIC, "Loop start and end expressions are evaluated only once before entering the loop", 0, 0); break; } foreach (var child in current.Children) { stack.Push(child); } } }
private void HandleExpression(Node expression, List<VariableType> acceptableTypes) { expression.Accept(this); if (!acceptableTypes.Contains(expression.NodeType()) && expression.NodeType() != VariableType.ERROR_TYPE) { var typeStr = BuildTypeErrorString(acceptableTypes); reporter.ReportError( Error.SEMANTIC_ERROR, "Expression must have " + typeStr + " but has type '" + expression.NodeType().Name() + "'", expression.Line, expression.Column); if (expression is IdentifierNode) { NoteVariableWasDeclaredHere(((IdentifierNode)expression).Name); } } }
private void CheckLoopControlVariableUsageInStartEndExpression(ForNode node, IdentifierNode loopVariable, Node startExpression, Node endExpression) { var stack = new Stack<Node>(); stack.Push(endExpression); stack.Push(startExpression); while (stack.Count != 0) { var current = stack.Pop(); if (current is IdentifierNode && ((IdentifierNode)current).Name == loopVariable.Name) { reporter.ReportError( Error.WARNING, "Possibly incorrect or confusing usage of loop control variable '" + loopVariable.Name + "' in loop expression", current.Line, current.Column); reporter.ReportError( Error.NOTE, "Loop is here", node.Line, node.Column); reporter.ReportError( Error.NOTE_GENERIC, "Loop start and end expressions are evaluated only once before entering the loop", 0, 0); break; } foreach (var child in current.Children) { stack.Push(child); } } }
private void CheckLoopControlVariableAssignmentInBody(ForNode node, IdentifierNode loopVariable, Node loopBody) { var stack = new Stack<Node>(); stack.Push(loopBody); while (stack.Count != 0) { var current = stack.Pop(); if (current is VariableAssignmentNode && ((VariableAssignmentNode)current).Name == loopVariable.Name) { reporter.ReportError( Error.SEMANTIC_ERROR, "Cannot reassign control variable '" + loopVariable.Name + "'", current.Line, current.Column); reporter.ReportError( Error.NOTE, "Loop is here", node.Line, node.Column); break; } foreach (var child in current.Children) { stack.Push(child); } } }
private void BinaryOperatorTypeChecks(Node node, string name, Func<VariableType> nodeType, IList<VariableType> acceptableOperandTypes) { // if one (or both) children are errors, the error has already been reported. // Just set the node type as error and return if (node.Children[0].NodeType() == VariableType.ERROR_TYPE || node.Children[1].NodeType() == VariableType.ERROR_TYPE) { node.SetType(VariableType.ERROR_TYPE); return; } if (node.Children[0].NodeType() != node.Children[1].NodeType()) { ReportInvalidTypes(node, name); node.SetType(VariableType.ERROR_TYPE); } else if (!acceptableOperandTypes.Contains(node.Children[0].NodeType()) || !acceptableOperandTypes.Contains(node.Children[1].NodeType())) { ReportUnacceptableTypes(node, name, acceptableOperandTypes); node.SetType(VariableType.ERROR_TYPE); } else { node.SetType(nodeType()); } }
public NotNode(int line, int column, Node child) : base(line, column) { Children.Add(child); }
private void ReportInvalidTypes(Node node, string op) { reporter.ReportError( Error.SEMANTIC_ERROR, "Incompatible types for operator '" + op + "'", node.Line, node.Column); LeftRightTypeNote(node); }
public AndNode(int line, int column, Node lhs, Node rhs) : base(line, column) { Children.Add(lhs); Children.Add(rhs); }
private void BinaryNode(Node node, byte code) { node.Children[0].Accept(this); node.Children[1].Accept(this); Emit(code); }