import java.util.*;
import java.io.*;
public class SmClassDecl {
public Hashtable h = new Hashtable();
// piggyback onto checkForErrors the checking for
// errors in replicated definitions within a single file.
// the error checking is performed on State definitions
// and Transition definitions
public void checkForErrors( int state, String file ) {
super.checkForErrors( state, file );
StatesList slb = ( StatesList ) arg[2].arg[0];
if ( slb!=null )
slb.add2Hash( h, kernelConstants.globals().currentFileName );
ESList esb = ( ESList ) arg[3].arg[0];
if ( esb!=null )
esb.add2Hash( h, kernelConstants.globals().currentFileName );
}
public void compose( AstNode etree ) {
// Step 0: Do some standard error checking - etree is of type
// SmClassDecl.
SmClassDecl e = ( SmClassDecl ) etree;
// Step 1: compose the root clauses
arg[0].compose( e.arg[0] );
// Step 2: compose and otherwise clauses. Just merge the lists
arg[1].compose( e.arg[1] );
// Step 3: foreach key in the extension's hashtable, try to
// add it to the base hash table. If there is a collision
// then we have an error.
for ( Enumeration c = e.h.keys(); c.hasMoreElements(); ) {
String key = ( String ) c.nextElement();
String source = ( String ) e.h.get( key );
String result = ( String ) h.get( key );
if ( result==null )
h.put( key,source );
else
// so there is a state already defined in base with 'key' as its name
// if either the extension or base has correctly defined the
// state, then don't issue a warning
if ( ! ( result.equals( "unknown layer" ) || source.equals( "unknown layer" ) ) )
AstNode.error( key + " is defined both in " + source + " and in " + result );
}
// Step 4: all that remains is to compose AST_FieldDecls. What's
// unusual here is that not only do we compose the base and
// extension AST_FieldDecls, but we also have to pass in
// a LinkedList of ASTs of extension method bodies that
// are not part of the extension AST_FieldDecl proper.
// so ASTs like edge actions, edge boolean tests, exit
// methods must first be harvested onto this list before
// we can officially compose. The reason for doing so
// is that these extra method bodies may reference methods
// of the "base" class via the Base() construct. These
// references must be rewritten.
// The sources of harvest include the: OtherwiseClause,
// and ESList. no class bodies are present in StatesLists
LinkedList ll = new LinkedList();
OtherwiseClauses oc = ( OtherwiseClauses ) e.arg[1].arg[0];
if ( oc!=null )
oc.harvestAst( ll );
ESList es = ( ESList ) e.arg[3].arg[0];
if ( es!=null )
es.harvestAst( ll );
// Step 5: compose the methods and data members of AST_FieldDecl
// in the approved manner
arg[4].arg[0] =
AST_FieldDecl.compose( arg[4].arg[0], e.arg[4].arg[0], ll );
// Step 6: the last step in composition is to assume that there
// are no semantic errors and compose directly the
// stateslist and eslist declarations
arg[2].compose( e.arg[2] );
arg[3].compose( e.arg[3] );
}
}