aspect AttributesCodegeneration { public static Modifiers Modifiers.create(int flags) { List list = new List(); if((flags & ACC_PUBLIC) != 0) list.add(new Modifier("public")); if((flags & ACC_PRIVATE) != 0) list.add(new Modifier("private")); if((flags & ACC_PROTECTED) != 0) list.add(new Modifier("protected")); if((flags & ACC_STATIC) != 0) list.add(new Modifier("static")); if((flags & ACC_SYNTHETIC) != 0) list.add(new Modifier("synthetic")); return new Modifiers(list); } public boolean AttributeDecl.declaredNTA = false; public AttributeDecl AttributeDecl.declareNTA() { declaredNTA = true; return this; } public boolean AttributeDecl.declaredNTA() { return declaredNTA; } public boolean AttributeDecl.declaredFinal = false; public AttributeDecl AttributeDecl.declareFinal() { declaredFinal = true; return this; } public boolean AttributeDecl.declaredFinal() { return declaredFinal; } // override behavior in IntertypeMethodCodegeneration // code gen synthesized attributes eq SynEq.implBodyName() = decl().implBodyName(); eq SynEq.delegateName() = decl().delegateName(); public void SynEq.createIntertypeMethod(TypeDecl introducedType) { if(introducedType.isInterfaceDecl()) { // equations do never generate code in interfaces } else { generateIntertypeDecls(); MethodDecl aspectMethod = createAspectMethod(); int lineNum = getParameterList().sourceLineNumber(); MethodDecl delegateMethod = decl().generateAttributeDecl(introducedType, aspectMethod, lineNum, shouldBeCached()); introducedType.addMemberMethod(delegateMethod); if(hostType() != introducedType) { aspectMethod.generateSuperDispatchDelegate(introducedType); } } } public void SynDecl.createIntertypeMethod(TypeDecl introducedType) { if(introducedType.isInterfaceDecl()) { introducedType.addMemberMethod(createAbstractMethod()); } else { if(hasEqBody()) { /* TODO: if(options().hasOption("-weave_inline") && !introducedType().isInterfaceDecl()) aspectMethod = introducedType().addMemberMethod(aspectMethod); else aspectMethod = hostAspect().addMemberMethod(aspectMethod); */ generateIntertypeDecls(); MethodDecl aspectMethod = createAspectMethod(); int lineNum = getParameterList().sourceLineNumber(); MethodDecl delegateMethod = generateAttributeDecl(introducedType, aspectMethod, lineNum, shouldBeCached()); introducedType.addMemberMethod(delegateMethod); if(hostType() != introducedType) { aspectMethod.generateSuperDispatchDelegate(introducedType); } } else if(introducedType instanceof ASTDecl && !((ASTDecl)introducedType).hasEquation(this) && introducedType == introducedType()) { // public abstract type name(p0, ..., PN-1); introducedType.addMemberMethod(createAbstractMethod()); } } } // code gen inherited attributes public void InhDecl.createIntertypeMethod(TypeDecl introducedType) { if(!options().hasOption("-inh_in_astnode")) { addDefiningInterface(); } addInterfaceTagging(); int lineNum = getParameterList().sourceLineNumber(); generateAttributeDecl(introducedType, lineNum); } public List InhEq.createParameterList() { List list = new List(); list.add(new ParameterDeclaration(introducedType().createQualifiedAccess(), "this")); for(int i = 0; i < getNumParameter(); i++) list.add(getParameter(i).qualifiedCopy()); if(hasChildParameter()) list.add(createChildParameter()); return list; } syn boolean InhEq.hasChildParameter() { if(getNumChildParameter() == 1) return true; if(!getChildName().startsWith("get")) return false; if(getChildName().equals("getChild")) return true; ASTChild child = child(); return child != null && child instanceof ASTListChild; } syn String InhEq.childParameterName() { if(getNumChildParameter() == 1) return getChildParameter(0).name(); else return "childIndex"; } public ParameterDeclaration InhEq.createChildParameter() { if(getNumChildParameter() == 1) return getChildParameter(0).qualifiedCopy(); return new ParameterDeclaration(new PrimitiveTypeAccess("int"), "childIndex"); } public List InhDecl.createArgumentList(InhEq inhEq) { List args = new List(); args.add(new ThisAccess("this")); for(int i = 0; i < getNumParameter(); i++) { args.add(new VarAccess("arg" + i)); //args.add(getParameter(i).createAccess()); } if(inhEq.hasChildParameter()) { args.add( new VarAccess("caller").qualifiesAccess( new MethodAccess( "getIndexOfChild", new List().add( new VarAccess("child") ) ) ) ); } return args; } syn boolean AttributeDecl.isNTA() { if(!name().startsWith("get") || getNumParameter() != 0 || !(introducedType() instanceof ASTDecl)) return false; String name = name().substring(3); // remove "get" prefix ASTDecl decl = (ASTDecl)introducedType(); if(name.endsWith("List") && decl.lookupChild(name.substring(0, name.length() - 4)) instanceof ASTListChild) return true; if(name.endsWith("Opt") && decl.lookupChild(name.substring(0, name.length() - 3)) instanceof ASTOptionalChild) return true; boolean result = decl.lookupChild(name) != null; return result; } syn boolean AttributeDecl.bindsToTokenChild() = isNTA() && ((ASTDecl)introducedType()).lookupChild(name().substring(3)) instanceof ASTTokenChild; // Add a possibly cached delegate in typeDecl that calls aspectMethod public MethodDecl SynDecl.generateAttributeDecl(TypeDecl typeDecl, MethodDecl aspectMethod, int lineNum, boolean isLazy) { if(isLazy) { // Add re-init of attribute cache in node clone method nodeCopyClearCache(typeDecl); } // check cached value, compute new value, store in cache, return value List statements = new List(); if(isLazy || !options().hasOption("-no_visit_check")) addParameterStructure(statements); if(isLazy) addComputedCheck(statements, typeDecl); if (!options().hasOption("-no_component_check")) addInterruptedCircleDeclaration(statements); if(!options().hasOption("-no_visit_check")) { addCheckVisited(statements, typeDecl); addSetVisited(statements, typeDecl); } if (!options().hasOption("-no_component_check")) addCheckInterruptCircle(statements); if(isLazy) addCacheComputeCall(statements, typeDecl, aspectMethod); else addComputeCall(statements, aspectMethod); if(isNTA() || declaredNTA()) { addStoreNTAValue(statements, typeDecl); } if(!options().hasOption("-no_visit_check")) { addClearVisited(statements, typeDecl); } if (!options().hasOption("-no_component_check")) addClearInterruptedCircle(statements); addReturnStmt(statements, typeDecl, isLazy); //statements.getChildNoTransform(0).setSourceLineNumber(lineNum); statements.getChildNoTransform(statements.getNumChild()-1).setSourceLineNumber(lineNum); // public type name(p0, ... , pN-1) { ... } //typeDecl.addMemberMethod( return new MethodDecl( Modifiers.create(Modifiers.ACC_PUBLIC | Modifiers.ACC_SYNTHETIC), type().createQualifiedAccess(), delegateName(), copyParameterList(getParameterList()), new List(), new Opt(new Block(statements)) //) ); } protected void AttributeDecl.addInterruptedCircleDeclaration(List list) { list.add( new VariableDeclaration( new TypeAccess("boolean"), "interruptedCircle", new BooleanLiteral(false) ) ); } protected void AttributeDecl.addCheckInterruptCircle(List list) { List ifStatements = new List(); // interruptedCircle = true; ifStatements.add( AssignExpr.asStmt( new VarAccess("interruptedCircle"), new BooleanLiteral(true) ) ); // IN_CIRCLE = FALSE; ifStatements.add( AssignExpr.asStmt( new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("IN_CIRCLE")), new BooleanLiteral(false) ) ); // circularEvalState.push(new BOOLEAN(CHANGE)); /*ifStatements.add( new ExprStmt( new VarAccess("circularEvalState").qualifiesAccess( new MethodAccess( "push", new List().add( new ClassInstanceExpr( lookupType("java.lang", "Boolean").createQualifiedAccess(), new List().add( new VarAccess("CHANGE") ), new Opt() ) ) ) ) ) );*/ ifStatements.add( new ExprStmt( new MethodAccess("state", new List()).qualifiesAccess( new MethodAccess("pushEvalStack", new List()) ) ) ); list.add( new IfStmt( new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("IN_CIRCLE")), new Block( ifStatements ) ) ); } protected void AttributeDecl.addClearInterruptedCircle(List list) { //if (interruptedCircle) { IN_CIRCLE = true; CHANGE = ((Boolean) circuralEvalStack().pop())booleanValue();} List ifStatements = new List(); ifStatements.add( AssignExpr.asStmt( new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("IN_CIRCLE")), new BooleanLiteral(true) ) ); /*Expr popStack = TypeDecl.createUnbox(lookupType("java.lang","Boolean"), "booleanValue", new VarAccess("circularEvalState").qualifiesAccess( new MethodAccess( "pop", new List() ) ) ); ifStatements.add( AssignExpr.asStmt( new VarAccess("CHANGE"), popStack ) );*/ ifStatements.add( new ExprStmt( new MethodAccess("state", new List()).qualifiesAccess( new MethodAccess("popEvalStack", new List()) ) ) ); list.add( new IfStmt( new VarAccess("interruptedCircle"), new Block( ifStatements ) ) ); } // createUnbox static // ((Boolean)STACK.pop()).booleanValue() // TypeDecl.createUnbox(lookupType("java.lang", "Boolean"), "booleanValue", new VarAccess("STACK").qualifiesAccess(new MethodAccess...) // Add a possibly cached delegate in typeDecl that calls aspectMethod public void InhDecl.generateAttributeDecl(TypeDecl typeDecl, int lineNum) { if(isLazy()) { // Add re-init of attribute cache in node clone method nodeCopyClearCache(typeDecl); } // check cached value, compute new value, store in cache, return value List statements = new List(); if(isLazy() || !options().hasOption("-no_visit_check")) addParameterStructure(statements); if(isLazy()) addComputedCheck(statements, typeDecl); if (!options().hasOption("-no_component_check")) addInterruptedCircleDeclaration(statements); if(!options().hasOption("-no_visit_check")) { // if(visited) throw new RuntimeException("Circular definition..."); addCheckVisited(statements, typeDecl); // visited = true; addSetVisited(statements, typeDecl); } if (!options().hasOption("-no_component_check")) addCheckInterruptCircle(statements); if(isLazy()) addCacheComputeCall(statements, typeDecl); else addComputeCall(statements); if(isNTA() || declaredNTA()) { addStoreNTAValue(statements, typeDecl); } if(!options().hasOption("-no_visit_check")) // visited = false; addClearVisited(statements, typeDecl); if (!options().hasOption("-no_component_check")) addClearInterruptedCircle(statements); addReturnStmt(statements, typeDecl, isLazy()); //statements.getChildNoTransform(0).setSourceLineNumber(lineNum); statements.getChildNoTransform(statements.getNumChild()-1).setSourceLineNumber(lineNum); // public type name(p0, ... , pN-1) { ... } typeDecl.addMemberMethod( new MethodDecl( Modifiers.create(Modifiers.ACC_PUBLIC | Modifiers.ACC_SYNTHETIC), type().createQualifiedAccess(), delegateName(), copyParameterList(getParameterList()), new List(), new Opt(new Block(statements)) ) ); } private Expr AttributeDecl.adoptNTA(FieldDeclaration f) { // f.setParent(this) return f.createQualifiedBoundAccess().qualifiesAccess( new MethodAccess("setParent", new List().add(new ThisAccess("this"))) ); } void AttributeDecl.storeNTAValue(List list) { // this.setNNN(computedValueName()) list.add( new ExprStmt( new ThisAccess("this").qualifiesAccess( new MethodAccess( "set" + name().substring(3), // replace initial get with set new List().add( new VarAccess(computedValueName()) ) ) ) ) ); } void AttributeDecl.makeNTAFinal(List list, Access f) { list.add(new ExprStmt( f.qualifiesAccess( new MethodAccess("is$Final", new List().add(new BooleanLiteral("true"))) ) )); } void AttributeDecl.addStoreNTAValue(List list, TypeDecl typeDecl) { // setNNN(computedValueName()); if(declaredNTA()) { if(getNumParameter() == 0) { FieldDeclaration f = fieldComputedValue(typeDecl); makeNTAFinal(list, f.createQualifiedBoundAccess()); list.add(new ExprStmt(adoptNTA(f))); } else { FieldDeclaration f = ntaListField(typeDecl); list.add( new IfStmt( new EQExpr( f.createQualifiedBoundAccess(), new NullLiteral("null") ), new Block( new List().add( AssignExpr.asStmt( f.createQualifiedBoundAccess(), new ClassInstanceExpr(listNode().createQualifiedAccess(), new List(), new Opt()) ) ).add( new ExprStmt( f.createQualifiedBoundAccess().qualifiesAccess( new MethodAccess("is$Final", new List().add(new BooleanLiteral("true"))) ) ) ).add( new ExprStmt(adoptNTA(f)) ) ), new Opt() ) ).add( new ExprStmt( new VarAccess(computedValueName()).qualifiesAccess( new MethodAccess("is$Final", new List().add(new BooleanLiteral("true"))) ) ) ).add( new ExprStmt( f.createQualifiedBoundAccess().qualifiesAccess( new MethodAccess("addChild", new List().add(new VarAccess(computedValueName()))) ) ) ); } } else { if(!bindsToTokenChild()) makeNTAFinal(list, new VarAccess(computedValueName())); storeNTAValue(list); } } protected void AttributeDecl.nodeCopyClearCache(TypeDecl type) { if(!(type instanceof ASTDecl)) return; ASTDecl typeDecl = (ASTDecl)type; Access fieldAccess = null; Expr expr = null; if(getNumParameter() == 0) { // node.computed = false; fieldAccess = new BoundFieldAccess(fieldComputedFlag(type)); expr = new BooleanLiteral(false); } else { // node.computed_value = new java.util.HashMap(4); fieldAccess = new BoundFieldAccess(fieldComputedValue(type)); expr = new ClassInstanceExpr( lookupType("java.util", "HashMap").createQualifiedAccess(), new List().add(new IntegerLiteral(4)) ); } typeDecl.addCloneNodeInit(fieldAccess, expr); } inh lazy TypeDecl AttributeDecl.typeObject(); inh lazy TypeDecl AttributeDecl.typeBoolean(); private HashMap AttributeDecl.fieldVisitedFlagAdded = new HashMap(); protected FieldDeclaration AttributeDecl.fieldVisitedFlag(TypeDecl typeDecl) { if(fieldVisitedFlagAdded.containsKey(typeDecl)) return (FieldDeclaration)fieldVisitedFlagAdded.get(typeDecl); TypeDecl fieldType = getNumParameter() == 0 ? typeBoolean() : lookupType("java.util", "HashSet"); Expr fieldInit; if(getNumParameter() == 0) fieldInit = new BooleanLiteral(false); else fieldInit = new ClassInstanceExpr( lookupType("java.util", "HashSet").createQualifiedAccess(), new List().add(new IntegerLiteral(4)) ); FieldDeclaration f = new FieldDeclaration( Modifiers.create(Modifiers.ACC_PRIVATE | Modifiers.ACC_SYNTHETIC), fieldType.createQualifiedAccess(), visitedFlagName(), fieldInit ); f = typeDecl.addMemberField(f); typeDecl.addFlushCode(f, (Expr)fieldInit.fullCopy()); fieldVisitedFlagAdded.put(typeDecl, f); return f; } void TypeDecl.addFlushCode(FieldDeclaration f, Expr init) { MethodDecl m = flushCacheMethod(); List list = m.getBlock().getStmtList(); list.add(AssignExpr.asStmt(f.createQualifiedBoundAccess(), init)); } private HashMap AttributeDecl.ntaListFieldAdded = new HashMap(); protected FieldDeclaration AttributeDecl.ntaListField(TypeDecl typeDecl) { if(ntaListFieldAdded.containsKey(typeDecl)) return (FieldDeclaration)ntaListFieldAdded.get(typeDecl); FieldDeclaration f = new FieldDeclaration( Modifiers.create(Modifiers.ACC_PRIVATE | Modifiers.ACC_SYNTHETIC), listNode().createQualifiedAccess(), ntaListName(), new Opt() ); f = typeDecl.addMemberField(f); ntaListFieldAdded.put(typeDecl, f); return f; } private HashMap AttributeDecl.fieldComputedFlagAdded = new HashMap(); protected FieldDeclaration AttributeDecl.fieldComputedFlag(TypeDecl typeDecl) { if(fieldComputedFlagAdded.containsKey(typeDecl)) return (FieldDeclaration)fieldComputedFlagAdded.get(typeDecl); Expr init; if(getNumParameter() == 0) { init = new BooleanLiteral(false); } else { init = new ClassInstanceExpr( lookupType("java.util", "HashSet").createQualifiedAccess(), new List().add(new IntegerLiteral(4)) ); } FieldDeclaration f = new FieldDeclaration( Modifiers.create(Modifiers.ACC_PRIVATE | Modifiers.ACC_SYNTHETIC), getNumParameter() == 0 ? typeBoolean().createQualifiedAccess() : lookupType("java.util", "HashSet").createQualifiedAccess(), computedFlagName(), init ); f = typeDecl.addMemberField(f); typeDecl.addFlushCode(f, (Expr)init.fullCopy()); fieldComputedFlagAdded.put(typeDecl, f); return f; } private HashMap AttributeDecl.fieldComputedValueAdded = new HashMap(); protected FieldDeclaration AttributeDecl.fieldComputedValue(TypeDecl typeDecl) { if(fieldComputedValueAdded.containsKey(typeDecl)) return (FieldDeclaration)fieldComputedValueAdded.get(typeDecl); FieldDeclaration f; if(getNumParameter() == 0) f = new FieldDeclaration( Modifiers.create(Modifiers.ACC_PRIVATE | Modifiers.ACC_SYNTHETIC), computedValueType().createQualifiedAccess(), computedValueName() ); else f = new FieldDeclaration( Modifiers.create(Modifiers.ACC_PRIVATE | Modifiers.ACC_SYNTHETIC), computedValueType().createQualifiedAccess(), computedValueName(), new ClassInstanceExpr( lookupType("java.util", "HashMap").createQualifiedAccess(), new List().add(new IntegerLiteral(4)) ) ); f = typeDecl.addMemberField(f); if(getNumParameter() != 0) { typeDecl.addFlushCode( f, new ClassInstanceExpr( lookupType("java.util", "HashMap").createQualifiedAccess(), new List().add(new IntegerLiteral(4)) ) ); } fieldComputedValueAdded.put(typeDecl, f); return f; } protected void AttributeDecl.addCheckVisited(List list, TypeDecl typeDecl) { if(getNumParameter() == 0) { // if(visited_flag) throw new RuntimeException("Circular definition of attr: signature in class: classname."); list.add( new IfStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess(), new ThrowStmt( new ClassInstanceExpr( lookupType("java.lang", "RuntimeException").createQualifiedAccess(), new List().add( new StringLiteral("Circular definition of attr: " + signature() + " in class: " + hostType().fullName()) ) ) ) ) ); } else { // if(visited_flag.contains("parameters$")) throw new RuntimeException("Circular definition of attr: signature in class: classname."); list.add( new IfStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess().qualifiesAccess( new MethodAccess( "contains", new List().add(new VarAccess("parameters$")) ) ), new ThrowStmt( new ClassInstanceExpr( lookupType("java.lang", "RuntimeException").createQualifiedAccess(), new List().add( new StringLiteral("Circular definition of attr: " + signature() + " in class: " + hostType().fullName()) ) ) ) ) ); } } protected void AttributeDecl.addSetVisited(List list, TypeDecl typeDecl) { if(getNumParameter() == 0) { // visited_flag = true; list.add( AssignExpr.asStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess(), new BooleanLiteral(true) ) ); } else { // visited_flag.set(parameters$) list.add( new ExprStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess().qualifiesAccess( new MethodAccess( "add", new List().add(new VarAccess("parameters$")) ) ) ) ); } } protected void AttributeDecl.addClearVisited(List list, TypeDecl typeDecl) { if(getNumParameter() == 0) { // visited_flag = true; list.add( AssignExpr.asStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess(), new BooleanLiteral(false) ) ); } else { // visited_flag.set(parameters$) list.add( new ExprStmt( fieldVisitedFlag(typeDecl).createQualifiedBoundAccess().qualifiesAccess( new MethodAccess( "remove", new List().add(new VarAccess("parameters$")) ) ) ) ); } } protected void AttributeDecl.addParameterStructure(List list) { if(getNumParameter() == 1) { // type parameters$ = parameter0; list.add( new VariableDeclaration( typeObject().createQualifiedAccess(), "parameters$", getParameter(0).type().box(getParameter(0).createAccess()) ) ); } else if(getNumParameter() > 1) { // object[] parameters$ = {parameter0, .. , paramterN-1}; List init = new List(); for(int i = 0; i < getNumParameter(); i++) init.add(getParameter(i).type().box(getParameter(i).createAccess())); list.add( new VariableDeclaration( lookupType("java.util", "List").createQualifiedAccess(), "parameters$", new ClassInstanceExpr( lookupType("java.util", "ArrayList").createQualifiedAccess(), new List().add(new IntegerLiteral(getNumParameter())) ) ) ); for(int i = 0; i < getNumParameter(); i++) { list.add( new ExprStmt( new VarAccess("parameters$").qualifiesAccess( new MethodAccess( "add", new List().add( getParameter(i).type().box(getParameter(i).createAccess()) ) ) ) ) ); } } } protected void AttributeDecl.addComputedCheck(List list, TypeDecl typeDecl) { if(isNTA() && !bindsToTokenChild()) { list.add( new IfStmt( fieldComputedFlag(typeDecl).createQualifiedBoundAccess(), // return (List)ASTNode.getChild(this, getDynamicTypeListChildPosition()); new ReturnStmt( new CastExpr( type().createQualifiedAccess(), astNode().createQualifiedAccess().qualifiesAccess( new MethodAccess( "getChild", new List().add( new ThisAccess("this") ).add( new MethodAccess(name() + "ChildPosition", new List()) ) ) ) ) ) /* // return (List)getChildNoTransform(getDynamicTypeListChildPosition()); new ReturnStmt( new CastExpr( type().createQualifiedAccess(), new MethodAccess( "getChildNoTransform", new List().add(new MethodAccess(name() + "ChildPosition", new List())) ) ) ) */ ) ); } else if(getNumParameter() == 0) { // if(computed_flag) return computed_value; list.add( new IfStmt( fieldComputedFlag(typeDecl).createQualifiedBoundAccess(), //new VarAccess(computedFlagName()), new ReturnStmt(fieldComputedValue(typeDecl).createQualifiedBoundAccess()/*new VarAccess(computedValueName())*/) ) ); } else { // if(computed_value.containsKey(parameters$) return (type)computed_value.get(parameters$); list.add( new IfStmt( fieldComputedValue(typeDecl).createQualifiedBoundAccess().qualifiesAccess( //new VarAccess(computedValueName()), new MethodAccess( "containsKey", new List().add(new VarAccess("parameters$")) ) ), new ReturnStmt( type().unbox( fieldComputedValue(typeDecl).createQualifiedBoundAccess().qualifiesAccess( //new VarAccess(computedValueName()), new MethodAccess( "get", new List().add(new VarAccess("parameters$")) ) ) ) ) ) ); } } /* public Access ParameterDeclaration.createAccess() { return new VarAccess(name()); } */ public Expr TypeDecl.box(Expr expr) { return expr; } protected Expr TypeDecl.createBox(TypeDecl typeDecl, Expr expr) { return new ClassInstanceExpr( typeDecl.createQualifiedAccess(), new List().add(expr) ); } public Expr BooleanType.box(Expr expr) { return createBox(lookupType("java.lang", "Boolean"), expr); } public Expr ByteType.box(Expr expr) { return createBox(lookupType("java.lang", "Byte"), expr); } public Expr ShortType.box(Expr expr) { return createBox(lookupType("java.lang", "Short"), expr); } public Expr IntType.box(Expr expr) { return createBox(lookupType("java.lang", "Integer"), expr); } public Expr LongType.box(Expr expr) { return createBox(lookupType("java.lang", "Long"), expr); } public Expr CharType.box(Expr expr) { return createBox(lookupType("java.lang", "Char"), expr); } public Expr FloatType.box(Expr expr) { return createBox(lookupType("java.lang", "Float"), expr); } public Expr DoubleType.box(Expr expr) { return createBox(lookupType("java.lang", "Double"), expr); } public Expr TypeDecl.unbox(Expr expr) { return new CastExpr(createQualifiedAccess(), expr); } protected static Expr TypeDecl.createUnbox(TypeDecl typeDecl, String methodName, Expr expr) { return new ParExpr( new CastExpr( typeDecl.createQualifiedAccess(), expr ) ).qualifiesAccess( new MethodAccess(methodName, new List()) ); } public Expr BooleanType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Boolean"), "booleanValue", expr); } public Expr ByteType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Byte"), "byteValue", expr); } public Expr ShortType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Short"), "shortValue", expr); } public Expr IntType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Integer"), "intValue", expr); } public Expr LongType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Long"), "longValue", expr); } public Expr CharType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Char"), "charValue", expr); } public Expr FloatType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Float"), "floatValue", expr); } public Expr DoubleType.unbox(Expr expr) { return createUnbox(lookupType("java.lang", "Double"), "doubleValue", expr); } protected void AttributeDecl.addComputeCall(List list, MethodDecl targetMethod) { List args = new List(); args.add(new ThisAccess("this")); for(int i = 0; i < getNumParameter(); i++) { args.add(getParameter(i).createAccess()); } // type computed_value = name(arg0, ... , argN-1); list.add( new VariableDeclaration( type().createQualifiedAccess(), computedValueName(), //new ComputeMethodAccess(name(), args, hostAspect(), type()) targetMethod.createBoundAccess(args) ) ); } protected void AttributeDecl.addCacheComputeCall(List list, TypeDecl typeDecl, MethodDecl targetMethod) { // int num$ = boundariesCrossed; list.add( new VariableDeclaration( new TypeAccess("int"), "num$", new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("boundariesCrossed")) ) ); // boolean localFinal$ = this.is$Final() list.add( new VariableDeclaration( new TypeAccess("boolean"), "localFinal$", new MethodAccess("is$Final", new List()) ) ); // localFinal$ && num$ == boundariesCrossed Expr cond; if(declaredFinal() || declaredNTA()) cond = new BooleanLiteral("true"); else cond = new AndLogicalExpr( new VarAccess("localFinal$"), new EQExpr( new VarAccess("num$"), new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("boundariesCrossed")) ) ); List args = new List(); args.add(new ThisAccess("this")); for(int i = 0; i < getNumParameter(); i++) { args.add(getParameter(i).createAccess()); } if(getNumParameter() == 0) { // computed_value = name(arg0, .. , argN-1); list.add( AssignExpr.asStmt( fieldComputedValue(typeDecl).createQualifiedBoundAccess(), //new VarAccess(computedValueName()), //new ComputeMethodAccess(name(), args, hostAspect(), type()) targetMethod.createBoundAccess(args) ) ); // if(cond) computed_flag = true; list.add( new IfStmt( cond, AssignExpr.asStmt( fieldComputedFlag(typeDecl).createQualifiedBoundAccess(), //new VarAccess(computedFlagName()), new BooleanLiteral(true) ) ) ); } else { // type computed_value = name(arg0, ... , argN-1); list.add( new VariableDeclaration( type().createQualifiedAccess(), computedValueName(), //new ComputeMethodAccess(name(), args, hostAspect(), type())) targetMethod.createBoundAccess(args) ) ); // if(cond) this.computed_value.put(parameters$, computed_value); list.add( new IfStmt( cond, new ExprStmt( fieldComputedValue(typeDecl).createQualifiedBoundAccess().qualifiesAccess( new MethodAccess( "put", new List().add( new VarAccess("parameters$") ).add( type().box(new VarAccess(computedValueName())) ) ) ) ) ) ); } } syn lazy String TypeDecl.typeNameInSignature() { return fullName(). replace('.', '$'). replace('@', '_'). replace('[', '$'). replace(']', 'A'); } syn lazy String InhDecl.definingInterfaceName() { StringBuffer s = new StringBuffer(); s.append("Defines$" + name()); for(int i = 0; i < getNumParameter(); i++) s.append("$" + getParameter(i).type().typeNameInSignature()); return s.toString(); } private HashSet ClassDecl.addImplementedInterface = null; public void ClassDecl.addImplementedInterface(String name) { if(addImplementedInterface == null) addImplementedInterface = new HashSet(); if(addImplementedInterface.contains(name)) return; addImplementedInterface.add(name); addImplements( astNode().createQualifiedAccess().qualifiesAccess( new TypeAccess(name) ) ); } private HashMap TypeDecl.addMethod = null; public MethodDecl TypeDecl.addMethod(String name, MethodDecl m) { if(addMethod == null) addMethod = new HashMap(); if(addMethod.containsKey(name)) return (MethodDecl)addMethod.get(name); addMethod.put(name, m); addMemberMethod(m); return (MethodDecl)getBodyDecl(getNumBodyDecl()-1); } private boolean InhDecl.addInterfaceTagging = false; public void InhDecl.addInterfaceTagging() { if(addInterfaceTagging) return; addInterfaceTagging = true; Map map = new HashMap(); HashSet set = new HashSet(); for(Iterator iter = decls().iterator(); iter.hasNext(); ) { InhEq inhEq = (InhEq)iter.next(); if(!map.containsKey(inhEq.introducedType())) map.put(inhEq.introducedType(), new ArrayList(1)); ArrayList c = (ArrayList)map.get(inhEq.introducedType()); if(inhEq.childName().equals("Child")) c.add(inhEq); else c.add(0, inhEq); if(inhEq.isRefinement()) set.add(inhEq); } for(Iterator iter = set.iterator(); iter.hasNext(); ) { InhEq inhEq = (InhEq)iter.next(); ArrayList c = (ArrayList)map.get(inhEq.introducedType()); c.remove(inhEq.refinedEntity()); } Map methodMap = new HashMap(); // Foreach class that has an introduced equation for this inh declaration for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) { TypeDecl typeDecl = (TypeDecl)iter.next(); if(typeDecl instanceof ClassDecl) { ClassDecl classDecl = (ClassDecl)typeDecl; if(!options().hasOption("-inh_in_astnode")) { // Add implements tag classDecl.addImplementedInterface(definingInterfaceName()); } MethodDecl m = classDecl.addMethod(definingInterfaceName(), new MethodDecl( Modifiers.create(Modifiers.ACC_PUBLIC | Modifiers.ACC_SYNTHETIC), type().createQualifiedAccess(), definingInterfaceName(), createDefiningInterfaceParameterList(), new List(), new Opt( ) ) ); methodMap.put(classDecl, m); } } for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) { TypeDecl typeDecl = (TypeDecl)iter.next(); if(typeDecl instanceof ClassDecl) { ClassDecl classDecl = (ClassDecl)typeDecl; // statements in delegation method List statements = new List(); boolean canCompleteNormally = true; // Foreach inh equation in this type for(Iterator i2 = ((Collection)map.get(typeDecl)).iterator(); i2.hasNext(); ) { InhEq inhEq = (InhEq)i2.next(); // add inh equation to aspect MethodDecl methodDecl = inhEq.addEqToAspect(type()); List modifierList = (List)getModifiers().getModifierList().boundCopy(); modifierList.add(new Modifier("static")); methodDecl.setModifiers(new Modifiers(modifierList)); if(inhEq.getChildName().equals("getChild")) { statements.add( new ReturnStmt( methodDecl.createBoundAccess(createArgumentList(inhEq)) ) ); canCompleteNormally = false; } else { boolean done = false; for(Iterator i3 = inhEq.introducedType().memberMethods(inhEq.getChildName()).iterator(); i3.hasNext(); ) { MethodDecl m = (MethodDecl)i3.next(); if(m instanceof AttributeDecl) { if(inhEq.getNumChildParameter() < 2 && m.getNumParameter() == 1 && m.getParameter(0).type().isInt()) { statements.add( new IfStmt( new EQExpr( new VarAccess("caller"), ((AttributeDecl)m).ntaListField(classDecl).createQualifiedBoundAccess() ), new ReturnStmt( methodDecl.createBoundAccess(createArgumentList(inhEq)) ) ) ); done = true; } else if(inhEq.getNumChildParameter() == 0 && m.getNumParameter() == 0) { statements.add( new IfStmt( new EQExpr( new VarAccess("caller"), new MethodAccess(inhEq.getChildName(), new List()) ), new ReturnStmt( methodDecl.createBoundAccess(createArgumentList(inhEq)) ) ) ); done = true; } } } if(!done) { // Add conditional delegation statements.add( new IfStmt( inhEq.child().createFromCorrectChildCheck(), new ReturnStmt( methodDecl.createBoundAccess(createArgumentList(inhEq)) ) ) ); } } } if(canCompleteNormally) { // Add last statement // use the previously built MethodDecl as a template for the super method access // since it may not have been built yet boolean eqInSuperClass = false; TypeDecl searchType = typeDecl; while(!eqInSuperClass && searchType != null && searchType instanceof ASTDecl) { ASTDecl astDecl = (ASTDecl)searchType; if(astDecl.hasSuperclass()) searchType = astDecl.superclass(); if(map.containsKey(searchType) && !((Collection)map.get(searchType)).isEmpty()) eqInSuperClass = true; } if(eqInSuperClass) { List args = new List(); args.add(new VarAccess("caller")); args.add(new VarAccess("child")); for(int i = 0; i < getNumParameter(); i++) { args.add(new VarAccess("arg" + i)); //args.add(getParameter(i).createAccess()); } MethodDecl superM = (MethodDecl)methodMap.get(searchType); statements.add( new ReturnStmt( new SuperAccess( "super" ).qualifiesAccess( superM.createBoundAccess(args) ) ) ); } else { addDelegateToAncestorDefinition(statements); } } MethodDecl m = (MethodDecl)methodMap.get(classDecl); m.setBlock( new Block( statements ) ); } } } syn boolean InhEq.weaveInline() = options().hasOption("-weave_inline") && !introducedType().isInterfaceDecl(); syn lazy MethodDecl InhEq.addEqToAspect(TypeDecl returnType) { MethodDecl methodDecl = new IntroducedMethodDecl( new Modifiers(new List().add(new Modifier("static"))), returnType.createQualifiedAccess(), name() + "$" + childName(), createParameterList(), new List(), new Opt( getBlock().boundCopy() ), introducedType(), this ); if(weaveInline()) return introducedType().addMemberMethod(methodDecl); else return hostType().addMemberMethod(methodDecl); } Expr ASTChild.createFromCorrectChildCheck() { return new EQExpr( new VarAccess("caller"), new MethodAccess("get" + name() + "NoTransform", new List()) ); } Expr ASTOptionalChild.createFromCorrectChildCheck() { return new EQExpr( new VarAccess("caller"), new MethodAccess("get" + name() + "OptNoTransform", new List()) ); } Expr ASTListChild.createFromCorrectChildCheck() { return new EQExpr( new VarAccess("caller"), new MethodAccess("get" + name() + "ListNoTransform", new List()) ); } inh SimpleSet InhDecl.lookupType(String name); public List InhDecl.createDefiningInterfaceParameterList() { List list = new List(); list.add(new ParameterDeclaration(astNode().createQualifiedAccess(), "caller")); list.add(new ParameterDeclaration(astNode().createQualifiedAccess(), "child")); for(int i = 0; i < getNumParameter(); i++) { //list.add(getParameter(i).qualifiedCopy()); list.add(new ParameterDeclaration(getParameter(i).type().createQualifiedAccess(), "arg" + i)); } return list; } private HashMap TypeDecl.inhEqDelegate; public MethodDecl TypeDecl.inhEqDelegate(String name) { return inhEqDelegate == null ? null : (MethodDecl)inhEqDelegate.get(name); } public void TypeDecl.addInhEqDelegate(String name, MethodDecl m) { if(inhEqDelegate == null) inhEqDelegate = new HashMap(); inhEqDelegate.put(name, m); } public MethodDecl InhDecl.inhEqDelegate() { MethodDecl m = astNode().inhEqDelegate(definingInterfaceName()); if(m == null) { List statements = new List(); m = new MethodDecl( (Modifiers)getModifiers().boundCopy(), type().createQualifiedAccess(), definingInterfaceName(), createDefiningInterfaceParameterList(), new List(), new Opt(new Block(statements)) ); List args = new List(); args.add(new ThisAccess("this")); args.add(new VarAccess("caller")); for(int i = 0; i < getNumParameter(); i++) { //args.add(new VarAccess(getParameter(i).name())); args.add(new VarAccess("arg" + i)); } statements.add( new ReturnStmt( new MethodAccess("getParent", new List()).qualifiesAccess( new BoundMethodAccess(definingInterfaceName(), args, m) ) ) ); m = astNode().addMemberMethod(m); astNode().addInhEqDelegate(definingInterfaceName(), m); } return m; } // TODO: currently needs to update remote attributes after this operation protected void InhDecl.addDefiningInterface() { if(astNode().firstDefiningInterfaceQuery(definingInterfaceName())) { astNode().addBodyDecl( new MemberInterfaceDecl( new InterfaceDecl( Modifiers.create(Modifiers.ACC_PUBLIC | Modifiers.ACC_SYNTHETIC), definingInterfaceName(), new List(), new List().add( new MethodDecl( Modifiers.create(Modifiers.ACC_PUBLIC | Modifiers.ACC_SYNTHETIC), type().createQualifiedAccess(), definingInterfaceName(), createDefiningInterfaceParameterList(), new List(), new Opt() ) ) ) ) ); } } private HashSet TypeDecl.hasDefiningInterface = null; public boolean TypeDecl.firstDefiningInterfaceQuery(String name) { if(hasDefiningInterface == null) hasDefiningInterface = new HashSet(); if(hasDefiningInterface.contains(name)) return false; hasDefiningInterface.add(name); return true; } protected void InhDecl.addSearchAncestorForEquation(List list) { if(options().hasOption("-inh_in_astnode")) { return; } // TODO: make this only call getParent() when other policy for inherited attributes // ASTNode n = getParent(); // ASTNode caller = this; // ASTNode child = null; list.add( new VariableDeclaration( astNode().createQualifiedAccess(), "n", new MethodAccess("getParent", new List()) ) ).add( new VariableDeclaration( astNode().createQualifiedAccess(), "caller", new ThisAccess("this") ) ).add( new VariableDeclaration( astNode().createQualifiedAccess(), "child", new NullLiteral("null") ) ); addSearchAncestorForEquationLoop(list); } protected void InhDecl.addSearchAncestorForEquationNoDecl(List list) { if(options().hasOption("-inh_in_astnode")) { return; } // TODO: make this only call getParent() when other policy for inherited attributes // ASTNode n = getParent(); // ASTNode caller = this; // ASTNode child = null; list.add( new VariableDeclaration( astNode().createQualifiedAccess(), "n", new MethodAccess("getParent", new List()) ) ).add( AssignExpr.asStmt(new VarAccess("caller"), new ThisAccess("this")) ).add( AssignExpr.asStmt(new VarAccess("child"), new NullLiteral("null")) ); addSearchAncestorForEquationLoop(list); } protected void InhDecl.addSearchAncestorForEquationLoop(List list) { // while(!(n instanceof definingInterfaceName)) { // child = caller; // caller = n; // n = n.getParent(); list.add( new WhileStmt( new LogNotExpr( new ParExpr( new InstanceOfExpr( new VarAccess("n"), astNode().createQualifiedAccess().qualifiesAccess( new TypeAccess(definingInterfaceName()) ) ) ) ), new Block( new List().add( AssignExpr.asStmt(new VarAccess("child"), new VarAccess("caller")) ).add( AssignExpr.asStmt(new VarAccess("caller"), new VarAccess("n")) ).add( AssignExpr.asStmt( new VarAccess("n"), new VarAccess("n").qualifiesAccess( new MethodAccess("getParent", new List()) ) ) ) ) ) ); } protected Expr AttributeDecl.createComputeCall(MethodDecl targetMethod) { throw new Error("createComputeCall(MethodDecl targetMethod) not implemented for " + getClass().getName()); } protected Expr SynDecl.createComputeCall(MethodDecl targetMethod) { List args = new List(); args.add(new ThisAccess("this")); for(int i = 0; i < getNumParameter(); i++) { args.add(getParameter(i).createAccess()); } // compute(this, p0, ... , pn-1) return targetMethod.createBoundAccess(args); } protected Expr AttributeDecl.createComputeCall() { throw new Error("createComputeCall() not implemented for " + getClass().getName()); } protected Expr InhDecl.createComputeCall() { if(options().hasOption("-inh_in_astnode")) { List args = new List(); args.add(new ThisAccess("this")); args.add(new NullLiteral("null")); for(int i = 0; i < getNumParameter(); i++) { //args.add(new VarAccess("arg" + i)); args.add(getParameter(i).createAccess()); } return new MethodAccess("getParent", new List()).qualifiesAccess( new BoundMethodAccess(definingInterfaceName(), args, inhEqDelegate()) ); } // ((hostType.definingInterfaceName)n).definingInterfaceName(caller, child, arg0, ... argN-1) List args = new List(); args.add(new VarAccess("caller")); args.add(new VarAccess("child")); for(int i = 0; i < getNumParameter(); i++) { //args.add(new VarAccess("arg" + i)); args.add(getParameter(i).createAccess()); } return new ParExpr( new CastExpr( astNode().createQualifiedAccess().qualifiesAccess( new TypeAccess(definingInterfaceName()) ), new VarAccess("n") ) ).qualifiesAccess( new MethodAccess(definingInterfaceName(), args) ); } protected Expr InhDecl.createComputeCallInDelegate() { if(options().hasOption("-inh_in_astnode")) { List args = new List(); args.add(new ThisAccess("this")); args.add(new NullLiteral("null")); for(int i = 0; i < getNumParameter(); i++) { args.add(new VarAccess("arg" + i)); //args.add(getParameter(i).createAccess()); } return new MethodAccess("getParent", new List()).qualifiesAccess( new BoundMethodAccess(definingInterfaceName(), args, inhEqDelegate()) ); } // ((hostType.definingInterfaceName)n).definingInterfaceName(caller, child, arg0, ... argN-1) List args = new List(); args.add(new VarAccess("caller")); args.add(new VarAccess("child")); for(int i = 0; i < getNumParameter(); i++) { args.add(new VarAccess("arg" + i)); //args.add(getParameter(i).createAccess()); } return new ParExpr( new CastExpr( astNode().createQualifiedAccess().qualifiesAccess( new TypeAccess(definingInterfaceName()) ), new VarAccess("n") ) ).qualifiesAccess( new MethodAccess(definingInterfaceName(), args) ); } protected void InhDecl.addDelegateToAncestorDefinition(List list) { addSearchAncestorForEquationNoDecl(list); list.add(new ReturnStmt(createComputeCallInDelegate())); } protected void InhDecl.addComputeCall(List list) { addSearchAncestorForEquation(list); list.add( new VariableDeclaration( type().createQualifiedAccess(), computedValueName(), createComputeCall() ) ); } protected void InhDecl.addCacheComputeCall(List list, TypeDecl typeDecl) { // int num$ = boundariesCrossed; list.add( new VariableDeclaration( new TypeAccess("int"), "num$", new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("boundariesCrossed")) ) ); // boolean localFinal$ = this.is$Final() list.add( new VariableDeclaration( new TypeAccess("boolean"), "localFinal$", new MethodAccess("is$Final", new List()) ) ); // localFinal$ && num$ == boundariesCrossed Expr cond; if(declaredFinal() || declaredNTA()) cond = new BooleanLiteral("true"); else cond = new AndLogicalExpr( new VarAccess("localFinal$"), new EQExpr( new VarAccess("num$"), new MethodAccess("state", new List()).qualifiesAccess(new VarAccess("boundariesCrossed")) ) ); addSearchAncestorForEquation(list); Expr computeCall = createComputeCall(); if(getNumParameter() == 0) { // computed_value = name(arg0, .. , argN-1); list.add( AssignExpr.asStmt( fieldComputedValue(typeDecl).createQualifiedBoundAccess(), //new VarAccess(computedValueName()), computeCall ) ); // if(cond) computed_flag = true; list.add( new IfStmt( cond, AssignExpr.asStmt( fieldComputedFlag(typeDecl).createQualifiedBoundAccess(), //new VarAccess(computedFlagName()), new BooleanLiteral(true) ) ) ); } else { // type computed_value = name(arg0, ... , argN-1); list.add( new VariableDeclaration( type().createQualifiedAccess(), computedValueName(), computeCall ) ); // if(cond) this.computed_value.put(parameters$, computed_value); list.add( new IfStmt( cond, new ExprStmt( fieldComputedValue(typeDecl).createQualifiedBoundAccess().qualifiesAccess( new MethodAccess( "put", new List().add( new VarAccess("parameters$") ).add( type().box(new VarAccess(computedValueName())) ) ) ) ) ) ); } } protected void AttributeDecl.addReturnStmt(List list, TypeDecl typeDecl, boolean isLazy) { // return computed_value; if(isNTA() && !bindsToTokenChild()) { list.add( // return (List)ASTNode.getChild(this, getDynamicTypeListChildPosition()); new ReturnStmt( new CastExpr( type().createQualifiedAccess(), astNode().createQualifiedAccess().qualifiesAccess( new MethodAccess( "getChild", new List().add( new ThisAccess("this") ).add( new MethodAccess(name() + "ChildPosition", new List()) ) ) ) ) ) /* // return (List)getChildNoTransform(getDynamicTypeListChildPosition()); new ReturnStmt( new CastExpr( type().createQualifiedAccess(), new MethodAccess( "getChildNoTransform", new List().add(new MethodAccess(name() + "ChildPosition", new List())) ) ) ) */ ); } else if(isLazy && getNumParameter() == 0) list.add(new ReturnStmt(fieldComputedValue(typeDecl).createQualifiedBoundAccess())); else list.add(new ReturnStmt(new VarAccess(computedValueName()))); } syn lazy String AttributeDecl.uniqueSignatureName() { StringBuffer s = new StringBuffer(); s.append(name()); if(getNumParameter() > 0) s.append("_"); for(int i = 0; i < getNumParameter(); i++) { ParameterDeclaration p = getParameter(i); s.append(p.type().typeNameInSignature()); } return s.toString(); } syn String AttributeDecl.visitedFlagName() = uniqueSignatureName() + "$visited"; syn String AttributeDecl.computedFlagName() = uniqueSignatureName() + "$computed"; syn String AttributeDecl.computedValueName() = uniqueSignatureName() + "$value"; syn TypeDecl AttributeDecl.computedValueType() = getNumParameter() == 0 ? type() : lookupType("java.util", "Map"); syn String AttributeDecl.ntaListName() = uniqueSignatureName() + "$list"; syn MethodDecl TypeDecl.flushCacheMethod() = ((MethodDecl)memberMethods("flushCache").iterator().next()).sourceMethodDecl(); }