import java.util.*;
import Jakarta.util.FixDosOutputStream;
import Jakarta.util.Util2;
import java.io.*;
//---------------------- AST_FIELD declarations-------------------
public class AST_FieldDecl {
// used for typeSorting and and in baseRewrites
public AstList makeList( AstNode n ) {
if ( n instanceof MethodDeclaration ) {
n = ( AstNode ) n.clone();
}
AST_FieldDecl l = new AST_FieldDecl();
l.add( new AST_FieldDeclElem().setParms( n ) );
return l;
}
public void compose( AstNode etree ) {
AstNode.fatalError( "don't invoke AST_FieldDecl.compose; use static" +
" AST_FieldDecl.compose( AstNode etree, LinkedList ll )" );
}
// the following compose method is applied to a base node of
// type AST_FieldDecl. It has two parameters: the corresponding
// AST_FieldDecl of the base AND a LinkedList of extension code
// fragments that may have Base() references. The trees in this
// vector are harvested from declarative specs (such as
// edge declarations in State Machine). These trees are not
// part of the extension code proper, but do belong there and
// should be transformed just as if they were part of the
// extension AST_FieldDecl
// part of the complexity of this method is that we blindly merged
// the classbodies of the base and extension. If the base was empty,
// we substituted the ClassBody of the extensioin. We can't quite
// do this because we should check for errors in the extension
// itself.
// FINALLY -- when you call this method, remember that it returns
// the updated node. so a call ALWAYS looks like:
// arg[?] = $TEqn.AST_FieldDecl( arg[?], ... , ... );
// otherwise results aren't propagated!
public static AstNode compose( AstNode btree,
AstNode etree, LinkedList ll ) {
ListIterator li = null;
// Step 0: validate correct type
AST_FieldDecl b = ( AST_FieldDecl ) btree;
AST_FieldDecl e = ( AST_FieldDecl ) etree;
if ( ll != null )
li = ll.listIterator();
// Step 1: collect signatures of all class member declarations
// in both the base and extension declarations
Hashtable hb = new Hashtable();
Hashtable he = new Hashtable();
AstCursor c = new AstCursor();
if ( b != null ) {
for ( c.FirstElement( b ); c.MoreElement(); c.NextElement() ) {
( ( ClassBodyDeclaration ) c.node ).add2Hash( hb );
}
}
if ( e != null ) {
for ( c.FirstElement( e ); c.MoreElement(); c.NextElement() ) {
( ( ClassBodyDeclaration ) c.node ).add2Hash( he );
}
}
// Step 2: invoke baseRewrite to rewrite all "Base(...).method(...)"
// invocations in the extension - both the extension proper
// and on the list itself
if ( e != null )
e.baseRewrite( hb, he, 0 );
if ( li != null ) {
while ( li.hasNext() ) {
AstNode n = ( AstNode ) li.next();
if ( n != null ) {
n.baseRewrite( hb, he, 0 );
}
}
}
// Step 3: now see if it is Ok to merge each element of the
// extension with the base
Enumeration en = he.elements();
for ( ; en.hasMoreElements(); ) {
AstNode elem = ( AstNode ) en.nextElement();
elem.ok2compose( 0, hb );
}
// Step 4: perform any cleanup activity on the base declarations
if ( b != null )
for ( c.FirstElement( b ); c.MoreElement(); c.NextElement() )
( ( ClassBodyDeclaration ) c.node ).cleanUpBase( c, he );
// Step 5: return if both b and e are null, otherwise
// merge the extension and base Classbodies
if ( b == null && e == null )
return null;
else
if ( b != null && e != null )
b.add( e );
else
if ( b == null )
b = e;
// if e == null, use the current value of b which we know is nonnull
// Step 6: optionally sort the declarations
if ( Main.keySort ) {
b = b.BodySort();
}
else
if ( Main.typeSort )
b.typeSort( new AST_FieldDecl() );
return b;
}
}