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);
            }
        }
Exemple #2
0
 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);
 }