aspect AST { public static boolean ASTNode.DEBUG = false; public static String ASTNode.unCapitalise(String s) { return Character.toLowerCase(s.charAt(0)) + s.substring(1); } syn String FieldDeclaration.capitalisedName() = Character.toUpperCase(name().charAt(0))+name().substring(1); public static Object ASTNode.epsilon(SimpleSet set, Object alt) { if(set.size() == 1) return set.iterator().next(); return alt; } public ASTNode ASTNode.getParent(int i) { if(i <= 0) return this; if(getParent() == null) return null; return getParent().getParent(i-1); } public int ASTNode.getChildIndex() { return getParent().getIndexOfChild(this); } public void ASTNode.removeChild(ASTNode child) { removeChild(getIndexOfChild(child)); } private static void ASTNode.addingChildParentCheck(ASTNode newParent, ASTNode node) { if (DEBUG && node != null && node.is$Final() && //programRootParentFromField() != null && programRootParentFromField().isRecordingASTChanges() && node.parent != null && node.parent != newParent //&& node.parent.getIndexOfChild(node) != -1 ) throw new RuntimeException("inserting node with parent already set"); } refine ASTNode public void ASTNode.setChild(T node, int i) { addingChildParentCheck(this, node); refined(node, i); } refine ASTNode public void ASTNode.insertChild(T node, int i) { addingChildParentCheck(this, node); refined(node, i); } public ASTNode ASTNode.fullCopyAndDetach() { ASTNode node = fullCopy(); //node.parent = null; return node; } public Program ASTNode.programRoot() { ASTNode n=this; while(n!=null && !(n instanceof Program)) n=n.getParent(); return (Program)n; } public CompilationUnit ASTNode.compilationUnit() { ASTNode n=this; while(n!=null && !(n instanceof CompilationUnit)) n=n.getParent(); return (CompilationUnit)n; } public BodyDecl ASTNode.hostBodyDecl() { ASTNode n=this; while(n!=null && !(n instanceof BodyDecl)) n=n.getParent(); return (BodyDecl)n; } syn lazy boolean ASTNode.fromSource() { CompilationUnit cu = compilationUnit(); return cu == null ? false : cu.fromSource(); } public boolean Stmt.isInBlock() { return getParent() != null && getParent().getParent() instanceof Block; } public boolean Variable.isField() { return isClassVariable() || isInstanceVariable(); } public void TypeDecl.removeBodyDecl(BodyDecl bd) { getBodyDeclList().removeChild(getBodyDeclList().getIndexOfChild(bd)); } public void ASTNode.flushCaches() { this.flushCache(); for(int i=0;i . f * / \ / \ * this f A this * * * . . * / \ / \ * A . . g * / \ ~> / \ * this . . f * / \ / \ * f g A this * */ public void Access.bundleQualifier() { if(isLeftChildOfDot()) { AbstractDot parent = parentDot(); if(!parent.isRightChildOfDot()) return; AbstractDot g = new AbstractDot(null, parent.getRight()); AbstractDot p = parent.parentDot(); p.setRight(this); while(p.isRightChildOfDot()) p = p.parentDot(); p.rotateLeft(); p.replaceWith(g); g.setLeft(p); } else if(isRightChildOfDot()) { AbstractDot p = parentDot(); while(p.isRightChildOfDot()) p = p.parentDot(); p.rotateLeft(); } } public Expr Access.getQualifier() { assert !hasParentDot() || (isLeftChildOfDot() && (!parentDot().hasParentDot() || parentDot().isLeftChildOfDot())) || isRightChildOfDot(); // i.e., is rotated to left return isRightChildOfDot() ? parentDot().getLeft() : null; } public boolean ASTNode.isInTree() { ASTNode node = this; while (node.getParent() != null && node.getChildIndex() != -1) node = node.getParent(); return node instanceof Program; } }