001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    aspect LocalNum {
011      inh lazy int VariableDeclaration.localNum();
012      inh lazy int Stmt.localNum();
013      inh lazy int ParameterDeclaration.localNum();
014    
015      eq Program.getChild(int index).localNum() = 0;
016    
017      syn lazy int MethodDecl.offsetBeforeParameters() = isStatic() ? 0 : 1;
018      
019      syn lazy int MethodDecl.offsetAfterParameters() {
020        if(getNumParameter() == 0)
021          return offsetBeforeParameters();
022        return getParameter(getNumParameter()-1).localNum() + 
023               getParameter(getNumParameter()-1).type().variableSize();
024      }
025      
026      eq MethodDecl.getParameter(int index).localNum() {
027        if(index == 0)
028          return offsetBeforeParameters();
029        return getParameter(index-1).localNum() + getParameter(index-1).type().variableSize();
030      }
031    
032      eq InstanceInitializer.getBlock().localNum() {
033        int localNum = 1;
034        for(Iterator iter = hostType().constructors().iterator(); iter.hasNext(); ) {
035          ConstructorDecl c = (ConstructorDecl)iter.next();
036          int num = c.getNumParameter() == 0 ? c.localNumOfFirstParameter() : 
037                    c.getParameter(c.getNumParameter()-1).localNum() + c.getParameter(c.getNumParameter()-1).type().variableSize();
038          if(num > localNum)
039            localNum = num;
040        }
041        return localNum;
042      }
043    
044      inh lazy int ReturnStmt.resultSaveLocalNum();
045      eq MethodDecl.getBlock().resultSaveLocalNum() = offsetAfterParameters();
046      eq Program.getChild().resultSaveLocalNum() {
047        throw new Error("Unsupported operation resultSaveLocalNum");
048      }
049    
050      syn lazy int MethodDecl.resultOffset() = type().isVoid() ? 0 : type().variableSize();
051      
052      eq MethodDecl.getBlock().localNum() = offsetAfterParameters() + 
053          resultOffset();
054    
055      syn lazy int ConstructorDecl.localNumOfFirstParameter() {
056        int i = 1;
057        if(hostType().needsEnclosing())
058          i++;
059        if(hostType().needsSuperEnclosing())
060          i++;
061        return i;
062      }
063    
064      syn lazy int ConstructorDecl.offsetFirstEnclosingVariable() {
065        int localIndex = localNumOfFirstParameter();
066        Collection vars = hostType().enclosingVariables();
067        if(vars.isEmpty())
068          return localIndex;
069        String name = "val$" + ((Variable)vars.iterator().next()).name();
070        for(int i = 0; !getParameter(i).name().equals(name); i++)
071          localIndex += getParameter(i).type().variableSize();
072        return localIndex;
073      }
074    
075      syn int ConstructorDecl.localIndexOfEnclosingVariable(Variable v) {
076        int localIndex  = offsetFirstEnclosingVariable();
077        Iterator iter = hostType().enclosingVariables().iterator();
078        Variable varDecl = (Variable)iter.next();
079        while(varDecl != v && iter.hasNext()) {
080          localIndex += varDecl.type().variableSize();
081          varDecl = (Variable)iter.next();
082        }
083        return localIndex;
084      }
085    
086      eq ConstructorDecl.getParameter(int index).localNum() = index == 0 ?
087        localNumOfFirstParameter() :
088        getParameter(index-1).localNum() + getParameter(index-1).type().variableSize();
089    
090      eq ConstructorDecl.getBlock().localNum() = getNumParameter() == 0 ? 
091        localNumOfFirstParameter() :
092        getParameter(getNumParameter()-1).localNum() + getParameter(getNumParameter()-1).type().variableSize();
093    
094      eq ForStmt.getStmt().localNum() {
095        if(getNumInitStmt() == 0)
096          return localNum();
097        if(getInitStmt(getNumInitStmt()-1) instanceof VariableDeclaration)
098          return getInitStmt(getNumInitStmt()-1).localNum() + ((VariableDeclaration)getInitStmt(getNumInitStmt()-1)).type().variableSize();
099        return getInitStmt(getNumInitStmt()-1).localNum();
100      }
101      
102      eq ForStmt.getInitStmt(int index).localNum() {
103        if(index == 0)
104          return localNum();
105        if(getInitStmt(index-1) instanceof VariableDeclaration)
106          return getInitStmt(index-1).localNum() + ((VariableDeclaration)getInitStmt(index-1)).type().variableSize();
107        return getInitStmt(index-1).localNum();
108      }
109      
110      eq Block.getStmt(int index).localNum() {
111        if(index == 0)
112          return localNum();
113        if(getStmt(index-1) instanceof VariableDeclaration)
114          return getStmt(index-1).localNum() + ((VariableDeclaration)getStmt(index-1)).type().variableSize();
115        return getStmt(index-1).localNum();
116      }
117    
118      eq TryStmt.getFinally().localNum() = localNum() + 2;
119    
120      eq BasicCatch.getBlock().localNum() = getParameter().localNum() + getParameter().type().variableSize();
121    
122      eq SynchronizedStmt.getBlock().localNum() = localNum() + 3;
123    
124      syn int TypeDecl.variableSize() = 0;
125      eq ReferenceType.variableSize() = 1;
126      eq PrimitiveType.variableSize() = 1;
127      eq LongType.variableSize() = 2;
128      eq DoubleType.variableSize() = 2;
129      eq NullType.variableSize() = 1;
130    }
131