public override ASTNode VisitReference([NotNull] DaedalusParser.ReferenceContext context) { List <ReferencePartNode> referencePartNodes = new List <ReferencePartNode>(); foreach (var referenceAtomContext in context.referenceAtom()) { AttributeNode attributeNode = new AttributeNode( referenceAtomContext.nameNode().GetText(), GetLocation(referenceAtomContext) ); referencePartNodes.Add(attributeNode); if (referenceAtomContext.arrayIndex() != null) { ArrayIndexNode arrayIndexNode = (ArrayIndexNode)VisitArrayIndex(referenceAtomContext.arrayIndex()); attributeNode.ArrayIndexNode = arrayIndexNode; referencePartNodes.Add(arrayIndexNode); } } string name = ((AttributeNode)referencePartNodes[0]).Name; referencePartNodes.RemoveAt(0); ReferenceNode referenceNode = new ReferenceNode(name, referencePartNodes, GetLocation(context)); ReferenceNodes.Add(referenceNode); return(referenceNode); }
protected override NodeValue VisitArrayIndexNode(ArrayIndexNode arrayIndexNode) { if (arrayIndexNode.ParentNode.Annotations.Count > 0) { return(null); } arrayIndexNode.Value = Visit(arrayIndexNode.ExpressionNode); switch (arrayIndexNode.Value) { case IntValue arrayIndexValue: ReferenceNode referenceNode = (ReferenceNode)arrayIndexNode.ParentNode; if (referenceNode.Symbol == null) { break; } if (referenceNode.Symbol.Node is IArrayDeclarationNode arrayDeclarationNode) { NodeValue arraySizeNodeValue = Visit(arrayDeclarationNode.ArraySizeNode); if (arraySizeNodeValue is IntValue arraySizeValue) { if (arrayIndexValue.Value >= arraySizeValue.Value) { arrayIndexNode.Annotations.Add(new IndexOutOfRangeError(arraySizeValue.Value)); //+ return(new UndefinedValue()); } if (arrayIndexValue.Value > 255) { arrayIndexNode.Annotations.Add(new TooBigArrayIndexError()); //+ return(new UndefinedValue()); } } else { return(new UndefinedValue()); } } break; case UndefinedValue _: break; default: arrayIndexNode.Annotations.Add(new ArrayIndexNotConstIntegerError()); return(new UndefinedValue()); } return(arrayIndexNode.Value); }
public ReferenceNode(string name, List <ReferencePartNode> partNodes, NodeLocation location) : base(location) { Symbol = null; BaseSymbol = null; Name = name; PartNodes = partNodes; IndexNode = null; DoCastToInt = false; DoesHaveNestedAttributes = false; /* * When CastToInt = true, this node should produce PushInt instruction. * It should happen in following situations: * - assignment/return/parameter of type func * - assignment/return/parameter of type int && symbol's builtin type isn't int * - inside conditional */ foreach (var partNode in partNodes) { partNode.ParentNode = this; } }
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; } }
protected virtual T VisitArrayIndexNode(ArrayIndexNode arrayIndexNode) { Visit(arrayIndexNode.ExpressionNode); return(DefaultResult); }
protected virtual void VisitArrayIndexNode(ArrayIndexNode arrayIndexNode) { Visit(arrayIndexNode.ExpressionNode); }
public AttributeNode(string name, NodeLocation location) : base(location) { Name = name; ArrayIndexNode = null; }