aspect LocalNum { inh lazy int VariableDeclaration.localNum(); inh lazy int Stmt.localNum(); inh lazy int Parameter.localNum(); eq Program.getCompilationUnit(int index).localNum() = 0; syn lazy int MethodDecl.offsetBeforeParameters() = isStatic() ? 0 : 1; syn lazy int MethodDecl.offsetAfterParameters() { if(getNumParameter() == 0) return offsetBeforeParameters(); return getParameter(getNumParameter()-1).localNum() + getParameter(getNumParameter()-1).type().size(); } eq MethodDecl.getParameter(int index).localNum() { if(index == 0) return offsetBeforeParameters(); return getParameter(index-1).localNum() + getParameter(index-1).type().size(); } eq InstanceInitializer.getBlock().localNum() = 1; inh lazy int ReturnStmt.resultSaveLocalNum(); eq MethodDecl.getBlock().resultSaveLocalNum() = offsetAfterParameters(); eq Program.getCompilationUnit().resultSaveLocalNum() { throw new Error("Unsupported operation resultSaveLocalNum"); } syn lazy int MethodDecl.resultOffset() = type().isVoid() ? 0 : 1; eq MethodDecl.getBlock().localNum() = offsetAfterParameters() + resultOffset(); syn lazy int ConstructorDecl.localNumOfFirstParameter() { int i = 1; if(hostType().isInnerType()) i++; /* for(Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); i += v.type().size(); }*/ return i; } syn lazy int ConstructorDecl.enclosingVariablesOffset() { int i = 0; for(Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); i += v.type().size(); } return i; } eq ConstructorDecl.getParameter(int index).localNum() { if(index == 0) { return localNumOfFirstParameter(); } return getParameter(index-1).localNum() + getParameter(index-1).type().size(); } eq ConstructorDecl.getBlock().localNum() { if(getNumParameter() == 0) { return localNumOfFirstParameter() + enclosingVariablesOffset(); } else { return getParameter(getNumParameter()-1).localNum() + getParameter(getNumParameter()-1).type().size() + enclosingVariablesOffset(); } } eq ForStmt.getStmt().localNum() { if(getNumInitStmt() == 0) return localNum(); if(getInitStmt(getNumInitStmt()-1) instanceof VariableDeclaration) return getInitStmt(getNumInitStmt()-1).localNum() + ((VariableDeclaration)getInitStmt(getNumInitStmt()-1)).type().size(); return getInitStmt(getNumInitStmt()-1).localNum(); } eq ForStmt.getInitStmt(int index).localNum() { if(index == 0) return localNum(); if(getInitStmt(index-1) instanceof VariableDeclaration) return getInitStmt(index-1).localNum() + ((VariableDeclaration)getInitStmt(index-1)).type().size(); return getInitStmt(index-1).localNum(); } eq Block.getStmt(int index).localNum() { if(index == 0) return localNum(); if(getStmt(index-1) instanceof VariableDeclaration) return getStmt(index-1).localNum() + ((VariableDeclaration)getStmt(index-1)).type().size(); return getStmt(index-1).localNum(); } eq TryStmt.getFinally().localNum() = localNum() + 2; eq SynchronizeStmt.getBlock().localNum() = localNum() + 1; syn lazy int ASTNode.maxLocals() // +1 if virtual (this) // +1 for each arg (+2 if double or long) // Algorithm: max of each subscope + value for this scope { int maxLocals = 0; for (int i=0; i