| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <meta name="GENERATOR" content="Mozilla/4.5 [en] (Win98; I) [Netscape]"> |
| <title>JDT - Abstract Syntax Trees</title> |
| </head> |
| <body> |
| |
| <h2> |
| Abstract Syntax Trees</h2> |
| <font color="#3366FF">Last revised 14:00 Friday October 26, 2001 (most |
| recent change in blue)</font> |
| <p>Original work item: "Exposing the AST API."</p> |
| <p>Related work item: "Improved Java code manipulation support, address |
| JDOM limitations; JDOM doesn't preserve markers and isn't document aware; |
| JDOM finer grained update support (e.g. change method name, type name); |
| buffer contents is duplicated in Java UI document and needs to be manually |
| synchronized."</p> |
| <h3> |
| Background</h3> |
| |
| <ul> |
| <li>refactoring is a key customer (Dirk B.)</li> |
| <li>for 2.0: have good support in place so that refactoring can be made an |
| open API; would need corresponding core APIs for abstract syntax trees</li> |
| <li>current refactoring appoach uses AST visitor which runs post-resolve on |
| designated compilation unit</li> |
| <li>visitor collects info (parent stack) including source positions</li> |
| <li>uses name environment (bindings, scopes) to validate/locate</li> |
| <li>all changes are formulated as reified undoable edits in a source buffer</li> |
| <li>a batch of changes are made at a time</li> |
| <li>refactoring does not reason hypothetically (changes are undoable)</li> |
| <li>JDOM is not used by refactoring, but potentially could be (JDOM is used |
| inside Java Model)</li> |
| </ul> |
| Dirk's wish list with regard to the AST support: |
| <ul> |
| <li> |
| consistent positions in AST (e.g. sourceStart and sourceEnd should always |
| cover the whole node).</li> |
| |
| <li> |
| comment handling in AST. Some node contain preceding comments other don't</li> |
| |
| <li> |
| Parent pointer in AST node.</li> |
| |
| <li> |
| Data pointer in AST node.</li> |
| |
| <li> |
| Expression should provide getType method (cached value of resolveType(Scope)).</li> |
| </ul> |
| |
| <h3> |
| Summary from Sept. 10-11 meetings</h3> |
| Dirk travelled to SNZ to discuss refactoring requirements and possible |
| solutions with Philippe M. and Jeem. |
| <p>Some of the forms of solutions discussed, but ultimately abandoned:</p> |
| <ul> |
| <li> |
| A vanilla DOM.</li> |
| |
| <ul> |
| <li> |
| too limiting: difficult to provide for pre-computing bindings.</li> |
| |
| <li> |
| clumsy for clients to use without AST node types represented by different |
| Java types</li> |
| </ul> |
| |
| <li> |
| AST plus resolves info in form of Java model elements.</li> |
| |
| <ul> |
| <li> |
| Java model methods are unsuitable canonical representation for resolved |
| methods because parameter types are as per source.</li> |
| |
| <li> |
| It is hard to map a type back to a Java element (need to remember package |
| fragment).</li> |
| |
| <li> |
| Would need additional Java model elements to represent variable declarations.</li> |
| |
| <li> |
| Would need special Java element implementations for local types, methods, |
| and fields.</li> |
| </ul> |
| </ul> |
| In the end, we agreed on AST plus bindings: |
| <ul> |
| <li> |
| AST is simple tree of typed nodes as determined by parser.</li> |
| |
| <li> |
| A different Java type for each AST node type.</li> |
| |
| <li> |
| TBD: are node types API classes, API interfaces, or both?</li> |
| |
| <li> |
| Simple case: no bindings.</li> |
| |
| <li> |
| Basic AST Lifecycle: client requests AST; compilation unit is parsed and |
| nodes are created; root is handed back to client; AST is garbage collected |
| after client lets go of all AST nodes. AST is not affected if underlying |
| compilation unit is changed (i.e., eager parse, with no residual dependence |
| on state of file in workspace).</li> |
| |
| <li> |
| Any syntax errors detected need to be reported to client. Problems are |
| opaque: source character position plus human-readable message. Clients |
| needs to determine whether an AST is only partial (e.g., busted flags).</li> |
| |
| <li> |
| Predicatable trees with simple correspondence to source code (parser should |
| not optimize ASTs).</li> |
| |
| <li> |
| Reliable source position information for all nodes.</li> |
| |
| <li> |
| Scratch "data" field on each AST node for client to record an Object.</li> |
| |
| <li> |
| Navigate AST upwards as well as downwards. Parent link.</li> |
| |
| <li> |
| AST walker for convenient traversal.</li> |
| |
| <li> |
| ASTs can be read-only or read-write.</li> |
| |
| <li> |
| Read-write ASTs can be modified in terms of ASTs. AST node factories (no |
| Java parser required). Cut/copy/paste.</li> |
| |
| <li> |
| Cut/copy/paste between separate ASTs requires fragment cloning to preserve |
| independence of storage.</li> |
| |
| <li> |
| Client may be interested in cut/copy/pasting comments too.</li> |
| |
| <li> |
| New nodes would not carry source positions.</li> |
| |
| <li> |
| Read-write AST can be serialized back to compilation unit char[].</li> |
| |
| <ul> |
| <li> |
| Preserve existing comments, whitespace, and use of \u.</li> |
| |
| <li> |
| Control whitespace and use of \u for insertions.</li> |
| |
| <li> |
| Provide edit map for updating markers.</li> |
| </ul> |
| |
| <li> |
| Resolved ASTs: basic AST annotated with bindings (non-syntactic information).</li> |
| |
| <li> |
| Binding information is derived from AST plus the Java model (relative to |
| some project).</li> |
| |
| <li> |
| Availability/validity of bindings ceases when Java model changes.</li> |
| |
| <li> |
| Client must request up front that bindings be created.</li> |
| |
| <li> |
| Certain AST nodes get decorated with bindings.</li> |
| |
| <li> |
| Client should have ways to communicate up front what kind of bindings are |
| required and where.</li> |
| |
| <li> |
| Availability/validity of bindings for a read-write AST ceases when it is |
| first modified.</li> |
| |
| <li> |
| Bindings (non-syntactic information) includes things such as the following:</li> |
| |
| <ul> |
| <li> |
| Resolved names - which type, field, method, or local variable does a AST |
| name refernce resolve to.</li> |
| |
| <li> |
| Resolved types - what is the resolved type of an AST expression or type |
| reference.</li> |
| |
| <li> |
| Resolved supertypes - what are the resolved supertypes of a resolved type.</li> |
| |
| <li> |
| Resolved declarations - what resolved type, field, method, or local variable |
| does an AST declaration map to.</li> |
| |
| <li> |
| Thrown exceptions - what are the resolved types of the exceptions thrown |
| by a given expression or statement.</li> |
| |
| <li> |
| Resolved members - what are the resolved members of a resolved type.</li> |
| </ul> |
| |
| <li> |
| Problems also should be reported with resolving. Problems are opaque: source |
| character position plus human-readable message.</li> |
| |
| <li> |
| Space for bindings storage is significant; increases monotonically as more |
| bindings are accessed.</li> |
| |
| <li> |
| Space for bindings is for lifetime of the AST.</li> |
| |
| <li> |
| Advanced AST Lifecycle: client requests AST with bindings; compilation |
| unit is parsed, nodes created, and perhaps some bindings created and annotated |
| on nodes; root is handed back to client; AST is garbage collected after |
| client lets go of all AST nodes and bindings. AST itself is not affected |
| if underlying compilation unit is changed (i.e., eager parse, with no residual |
| dependence on state of file in workspace). Bindings may become stale or |
| invalid if workspace changes (i.e., possibly lazy and incremental construction |
| of bindings using Java model).</li> |
| |
| <li> |
| <font color="#000000">Bindings from two ASTs are not generally comparable.</font></li> |
| |
| <ul> |
| <li> |
| <font color="#000000">For bindings with stable global names, API provides |
| strings that can be compared between ASTs.</font></li> |
| </ul> |
| </ul> |
| AST will either extend or replace JDOM. In the latter case, JDOM would |
| be deprecated. |
| <p>AST will exist along side Java model.</p> |
| <h3> |
| API Design Issue: AST Node Types - Classes, interface, or both</h3> |
| There are on the order of 87 node types for Java ASTs. Bindings will add |
| some more. There are a couple of way this can be mapped to Java types. |
| <p>(1) Use org.w3c.DOM interfaces as API. Provide a private concrete implementation |
| of the DOM.</p> |
| <p>Pro: Very small, and standard API for read-write documents. |
| <br>Con: API is not convenient for clients. |
| <br>Con: API is not amenable to exposing bindings and other non-structural |
| information.</p> |
| <p>(2) Concrete API class per AST node type.</p> |
| <p>Pro: API as small as possible. |
| <br>Pro: Client can create nodes directly.</p> |
| <p>Con: Cannot easily hide implementation details; e.g. representation |
| and mechanism for reassembling compilation unit text after editing; lazy |
| binding creation.</p> |
| <p>Clients who create node from scratch only ever need basic constructors |
| (the nodes they create do not have source positions, bindings, or other |
| decorations). On the other hand, the parser needs to remember more info |
| including fine-grained source positions.</p> |
| <p>(3) API interface per AST node type, along with node factory methods. |
| Provide a private concrete implementation. Allow clients to reimplement |
| node types (from scratch) and supply a factory.</p> |
| <p>Like JDOM (except JDOM does not permit client to reimplement) and org.w3c.dom.</p> |
| <p>Pro: API as small as possible. |
| <br>Pro: Easy to tailor different kinds of representation: read-write vs. |
| read-only ASTs; raw ASTs vs. AST+bindings.</p> |
| <p>Con: Hidden concrete implementation classes takes more space. |
| <br>Con: Using factory methods is a bit less direct than using constructors.</p> |
| <p>We will use API interfaces for bindings, and exposed API classes for |
| AST nodes.</p> |
| <h3> |
| API Design Issue: Statement vs. Statement Lists</h3> |
| <p>For structured statements, like while, the child statement is grammatically |
| a single statement. However, since a block is one type of statement, it |
| is possible to have a list of statements underneath. There are options |
| for rendering this:</p> |
| <p>(1) Child is a single statement.</p> |
| <p>(Like current compiler's internal ASTs.)</p> |
| <p>Pro: As per the Java grammar. |
| <br>Con: A client wanting to insert an additional statement into the child |
| must be prepared to replace by a block if there isn't one.</p> |
| <p>(2) Child is a list of statements.</p> |
| <p>(Like the .net codeDOM.)</p> |
| <p>Pro: More convenient for clients that edit ASTs. Uniform mechanism for |
| inserting and removing statements from child. |
| <br>Con: Muddies scopes (enclosing braces around statements introduce a |
| scope and make declarations syntactically legal).</p> |
| <p>We will go with (1) and stick closely to the grammar.</p> |
| <h3> |
| Usage</h3> |
| There are a couple different usage scenarios for ASTs: |
| <ul> |
| <li> |
| Analyze an existing compilation unit to discover syntactic structure.</li> |
| |
| <li> |
| Discover relationship between syntactic structure and original text.</li> |
| |
| <li> |
| Discover relationship between syntactic structure and resolved world.</li> |
| |
| <li> |
| Create a new compilation unit from scratch.</li> |
| |
| <li> |
| Edit an existing compilation unit.</li> |
| </ul> |
| |
| <h3> |
| Source Construct Normalization</h3> |
| |
| <ul> |
| <li> |
| Most syntactic constructions are rendered in one and only one way.</li> |
| |
| <li> |
| When this is not the case, the AST construction is "lossy".</li> |
| |
| <li> |
| Some forms cannot be distinguised in input (if one cares).</li> |
| |
| <li> |
| Some forms cannot be produced in output.</li> |
| |
| <li> |
| Copying the construct normalizes it.</li> |
| |
| <li> |
| Example: Modifier order</li> |
| |
| <ul> |
| <li> |
| final static public int X = 1;</li> |
| |
| <li> |
| public static final int X = 1; // preferred form</li> |
| </ul> |
| |
| <li> |
| Example: Compound variable declarations</li> |
| |
| <ul> |
| <li> |
| int i = 1, j = 2;</li> |
| |
| <li> |
| int i = 1; int j = 2; // preferred form</li> |
| </ul> |
| |
| <li> |
| Example: Array type declarators</li> |
| |
| <ul> |
| <li> |
| int[] x[];</li> |
| |
| <li> |
| int[][] x; // preferred form</li> |
| </ul> |
| |
| <li> |
| Example: Short ifs</li> |
| |
| <ul> |
| <li> |
| if (a) f(); else ;</li> |
| |
| <li> |
| if (a) f(); // preferred form</li> |
| </ul> |
| |
| <li> |
| Can only be done for syntactic nuances that are have no semantic import.</li> |
| |
| <li> |
| Normalization is generally acceptable where unimportant syntactic nuances |
| are involved.</li> |
| |
| <li> |
| Normal form should follow JLS recommendations and Java coding standards.</li> |
| |
| <li> |
| Note that parentheses and blocks are important to user and should not be |
| normalized.</li> |
| </ul> |
| |
| <h3> |
| Source Positions</h3> |
| |
| <ul> |
| <li> |
| When AST is obtained by parsing a text string, exposing source ranges for |
| nodes allows clients to navigate back into original string; e.g., for making |
| text editor selections.</li> |
| |
| <li> |
| AST supports only character-oriented position information; mapping character |
| positions to lines are handled elsewhere (e.g., text editor).</li> |
| |
| <li> |
| Source ranges are irrelevant for nodes created by other means.</li> |
| |
| <li> |
| Source ranges give original position in original string.</li> |
| |
| <ul> |
| <li> |
| Editing the AST does not alter positions or anything clever.</li> |
| </ul> |
| |
| <li> |
| Most constructs occupy contiguous character positions, or ranges.</li> |
| |
| <li> |
| Ranges are represented by 0-based start position and length.</li> |
| |
| <li> |
| Start position begins at first significant character of construct corresponding |
| to AST node.</li> |
| |
| <ul> |
| <li> |
| First significant character.</li> |
| |
| <li> |
| Does not include leading whitespace.</li> |
| |
| <li> |
| Does not include preceding comment (except the javadoc comment preceding |
| a declaration, or the comment preceding a statement - see below).</li> |
| </ul> |
| |
| <li> |
| End position includes last significant character of construct corresponding |
| to AST node.</li> |
| |
| <ul> |
| <li> |
| Last significant character.</li> |
| |
| <li> |
| Includes trailing terminators that are part of construct; e.g., include |
| trailing semicolon at end of local variable declaration.</li> |
| |
| <li> |
| Does not include separators; e.g., exclude trailing comma in parameter |
| list.</li> |
| |
| <li> |
| Does not include trailing whitespace.</li> |
| |
| <li> |
| Does not include trailing comment.</li> |
| |
| <li> |
| Statement end-of-line comments are not encompassed by statement.</li> |
| |
| <ul> |
| <li> |
| <tt>System.out.println("hello"); // $non-nls$</tt></li> |
| </ul> |
| |
| <li> |
| <font color="#000000">Embedded comments are encompassed if they occur before |
| end position.</font></li> |
| |
| <ul> |
| <li> |
| <tt><font color="#000000">System.out.println("hello") /* comment */;</font></tt></li> |
| </ul> |
| </ul> |
| |
| <li> |
| Some node types would have source ranges for significant contiguous subconstructs |
| not readily gleanable from source ranges of the subnodes.</li> |
| |
| <ul> |
| <li> |
| Additional source ranges would be specified for each node type.</li> |
| |
| <li> |
| E.g., method declaration has additional source range for the method name |
| and for the method declaration excluding its javadoc comment.</li> |
| |
| <li> |
| Use start and length arrays rather than proliferate API methods for additional |
| source ranges.</li> |
| </ul> |
| </ul> |
| |
| <h3> |
| Unicode Escapes</h3> |
| |
| <ul> |
| <li> |
| Original source text might contain Unicode escapes (JLS 3.2, 3.3).</li> |
| |
| <li> |
| E.g., void\u0040\u005a(); declares a method named Z.</li> |
| |
| <li> |
| Scanner removes all Unicode escapes and returns a Unicode token stream.</li> |
| |
| <li> |
| Newly created AST nodes are "post" Unicode escaping.</li> |
| |
| <li> |
| Output options:</li> |
| |
| <ul> |
| <li> |
| Preserve existing Unicode escapes (default); remove all existing Unicode |
| escapes.</li> |
| |
| <li> |
| Do not introduce Unicode escapes (default); introduce Unicode escapes for |
| characters in a specified set (e.g., all non-ASCII).</li> |
| </ul> |
| |
| <li> |
| Initial implementation: support default behavior only.</li> |
| </ul> |
| |
| <h3> |
| Comments</h3> |
| |
| <ul> |
| <li> |
| Comments are problematic for ASTs; these lexical items are normally filtered |
| out of token stream.</li> |
| |
| <li> |
| Comments are significant to user.</li> |
| |
| <li> |
| Editing an existing compilation unit should generally preserve existing |
| comments.</li> |
| |
| <li> |
| Should be able to include comments for newly created subtrees.</li> |
| |
| <li> |
| Copying a subtree from one place to another should include relevant comments.</li> |
| |
| <li> |
| Most common forms of comments:</li> |
| |
| <ul> |
| <li> |
| Javadoc comments - on one or more lines preceding field, method, and type |
| declarations.</li> |
| |
| <li> |
| Boilerplace comments (copyright notices) - one or more lines preceding |
| the package declaration, or between the package declaration and first import |
| or type declaration.</li> |
| |
| <li> |
| Statement comments - one or more lines between statements in a block.</li> |
| |
| <li> |
| Statement end-of-line comments.</li> |
| </ul> |
| |
| <li> |
| VA/ST experience: not worth bending over backwards to accomodate all comments.</li> |
| |
| <li> |
| Determined clients can rescan original string to get at all comments.</li> |
| |
| <li> |
| Expose high value comments:</li> |
| |
| <li> |
| Javadoc comments - treat as attribute of the field, method, and type declarations.</li> |
| |
| <ul> |
| <li> |
| Clients can extract Javadoc attributes (including @deprecated).</li> |
| |
| <li> |
| Clients can create declarations with Javadoc.</li> |
| </ul> |
| |
| <li> |
| Statement comments within blocks</li> |
| |
| <ul> |
| <li> |
| Approach 1: Treat as pseudo-statements with a special AST node type.</li> |
| |
| <ul> |
| <li> |
| Pro: Clients can include comments with blocks.</li> |
| |
| <li> |
| Con: Only works for comments within genuine blocks. E.g., can't handle</li> |
| |
| <li> |
| <tt>if (test)</tt></li> |
| |
| <li> |
| <tt> // should not happen</tt></li> |
| |
| <li> |
| <tt> throw new RuntimeException();</tt></li> |
| |
| <li> |
| Would work better if we were using statement lists in more places.</li> |
| </ul> |
| |
| <li> |
| Approach 2: Treat as a property of following statment node.</li> |
| |
| <ul> |
| <li> |
| Pro: Clients can include comments before any statement.</li> |
| |
| <li> |
| Con: Does not handle trailing comments in blocks. E.g.,</li> |
| |
| <li> |
| <tt>{</tt></li> |
| |
| <li> |
| <tt> throw new RuntimeException();</tt></li> |
| |
| <li> |
| <tt> // can't reach here</tt></li> |
| |
| <li> |
| <tt>}</tt></li> |
| </ul> |
| |
| <li> |
| Recommend approach 2 since it covers most cases.</li> |
| </ul> |
| |
| <li> |
| Boilerplate comments would not be exposed, but would be preserved through |
| edit and output.</li> |
| </ul> |
| |
| <h3> |
| Whitespace</h3> |
| |
| <ul> |
| <li> |
| Whitespace (JLS 3.6) includes ASCII SP, HT, and FF characters, and line |
| terminators.</li> |
| |
| <li> |
| Like comments, whitespace is significant to user.</li> |
| |
| <li> |
| Editing an existing compilation unit should generally preserve whitespace.</li> |
| |
| <li> |
| Whitespace for newly created subtrees automatically generated to produce |
| output that follows common conventions and blends in with surrounding text |
| (use the same leading whitespace).</li> |
| |
| <li> |
| Copying a subtree from one place to another should should generally preserve |
| whitespace.</li> |
| </ul> |
| |
| <h3> |
| AST Parent Backpointer</h3> |
| |
| <ul> |
| <li> |
| Each AST node will carry a backpointer to its parent node.</li> |
| |
| <li> |
| ASTNode.getParent() returns ASTNode</li> |
| |
| <li> |
| This permits clients to traverse ASTs in upward as well as downward direction.</li> |
| |
| <li> |
| Bidirectional links must be maintained during editing.</li> |
| |
| <li> |
| Deletion API must unlink child from parent.</li> |
| |
| <li> |
| Insertion API must link child to parent.</li> |
| |
| <ul> |
| <li> |
| To preserve treeness, automatically clone child subtree if child already |
| has parent.</li> |
| </ul> |
| |
| <li> |
| Replace API must unlink old child before inserting new child.</li> |
| |
| <li> |
| Parent backlinks means that hanging on to <i>any</i> node in an AST instance |
| will prevent any part of the AST instance from being garbage collected.</li> |
| </ul> |
| |
| <h3> |
| Multiple ASTs</h3> |
| |
| <ul> |
| <li> |
| Muliple ASTs can exist side by side (and ASTs are potentially for same |
| compilation unit).</li> |
| |
| <li> |
| Allow insertion of nodes from one AST into another AST.</li> |
| |
| <ul> |
| <li> |
| Automatically clones child subtree (forgetting source positions and binding |
| decorations).</li> |
| |
| <li> |
| Ensure memory representation of ASTs remain completely independent.</li> |
| </ul> |
| </ul> |
| |
| <h3> |
| <font color="#3366FF">Structural Equality</font></h3> |
| |
| <ul> |
| <li> |
| <font color="#3366FF">Structural equality predicate on AST nodes.</font></li> |
| |
| <li> |
| <font color="#3366FF">Isomorphic subtrees.</font></li> |
| |
| <li> |
| <font color="#3366FF">Belonging to same or different AST.</font></li> |
| |
| <li> |
| <font color="#3366FF">Considers structural info only; ignores source positions, |
| bindings, etc.</font></li> |
| |
| <li> |
| <font color="#3366FF">Named something other than "equals" to avoid having |
| to reimplement hashCode too.</font></li> |
| </ul> |
| |
| <h3> |
| Syntactic Correctness of Parser-built ASTs</h3> |
| |
| <ul> |
| <li> |
| For ASTs built by a Java parser, there are issues of syntactic correctness.</li> |
| |
| <li> |
| Syntactic correctness is judged by the Syntactic Grammar (as defined in |
| JLS2 section 2.3).</li> |
| |
| <li> |
| Java parser <b>must</b> guarantee to produce a faithful AST for any syntactically |
| correct compilation unit.</li> |
| |
| <li> |
| Java parser <b>may</b> also build ASTs for syntactically incorrect compilation |
| units.</li> |
| |
| <li> |
| Complicant Java compilers must reject syntactically incorrect compilation |
| units.</li> |
| |
| <li> |
| What principle do we apply to Java parsers and the ASTs they return?</li> |
| |
| <li> |
| Real Java parsers are invariably more liberal than the Syntactic Grammar, |
| and rely on post-parse checks to report errors for any syntactically incorrect |
| constructs that makes it past the parser.</li> |
| |
| <ul> |
| <li> |
| E.g., conflicting modifiers: public private</li> |
| |
| <li> |
| E.g., field declared with no initializer occurs in an interface</li> |
| |
| <li> |
| E.g., void foo() [];</li> |
| </ul> |
| |
| <li> |
| In the current Eclipse compiler, many of these checks are done in the course |
| of type and name resolution. If client only wants AST, we want to avoid |
| doing expensive name and type analysis.</li> |
| |
| <li> |
| Approach 1: Guarantee that no ASTs are built for syntactically incorrect |
| compilation units.</li> |
| |
| <ul> |
| <li> |
| You do not get an AST at all for compilation units with syntax errors.</li> |
| |
| <li> |
| Pro: Client can trust parser to distinguish syntactically correct from |
| incorrect.</li> |
| |
| <li> |
| Con: Client cannot manipulate syntactically incorrect compilation units |
| at all.</li> |
| |
| <li> |
| Con: Requires post-parse check to detect residual syntax errors.</li> |
| </ul> |
| |
| <li> |
| Approach 2: Provide no guarantee about the ASTs for syntactically incorrect |
| compilation units.</li> |
| |
| <ul> |
| <li> |
| You might not get a useful AST at all.</li> |
| |
| <li> |
| You might get an AST that had pieces missing; e.g., a malformed method |
| was excised</li> |
| |
| <li> |
| You might get an AST that is incoherent or self-contradictory; e.g., a |
| transient class!?</li> |
| |
| <li> |
| Pro: Maximum flexibility for implementation.</li> |
| |
| <li> |
| Pro: Client can get useful ASTs for some syntactically incorrect programs.</li> |
| |
| <li> |
| Con: Client cannot trust parser to distinguish syntactically correct from |
| incorrect.</li> |
| </ul> |
| |
| <li> |
| Approach 3: Guarantee that the client examining the resulting AST has some |
| way to determine whether the compilation units is incorrect.</li> |
| |
| <ul> |
| <li> |
| Priniciple: Syntactic errors must not be suppressed.</li> |
| |
| <li> |
| AST nodes could carry flags indicating certain syntax problem; e.g., duplicate |
| modifiers public public</li> |
| |
| <li> |
| A bit on root node could say "unspecified syntax errors".</li> |
| |
| <li> |
| Could be special AST nodes types indicating major problems; e.g., bogus |
| method body</li> |
| |
| <li> |
| Could be representable configurations of AST node types that are recognizable |
| as syntactially incorrect; e.g., conflicting modifiers public private; |
| missing field initializer in interface</li> |
| |
| <li> |
| Pro: Client can trust parser to not hide any syntax errors that are in |
| the source.</li> |
| |
| <li> |
| Pro: Client can get useful ASTs for syntactically incorrect programs.</li> |
| |
| <li> |
| Con: Client must do extra work to determine whether there are syntax errors.</li> |
| |
| <li> |
| Con: Extra work to include this information if no client really cares about |
| the difference between syntactically correct and incorrect.</li> |
| </ul> |
| |
| <li> |
| The first approach is too harsh. It is much more reasonable, and interesting, |
| to be able to work with some syntactically incorrect compilation units.</li> |
| |
| <li> |
| The second approach feels reasonable if clients never care whether the |
| source is syntactically correct or not.</li> |
| |
| <li> |
| The third approach feels reasonable if some clients would care whether |
| the source is syntactically correct or not.</li> |
| |
| <li> |
| The principle difference between the second and third appoaches is that |
| the former sanctions quietly suppressing syntax errors whereas the latter |
| precludes it.</li> |
| |
| <li> |
| The nature of the AST nodes inherently makes room to express a wide range |
| of syntactically malformed programs.</li> |
| |
| <li> |
| An extra flag per node for "unspecified syntax errors" should cover the |
| bases.</li> |
| |
| <li> |
| The existing compiler's ASTs already carry enough information to enable |
| the compiler to do thorough post-parse detecting of residual syntax errors.</li> |
| |
| <li> |
| Therefore the third approach is within easy reach.</li> |
| |
| <li> |
| The third approach gives clients more than the second approach.</li> |
| |
| <li> |
| Recommendation: we adopt the third approach.</li> |
| </ul> |
| |
| <h3> |
| Syntactic Correctness of Non-parser-built ASTs</h3> |
| |
| <ul> |
| <li> |
| ASTs do not just come from a parser.</li> |
| |
| <ul> |
| <li> |
| They can be created from scratch.</li> |
| |
| <li> |
| A parser-build AST can be edited.</li> |
| </ul> |
| |
| <li> |
| These ASTs will need to be serialized to a source compilation unit (why |
| else would they exist?).</li> |
| |
| <li> |
| What kinds of support and guarantees are in place to ensure that such a |
| suitable source compilation unit can be generated?</li> |
| |
| <li> |
| Basic guarantee: any AST that could have come from parsing a syntactically |
| correct compilation unit will serialize to a compilation unit that is</li> |
| |
| <ul> |
| <li> |
| (a) syntactically correct</li> |
| |
| <li> |
| (b) strongly semantically equivalent to the original compilation unit.</li> |
| |
| <li> |
| and possibly (c) normalized; that is, parse(serialize(x)) is isomorphic |
| to x</li> |
| </ul> |
| |
| <li> |
| There are likely many ways to get ASTs that do not correspond to any syntactically |
| correct compilation unit.</li> |
| |
| <ul> |
| <li> |
| E.g., use illegal identifiers ("1abc" or "try" or "//").</li> |
| |
| <li> |
| E.g., use illegal modifier combinations with modifier bit masks.</li> |
| </ul> |
| |
| <li> |
| Post-screening the AST for syntactic correctness would be misguided.</li> |
| |
| <li> |
| Should just go ahead and generate the obvious, syntactically incorrect, |
| compilation unit.</li> |
| |
| <li> |
| More importantly: ensure semantic equivalence.</li> |
| |
| <li> |
| Operator precedence creates issues:</li> |
| |
| <ul> |
| <li> |
| E.g., given AST for expression <tt>v1*v2</tt>, replace <tt>v1</tt> node |
| by expression <tt>v1+v3</tt>.</li> |
| |
| <li> |
| Naive serialization yields <tt>v1+v3*v2</tt> which is not semantically |
| equivalent to the AST.</li> |
| |
| <li> |
| Result should be (<tt>v1+v3)*v2</tt>.</li> |
| |
| <li> |
| Parentheses may need to be introduced during serialization.</li> |
| </ul> |
| |
| <li> |
| Nested if statement creates issues:</li> |
| |
| <ul> |
| <li> |
| E.g., given AST for statement <tt>if (a) f(); else g();</tt>, replace <tt>f();</tt> |
| by <tt>if (b) h();</tt></li> |
| |
| <li> |
| Naive serialization yields <tt>if (a) if (b) h(); else g();</tt></li> |
| |
| <li> |
| Result should be <tt>if (a) if (b) h(); <b>else </b>; else g();</tt></li> |
| |
| <li> |
| Extra verbiage may need to be introduced during serialization.</li> |
| </ul> |
| </ul> |
| |
| <h3> |
| Deep Constructs</h3> |
| |
| <ul> |
| <li> |
| Some programs involve impossibly deep constructs.</li> |
| |
| <li> |
| Multi-line string concatenation expressions are the main offender.</li> |
| |
| <ul> |
| <li> |
| For example, <tt>"Line 1\\n"+"Line 2\\n"+...+"Line 5000"</tt></li> |
| </ul> |
| |
| <li> |
| Runtime stacks blow when recursing over deep ASTs.</li> |
| |
| <li> |
| AST node types should be designed to keep trees reasonably shallow for |
| reasonably typical programs.</li> |
| |
| <li> |
| Introduce N-ary operator expression node type to deal with multi-line string |
| concatenation expressions.</li> |
| |
| <li> |
| N.B. Current compiler performs compile-time concatenations during parse |
| phase to deal with this problem.</li> |
| </ul> |
| |
| <h3> |
| Editing Protocol</h3> |
| |
| <ul> |
| <li> |
| What general form should the editing API take?</li> |
| |
| <li> |
| Setters on receiver to manipulate its children (parent never affected)</li> |
| |
| <ul> |
| <li> |
| E.g., whileStatement.setCondition(newExpression)</li> |
| |
| <li> |
| Use null for optional children</li> |
| </ul> |
| |
| <li> |
| Treat lists as an array-valued property.</li> |
| |
| <ul> |
| <li> |
| E.g., block.getStatements() returns Statement[]</li> |
| |
| <li> |
| E.g., block.setStatements(Statement[] statements)</li> |
| |
| <li> |
| Use empty list for no children (rather than null)</li> |
| </ul> |
| |
| <li> |
| Alternative approach for lists: use Collection-like protocol</li> |
| |
| <ul> |
| <li> |
| E.g., block.addStatement(pos, newChildStatement)</li> |
| |
| <li> |
| E.g., block.removeStatement(oldChildStatement)</li> |
| |
| <li> |
| Con: Increased number of methods on API; bad when a node type has several |
| list properties.</li> |
| </ul> |
| |
| <li> |
| Alternative approach for delete/replace: use parent backpointers to implement |
| generic delete and replace operation which affect the receiver's relationship |
| to its parent</li> |
| |
| <ul> |
| <li> |
| E.g., oldChildStatement.delete()</li> |
| |
| <li> |
| Con: semantics of deletion ugly when node occurs outside of any list</li> |
| </ul> |
| </ul> |
| |
| <h3> |
| User Data Field</h3> |
| |
| <ul> |
| <li> |
| Each AST node has a user data slot reserved for client use.</li> |
| |
| <li> |
| ASTNode.getClientData() returns Object</li> |
| |
| <li> |
| ASTNode.setClientData(Object data)</li> |
| |
| <li> |
| The initial value is null.</li> |
| |
| <li> |
| Client may use for decorations, or whatever.</li> |
| |
| <li> |
| AST nodes created by parser carry no data initially.</li> |
| |
| <li> |
| AST nodes created explicitly carry no data initially.</li> |
| |
| <li> |
| Even read-only ASTs have read-write data slots.</li> |
| |
| <li> |
| Cloning an AST node creates a new node (does <b>not</b> copy or clone data).</li> |
| </ul> |
| |
| <h3> |
| Lists of Members</h3> |
| |
| <ul> |
| <li> |
| List of field, method, and type members of a type declaration.</li> |
| |
| <li> |
| This list is syntactically and semantically heterogenous.</li> |
| |
| <li> |
| No syntactic constraints on number and order.</li> |
| |
| <li> |
| Order is significant to user.</li> |
| |
| <li> |
| Within field declarations, relative order is semantically significant.</li> |
| |
| <li> |
| Standard practices:</li> |
| |
| <ul> |
| <li> |
| Place field declarations before member methods and types.</li> |
| |
| <li> |
| Place types before methods.</li> |
| </ul> |
| |
| <li> |
| Option (1): expose separate lists for field, methods, and types.</li> |
| |
| <li> |
| Pro: This is way internal AST works.</li> |
| |
| <li> |
| Pro: Convenient for clients to locate member fields, methods, and types.</li> |
| |
| <li> |
| Con: Not flexible for editing; editing will mangle member order.</li> |
| |
| <li> |
| Option (2): expose a single list of members</li> |
| |
| <li> |
| Pro: parser does not normalize; client controls order of members.</li> |
| |
| <li> |
| Con: More work for clients to locate member fields, methods, and types.</li> |
| |
| <li> |
| Option (3): expose a single list of members, with extra getters for locating |
| member fields, methods, and types.</li> |
| |
| <li> |
| Pro: Combines advantage of (2) with convenience of (1).</li> |
| |
| <li> |
| Recommended approach: (3).</li> |
| |
| <li> |
| For class declarations, treat initializers and constructors as members.</li> |
| |
| <ul> |
| <li> |
| Lump instance and static initializers in with field declarations.</li> |
| |
| <li> |
| Lump constructor declarations in with method declarations.</li> |
| </ul> |
| </ul> |
| |
| <h3> |
| Serialization</h3> |
| |
| <ul> |
| <li> |
| Clients of read-write ASTs will generally want to serialize to a Java compilation |
| unit.</li> |
| |
| <li> |
| Serialization via simple AST tree walk.</li> |
| |
| <ul> |
| <li> |
| Straightforward.</li> |
| |
| <li> |
| Introduce line breaks and whitespace to make it look pretty.</li> |
| |
| <li> |
| Or post-process it with the Java formatter.</li> |
| |
| <li> |
| If AST originated by parsing, the result is likely unacceptable to user:</li> |
| |
| <ul> |
| <li> |
| Completely reformatted.</li> |
| |
| <li> |
| Constructs are normalized.</li> |
| |
| <li> |
| Some comments may have be lost.</li> |
| </ul> |
| |
| <li> |
| Could be provided by API that makes use of regular AST API only.</li> |
| |
| <li> |
| Could be written by clients.</li> |
| </ul> |
| |
| <li> |
| Serialization via source reconstruction.</li> |
| |
| <ul> |
| <li> |
| Only applicable to ASTs initially constructed by parser.</li> |
| |
| <li> |
| Use source position information in modified AST to reconstruct compilation |
| unit.</li> |
| |
| <li> |
| Retain passages of original text corresponding to unchanged AST trees.</li> |
| |
| <li> |
| Generates new text only where required.</li> |
| |
| <li> |
| Produce a result that a user will recognize and accept.</li> |
| |
| <ul> |
| <li> |
| Preserve formatting wherever possible.</li> |
| |
| <li> |
| Preserve source construct normalization wherever possible.</li> |
| |
| <li> |
| Preserve arbitrarily-placed comments wherever possible.</li> |
| </ul> |
| |
| <li> |
| Requires retaining the original compilation unit, and likely recording |
| additional information in nodes to allow reconstruction.</li> |
| |
| <li> |
| This is the way the current JDOM implementation works.</li> |
| |
| <li> |
| Could be provided by API that has privileged access to AST nodes and parser-recorded |
| information.</li> |
| |
| <li> |
| Should also return a list of edit instructions so that markers can be adjusted, |
| etc.</li> |
| |
| <li> |
| Clients would have a hard time doing this themselves.</li> |
| </ul> |
| |
| <li> |
| <font color="#000000">Recommend deferring implementation of serializer |
| that does source reconstruction.</font></li> |
| |
| <ul> |
| <li> |
| <font color="#000000">In interim, refactoring can apply edits to original |
| compilation unit text directly.</font></li> |
| </ul> |
| </ul> |
| |
| <h3> |
| Node types</h3> |
| The AST node types are based on the standard grammar for the Java language |
| given in the JLS2. |
| <p>Every AST node belongs to a single AST instance. (In DOM terminology, |
| the AST is the document and the AST nodes are the elements). The AST instance |
| can serve as a factory for creating new nodes. Nodes point to their owning |
| AST (fixed for the node's lifetime). The AST points directly to the root |
| node (a compilation unit).</p> |
| <p>The AST node types do not define their own notion of equality; they |
| just inherit the object identity based implementation from Object.</p> |
| <p>Note: Grammar rules (in comments) are expressed in the Pascal-style |
| extended BNF used in <tt>section 18</tt> of JLS2. We use C# style property |
| declarations as a convenient abbreviation for a standard matched pair of |
| get and set methods.</p> |
| <p><tt>public class AST</tt> |
| <br><tt> public AST();</tt> |
| <br><tt> public property CompilationUnit root;</tt> |
| <br><tt> public void loadFromSource(char[] source);</tt> |
| <br><tt> public void setOptions(...);</tt> |
| <br><tt> public char[] serialize();</tt></p> |
| <p><tt>public abstract class ASTNode</tt> |
| <br><tt> protected ASTNode(AST ast);</tt> |
| <br><tt> public AST getOwner();</tt> |
| <br><tt> public property int[] startPositions;</tt> |
| <br><tt> public property int[] lengths;</tt> |
| <br><tt> public property boolean isWholeLine;</tt> |
| <br><tt> public property Object clientData;</tt> |
| <br><tt> public ASTNode getParent();</tt> |
| <br><tt> ... other protocol common to all AST node types</tt></p> |
| <h4> |
| Names</h4> |
| <p>As explained in JLS2 section 6.5, the grammar does not allow names to be |
| resolved more finely than the following 6 categories by syntactic means |
| alone:</p> |
| <p><tt>PackageName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| PackageName . Identifier</tt> |
| <br><tt>TypeName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| PackageOrTypeName . Identifier</tt></p> |
| <p><tt>ExpressionName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| AmbiguousName . Identifier</tt></p> |
| <p><tt>MethodName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| AmbiguousName . Identifier</tt></p> |
| <p><tt>PackageOrTypeName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| PackageOrTypeName . Identifier</tt></p> |
| <p><tt>AmbiguousName:</tt> |
| <br><tt> |
| Identifier</tt> |
| <br><tt> |
| AmbiguousName . Identifier</tt></p> |
| <p>Given that names cannot be resolved definitively to a package, type, |
| field, or variable at AST node construction time, an open question is how |
| much of the categorization that could be done should be reflected in the |
| AST. More categories means more information flow from the parser to the |
| AST client; on the other hand, a variety of categories is not necessarily |
| convenient for clients. For example, in <tt>import a.b.c</tt> the name |
| is a <tt>TypeName</tt> whereas in <tt>import a.b.c.*</tt> the name <tt>a.b.c</tt> |
| is a <tt>PackageOrTypeName</tt>. If the name category was to be reflected |
| in the type of the AST nodes, the client would need to know to create the |
| appropriate type of name nodes when editing the AST.</p> |
| <p>Proposal: Use two AST node types for names: simple names, and qualified |
| names. Qualified names are expressed recursively, to facilitate clients |
| discovering how the qualifier part of a name resolves. Use these for everything |
| but <tt>MethodName</tt>; for <tt>MethodName</tt>, which can appear only |
| in a method invocation expression, separate the selector identifier from |
| any preceding qualifier.</p> |
| <p>(Note: The current internal AST nodes go beyond making the simple/qualified |
| distinction: they also have simple & qualified type names (classes |
| <tt>SimpleTypeReference</tt> |
| and <tt>QualifiedTypeReference</tt>) in additional to simple & qualified |
| named (classes <tt>SimpleNameReference</tt> and |
| <tt>QualifiedNameReference</tt>).)</p> |
| <p><tt>// Name:</tt> |
| <br><tt>// |
| SimpleName</tt> |
| <br><tt>// |
| QualifiedName</tt> |
| <br><tt>// SimpleName:</tt> |
| <br><tt>// |
| Identifier</tt> |
| <br><tt>// QualifiedName:</tt> |
| <br><tt>// |
| Name <b><u>.</u></b> Identifier</tt> |
| <br><tt>public interface IName // "marker" interface</tt> |
| <br><tt> public IBinding resolvedBinding(); // |
| optional</tt></p> |
| <p><tt>public class SimpleName extends ASTNode implements IName, IExpression</tt> |
| <br><tt> public SimpleName(AST ast);</tt> |
| <br><tt> public property char[] identifier;</tt></p> |
| <p><tt>public class QualifiedName extends ASTNode implements IName, IExpression</tt> |
| <br><tt> public QualifiedName(AST ast);</tt> |
| <br><tt> public property IName qualifier;</tt> |
| <br><tt> public property char[] identifier;</tt></p> |
| <h3> |
| Compilation Units and Major Declarations</h3> |
| <p><tt>// CompilationUnit:</tt> |
| <br><tt>// |
| [<b><u>package</u></b> Identifier { <b><u>.</u></b> Identifier } <b><u>;</u></b> |
| ]</tt> |
| <br><tt>// |
| {ImportDeclaration}</tt> |
| <br><tt>// |
| {TypeDeclaration | <b><u>;</u></b>}</tt> |
| <br><tt>public class CompilationUnit extends ASTNode</tt> |
| <br><tt> public CompilationUnit(AST ast);</tt> |
| <br><tt> public property Name packageName; // optional</tt> |
| <br><tt> public property ImportDeclaration[] imports;</tt> |
| <br><tt> public property TypeDeclaration[] types;</tt></p> |
| <p><tt>// ImportDeclaration:</tt> |
| <br><tt>// <b><u>import</u></b> |
| Identifier { <b><u>.</u></b> Identifier } [ <b><u>.</u></b> <b><u>*</u></b> |
| ] |
| <b><u>;</u></b></tt> |
| <br><tt>public class ImportDeclaration extends ASTNode</tt> |
| <br><tt> public ImportDeclaration(AST ast);</tt> |
| <br><tt> public property Name importName;</tt> |
| <br><tt> public property boolean onDemand;</tt> |
| <br><tt> public IBinding resolveBinding();</tt></p> |
| <p><tt>// TypeDeclaration:</tt> |
| <br><tt>// |
| {Modifier} <b><u>class</u></b> Identifier</tt> |
| <br><tt>// |
| [<b><u>extends</u></b> Type]</tt> |
| <br><tt>// |
| [<b><u>implements</u></b> Type { <b><u>,</u></b> Type}]</tt> |
| <br><tt>// |
| <b><u>{</u></b> {ClassBodyDeclaration | <b><u>;</u></b> } <b><u>}</u></b></tt> |
| <br><tt>// |
| {Modifier} <b><u>interface</u></b> Identifier</tt> |
| <br><tt>// |
| [<b><u>extends</u></b> Type { <b><u>,</u></b> Type}]</tt> |
| <br><tt>// |
| <b><u>{</u></b> {InterfaceBodyDeclaration | <b><u>;</u></b> } <b><u>}</u></b></tt> |
| <br><tt>// Modifier:</tt> |
| <br><tt>// <b><u>public</u></b></tt> |
| <br><tt>// <b><u>protected</u></b></tt> |
| <br><tt>// <b><u>private</u></b></tt> |
| <br><tt>// <b><u>static</u></b></tt> |
| <br><tt>// <b><u>abstract</u></b></tt> |
| <br><tt>// <b><u>final</u></b></tt> |
| <br><tt>// <b><u>native</u></b></tt> |
| <br><tt>// <b><u>synchronized</u></b></tt> |
| <br><tt>// <b><u>transient</u></b></tt> |
| <br><tt>// <b><u>volatile</u></b></tt> |
| <br><tt>// <b><u>strictfp</u></b></tt> |
| <br><tt>// ClassBodyDeclaration:</tt> |
| <br><tt>// |
| MethodDeclaration</tt> |
| <br><tt>// |
| ConstructorDeclaration</tt> |
| <br><tt>// |
| FieldDeclaration</tt> |
| <br><tt>// |
| ClassDeclaration</tt> |
| <br><tt>// |
| TypeDeclaration</tt> |
| <br><tt>// |
| Initializer</tt> |
| <br><tt>// InterfaceBodyDeclaration:</tt> |
| <br><tt>// |
| MethodDeclaration</tt> |
| <br><tt>// |
| FieldDeclaration</tt> |
| <br><tt>// |
| TypeDeclaration</tt> |
| <br><tt>public class TypeDeclaration extends ASTNode implements IStatement, |
| IMember</tt> |
| <br><tt> public TypeDeclaration(AST ast);</tt> |
| <br><tt> public property int modifiers;</tt> |
| <br><tt> public property char[] name;</tt> |
| <br><tt> public property Name superclass; // optional</tt> |
| <br><tt> public property Name[] superInterfaces;</tt> |
| <br><tt> public property IMember[] members;</tt> |
| <br><tt> public property char[][] javadocComment; // |
| optional</tt> |
| <br><tt> // convenience methods</tt> |
| <br><tt> public FieldDeclaration[] getFields; // includes |
| constants; excludes initializers</tt> |
| <br><tt> public AbstractMethodDeclaration[] getMethods; |
| // includes constructors</tt> |
| <br><tt> public TypeDeclaration[] getTypes;</tt> |
| <br><tt> public ITypeBinding resolveBinding();</tt></p> |
| <p><tt>// MethodDeclaration:</tt> |
| <br><tt>// |
| {Modifier} (Type | <b><u>void</u></b>) Identifier <b><u>(</u></b></tt> |
| <br><tt>// |
| [FormalParameter { <b><u>,</u></b> FormalParameter}] <b><u>)</u></b> |
| {<b><u>[</u></b> <b><u>]</u></b>}</tt> |
| <br><tt>// |
| [<b><u>throws</u></b> QualifiedIdentifierList] ( MethodBody | <b><u>;</u></b> |
| )</tt> |
| <br><tt>// ConstructorDeclaration:</tt> |
| <br><tt>// |
| {Modifier} Identifier <b><u>(</u></b> [FormalParameter { <b><u>,</u></b> |
| FormalParameter}] <b><u>)</u></b></tt> |
| <br><tt>// |
| [<b><u>throws</u></b> QualifiedIdentifierList] MethodBody</tt> |
| <br><tt>// FormalParameter:</tt> |
| <br><tt>// |
| [<b><u>final</u></b>] Type Identifier {<b><u>[</u></b> <b><u>]</u></b>}</tt> |
| <br><tt>public abstract class AbstractMethodDeclaration extends ASTNode |
| implements IMember</tt> |
| <br><tt> protected AbstractMethodDeclaration(AST ast);</tt> |
| <br><tt> public property int modifiers;</tt> |
| <br><tt> public property char[] selector;</tt> |
| <br><tt> public property FormalParameter[] parameters;</tt> |
| <br><tt> public property Name[] thrownExceptions;</tt> |
| <br><tt> public property char[][] javadocComment; // |
| optional</tt> |
| <br><tt> public property Block body; // optional</tt> |
| <br><tt> public IMethodBinding resolveBinding();</tt></p> |
| <p><tt>public class MethodDeclaration extends AbstractMethodDeclaration</tt> |
| <br><tt> public MethodDeclaration(AST ast);</tt> |
| <br><tt> public property Type returnType; // includes |
| void</tt></p> |
| <p><tt>public class ConstructorDeclaration extends AbstractMethodDeclaration</tt> |
| <br><tt> public ConstructorDeclaration(AST ast);</tt></p> |
| <p><tt>// FieldDeclaration:</tt> |
| <br><tt>// |
| {Modifier} Type Identifier {<b><u>[</u></b> <b><u>]</u></b>} [ <b><u>=</u></b> |
| Expression]</tt> |
| <br><tt>// |
| { <b><u>,</u></b> Identifier {<b><u>[</u></b> <b><u>]</u></b>} [ <b><u>=</u></b> |
| Expression] }</tt> |
| <br><tt>public class FieldDeclaration extends ASTNode implements IMember</tt> |
| <br><tt> public AbstractMethodDeclaration(AST ast);</tt> |
| <br><tt> public property int modifiers;</tt> |
| <br><tt> public property char[] name;</tt> |
| <br><tt> public property Type type;</tt> |
| <br><tt> public property char[][] javadocComment; // |
| optional</tt> |
| <br><tt> public property IExpression initializer; // |
| optional</tt> |
| <br><tt> public IFieldBinding resolveBinding();</tt></p> |
| <p><tt>// Initializer:</tt> |
| <br><tt>// |
| [<b><u>static</u></b>] Block</tt> |
| <br><tt>public final class Initializer extends ASTNode implements IMember</tt> |
| <br><tt> public Initializer(AST ast);</tt> |
| <br><tt> public property int modifiers;</tt> |
| <br><tt> public property Block body;</tt></p> |
| <p><tt>// LocalVariableDeclaration:</tt> |
| <br><tt>// |
| [<b><u>final</u></b>] Type Identifier {<b><u>[]</u></b>} [ <b><u>=</u></b> |
| Expression ]</tt> |
| <br><tt>// |
| { <b><u>,</u></b> Identifier {<b><u>[]</u></b>} [ <b><u>=</u></b> Expression] |
| } <b><u>;</u></b></tt> |
| <br><tt>public class LocalVariableDeclaration extends ASTNode implements |
| IStatement</tt> |
| <br><tt> public LocalVariableDeclaration(AST ast);</tt> |
| <br><tt> public property int modifiers;</tt> |
| <br><tt> public property char[] name;</tt> |
| <br><tt> public property Type type;</tt> |
| <br><tt> public property IExpression initializer; // |
| optional</tt> |
| <br><tt> public ILocalVariableBinding resolveBinding();</tt> |
| </p> |
| <h4> |
| Types</h4> |
| <p>The Type node (= TypeReference) represents a reference to a base type, |
| a named type, or an array thereof.</p> |
| <p><tt>// Type:</tt> |
| <br><tt>// |
| (BasicType | TypeName ) {<b><u>[]</u></b>}</tt> |
| <br><tt>// BasicType:</tt> |
| <br><tt>// <b><u>byte</u></b></tt> |
| <br><tt>// <b><u>short</u></b></tt> |
| <br><tt>// <b><u>char</u></b></tt> |
| <br><tt>// <b><u>int</u></b></tt> |
| <br><tt>// <b><u>long</u></b></tt> |
| <br><tt>// <b><u>float</u></b></tt> |
| <br><tt>// <b><u>double</u></b></tt> |
| <br><tt>// <b><u>boolean</u></b></tt> |
| <br><tt>public class Type extends ASTNode implements IExpression</tt> |
| <br><tt> public Type (AST ast);</tt> |
| <br><tt> public property int baseType; // either</tt> |
| <br><tt> public property Name typeName; // or</tt> |
| <br><tt> public property int dimensions;</tt> |
| <br><tt> public IBinding resolvedType();</tt></p> |
| <h4> |
| Statements</h4> |
| <p>There is a different AST node type for each different kind of statement. |
| Use a "marker" interface (<tt>IStatement</tt>) to bring all constructs |
| that can appear within a block (nonterminal <tt>BlockStatement</tt>, which |
| includes local variable and type declarations).</p> |
| <p><tt>// Block:</tt> |
| <br><tt>// <b><u>{</u></b> |
| BlockStatement <b><u>}</u></b></tt> |
| <br><tt>// BlockStatement :</tt> |
| <br><tt>// LocalVariableDeclaration</tt> |
| <br><tt>// TypeDeclaration</tt> |
| <br><tt>// [Identifier |
| <b><u>:</u></b> |
| ] Statement</tt> |
| <br><tt>//Statement:</tt> |
| <br><tt>// Block</tt> |
| <br><tt>// <b><u>if |
| (</u></b>Expression <b><u>)</u></b> Statement [<b><u>else</u></b> Statement]</tt> |
| <br><tt>// <b><u>for |
| (</u></b> ForInitOpt <b><u>;</u></b> [Expression] |
| <b><u>;</u></b> |
| ForUpdateOpt <b><u>)</u></b> Statement</tt> |
| <br><tt>// <b><u>while |
| (</u></b> Expression <b><u>)</u></b> Statement</tt> |
| <br><tt>// <b><u>do</u></b> |
| Statement <b><u>while</u></b> <b><u>(</u></b> Expression |
| <b><u>);</u></b></tt> |
| <br><tt>// <b><u>try</u></b> |
| Block [Catches] [ <b><u>finally</u></b> Block ]</tt> |
| <br><tt>// <b><u>switch |
| (</u></b> Expression <b><u>)</u></b> <b><u>{</u></b> SwitchBlockStatementGroups |
| <b><u>}</u></b></tt> |
| <br><tt>// <b><u>synchronized |
| (</u></b> Expression <b><u>)</u></b> Block</tt> |
| <br><tt>// <b><u>return</u></b> |
| [Expression] <b><u>;</u></b></tt> |
| <br><tt>// <b><u>throw</u></b> |
| Expression <b><u>;</u></b></tt> |
| <br><tt>// <b><u>break</u></b> |
| [Identifier] <b><u>;</u></b></tt> |
| <br><tt>// <b><u>continue</u></b> |
| [Identifier] <b><u>;</u></b></tt> |
| <br><tt>// <b><u>;</u></b></tt> |
| <br><tt>// ExpressionStatement</tt> |
| <br><tt>// Identifier |
| <b><u>:</u></b> |
| Statement</tt> |
| <br><tt>public interface IStatement // "marker" interface</tt></p> |
| <p><tt>public class Block extends ASTNode implements IStatement</tt> |
| <br><tt> public Block(AST ast);</tt> |
| <br><tt> public property IStatement[] statements;</tt> |
| <br><tt>public class IfStatement extends ASTNode implements IStatement</tt> |
| <br><tt> public IfStatement(AST ast);</tt> |
| <br><tt> public property IExpression test;</tt> |
| <br><tt> public property IStatement thenPart;</tt> |
| <br><tt> public property IStatement elsePart; // |
| optional</tt> |
| <br><tt>public class WhileStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class ForStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class DoStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class TryStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class SwitchStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class SynchronizedStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class ReturnStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class ThrowStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class BreakStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class ContinueStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class NullStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class LabeledStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <br><tt>public class AssertStatement extends ASTNode implements IStatement</tt> |
| <br><tt> ...</tt> |
| <h4> |
| <font color="#000000">Expression Statements</font></h4> |
| <font color="#000000">Certain types of expressions can also appear as statements. |
| The ExpressionStatement node wraps an expression up as a statement. The |
| source range for the ExpressionStatement includes the trailing semicolon.</font><font color="#000000"></font></p> |
| <p><tt><font color="#000000">public class ExpressionStatement extends ASTNode |
| implements IStatement</font></tt> |
| <br><tt><font color="#000000"> public ExpressionStatement(AST |
| ast);</font></tt> |
| <br><tt><font color="#000000"> public property IExpression |
| expression;</font></tt> |
| <h4> |
| Expressions</h4> |
| There is a different AST node type for each different kind of expression. |
| Use a "marker" interface (<tt>IExpression</tt>) to bring all constructs |
| that can appear as expressions.</p> |
| <p>(Many details TBD).</p> |
| <p><tt>// Expression:</tt> |
| <br><tt>// |
| Identifier</tt> |
| <br><tt>// |
| ArrayAllocationExpression</tt> |
| <br><tt>// |
| StringLiteral</tt> |
| <br><tt>// |
| FloatingPointLiteral</tt> |
| <br><tt>// |
| BooleanLiteral</tt> |
| <br><tt>// |
| CharacterLiteral</tt> |
| <br><tt>// |
| StringLiteral</tt> |
| <br><tt>// |
| NullLiteral</tt> |
| <br><tt>// |
| ( Type | <b><u>void</u></b> ) <b><u>.</u></b> class</tt> |
| <br><tt>// |
| [ ClassName <b><u>.</u></b> ] <b><u>this</u></b></tt> |
| <br><tt>// <b><u>(</u></b> |
| Expression <b><u>)</u></b></tt> |
| <br><tt>// |
| [ Expression <b><u>.</u></b> ] <b><u>new</u></b> Type <b><u>(</u></b></tt> |
| <br><tt>// |
| [ Expression { <b><u>,</u></b> Expression } ] <b><u>)</u></b> [ ClassBody |
| ]</tt> |
| <br><tt>// |
| Expression <b><u>.</u></b> Identifier</tt> |
| <br><tt>// |
| [ ClassName <b><u>.</u></b> ] <b><u>super .</u></b> Identifier</tt> |
| <br><tt>// |
| MethodName <b>(</b> [ Expression { <b><u>,</u></b> Expression } ] <b><u>)</u></b></tt> |
| <br><tt>// |
| Expression <b><u>.</u></b> Identifier <b>(</b> [ Expression { <b><u>,</u></b> |
| Expression } ] <b><u>)</u></b></tt> |
| <br><tt>// |
| [ ClassName <b><u>.</u></b> ] <b><u>super .</u></b> Identifier <b>(</b></tt> |
| <br><tt>// |
| [ Expression { <b><u>,</u></b> Expression } ] <b><u>)</u></b></tt> |
| <br><tt>// |
| Expression <b><u>[</u></b> Expression <b><u>]</u></b></tt> |
| <br><tt>// |
| Expression InfixOperator Expression</tt> |
| <br><tt>// |
| Expression <b><u>instanceof</u></b> Type</tt> |
| <br><tt>// |
| Expression PostfixOperator</tt> |
| <br><tt>// |
| PrefixOperator Expression</tt> |
| <br><tt>// <b><u>(</u></b> |
| Type <b><u>)</u></b> Expression</tt> |
| <br><tt>// |
| Expression <b><u>?</u></b> Expression <b><u>:</u></b> Expression</tt> |
| <br><tt>// |
| Expression AssignmentOperator Expression</tt> |
| <br><tt>// ArrayInitializer</tt> |
| <br><tt>public interface IExpression // "marker" interface</tt> |
| <br><tt> public IBinding resolvedType(); // optional</tt></p> |
| <p><tt>// ArrayAllocationExpression:</tt> |
| <br><tt>// <b><u>new</u></b> |
| PrimitiveType <b><u>[</u></b> Expression <b><u>]</u></b> { <b><u>[</u></b> |
| Expression <b><u>]</u></b> } { <b><u>[</u></b> <b><u>]</u></b> }</tt> |
| <br><tt>// <b><u>new</u></b> |
| TypeName <b><u>[</u></b> Expression <b><u>]</u></b> { |
| <b><u>[</u></b> Expression |
| <b><u>]</u></b> |
| } { <b><u>[</u></b> <b><u>]</u></b> }</tt> |
| <br><tt>// <b><u>new</u></b> |
| PrimitiveType <b><u>[</u></b> <b><u>]</u></b> { <b><u>[]</u></b> } ArrayInitializer</tt> |
| <br><tt>// <b><u>new</u></b> |
| TypeName <b><u>[</u></b> <b><u>]</u></b> { <b><u>[]</u></b> } ArrayInitializer</tt> |
| <br><tt>public class ArrayAllocationExpression</tt> |
| <br><tt> extends ASTNode implements IExpression</tt> |
| <br><tt> public ArrayAllocationExpression(AST ast);</tt> |
| <br><tt> public property Type type;</tt> |
| <br><tt> public property Expression[] dimensions; // |
| optional</tt> |
| <br><tt> public property Expression arrayInitializer; |
| // optional</tt></p> |
| <p><tt>public class StringLiteral extends ASTNode implements IExpression</tt> |
| <br><tt> public StringLiteral(AST ast);</tt> |
| <br><tt> public property String value;</tt> </p> |
| <p><tt>public class CastExpression extends ASTNode implements IExpression</tt> |
| <br><tt> public CastExpression(AST ast);</tt> |
| <br><tt> public property Type type;</tt> |
| <br><tt> public property IExpression value;</tt></p> |
| <p><tt>public class InfixExpression extends ASTNode implements IExpression</tt> |
| <br><tt> public InfixExpression(AST ast);</tt> |
| <br><tt> public property int infixOperator;</tt> |
| <br><tt> public property IExpression leftOperand;</tt> |
| <br><tt> public property IExpression rightOperand;</tt> |
| <br><tt> public property IExpression[] extendedOperands; |
| // L op R op R2 op R3...</tt></p> |
| <h3> |
| Bindings</h3> |
| <p>The "world of bindings" is an integrated picture of the structure of the |
| program as seen from the compiler's point of view. The bindings correspond |
| to named entities (packages, types, fields, methods, local variables).</p> |
| <p>Clients navigate from AST nodes into the world of bindings to discover |
| things like:</p> |
| <ul> |
| <li> |
| the entity an identifier resolves to</li> |
| |
| <li> |
| the resolved type of an expression node</li> |
| |
| <li> |
| the resolved binding of a declaration node</li> |
| |
| <li> |
| others?</li> |
| </ul> |
| Once in the world of bindings, the client can navigate the web of bindings: |
| <ul> |
| <li> |
| from array type to its component type, and vice versa</li> |
| |
| <li> |
| from field or variable to its declared type</li> |
| |
| <li> |
| from method to its parameter and return types</li> |
| |
| <li> |
| from type to its constructors and its declared method, field, and type |
| members</li> |
| |
| <li> |
| from constructor, method, or field to its declaring type</li> |
| |
| <li> |
| from nested type to its enclosing type</li> |
| |
| <li> |
| from type to declaring package</li> |
| |
| <li> |
| from type to its supertypes (but, significantly, <i>not</i> to its subtypes)</li> |
| |
| <li> |
| directly to the binding for any base type (int, float, char, etc.)</li> |
| |
| <li> |
| directly to the binding for a handful of well-known types (java.lang.Object, |
| etc.)</li> |
| </ul> |
| Some of the navigations that are not supported (quite intentionally): |
| <ul> |
| <li> |
| from package to its (known) types - very expensive</li> |
| |
| <li> |
| from package to one of its types by name - very expensive</li> |
| |
| <li> |
| from type to its (known) subtypes - very expensive</li> |
| |
| <li> |
| from type or method to the local types it encloses - binding for local |
| types are only of interest to those with the enclosing type's AST in their |
| hand</li> |
| |
| <li> |
| from method to the variables declared within it - binding for variables |
| are only of interest to those with the method's AST in their hand</li> |
| </ul> |
| There are no links from the world of bindings back to the world of ASTs. |
| <p>Other things dealt with in the world of bindings:</p> |
| <ul> |
| <li> |
| synthetic entities stemming from default constructors, abstract method |
| copy-down from interfaces, and inner class emulation</li> |
| |
| <li> |
| missing bindings for entities that are required (mentioned by name) but |
| were not found</li> |
| |
| <li> |
| type hierachy circularities</li> |
| |
| <li> |
| internal inconsistencies</li> |
| </ul> |
| Other issues: |
| <ul> |
| <li> |
| Compile-time-computed values for constants (public static final fields |
| with compile-time computable values)</li> |
| </ul> |
| |
| <h4> |
| Existing Binding classes</h4> |
| <p>To give an idea of the scope of the existing binding infrastructure, below |
| is a dump of the type hierarchy of the compiler's binding classes from |
| package <tt>rg.eclipse.jdt.internal.compiler.lookup</tt>.</p> |
| <p><tt>public abstract class Binding</tt> |
| <br><tt> public abstract class TypeBinding</tt> |
| <br><tt> public final class ArrayBinding</tt> |
| <br><tt> public final class BaseTypeBinding</tt> |
| <br><tt> public abstract class |
| ReferenceBinding</tt> |
| <br><tt> |
| public class SourceTypeBinding</tt> |
| <br><tt> |
| public class NestedTypeBinding</tt> |
| <br><tt> |
| public final class LocalTypeBinding</tt> |
| <br><tt> |
| public final class MemberTypeBinding</tt> |
| <br><tt> |
| public class ProblemReferenceBinding</tt> |
| <br><tt> |
| public class UnresolvedReferenceBinding</tt> |
| <br><tt> public class PackageBinding</tt> |
| <br><tt> public class ProblemPackageBinding</tt> |
| <br><tt> public abstract class VariableBinding</tt> |
| <br><tt> public class LocalVariableBinding</tt> |
| <br><tt> |
| public class SyntheticArgumentBinding</tt> |
| <br><tt> public class FieldBinding</tt> |
| <br><tt> |
| public class SyntheticFieldBinding</tt> |
| <br><tt> |
| public class ProblemFieldBinding</tt> |
| <br><tt> public class MethodBinding</tt> |
| <br><tt> public class ProblemMethodBinding</tt> |
| <br><tt> public class SyntheticAccessMethodBinding</tt> |
| <br><tt> public class ImportBinding</tt> |
| <br><tt> public class ProblemBinding</tt></p> |
| <h4> |
| Binding API</h4> |
| <p>The existing binding classes are not immediately suitable for exposing |
| as a binding API.</p> |
| <p>However, the Java builder does have an API for the built "image", in |
| package <tt>org.eclipse.jdt.internal.core.builder</tt>. (This API is a |
| hold-over from Leapfrog era, and is not exposed in the Eclipse code base). |
| This API was designed to expose the same kind of integrated picture of |
| the structure of the program as seen from the compiler's point of view. |
| This API has a detailed specification that does not expose implementation |
| details, so the proposal is to use it as the basis for the new binding |
| API.</p> |
| <p>Re-purposing this API would entail:</p> |
| <ul> |
| <li> |
| introducing entities for local variables</li> |
| |
| <li> |
| removing protocol for navigations that are not supported (e.g., from package |
| to its known types)</li> |
| |
| <li> |
| removing unneeded protocol; including states, non-state-specific handles, |
| deltas, report cards, dependency graph, package references</li> |
| </ul> |
| Below is a dump of the relevant interfaces from package <tt>org.eclipse.jdt.internal.core.builder</tt>. |
| Unnecessary protocol has been omitted. (Note that NotPresentException is |
| an unchecked exception, and would not be required.) |
| <p><tt>public interface IHandle</tt> |
| <br><tt> int K_JAVA_IMAGE = 1;</tt> |
| <br><tt> int K_JAVA_PACKAGE = 2;</tt> |
| <br><tt> int K_JAVA_TYPE = 3;</tt> |
| <br><tt> int K_JAVA_FIELD = 4;</tt> |
| <br><tt> int K_JAVA_METHOD = 5;</tt> |
| <br><tt> int K_JAVA_CONSTRUCTOR = 6;</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> int hashCode();</tt> |
| <br><tt> boolean isFictional() throws NotPresentException;</tt> |
| <br><tt> boolean isPresent();</tt> |
| <br><tt> int kind();</tt></p> |
| <p><tt>public interface IMember extends IHandle</tt> |
| <br><tt> IType getDeclaringClass();</tt> |
| <br><tt> int getModifiers() throws NotPresentException;</tt> |
| <br><tt> String getName();</tt> |
| <br><tt> boolean isBinary() throws NotPresentException;</tt> |
| <br><tt> boolean isDeprecated() throws NotPresentException;</tt> |
| <br><tt> boolean isSynthetic() throws NotPresentException;</tt></p> |
| <p><tt>public interface IPackage extends IHandle</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType getClassHandle(String name);</tt> |
| <br><tt> String getName();</tt> |
| <br><tt> boolean isUnnamed();</tt> </p> |
| <p><tt>public interface IType extends IMember</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType getArrayHandle();</tt> |
| <br><tt> IType getComponentType();</tt> |
| <br><tt> IConstructor getConstructorHandle(IType[] parameterTypes);</tt> |
| <br><tt> IType[] getDeclaredClasses() throws NotPresentException;</tt> |
| <br><tt> IConstructor[] getDeclaredConstructors() throws |
| NotPresentException;</tt> |
| <br><tt> IField[] getDeclaredFields() throws NotPresentException;</tt> |
| <br><tt> IMethod[] getDeclaredMethods() throws NotPresentException;</tt> |
| <br><tt> int getDeclaredModifiers() throws NotPresentException;</tt> |
| <br><tt> String getDeclaredName() throws NotPresentException;</tt> |
| <br><tt> IType getDeclaringClass() throws NotPresentException;</tt> |
| <br><tt> IField getFieldHandle(String name);</tt> |
| <br><tt> IType[] getInterfaces() throws NotPresentException;</tt> |
| <br><tt> IMethod getMethodHandle(String name, IType[] |
| parameterTypes);</tt> |
| <br><tt> int getModifiers() throws NotPresentException;</tt> |
| <br><tt> String getName();</tt> |
| <br><tt> IPackage getPackage();</tt> |
| <br><tt> String getSimpleName();</tt> |
| <br><tt> IType getSuperclass() throws NotPresentException;</tt> |
| <br><tt> boolean isAnonymous() throws NotPresentException;</tt> |
| <br><tt> boolean isArray();</tt> |
| <br><tt> boolean isBinary() throws NotPresentException;</tt> |
| <br><tt> boolean isClass() throws NotPresentException;</tt> |
| <br><tt> boolean isDeprecated() throws NotPresentException;</tt> |
| <br><tt> boolean isInnerClass() throws NotPresentException;</tt> |
| <br><tt> boolean isInterface() throws NotPresentException;</tt> |
| <br><tt> boolean isLocal() throws NotPresentException;</tt> |
| <br><tt> boolean isPackageMember() throws NotPresentException;</tt> |
| <br><tt> boolean isPresent();</tt> |
| <br><tt> boolean isPrimitive();</tt> |
| <br><tt> boolean isSynthetic() throws NotPresentException;</tt> |
| <br><tt> boolean isTopLevel() throws NotPresentException;</tt></p> |
| <p><tt>public interface IMethod extends IMember</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType[] getExceptionTypes() throws NotPresentException;</tt> |
| <br><tt> IType[] getParameterTypes();</tt> |
| <br><tt> IType getReturnType() throws NotPresentException;</tt> |
| <br><tt> boolean isPresent();</tt> </p> |
| <p><tt>public interface IConstructor extends IMember</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType[] getExceptionTypes() throws NotPresentException;</tt> |
| <br><tt> IType[] getParameterTypes();</tt> |
| <br><tt> boolean isPresent();</tt></p> |
| <p><tt>public interface IField extends IMember</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType getType() throws NotPresentException;</tt> |
| <br><tt> boolean isPresent();</tt></p> |
| <p>In this vein, the interface for local variables would look something |
| like:</p> |
| <p><tt>public interface IVariable extends IHandle</tt> |
| <br><tt> boolean equals(Object obj);</tt> |
| <br><tt> IType getDeclaringClass();</tt> |
| <br><tt> int getModifiers() throws NotPresentException;</tt> |
| <br><tt> String getName();</tt> |
| <br><tt> boolean isSynthetic() throws NotPresentException;</tt> |
| <br><tt> IType getType() throws NotPresentException;</tt> |
| <br><tt> boolean isPresent();</tt></p> |
| <p>Also will need to add:</p> |
| <ul> |
| <li> |
| Pseudo-bindings for base types: boolean, int, float, etc.</li> |
| |
| <li> |
| Access to well-known java.lang bindings: Object, String, Throwable, Exception, |
| RuntimeException, Error, Class.</li> |
| </ul> |
| |
| <h3> |
| Document History</h3> |
| 18:30 Thursday September 27, 2001 - incorporated first round comments from |
| PM and DB. |
| <br><font color="#000000">10:45 Monday October 1, 2001 - incorporated comments |
| from DB.</font> |
| <br><font color="#000000">10:45 Tuesday October 2, 2001 - clarify handing |
| of ExpressionStatement.</font> |
| <br><font color="#3366FF">14:00 Friday October 26, 2001 - add subtree structural |
| equality.</font> |
| <br> |
| </body> |
| </html> |