public void TwoVariableNodesWithSameNameAndTypeAreEqual()
        {
            var node1 = new VariableDeclarationNode(1, 2, "test", VariableType.STRING);
            var node2 = new VariableDeclarationNode(71, 122, "test", VariableType.STRING);

            Assert.AreEqual(node1, node2);
        }
        public void TwoVariableNodesWithSameNameAndTypeHaveSameHashCode()
        {
            var node1 = new VariableDeclarationNode(1, 2, "test", VariableType.STRING);
            var node2 = new VariableDeclarationNode(71, 122, "test", VariableType.STRING);

            Assert.AreEqual(node1.GetHashCode(), node2.GetHashCode());
        }
 public VariableData(int id, VariableDeclarationNode node)
 {
     this.id = id;
     this.node = node;
 }
 public void TwoVariableNodesWithDifferentNameAndSameTypeAreNotEqual()
 {
     var node1 = new VariableDeclarationNode(1, 2, "test", VariableType.BOOLEAN);
     var node2 = new VariableDeclarationNode(71, 122, "dfasdasd", VariableType.BOOLEAN);
     Assert.AreNotEqual(node1, node2);
 }
        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 static Node HasSelfAssignment(VariableDeclarationNode node)
        {
            var stack = new Stack<Node>();
            foreach (var child in node.Children)
            {
                stack.Push(child);
            }

            while (stack.Count != 0)
            {
                var current = stack.Pop();

                if (current is IdentifierNode && ((IdentifierNode)current).Name == node.Name)
                {
                    return current;
                }

                foreach (var child in current.Children)
                {
                    stack.Push(child);
                }
            }
            return null;
        }
        public void Visit(VariableDeclarationNode node)
        {
            if (SymbolTable.ContainsKey(node.Name))
            {
                reporter.ReportError(
                    Error.SEMANTIC_ERROR,
                    "Redeclaration of variable '" + node.Name + "'",
                    node.Line,
                    node.Column);

                var name = node.Name;
                NoteVariableWasDeclaredHere(name);
            }
            else
            {
                SymbolTable[node.Name] = new VariableData(variableId++, node);
            }

            if (node.Children.Count == 0)
            {
                return;
            }

            if (node.Children.Count > 1)
            {
                throw new InternalCompilerError("Variable declaration node has more children than 1");
            }

            node.Children[0].Accept(this);
            TypeCheckVariableAssignment(node, node);

            Node n = null;
            if ((n = HasSelfAssignment(node)) != null)
            {
                reporter.ReportError(
                    Error.SEMANTIC_ERROR,
                    "Cannot initialize variable with self",
                    n.Line,
                    n.Column);
            }
        }
        public void Visit(VariableDeclarationNode node)
        {
            if (node.Children.Count == 0)
            {
                // default initialize
                if (node.Type == VariableType.INTEGER)
                {
                    Emit(Bytecode.PUSH_INT);
                    Emit(0L);
                }
                else if (node.Type == VariableType.STRING)
                {
                    Emit(Bytecode.PUSH_STRING);
                    Emit(0);
                }
                else if (node.Type == VariableType.BOOLEAN)
                {
                    Emit(Bytecode.PUSH_FALSE);
                }
                else
                {
                    throw new InternalCompilerError("Invalid variable type for variable declaration");
                }
            }
            else
            {
                node.Children[0].Accept(this);
            }

            Emit(Bytecode.STORE_VARIABLE);
            Emit(symbolTable[node.Name].id);
        }