]> source.dussan.org Git - aspectj.git/commitdiff
first pass at a guide for developers of compiler and weaver
authorjhugunin <jhugunin>
Thu, 19 Feb 2004 22:46:06 +0000 (22:46 +0000)
committerjhugunin <jhugunin>
Thu, 19 Feb 2004 22:46:06 +0000 (22:46 +0000)
13 files changed:
docs/developer/compiler-weaver/advice-dec.gif [new file with mode: 0644]
docs/developer/compiler-weaver/ajdt-uml.gif [new file with mode: 0644]
docs/developer/compiler-weaver/dev-guide-diagrams.vsd [new file with mode: 0644]
docs/developer/compiler-weaver/dev-guide-uml.vsd [new file with mode: 0644]
docs/developer/compiler-weaver/index.html [new file with mode: 0644]
docs/developer/compiler-weaver/overview.gif [new file with mode: 0644]
docs/developer/compiler-weaver/pointcut-dec.gif [new file with mode: 0644]
docs/developer/compiler-weaver/top-tree.gif [new file with mode: 0644]
docs/developer/compiler.html [deleted file]
docs/developer/index.html [new file with mode: 0644]
docs/developer/language.html
docs/developer/overview.html [deleted file]
docs/developer/weaver.html [deleted file]

diff --git a/docs/developer/compiler-weaver/advice-dec.gif b/docs/developer/compiler-weaver/advice-dec.gif
new file mode 100644 (file)
index 0000000..43f540a
Binary files /dev/null and b/docs/developer/compiler-weaver/advice-dec.gif differ
diff --git a/docs/developer/compiler-weaver/ajdt-uml.gif b/docs/developer/compiler-weaver/ajdt-uml.gif
new file mode 100644 (file)
index 0000000..3a6ff79
Binary files /dev/null and b/docs/developer/compiler-weaver/ajdt-uml.gif differ
diff --git a/docs/developer/compiler-weaver/dev-guide-diagrams.vsd b/docs/developer/compiler-weaver/dev-guide-diagrams.vsd
new file mode 100644 (file)
index 0000000..5636872
Binary files /dev/null and b/docs/developer/compiler-weaver/dev-guide-diagrams.vsd differ
diff --git a/docs/developer/compiler-weaver/dev-guide-uml.vsd b/docs/developer/compiler-weaver/dev-guide-uml.vsd
new file mode 100644 (file)
index 0000000..d3fa03d
Binary files /dev/null and b/docs/developer/compiler-weaver/dev-guide-uml.vsd differ
diff --git a/docs/developer/compiler-weaver/index.html b/docs/developer/compiler-weaver/index.html
new file mode 100644 (file)
index 0000000..7265bed
--- /dev/null
@@ -0,0 +1,917 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>AspectJ Developer's Guide</title>
+<style>
+<!--
+pre          { border-style: solid; border-width: 1px; margin-left: 24; padding-left: 4px; 
+               padding-right: 4px; padding-top: 1px; padding-bottom: 1px; 
+               background-color: #EAF3FF; margin-right:24 }
+h3           { background-color: #99CCFF }
+h2           { background-color: #CCCCFF }
+h1           { background-color: #99CCFF }
+-->
+</style>
+</head>
+
+<body>
+
+<h1 align="center">Guide for Developers of the AspectJ Compiler and Weaver</h1>
+<p>This document is written for developers who want to understand the 
+implementation of AspectJ. It provides a top-down picture of the compiler 
+and weaver implementations. This high-level picture should make it easier 
+to read and understand the source code for AspectJ.</p>
+<p>The AspectJ compiler/weaver (ajc) is composed of three primary modules.</p>
+<ul>
+       <li><b>org.aspectj.ajdt.core</b> - this is the compiler front-end and 
+       extends the eclipse Java compiler from <b>org.eclipse.jdt.core</b>. 
+       Because of the dependencies on parts of eclipse this generates a large ~6MB jar.</li>
+       <li><b>weaver</b> - this provides the bytecode weaving functionality. 
+       It has very few external dependencies to minimize the size required for 
+       deployment of load-time weavers. Currently the build process doesn't 
+       produce a separate jar for just the weaver, but that will have to change for 
+       AspectJ-1.2.</li>
+       <li><b>runtime</b> - these are the classes that are used by generated code 
+       at runtime and must be redistributed with any system built using AspectJ. 
+       This module has no external dependencies and produces a tiny ~30KB jar.</li>
+</ul>
+<p>
+<img border="0" src="overview.gif"></p>
+<p>The AspectJ compiler accepts both AspectJ bytecode and source code and 
+produces pure Java bytecode as a result. Internally it has two stages. The 
+front-end (org.aspectj.ajdt.core) compiles both AspectJ and pure Java source 
+code into pure Java bytecode annotated with additional attributes representing 
+any non-java forms such as advice and pointcut declarations. The back-end of the 
+AspectJ compiler (weaver) implements the transformations encoded in these 
+attributes to produce woven class files. The back-end can be run stand-alone to 
+weave pre-compiled aspects into pre-compiled .jar files. In addition, the 
+back-end exposes a weaving API which can be used to implement ClassLoaders that 
+will weave advice into classes dynamically as they are loaded by the virtual 
+machine.</p>
+<h2>Compiler front-end (org.aspectj.ajdt.core)</h2>
+<p>The front-end of the AspectJ compiler is implemented as an extension of the 
+Java compiler from eclipse.org. The source-file portion of the AspectJ compiler 
+is made complicated by inter-type declarations, declare parents, declare soft, 
+and privileged aspects. All of these constructs require changes to the 
+underlying compiler to modify Java\92s name-binding and static checking behavior.</p>
+<p>As the compiler extends the jdt.core compiler, the package structure of this 
+module mimics that of the jdt.core module. The design works hard to minimize the 
+set of changes required to org.eclipse.jdt.core because a fun 3-way merge is 
+required each time we want to move to a new underlying version of this code.&nbsp; 
+The ultimate goal is to contribute all of our changes to jdt.core back into the 
+main development branch some day.</p>
+<p>The basic structure of a compile is very simple:</p>
+<ol>
+       <li>Perform a shallow parse on all source files</li>
+       <li>Pass these compilation units through AjLookupManager to do type binding 
+       and some AspectJ augmentation</li><li>For each source file do a deep parse, 
+       annotation/analysis, and then code generation</ol>
+<h3>Top-level parse tree</h3>
+<p>Let's trace the following example program through the compiler.</p>
+<pre>package example.parse.tree;
+
+import org.aspectj.lang.*;
+
+public class Main {
+    public static void main(String[] args) {
+        new Main().doit();
+    }
+    
+    private void doit() {
+        System.out.println("hello");
+    }
+}
+
+aspect A {
+    pointcut entries(Main o): execution(void doit()) &amp;&amp; this(o);
+    before(Main o): entries(o) {
+        o.counter++;
+        System.out.println("entering: " + thisJoinPoint);
+    }
+
+    private int Main.counter = 0;
+}</pre>
+<p>When parsed, this program will produce the following tree.</p>
+<p><img border="0" src="top-tree.gif"></p>
+<h3>PointcutDeclaration processing</h3>
+<p>Let's look more closely at the pointcut 
+declaration:</p>
+<pre>pointcut entries(Main o): execution(void doit()) &amp;&amp; this(o);</pre>
+<p><img border="0" src="pointcut-dec.gif"></p>
+<p>The pointcut declaration is implemented as a subtype of a method declaration. 
+The actual pointcut is parsed by the weaver module. This parsing happens 
+as part of the shallow parse phase. This is because this information might 
+be needed to implement a declare soft.</p>
+<h3>AdviceDeclaration processing</h3>
+<p>Next we look at the processing for an advice declaration:</p>
+<pre>before(Main o): entries(o) {
+    o.counter++;
+    System.out.println("entering: " + thisJoinPoint);
+}</pre>
+<p>
+After parsing, the AdviceDeclaration.postParse method will be called to make this 
+a valid MethodDeclaration so that the standard eclipse code for analyzing a 
+method body can be applied to the advice. After postParse, the selector is 
+filled in and several additional arguments are added for the special 
+thisJoinPoint forms that could be used in the body.</p>
+<p>
+<img border="0" src="advice-dec.gif"></p>
+<p>
+At this point the statements field which will hold the body of the advice is 
+still null. This field is not filled in until the second stage of the 
+compiler when full parsing is done on each source file as a prelude to 
+generating the classfile.</p>
+<h3>
+Overview of the main classes in org.aspectj.ajdt.core</h3>
+<p>
+The main classes in this module are shown in the following diagram:</p>
+<p>
+<img border="0" src="ajdt-uml.gif"></p>
+<h2>Weaving back-end (weaver)</h2>
+<p>This provides all of the weaving functionality. It has very few 
+dependencies to keep the code as small as possible for deployment in load-time 
+weavers - only asm, bridge and util which are each very small modules with no 
+further dependencies. This also depends on a patched version of the bcel library from apache.org. 
+The patches are only to fix bcel bugs that can't be 
+worked around in any other way.</p>
+<p>There are only four packages in this system.</p>
+<ul>
+       <li>org.aspectj.weaver - general classes that can be used by any weaver 
+       implementation</li>
+       <li>org.aspectj.weaver.patterns - patterns to represent pointcut designators 
+       and related matching constructs</li>
+       <li>org.aspectj.weaver.ast - a very small library to represent simple 
+       expressions without any bcel dependencies</li>
+       <li>org.aspectj.weaver.bcel - the concrete implementation of shadows and the 
+       weaver using the bcel library from apache.org</li>
+</ul>
+<p class="MsoNormal">The back-end of the AspectJ compiler instruments the code 
+of the system by inserting calls to the precompiled advice methods.&nbsp; It does 
+this by considering that certain principled places in bytecode represent 
+possible join points; these are the \93static shadow\94 of those join points.&nbsp; For 
+each such static shadow, it checks each piece of advice in the system and 
+determines if the advice's pointcut could match that static shadow.&nbsp; If it could 
+match, it inserts a call to the advice\92s implementation method guarded by any 
+dynamic testing needed to ensure the match.</p>
+<h2>Runtime support library (runtime)</h2>
+<p>This library provides classes that are used by the generated code at runtime.&nbsp; 
+These are the only classes that must be redistributed with a system built using 
+AspectJ.&nbsp; Because these classes are redistributed this library must always 
+be kept as small as possible.&nbsp; It is also important to worry about binary 
+compatibility when making changes to this library.&nbsp; There are two packages 
+that are considered public and may be used by AspectJ programs.</p>
+<ul>
+       <li>org.aspectj.lang</li>
+       <li>org.apectj.lang.reflect</li>
+</ul>
+<p>There are also several packages all under the header org.aspectj.runtime that 
+are considered private to the implementation and may only be used by code 
+generated by the AspectJ compiler.</p>
+<p></p>
+<h2>Mappings from AspectJ language to implementation</h2>
+<table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%" height="234">
+  <tr>
+    <td width="12%" height="19"></td>
+    <td width="23%" height="19">org.aspectj.ajdt.internal.compiler</td>
+    <td width="40%" height="19">weaver - org.aspectj.weaver.</td>
+  </tr>
+  <tr>
+    <td width="12%" height="19">aspect</td>
+    <td width="23%" height="19">ast.AspectDeclaration</td>
+    <td width="40%" height="19">CrosscuttingMembers</td>
+  </tr>
+  <tr>
+    <td width="12%" height="19">advice</td>
+    <td width="23%" height="19">ast.AdviceDeclaration</td>
+    <td width="40%" height="19">Advice + bcel.BcelShadowMunger</td>
+  </tr>
+  <tr>
+    <td width="12%" height="19">pointcut declaration</td>
+    <td width="23%" height="19">ast.PointcutDeclaration</td>
+    <td width="40%" height="19">ResolvedPointcutDefinition</td>
+  </tr>
+  <tr>
+    <td width="12%" height="19">declare error/warning</td>
+    <td width="23%" height="19">ast.DeclareDeclaration</td>
+    <td width="40%" height="19">Checker + patterns.DeclareErrorOrWarning</td>
+  </tr>
+  <tr>
+    <td width="12%" height="38">declare soft</td>
+    <td width="23%" height="38">ast.DeclareDeclaration + 
+    problem.AjProblemReporter</td>
+    <td width="40%" height="38">Advice (w/ kind = Softener) + 
+    patterns.DeclareSoft</td>
+  </tr>
+  <tr>
+    <td width="12%" height="38">declare parents</td>
+    <td width="23%" height="38">ast.DeclareDeclaration + 
+    lookup.AjLookupEnvironment</td>
+    <td width="40%" height="38">patterns.DeclareParents + NewParentTypeMunger</td>
+  </tr>
+  <tr>
+    <td width="12%" height="18">inter-type decls</td>
+    <td width="23%" height="18">ast.InterType*Declaration + lookup.InterType*Binding 
+    + lookup.AjLookupEnvironment</td>
+    <td width="40%" height="18">New*TypeMunger + bcel.BcelTypeMunger</td>
+  </tr>
+  <tr>
+    <td width="12%" height="19">if pcd</td>
+    <td width="23%" height="19">ast.IfPseudoToken + ast.IfMethodDeclaration</td>
+    <td width="40%" height="19">patterns.IfPointcut</td>
+  </tr>
+  <tr>
+    <td width="12%" height="17">pcd</td>
+    <td width="23%" height="17">ast.PointcutDesignator</td>
+    <td width="40%" height="17">patterns.Pointcut hierarchy</td>
+  </tr>
+</table>
+<p></p>
+<h1>Tutorial: implementing a throw join point</h1>
+<p>This tutorial will walk step-by-step through the process of adding a new join 
+point to AspectJ for the moment when an exception is thrown.&nbsp; In Java 
+source code, the shadow of this point is a throw statement. In Java bytecode, 
+the shadow is the athrow instruction.</p>
+<p>This tutorial is recommended to anyone who wants to get a better feel for how 
+the implementation of AspectJ really works.&nbsp; Even if you're just working on 
+a bug fix or minor enhancement, the process of working with the AspectJ 
+implementation will be similar to that described below.&nbsp; The size of your 
+actual code changes will likely be smaller, but you are likely to need to be 
+familiar with all of the pieces of the implementation described below.</p>
+<h2>Part 1: Adding the join point and corresponding pcd</h2>
+<p>The first part of this tutorial will implement the main features of the throw 
+join point. We will create a new join point shadow corresponding to the athrow 
+instruction and also create a new pointcut designator (pcd) for matching it.</p>
+<h3>Step 1. Synchronize with repository and run the existing test suite</h3>
+<p>Do a Team-&gt;Synchronize With Repository and make sure that your tree is 
+completely in sync with the existing repository. Make sure to address any 
+differences before moving on.</p>
+<p>Run the existing test suite. I currently do this in four steps:</p>
+<ul>
+       <li>weaver/testsrc/BcWeaverModuleTests.java</li>
+       <li>org.aspectj.ajdt.core/testsrc/EajcModuleTests.java</li>
+       <li>ajde/testsrc/AjdeModuleTests.java</li>
+       <li>Harness on ajctests.xml -- at least under 1.4, preferably under both 1.3 and 
+1.4.</li>
+</ul>
+<p>There should be no failures when you run these tests. If there are 
+failures, resolve them with the AspectJ developers before moving on.</p>
+<h3>Step 2. Write a proto test case</h3>
+<p>a. Create a new file in tests/design/pcds/Throw.java</p>
+<pre>import org.aspectj.testing.Tester;
+
+public class Throws {
+    public static void main(String[] args) {
+        try {
+            willThrow();
+            Tester.checkFailed("should have thrown exception");
+        } catch (RuntimeException re) {
+            Tester.checkEqual("expected exception", re.getMessage());
+        }
+    }
+    
+    static void willThrow() {
+        throw new RuntimeException("expected exception");
+    }
+}
+
+aspect A {
+    before(): withincode(void willThrow()) {
+        System.out.println("about to execute: " + thisJoinPoint);
+    }
+}</pre>
+<p>b. Create a temporary test harness file to run just this test in myTests.xml</p>
+<pre>&lt;!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"&gt;
+&lt;suite&gt;
+    &lt;ajc-test dir="design/pcds"
+        title="simple throw join point"&gt;
+        &lt;compile files="Throws.java" /&gt;
+        &lt;run class="Throws"/&gt;
+    &lt;/ajc-test&gt;
+&lt;/suite&gt;
+</pre>
+<p>c. Run this test using the harness. You should see:</p>
+<pre>about to execute: execution(void Throws.willThrow())
+about to execute: call(java.lang.RuntimeException(String))
+PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 2 seconds</pre>
+<h3>Step 3. Implement the new join point shadow kind</h3>
+<p>Modify runtime/org.aspectj.lang/JoinPoint.java to add a name for the Throw 
+shadow kind.</p>
+<pre>static String THROW = "throw";</pre>
+<p>Modify weaver/org.aspectj.weaver/Shadow.java to add the Throw shadow kind. 
+This adds a static typesafe enum for the Throw Kind. The constructor uses the 
+name from the runtime API to ensure that these names will always match. The '12' 
+is used for serialization of this kind to classfiles and is part of the binary 
+API for aspectj. The final 'true' indicates that this joinpoint has its 
+arguments on the stack. This is because the throw bytecode in Java operates on a 
+single argument that is a Throwable which must be the top element on the stack. 
+This argument is removed from the stack by the bytecode.
+</p>
+<pre>public static final Kind Throw = new Kind(JoinPoint.THROW, 12, true);
+</pre>
+<p>We also modify the neverHasTarget method to include the Throw kind because in 
+Java there is no target for the throwing of an exception.</p>
+<pre>public boolean neverHasTarget() {
+    return this == ConstructorCall
+        || this == ExceptionHandler
+        || this == PreInitialization
+        || this == StaticInitialization
+        || this == Throw;
+}
+</pre>
+<p>In the read method on Shadow.Kind, add another case to read in our new 
+Shadow.Kind.</p>
+<pre>case 12: return Throw;
+</pre>
+<h3>Step 4. Create this new kind of joinpoint for the throw bytecode</h3>
+<p>Modify weaver/org.aspectj.weaver.bcel/BcelClassWeaver.java to recognize this 
+new joinpoint kind. In the method
+<pre>private void match(
+    LazyMethodGen mg,
+    InstructionHandle ih,
+    BcelShadow enclosingShadow,
+    List shadowAccumulator) 
+{
+</pre>
+<p>Add a test for this instruction, i.e.</p>
+<pre>} else if (i == InstructionConstants.ATHROW) {
+    match(BcelShadow.makeThrow(world, mg, ih, enclosingShadow),
+          shadowAccumulator);
+}
+</pre>
+<p>Then, modify BcelShadow.java to create this new kind of join point shadow:</p>
+<pre>public static BcelShadow makeThrow(
+        BcelWorld world,
+        LazyMethodGen enclosingMethod,
+        InstructionHandle throwHandle,
+        BcelShadow enclosingShadow) 
+{
+    final InstructionList body = enclosingMethod.getBody();
+    TypeX throwType = TypeX.THROWABLE; //!!! not as precise as we'd like
+    TypeX inType = enclosingMethod.getEnclosingClass().getType();
+    BcelShadow s =
+        new BcelShadow(
+            world,
+            Throw,
+            Member.makeThrowSignature(inType, throwType),
+            enclosingMethod,
+            enclosingShadow);
+    ShadowRange r = new ShadowRange(body);
+    r.associateWithShadow(s);
+    r.associateWithTargets(
+        Range.genStart(body, throwHandle),
+        Range.genEnd(body, throwHandle));                
+    retargetAllBranches(throwHandle, r.getStart());
+    return s;
+}    </pre>
+<p>Finally modify weaver/org.aspectj.weaver/Member.java to generate the needed 
+signature</p>
+<pre>public static Member makeThrowSignature(TypeX inType, TypeX throwType) {
+    return new Member(
+        HANDLER,
+        inType,
+        Modifier.STATIC,
+        "throw",
+        "(" + throwType.getSignature() + ")V");
+}</pre>
+<p>Run the proto test again and you should see:</p>
+<pre>about to execute: execution(void Throws.willThrow())
+about to execute: call(java.lang.RuntimeException(String))
+about to execute: throw(catch(Throwable))
+PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 3 seconds
+</pre>
+<p>That last line shows the 'throw(catch(Throwable))' 
+join point. This is a slightly confusing string form, but it is the first sign 
+of our brand new join point. The reason for the weird 'catch(Throwable)' part is 
+that we used Member.HANDLER for the kind of the signature of this join point. 
+That's clearly not correct. We'll fix that at the end of the lesson as 
+part of the clean-up. For now, let's go on with the interesting parts.</p>
+<h3>Step 5. Extend our proto-test to use a pointcut designator for matching</h3>
+<p>Add a second piece of before advice to the test aspect A:</p>
+<pre>before(): throw(Throwable) {
+    System.out.println("about to throw: " + thisJoinPoint);
+}</pre>
+       
+<p>When we run the test again we'll get a long error message from the harness. 
+The interesting part of the message is the following:</p>
+<pre>[  0] [error   0]: error can't find referenced pointcut at C:\aspectj\eclipse\tests\design\pcds\Throws.java:23:0
+</pre>
+<p>This error is not quite what you might have expected. You might have 
+hoped for a syntax error saying that there is not 'throw' pointcut designator 
+defined. Unfortunately, this is a weakness in the syntax of AspectJ where 
+primitive PCDs and named PCDs have the same syntax, so the compiler can't tell 
+the difference between a misspelled or non-existent primitive PCD and a named 
+PCD reference that is missing. This also has some impact on extending the 
+primitive PCDs because it will break existing programs. In this case, when 
+we add the throw PCD we will break any existing programs that use throw as the 
+name for a user-defined PCD. Fortunately because throw is a Java keyword 
+this particular change is very safe.</p>
+<h3>Step 6. Extend the PCD parser to handle this new primitive PCD</h3>
+<p>Modify  the 
+parseSinglePointcut method in weaver/org.aspectj.weaver.patterns/PatternParser.java to add one more else if clause for the throw pcd:</p>
+<pre>} else  if (kind.equals("throw")) {
+    parseIdentifier(); eat("(");
+    TypePattern typePat = parseTypePattern();
+    eat(")");
+    return new KindedPointcut(Shadow.Throw,
+        new SignaturePattern(Member.HANDLER, ModifiersPattern.ANY,
+            TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, 
+            new TypePatternList(new TypePattern[] {typePat}), 
+            ThrowsPattern.ANY));</pre>
+<p>Modify the matches method in weaver/org.aspectj.weaver.patterns/SignaturePattern.java 
+to add:</p>
+<pre>if (kind == Member.HANDLER) {
+    return parameterTypes.matches(world.resolve(sig.getParameterTypes()), 
+                                  TypePattern.STATIC).alwaysTrue();
+} </pre>
+<p>Run the  proto test again and you should see:</p>
+
+<pre>about to execute: execution(void Throws.willThrow())
+about to execute: call(java.lang.RuntimeException(String))
+about to execute: throw(catch(Throwable))
+about to throw: throw(catch(Throwable))
+PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds
+</pre>
+
+Make sure that you see the 'about to throw' printed before moving on.  
+This shows that the throw PCD is now successfully matching the throw join point 
+shadow we added earlier.<h3>Step 7. Check that we're properly providing the 
+single thrown argument (and clean-up the test)</h3>
+<p>Now that we have a valid pcd for this advice, we can simplify our test case. 
+Modify our test aspect A to be the following. In addition to removing the 
+overly generic withincode pcd, this change also prints the actual  
+object that is about to be thrown:</p>
+<pre>aspect A {
+    before(Throwable t): throw(*) && args(t) {
+        System.out.println("about to throw: '" + t+ "' at " + thisJoinPoint);
+    }
+}</pre>
+       
+<p>When we run the test again we should see the output below:</p>
+<pre>about to throw: 'java.lang.RuntimeException: expected exception' at throw(catch(Throwable))
+PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds
+</pre>
+<p>Congratulations! You've just 
+implemented the throw join point and PCD. This code isn't yet ready to be checked into any repository. It still 
+has some rough edges that need to be smoothed. However, you've now 
+added a new join point to the AspectJ language and a corresponding PCD to match 
+it. This is a good time to take a break before moving on to part two.</p>
+<h2>Part 2: Getting the signature of this new join point right</h2>
+<p>We know that throw(catch(Throwable)) is not the right thing to be printing 
+for the signature at this join point. What is the correct signature? 
+At the beginning of the tutorial, we explained that the preferred design for the 
+pcd was to have throw(StaticTypeOfExceptionThrown). In step 4, we set the 
+type of the exception thrown to be 'Throwable'. Can we set this to be more 
+accurate? Looking at the source code, it seems easy to identify the static 
+type of the exception that is thrown:</p>
+<pre>throw new RuntimeException("expected exception");</pre>
+<p>In the source code to a Java program there is a well-defined static type for 
+the exception that is thrown. This static type is used for various stages 
+of flow analysis to make sure that checked exceptions are always correctly 
+handled or declared. The ThrowStatement class in our own compiler has a 
+special field for exceptionType that stores the static type of the exception 
+thrown. Unfortunately, this static type is much harder to recover from the 
+corresponding bytecode. In this case we would need to do flow analysis to 
+figure out what the static type is for the object on the top of the stack 
+when the athrow instruction executes. This analysis can certainly be done. 
+In fact this analysis is a small part of what every JVM must do to verify the 
+type safety of a loaded classfile.</p>
+<p>However, the current AspectJ weaver doesn't do any of this analysis. 
+There are many good reasons to extend it in this direction in order to optimize 
+the code produced by the weaver. If we were really implementing this 
+feature, this would be the time for a long discussion on the aspectj-dev list to 
+decide if this was the right time to extend the weaver with the code flow 
+analysis needed to support a static type for the throw join point. For the 
+purposes of this tutorial, we're going to assume that it isn't the right time to 
+do this (implementing flow analysis for bytecodes would add another 50 pages to 
+this tutorial). Instead we're going to change the definition of the throw 
+join point to state that its argument always has a static type of Throwable. 
+We still allow dynamic matching in args to select more specific types. In 
+general, good AspectJ code should use this dynamic matching anyway to correspond 
+to good OO designs.</p>
+<h3>Step 1. Change the signature of the throw pcd</h3>
+<p>Since we aren't going to recover the static type of the exception thrown, we 
+need to fix the parser for the throw pcd to remove this information. We'll 
+fix the PatternParser code that we added in step 1.6 to read as follows:</p>
+<pre>} else  if (kind.equals("throw")) {
+    parseIdentifier(); eat("(");
+    eat(")");
+    return new KindedPointcut(Shadow.Throw,
+        new SignaturePattern(Member.THROW, ModifiersPattern.ANY,
+            TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, 
+            TypePatternList.ANY, 
+            ThrowsPattern.ANY));</pre>
+<p>Notice that this code also starts to fix the member kind to be Member.THROW 
+instead of the bogus Member.HANDLER that we were using before. To make 
+this work we have a set of things to do. First, let's create this new kind 
+in org.aspectj.weaver.Member. Find where the HANDLER kind is defined 
+there, and add a corresponding throw kind:</p>
+<pre>public static final Kind THROW         = new Kind("THROW", 8);
+</pre>
+<p>We also need to fix the serialization kind in 
+Member.Kind.read(DataInputStream) just above this constant list to add a case 
+for this new kind:</p>
+<pre>case 8: return THROW;
+</pre>
+<p>Still in this file, we also need to fix Member.makeThrowSignature to use this 
+new kind:</p>
+<pre>public static Member makeThrowSignature(TypeX inType, TypeX throwType) {
+    return new ResolvedMember(
+        THROW,
+        inType,
+        Modifier.STATIC,
+        "throw",
+        "(" + throwType.getSignature() + ")V");
+}
+</pre>
+<p>If you run the test now you'll get an error from the parser reminding us that 
+the throw pcd now doesn't accept a type pattern:</p>
+<pre>------------  FAIL: simple throw join point()
+...
+C:\aspectj\eclipse\tests\design\pcds\Throws.java:19:0 Syntax error on token "*", ")" expected
+
+FAIL Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 failed) 1 seconds</pre>
+<p>This is an easy fix to the test case as we modify our pcd for the new syntax 
+in the aspect A in our Throws.java test code:</p>
+<pre>before(Throwable t): throw() && args(t) {</pre>
+<p>    Now when we run the test case it looks like everything's fixed and we're 
+passing:</p>
+<pre>PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 2 seconds</pre>
+<h3>Part 2. Make a real test case</h3>
+<p>The pass result from running our test should worry you. Unlike previous 
+runs, this test run doesn't show the output from our System.out.println in the 
+before advice. So, it's clear this advice is not running. The 
+problem is that even though the advice is not running, the test case is passing. 
+We need to make this a real test case to fix this. We'll do that by adding 
+code that notes when the advice runs and then checks for this event. This 
+code uses the Tester.event and Tester.checkEvent methods:</p>
+<pre>import org.aspectj.testing.Tester;
+
+public class Throws {
+    public static void main(String[] args) {
+        try {
+            willThrow();
+            Tester.checkFailed("should have thrown exception");
+        } catch (RuntimeException re) {
+            Tester.checkEqual("expected exception", re.getMessage());
+        }
+        Tester.checkEvents(new String[] { "before throw" });
+    }
+    
+    static void willThrow() {
+        throw new RuntimeException("expected exception");
+    }
+}
+
+aspect A {
+    before(Throwable t): throw() && args(t) {
+        Tester.event("before throw");
+        //System.out.println("about to throw: '" + t+ "' at " + thisJoinPoint);
+    }
+}</pre>
+<p>Now when we run our test case it will fail. This failure is good 
+because we're not matching the throw join point anymore.</p>
+<pre>------------  FAIL: simple throw join point()
+...
+[ 1] [fail 0]: fail [ expected event &quot;before throw&quot; not found]
+
+FAIL Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 failed) 1 seconds</pre>
+<h3>Step 3. Fix signature matching again</h3>
+<p>In org.aspectj.weaver.patterns.SignaturePattern.matches, we need to handle 
+throw signature matching the same way we handle advice signature matching. 
+Both of these pcds match solely on the kind of join point and use combinations 
+with other pcds to narrow their matches. So, find the line for kind == 
+Member.ADVICE and add the same line below it for Member.THROW.</p>
+<pre>if (kind == Member.ADVICE) return true;
+if (kind == Member.THROW) return true;</pre>
+<p>This change will make our test case pass again. Run it to be sure.</p>
+<p>There's an interesting tension between a good automated test and a good test 
+for development. Our new test case now correctly includes an automated 
+test to let us know when we are and are not matching the new throw join point. 
+However, without the println the test doesn't feel as satisfactory to me to run 
+during development. I often like to turn this kind of printing back on the 
+see what's happening. If you uncomment to System.out.println in the test 
+aspect A and rerun the test, you won't be very happy with the results:</p>
+<pre>------------  FAIL: simple throw join point()
+...
+unimplemented
+java.lang.RuntimeException: unimplemented
+    at org.aspectj.weaver.Member.getSignatureString(Member.java:596)
+...
+
+FAIL Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 failed) 1 seconds</pre>
+<p>It looks like there's more work to do to add the new member kind for 
+Member.THROW. This problem only shows up when we try to print 
+thisJoinPoint. It's showing that we haven't updated the reflection API to 
+understand this new signature kind.</p>
+<h3>Step 4. Extend org.aspectj.lang.reflect to understand throw signatures</h3>
+<p>We need to add a couple of classes to the reflection API to implement the 
+throw signature. Because we decided at the beginning of this section to 
+not include the static type of the exception thrown in the throw signature, 
+these classes are extremely simple. Nevertheless, we have to build them. 
+Notice that when we add new source files to the system we need to include the 
+standard eclipse CPL license header.</p>
+<pre>/* *******************************************************************
+ * Copyright (c) 2004 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     Jim Hugunin    initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.lang.reflect;
+import org.aspectj.lang.Signature;
+
+public interface ThrowSignature extends Signature { }</pre>
+<pre>/* *******************************************************************
+ * Copyright (c) 2004 Contributors.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * Contributors: 
+ *     Jim Hugunin    initial implementation 
+ * ******************************************************************/
+
+package org.aspectj.runtime.reflect;
+import org.aspectj.lang.reflect.ThrowSignature;
+
+class ThrowSignatureImpl extends SignatureImpl implements ThrowSignature {
+    
+    ThrowSignatureImpl(Class declaringType) {
+        super(0, "throw", declaringType);
+    }
+    
+    ThrowSignatureImpl(String stringRep) {
+        super(stringRep);
+    }
+
+    String toString(StringMaker sm) {
+        return "throw";
+    }    
+}</pre>
+<p>To finish up our work in the runtime module, we need to extend 
+org.aspectj.runtime.reflect.Factory to add a factory method for this new 
+signature kind:</p>
+<pre>public ThrowSignature makeThrowSig(String stringRep) {
+    ThrowSignatureImpl ret = new ThrowSignatureImpl(stringRep);
+    ret.setLookupClassLoader(lookupClassLoader);
+    return ret;
+}</pre>
+<p>We're not done yet. We still need to fix up the 
+org.aspectj.weaver.Member class to use these new methods and types and fix the 
+unimplemented exception that started us down this road in the first place. 
+First let's add a method to create a string for the throw signature. This 
+is a very simple method copied from the other create*SignatureString methods.</p>
+<pre>private String getThrowSignatureString(World world) {
+    StringBuffer buf = new StringBuffer();
+    buf.append('-'); // no modifiers
+    buf.append('-'); // no name
+    buf.append(makeString(getDeclaringType()));
+    buf.append('-');
+    return buf.toString();
+}</pre>
+<p>Now we need to modify three methods to add cases for the new Member.THROW 
+kind. First, Member.getSignatureMakerName add:</p>
+<pre>} else if (kind == THROW) {
+    return "makeThrowSig";
+</pre>
+<p>Next, to Member.getSignatureType add:</p>
+<pre>} else if (kind == THROW) {
+    return "org.aspectj.lang.reflect.ThrowSignature";
+</pre>
+<p>Finally, to Member.getSignatureString add:</p>
+<pre>} else if (kind == THROW) {
+    return getThrowSignatureString(world);
+</pre>
+<p>With all of these changes in place we should have working code for 
+thisJoinPoint reflection using our new join point and signature kinds. 
+Rerun the test to confirm:</p>
+<pre>about to throw: 'java.lang.RuntimeException: expected exception' at throw(throw)
+PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds</pre>
+<h3>Step 5. Extend the test for automated coverage of reflection</h3>
+<p>Modify the before advice to include at least minimal checks of the new 
+reflective information:</p>
+<pre>before(Throwable t): throw() && args(t) {
+    Tester.event("before throw");
+    Tester.checkEqual(thisJoinPoint.getSignature().toShortString(), "throw");
+    Tester.checkEqual(t.getMessage(), "expected exception");
+}</pre>
+<p>    As usual, you should rerun the tests and make sure they pass.</p>
+<p>    With these changes to the reflection code, it looks like we have a working 
+version of the throw join point and there are no obvious pieces that we've 
+skipped. Take a break before proceeding to the final phase of tests.</p>
+<h2>Part 3: More serious testing</h2>
+<p>Now it's time to get a decent testing story. The test work that we will 
+do here is probably too little for adding a new join point to the aspectj 
+language; however, it should at least give you a sense of what's involved.</p>
+<h3>Step 1. Run the test suite again</h3>
+<p>Rerun the tests you ran at the beginning of part 1. Any failures that 
+occur should be resolved at this point. At the time of writing this 
+tutorial, I found 31 failures in the BcWeaverModuleTests. These failures 
+are for all of the test cases that check the exact set of shadows produces by a 
+given program. These test cases need to be updated based on the new join 
+point we're adding. These particular test cases will probably be removed 
+from the AspectJ test suite very soon because they've shown themselves to be 
+very fragile over time and they often break for changes that are not introducing 
+new bugs. However, you should be aware of this kind of failure because you 
+may find it in other unit tests.</p>
+<p>You should expect to see at least one other test case fail when you run 
+ajcTests.xml. Here's the failure message:</p>
+<pre>------------  FAIL: validate (enclosing) join point and source locations()
+...
+[  1] [fail   0]: fail [ unexpected event "before AllTargetJoinPoints throw(throw)" found]</pre>
+<p>Most of this message can be ignored. To find out what went wrong you 
+should look for messages that have &quot;fail&quot; in them. The last line tells you 
+what happened. There was an unexpected event, &quot;before AllTargetJoinPoints throw(catch(Throwable))&quot;. 
+This is the signature for one of the new throw join points that we added in part 
+1. How could an existing test case match this new join point? The 
+failing test case uses 'within(TargetClass)' to collect information about ALL 
+join points that are lexically within a given class. Whenever we add a new 
+kind of join point to the language we will extend the set of points matched by 
+pcds like within. This means that these changes need to be very 
+prominently noted in the release notes for any AspectJ release. Since 
+we're not writing documentation in this tutorial, we will move on an fix the 
+test case.</p>
+<h3>Step 2. Fix the failing test case</h3>
+<p>Now we need to fix this failing test case. The first step is to copy 
+the test specification into our local myTests.xml file. The easiest way to 
+do this is to copy the title of the failing test from the output buffer, then 
+open ajcTests.xml and use find to search for this title. Then copy the xml 
+spec for this one test into myTests.xml. Finally, run myTests.xml to make 
+sure you got the failing test. You should see the same failure as before 
+in step 1, but you should see it a lot faster because we're only running 2 
+tests.</p>
+<p>To fix the test we need to find the source code. If you look at the 
+test specification, you can see that the source file is the new directory with 
+the name NegativeSourceLocation.java. Looking at the bottom of this file, 
+we see a large list of expected events. These are the join points that we 
+expect to see. If we look back up in TargetClass, we can see that the only 
+occurence of throw is just before the handler for catch(Error) and right after 
+the call to new Error. We should add our new expected event between these 
+two:</p>
+<pre>, "before AllTargetJoinPoints call(java.lang.Error(String))"
+, "before AllTargetJoinPoints throw(throw)"  // added for new throw join point
+, "before AllTargetJoinPoints handler(catch(Error))"</pre>
+<p>Run the test suite again to see that this test now passes.</p>
+<h3>Step 3. Extend test coverage to after advice</h3>
+<p>There is a lot we should do now to extend test coverage for this new kind of 
+join point. For the purpose of this tutorial, we're just going to make 
+sure that the new join point kind is compatible with all 5 kinds of advice. 
+Let's extend our current simple Throws test to check for before and the three 
+kinds of after advice:</p>
+<pre>import org.aspectj.testing.Tester;
+
+public class Throws {
+    public static void main(String[] args) {
+        try {
+            willThrow(true);
+            Tester.checkFailed("should have thrown exception");
+        } catch (RuntimeException re) {
+            Tester.checkEqual("expected exception", re.getMessage());
+        }
+        Tester.checkEvents(new String[] 
+            { "before throw", "after throwing throw", "after throw" });
+    }
+    
+    static void willThrow(boolean shouldThrow) {
+        int x;
+        if (shouldThrow) throw new RuntimeException("expected exception");
+        else x = 42;
+        System.out.println("x = " + x);
+    }
+}
+
+aspect A {    
+    before(Throwable t): throw() && args(t) {
+        Tester.event("before throw");
+        Tester.checkEqual(thisJoinPoint.getSignature().toShortString(), "throw");
+        Tester.checkEqual(t.getMessage(), "expected exception");
+    }
+    
+    after() returning: throw() {
+        Tester.checkFailed("shouldn't ever return normally from a throw");
+    }
+    
+    after() throwing(RuntimeException re): throw() {
+        Tester.event("after throwing throw");
+        Tester.checkEqual(re.getMessage(), "expected exception");
+    }
+    
+    after(): throw() {
+        Tester.event("after throw");
+    }
+}</pre>
+<p>Run this test to confirm that it still passes. This is a very nice 
+property of the orthogonality of the implementation of join points and advice. 
+We never had to do any implementation work to make our new join point kind work 
+for before and all three kinds of after advice.</p>
+<h3>Step 4. Look at around advice on throw join points</h3>
+<p>Let's create a new test case to see how this new join point interacts with 
+around advice.</p>
+<pre>import org.aspectj.testing.Tester;
+
+public class AroundThrows {
+    public static void main(String[] args) {
+        try {
+            willThrow(true);
+            Tester.checkFailed("should have thrown exception");
+        } catch (RuntimeException re) {
+            Tester.checkEqual("expected exception", re.getMessage());
+        }
+    }
+    
+    static void willThrow(boolean shouldThrow) {
+        int x;
+        if (!shouldThrow) x = 42;
+        else throw new RuntimeException("expected exception");
+        System.out.println("x = " + x);
+    }
+}
+
+aspect A {    
+    void around(): throw() {
+        System.out.println("about to throw something");
+        proceed();
+    }
+}</pre>
+<p>When we run this test case we get a very unpleasant result:</p>
+<pre>------------  FAIL: simple throw join point with around()
+...
+[  1] --- thrown
+java.lang.VerifyError: (class: AroundThrows, method: willThrow signature: (Z)V) Accessing value from uninitialized register 1
+...
+FAIL Suite.Spec(c:\aspectj\eclipse\tests) 3 tests (1 failed, 2 passed) 3 seconds
+</pre>
+<p>A VerifyError at runtime is the second worst kind of bug the AspectJ compiler 
+can produce. The worst is silently behaving incorrectly.</p>
+<p>Unfortunately, this VerifyError is either impossible or very hard to fix. 
+Think about what would happen if the around advice body didn't call proceed. 
+In this case the local variable x would in fact be uninitialized. There is 
+another serious language design question here, and for a real implementation 
+this would once again be the time to start a discussion on the aspectj-dev 
+mailing list to reach consensus on the best design. For the purpose of 
+this tutorial we're once again going to make the language design choice that is 
+easiest to implement and press on.</p>
+<h3>Step 5. Prohibit around advice on this new join point kind</h3>
+<p>The easiest solution to implement is to prohibit around advice on throw join 
+points. There are already a number of these kinds of rules implemented in 
+the org.aspectj.weaver.Shadow.match(Shadow, World) method. We can add our 
+new rule at the beginning of the if(kind == AdviceKind.Around) block:</p>
+<pre>} else if (kind == AdviceKind.Around) {
+     if (shadow.getKind() == Shadow.Throw) {
+         world.showMessage(IMessage.ERROR,
+             "around on throw not supported (possibly compiler limitation)", 
+             getSourceLocation(), shadow.getSourceLocation());
+         return false;
+     }</pre>
+<p>            Now if we rerun our test we'll see errors telling us that around 
+is prohibited on throw join points:</p>
+<pre>------------  FAIL: simple throw join point with around()
+...
+[  0] [error   0]: error at C:\aspectj\eclipse\tests\design\pcds\AroundThrows.java:22 around on throw not supported (possibly compiler limitation)
+[  0] [error   1]: error at C:\aspectj\eclipse\tests\design\pcds\AroundThrows.java:16 around on throw not supported (possibly compiler limitation)
+...
+FAIL Suite.Spec(c:\aspectj\eclipse\tests) 3 tests (1 failed, 2 passed) 3 seconds</pre>
+<p>To finish this test case up we need to modify the specification to be looking 
+for these errors as the correct behavior. This will produce the following 
+specification:</p>
+<pre>&lt;ajc-test dir=&quot;design/pcds&quot;
+  title=&quot;simple throw join point with around&quot;&gt;
+    &lt;compile files=&quot;AroundThrows.java&quot;&gt;
+        &lt;message kind=&quot;error&quot; line=&quot;16&quot;/&gt;
+        &lt;message kind=&quot;error&quot; line=&quot;22&quot;/&gt; 
+    &lt;/compile&gt;
+&lt;/ajc-test&gt;</pre>
+<p>Run myTests.xml one last time to see both tests passing.</p>
+<h3>Step 6. Final preparations for a commit or patch</h3>
+<p>You probably want to stop here for the purposes of this tutorial. We've 
+pointed out several language design decisions that would need to be resolved 
+before actually adding a throw join point to AspectJ. Some of those might 
+involve a large amount of additional implementation work. If this was 
+actually going into the tree, it would also be important to add several more 
+test cases exploring the space of what can be done with throw.</p>
+<p>Assuming those issues were resolved and you are ready to commit this new 
+feature to the tree there are three steps left to follow:</p>
+<ol>
+       <li>Move our new test specifications from myTests.xml to the end of 
+       ajcTests.xml</li>
+       <li>Rerun ajcTests.xml and the unit tests to ensure everything's okay.</li>
+       <li>Update from the repository to get any changes from other committers 
+       since you started work on this new feature.</li>
+       <li>Rerun ajcTests.xml and the unit tests to make sure nothing broke as a 
+       result of the update.</li>
+       <li>Finally you can commit these changes to the AspectJ tree.</li>
+</ol>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/docs/developer/compiler-weaver/overview.gif b/docs/developer/compiler-weaver/overview.gif
new file mode 100644 (file)
index 0000000..b32f11b
Binary files /dev/null and b/docs/developer/compiler-weaver/overview.gif differ
diff --git a/docs/developer/compiler-weaver/pointcut-dec.gif b/docs/developer/compiler-weaver/pointcut-dec.gif
new file mode 100644 (file)
index 0000000..fed640d
Binary files /dev/null and b/docs/developer/compiler-weaver/pointcut-dec.gif differ
diff --git a/docs/developer/compiler-weaver/top-tree.gif b/docs/developer/compiler-weaver/top-tree.gif
new file mode 100644 (file)
index 0000000..d8e2b26
Binary files /dev/null and b/docs/developer/compiler-weaver/top-tree.gif differ
diff --git a/docs/developer/compiler.html b/docs/developer/compiler.html
deleted file mode 100644 (file)
index da99eb5..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-<html>
-
-<head>
-<meta http-equiv="Content-Language" content="en-us">
-<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
-<meta name="ProgId" content="FrontPage.Editor.Document">
-<title>AJDT Project Proposal</title>
-<STYLE TYPE="text/css">
-<!--
-   /* FOR THE SDA PAGE */
-       /*
-       BODY {margin-top: 15px; margin-left: 15px; margin-right: 15px;}
-       */
-
-       A:link {
-               color:#4756AC;
-       }
-       A:visited {
-               color:#60657B;
-       }
-       A:hover {
-               color:red
-       }
-       
-       INPUT {font:12px "Courier New", sans-serif;}
-       
-       H2 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H3 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H4 {
-               font:15px/16px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:140%;
-       }
-       P {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .paragraph {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       LI {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       /*
-       UL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }*/
-       
-       DL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       B { font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold; 
-               line-height:140%;
-       }
-       .footer {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif;  
-               color:#888888; 
-               text-align:left
-       }
-       .figureTitle {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               text-align:justify; 
-               text-align:center
-       }
-       .copyrightNotice {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif; 
-               color:#999999; 
-               line-height:110%;
-       }
-       .smallHeading {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:110%;
-       }
-       .tinyHeading {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:120%;
-       }
-       .newsText {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .fancyHeading {
-               font:20px/20px Chantilly, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               color:#6f7a92;
-               margin-left: 10px;
-               line-height:130%;
-       }
--->
-</STYLE>
-</head>
-
-<BODY BGCOLOR="white">
-
-<h3 align="center">AspectJ Compiler Design</h3>
-<p>Todo: add content.&nbsp; In the meantime, the following email post have 
-relevant content:</p>
-<ul>
-       <li>Description of ajc-1.1 inter-type declaration implementation:<br>
-       <a href="http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg00430.html">
-       http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg00430.html</a> </li>
-</ul>
-
-</body>
-
-</html>
\ No newline at end of file
diff --git a/docs/developer/index.html b/docs/developer/index.html
new file mode 100644 (file)
index 0000000..b015268
--- /dev/null
@@ -0,0 +1,176 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>AJDT Project Proposal</title>
+<STYLE TYPE="text/css">
+<!--
+   /* FOR THE SDA PAGE */
+       /*
+       BODY {margin-top: 15px; margin-left: 15px; margin-right: 15px;}
+       */
+
+       A:link {
+               color:#4756AC;
+       }
+       A:visited {
+               color:#60657B;
+       }
+       A:hover {
+               color:red
+       }
+       
+       INPUT {font:12px "Courier New", sans-serif;}
+       
+       H2 {
+               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
+               color:black; 
+               font-weight:bold; 
+               margin-left: 10px;
+               line-height:110%; 
+       }
+       H3 {
+               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
+               color:black; 
+               font-weight:bold; 
+               margin-left: 10px;
+               line-height:110%; 
+       }
+       H4 {
+               font:15px/16px Verdana, Arial, Helvetica, sans-serif; 
+               color:black; 
+               font-weight:bold; 
+               margin-left: 10px;
+               line-height:140%;
+       }
+       P {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
+               margin-right: 10px;
+               margin-left: 10px;
+               line-height:130%; 
+       }
+       .paragraph {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
+               margin-right: 10px;
+               margin-left: 10px;
+               line-height:130%; 
+       }
+       .smallParagraph {
+               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
+               margin-right: 10px;
+               margin-left: 10px;
+               line-height:130%; 
+       }
+       LI {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+               text-align:justify; 
+               margin-right: 10px;
+               margin-left: 15px;
+               line-height:120%; 
+       }
+       /*
+       UL {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+               text-align:justify; 
+               margin-right: 10px;
+               margin-left: 15px;
+               line-height:120%; 
+       }*/
+       
+       DL {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+               text-align:justify; 
+               margin-right: 10px;
+               margin-left: 15px;
+               line-height:120%; 
+       }
+       B { font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
+               font-weight:bold; 
+               line-height:140%;
+       }
+       .footer {
+               font:10px/10px Verdana, Arial, Helvetica, sans-serif;  
+               color:#888888; 
+               text-align:left
+       }
+       .figureTitle {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
+               text-align:justify; 
+               text-align:center
+       }
+       .copyrightNotice {
+               font:10px/10px Verdana, Arial, Helvetica, sans-serif; 
+               color:#999999; 
+               line-height:110%;
+       }
+       .smallHeading {
+               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
+               font-weight:bold;
+               line-height:110%;
+       }
+       .tinyHeading {
+               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
+               font-weight:bold;
+               line-height:120%;
+       }
+       .newsText {
+               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
+               line-height:130%;
+       }
+       .smallParagraph {
+               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
+               line-height:130%;
+       }
+       .fancyHeading {
+               font:20px/20px Chantilly, Arial, Helvetica, sans-serif; 
+               margin-right: 10px;
+               color:#6f7a92;
+               margin-left: 10px;
+               line-height:130%;
+       }
+-->
+</STYLE>
+</head>
+
+<BODY BGCOLOR="white">
+
+<h3 align="center">AspectJ Design Overview</h3>
+
+<h4>Contents</h4>
+<ul>
+       <li><a href="compiler-weaver/index.html">Guide for Developers of the AspectJ Compiler and Weaver</a></li>
+       <li><a href="modules.html">Module Structure</a></li>
+       <li><a href="language.html">Language Design</a></li>
+</ul>
+
+<h4 class="paragraph">Here are some sobering words from David Parnas on 
+&quot;Ignorant Surgery&quot; in his paper on Software Aging:</h4>
+<h4 class="smallParagraph">&quot;Although it is essential to upgrade software to 
+prevent aging, changing software can cause a different form of aging. The 
+designer of a piece of software usually had a simple concept in mind when 
+writing the program. If the program is large, understanding the concept allows 
+one to find those sections of the program that must be altered when an update or 
+correction is needed. Understanding that concept also implies understanding the 
+interfaces used within the system and between the system and its environment.&nbsp; 
+Changes made by people who do not understand the original design concept almost 
+always cause the structure of the program to degrade. Under those circumstances, 
+changes will be inconsistent with the original concept; in fact, they will 
+invalidate the original concept. Sometimes the damage is small, but often it is 
+quite severe. After those changes, one must know both the original design rules 
+and the newly introduced exceptions to the rules, to understand the product. 
+After many such changes, the original designers no longer understand the 
+product. Those who made the changes, never did. In other words, *nobody* 
+understands the modified product.<br>
+Software that has been repeatedly modified (maintained) in this way becomes very 
+expensive to update. Changes take longer and are more likely to introduce new 
+'bugs'.&quot;</h4>
+
+</body>
+
+</html>
\ No newline at end of file
index dd746ba7e8fd7ee2e276cde5ecca68878af51b3b..e047dc87c9f08c2995fe2eadabaf3763a9fe156c 100644 (file)
        </ul>
        </li>
 </ul>
-<h4>Key Language Design Properties (from Gregor)</h4>
+<h4>Key Language Design Properties</h4>
 <p>(1) Orthogonal join point model - the different kinds of join points, the 
 different primitive pointcuts, and the different kinds of advice can be used in 
 any combination.</p>
diff --git a/docs/developer/overview.html b/docs/developer/overview.html
deleted file mode 100644 (file)
index 4850570..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-<html>
-
-<head>
-<meta http-equiv="Content-Language" content="en-us">
-<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
-<meta name="ProgId" content="FrontPage.Editor.Document">
-<title>AJDT Project Proposal</title>
-<STYLE TYPE="text/css">
-<!--
-   /* FOR THE SDA PAGE */
-       /*
-       BODY {margin-top: 15px; margin-left: 15px; margin-right: 15px;}
-       */
-
-       A:link {
-               color:#4756AC;
-       }
-       A:visited {
-               color:#60657B;
-       }
-       A:hover {
-               color:red
-       }
-       
-       INPUT {font:12px "Courier New", sans-serif;}
-       
-       H2 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H3 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H4 {
-               font:15px/16px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:140%;
-       }
-       P {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .paragraph {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       LI {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       /*
-       UL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }*/
-       
-       DL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       B { font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold; 
-               line-height:140%;
-       }
-       .footer {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif;  
-               color:#888888; 
-               text-align:left
-       }
-       .figureTitle {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               text-align:justify; 
-               text-align:center
-       }
-       .copyrightNotice {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif; 
-               color:#999999; 
-               line-height:110%;
-       }
-       .smallHeading {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:110%;
-       }
-       .tinyHeading {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:120%;
-       }
-       .newsText {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .fancyHeading {
-               font:20px/20px Chantilly, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               color:#6f7a92;
-               margin-left: 10px;
-               line-height:130%;
-       }
--->
-</STYLE>
-</head>
-
-<BODY BGCOLOR="white">
-
-<h3 align="center">AspectJ Design Overview</h3>
-
-<h4 class="paragraph">Here are some sobering words from David Parnas on 
-&quot;Ignorant Surgery&quot; in his paper on Software Aging:</h4>
-<h4 class="smallParagraph">&quot;Although it is essential to upgrade software to 
-prevent aging, changing software can cause a different form of aging. The 
-designer of a piece of software usually had a simple concept in mind when 
-writing the program. If the program is large, understanding the concept allows 
-one to find those sections of the program that must be altered when an update or 
-correction is needed. Understanding that concept also implies understanding the 
-interfaces used within the system and between the system and its environment.&nbsp; 
-Changes made by people who do not understand the original design concept almost 
-always cause the structure of the program to degrade. Under those circumstances, 
-changes will be inconsistent with the original concept; in fact, they will 
-invalidate the original concept. Sometimes the damage is small, but often it is 
-quite severe. After those changes, one must know both the original design rules 
-and the newly introduced exceptions to the rules, to understand the product. 
-After many such changes, the original designers no longer understand the 
-product. Those who made the changes, never did. In other words, *nobody* 
-understands the modified product.<br>
-Software that has been repeatedly modified (maintained) in this way becomes very 
-expensive to update. Changes take longer and are more likely to introduce new 
-'bugs'.&quot;</h4>
-<h4>Contents</h4>
-<ul>
-       <li><a href="modules.html">Module Structure</a></li>
-       <li><a href="compiler.html">Compiler Design</a></li>
-       <li><a href="language.html">Language Design</a></li>
-</ul>
-
-</body>
-
-</html>
\ No newline at end of file
diff --git a/docs/developer/weaver.html b/docs/developer/weaver.html
deleted file mode 100644 (file)
index 76a11aa..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-<html>
-
-<head>
-<meta http-equiv="Content-Language" content="en-us">
-<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
-<meta name="ProgId" content="FrontPage.Editor.Document">
-<title>AJDT Project Proposal</title>
-<STYLE TYPE="text/css">
-<!--
-   /* FOR THE SDA PAGE */
-       /*
-       BODY {margin-top: 15px; margin-left: 15px; margin-right: 15px;}
-       */
-
-       A:link {
-               color:#4756AC;
-       }
-       A:visited {
-               color:#60657B;
-       }
-       A:hover {
-               color:red
-       }
-       
-       INPUT {font:12px "Courier New", sans-serif;}
-       
-       H2 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H3 {
-               font:18px/18px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:110%; 
-       }
-       H4 {
-               font:15px/16px Verdana, Arial, Helvetica, sans-serif; 
-               color:black; 
-               font-weight:bold; 
-               margin-left: 10px;
-               line-height:140%;
-       }
-       P {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .paragraph {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               margin-left: 10px;
-               line-height:130%; 
-       }
-       LI {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       /*
-       UL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }*/
-       
-       DL {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif;
-               text-align:justify; 
-               margin-right: 10px;
-               margin-left: 15px;
-               line-height:120%; 
-       }
-       B { font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold; 
-               line-height:140%;
-       }
-       .footer {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif;  
-               color:#888888; 
-               text-align:left
-       }
-       .figureTitle {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               text-align:justify; 
-               text-align:center
-       }
-       .copyrightNotice {
-               font:10px/10px Verdana, Arial, Helvetica, sans-serif; 
-               color:#999999; 
-               line-height:110%;
-       }
-       .smallHeading {
-               font:13px/13px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:110%;
-       }
-       .tinyHeading {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               font-weight:bold;
-               line-height:120%;
-       }
-       .newsText {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .smallParagraph {
-               font:11px/11px Verdana, Arial, Helvetica, sans-serif; 
-               line-height:130%;
-       }
-       .fancyHeading {
-               font:20px/20px Chantilly, Arial, Helvetica, sans-serif; 
-               margin-right: 10px;
-               color:#6f7a92;
-               margin-left: 10px;
-               line-height:130%;
-       }
--->
-</STYLE>
-</head>
-
-<BODY BGCOLOR="white">
-
-<h3 align="center">AspectJ Compiler Design</h3>
-<p>Todo: add content.&nbsp; In the meantime, the following email post have 
-relevant content:</p>
-<ul>
-       <li>&quot;What does the weaver take as input?&nbsp; How does it know where to 
-       insert advice?&quot;<br>
-       <a href="http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg00519.html">
-       http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg00519.html</a> <br>
-       &nbsp;</li>
-</ul>
-
-</body>
-
-</html>
\ No newline at end of file