import java.util.*; import Jakarta.util.*; import java.io.*; //******************************* AST_CLASS *************************/ // root of series of class and interface declarations, // in general, we assume only one class or one interface defined. public class AST_Class { // has tree already been prepared? public boolean alreadyPrepared( JTSParseTree t ) { AstCursor k = new AstCursor(); // Step 1: walk through list of Type declarations. If any of them // are source, return true. Else false. for ( k.FirstElement( this ); k.MoreElement(); k.NextElement() ) { if ( k.node instanceof SourceDecl ) return true; } return false; } // compose AST_Class base tree with extension AST_Class tree // @param etree - extension tree of type AST_Class public void compose( AstNode etree, JTSParseTree base, JTSParseTree ext ) { // Step 1: if there is no base file Type Declaration, stop if ( base.lastType == null ) AstNode.fatalError( "base file missing TypeDeclaration -- nothing to extend" ); // Step 2: make sure there is an extension if ( ext.firstType == null ) AstNode.fatalError( "extension file missing TypeDeclaration -- nothing to extend" ); // Step 3: it is ok to compose if (1) the types are compatible // and (2) the names of the artifacts are the same. if ( base.lastType.getClass() != ext.firstType.getClass() ) AstNode.fatalError( "attempting to compose files of different types " + base.firstType.getClass().getName() + " " + ext.firstType.getClass().getName() ); String baseName = Util2.unmangleId( base.lastType.getName() ); String extName = Util2.unmangleId( ext.firstType.getName() ); if ( !baseName.equals( extName ) ) AstNode.fatalError( "attempting to compose files with different names " + base.firstType.getName() + " " + ext.firstType.getName() ); // Step 4: compose them by concatenating the extension declarations // to the base declarations add( ( AST_Class ) etree ); // Step 5: finally, have the firstType in the extension // extend the lastType in the base. This emulates the // parameter instantion of mixins. // Also, propagate the modifiers of base.lastType // to ext.lastType, and set all other modifiers to be // abstract ext.firstType.extensionOf( base.lastType.getAndMangleName() ); AST_Modifiers m = base.lastType.getModifier(); base.lastType.setAbstractModifier(); if ( ext.firstType != ext.lastType ) ext.firstType.setAbstractModifier(); ext.lastType.addModifiers( m ); base.lastType = ext.lastType; } // can remove into its own layer! public boolean isExtension() { AstCursor c = new AstCursor(); for ( c.FirstElement( this ); c.MoreElement(); c.NextElement() ) { if ( c.node instanceof SourceDecl ) return ( ( SourceDecl ) c.node ).isExtension(); if ( c.node instanceof ModTypeDecl ) return ( ( ModTypeDecl ) c.node ).isExtension(); } AstNode.fatalError( "file missing Modified Type declaration" ); return false; // pacify whiney compiler } }