Beispiel #1
0
        protected override void VisitReference(ReferenceNode referenceNode)
        {
            Symbol symbol = GetBaseReferenceSymbol(referenceNode);

            referenceNode.BaseSymbol = symbol;
            if (symbol == null)
            {
                referenceNode.Annotations.Add(new UndeclaredIdentifierError(referenceNode.Name));
                return;
            }

            if (symbol.Node.Annotations.Count > 0)
            {
                return;
            }

            DeclarationNode declarationNode;

            declarationNode = (DeclarationNode)symbol.Node;
            declarationNode.Usages.Add(referenceNode);

            int            attributeDepth      = 0;
            bool           arrayIndexNodeFound = false;
            ArrayIndexNode firstArrayIndexNode = null;

            string symbolLocalPath = referenceNode.Name;

            foreach (ReferencePartNode partNode in referenceNode.PartNodes)
            {
                if (arrayIndexNodeFound)
                {
                    partNode.Annotations.Add(new AccessToAttributeOfArrayElementNotSupportedError());
                    return;
                }

                switch (partNode)
                {
                case AttributeNode attributeNode:


                    NestableSymbol resultNestableSymbol;
                    switch (symbol)
                    {
                    case InstanceSymbol instanceSymbol:
                        ClassSymbol baseClassSymbol = instanceSymbol.BaseClassSymbol;
                        if (baseClassSymbol != null)
                        {
                            if (baseClassSymbol.BodySymbols.TryGetValue(attributeNode.Name.ToUpper(), out resultNestableSymbol))
                            {
                                symbol               = resultNestableSymbol;
                                symbolLocalPath      = $"{symbolLocalPath}.{attributeNode.Name}";
                                attributeNode.Symbol = symbol;
                                attributeDepth++;

                                declarationNode = (DeclarationNode)symbol.Node;
                                declarationNode.Usages.Add(attributeNode);
                            }
                            else
                            {
                                attributeNode.Annotations.Add(new ClassDoesNotHaveAttributeError(symbolLocalPath, baseClassSymbol.Name, attributeNode.Name));
                                return;
                            }
                        }
                        else
                        {
                            // TODO shouldn't we annotate something here?
                        }
                        break;

                    case NestableSymbol nestableSymbol:
                        if (nestableSymbol.ComplexType is ClassSymbol classSymbol)
                        {
                            if (classSymbol.BodySymbols.TryGetValue(attributeNode.Name.ToUpper(), out resultNestableSymbol))
                            {
                                symbol               = resultNestableSymbol;
                                symbolLocalPath      = $"{symbolLocalPath}.{attributeNode.Name}";
                                attributeNode.Symbol = symbol;
                                attributeDepth++;

                                declarationNode = (DeclarationNode)symbol.Node;
                                declarationNode.Usages.Add(attributeNode);
                            }
                            else
                            {
                                attributeNode.Annotations.Add(new ClassDoesNotHaveAttributeError(symbolLocalPath, classSymbol.Name, attributeNode.Name));         //TODO does it ever occur?
                                return;
                            }
                        }
                        else
                        {
                            attributeNode.Annotations.Add(new AttributeOfNonInstanceError(attributeNode.Name, symbolLocalPath));
                        }
                        break;


                    default:
                        attributeNode.Annotations.Add(new AttributeOfNonInstanceError(attributeNode.Name, symbolLocalPath));
                        return;
                    }
                    break;

                case ArrayIndexNode arrayIndexNode:
                    arrayIndexNodeFound = true;
                    firstArrayIndexNode = arrayIndexNode;

                    if (!(symbol.Node is IArrayDeclarationNode))
                    {
                        referenceNode.Annotations.Add(new ReferencedSymbolIsNotArrayError(referenceNode.Name));
                        return;
                    }

                    ArrayIndexNodes.Add(arrayIndexNode);
                    break;

                default:
                    throw new Exception();
                }
            }
            referenceNode.Symbol    = symbol;
            referenceNode.IndexNode = firstArrayIndexNode;
            if (attributeDepth > 1)
            {
                referenceNode.DoesHaveNestedAttributes = true;
            }
        }
        public CompoundAssignmentNode(NodeLocation location, CompoundAssignmentOperator @operator, NodeLocation operatorLocation, ReferenceNode leftSideNode,
                                      ExpressionNode rightSideNode) : base(location)
        {
            leftSideNode.ParentNode  = this;
            rightSideNode.ParentNode = this;

            Operator         = @operator;
            OperatorLocation = operatorLocation;
            LeftSideNode     = leftSideNode;
            RightSideNode    = rightSideNode;
        }
Beispiel #3
0
        private Symbol GetBaseReferenceSymbol(ReferenceNode referenceNode)
        {
            ASTNode ancestor           = referenceNode.GetFirstSignificantAncestorNode();
            string  referenceNameUpper = referenceNode.Name.ToUpper();

            if (ancestor is InstanceDefinitionNode instanceDefinitionNode)
            {
                /*
                 * TODO once transpiler is done, make only THIS to be available keywords since SELF makes name collision with self global object
                 */
                if (referenceNameUpper == "THIS" || referenceNameUpper == "SELF")
                {
                    referenceNode.Name = instanceDefinitionNode.NameNode.Value;
                    referenceNameUpper = referenceNode.Name.ToUpper();
                    return(_symbolTable[referenceNameUpper]);
                }
            }


            NestableSymbol nestableSymbol;

            switch (ancestor)
            {
            case SubclassNode subclassNode:

                // look for local variable
                SubclassSymbol subclassSymbol = (SubclassSymbol)subclassNode.Symbol;
                if (subclassSymbol.BodySymbols.TryGetValue(referenceNameUpper, out nestableSymbol))
                {
                    return(nestableSymbol);
                }

                // look for class variable
                if (subclassSymbol.BaseClassSymbol != null)
                {
                    var classSymbol = subclassSymbol.BaseClassSymbol;
                    if (classSymbol.BodySymbols.TryGetValue(referenceNameUpper, out nestableSymbol))
                    {
                        return(nestableSymbol);
                    }
                }
                break;

            case FunctionDefinitionNode functionDefinitionNode:
                // look for local variable
                FunctionSymbol functionSymbol = (FunctionSymbol)functionDefinitionNode.Symbol;
                if (functionSymbol.BodySymbols.TryGetValue(referenceNameUpper, out nestableSymbol))
                {
                    return(nestableSymbol);
                }
                break;

            case ClassDefinitionNode _:
            case FileNode _:
                break;

            default:
                throw new Exception();
            }

            if (_symbolTable.ContainsKey(referenceNameUpper))
            {
                return(_symbolTable[referenceNameUpper]);
            }

            return(null);
        }
Beispiel #4
0
        protected override void VisitAssignment(AssignmentNode node)
        {
            ReferenceNode referenceNode = node.LeftSideNode;

            if (referenceNode.Symbol is InstanceSymbol)
            {
                // instances as of now aren't of type NestableSymbol, they can appear tough
                // however they are always initialized when they are created
                return;
            }

            Visit(node.RightSideNode);
            NestableSymbol nestableSymbol = (NestableSymbol)referenceNode.Symbol;

            switch (nestableSymbol?.Node)
            {
            case ConstDefinitionNode _:
            case ParameterDeclarationNode _:
                break;

            case VarDeclarationNode _:



                if (_currentBlockSymbol == null)
                {
                    throw new Exception();
                }

                NestableSymbol baseSymbol = referenceNode.BaseSymbol as NestableSymbol;
                if (baseSymbol == null)
                {
                    break;
                }

                ReferenceData referenceData = GetDataFromReferenceNode(referenceNode);
                if (referenceData == null || referenceData.HasDotInPath)
                {
                    break;
                }

                string relativePath = referenceData.PreDotPath;

                if (_currentBlockSymbol is SubclassSymbol currentSubclassSymbol)
                {
                    if (baseSymbol.ParentBlockSymbol == currentSubclassSymbol.BaseClassSymbol)
                    {
                        _initializedAttributesPaths.Add(relativePath);
                        break;
                    }
                }

                if (nestableSymbol.ParentBlockSymbol == _currentBlockSymbol)
                {
                    _initializedLocalsPaths.Add(relativePath);
                }

                break;
            }

            Visit(node.LeftSideNode);
        }