public static Class < ? > generateClassImpl ( String name , Modifiers modifiers , Class < ? > [ ] interfaces , Class < ? > superClass , BSHBlock block , Type type , CallStack callstack , Interpreter interpreter ) throws EvalError { NameSpace enclosingNameSpace = callstack . top ( ) ; String packageName = enclosingNameSpace . getPackage ( ) ; String className = enclosingNameSpace . isClass ? ( enclosingNameSpace . getName ( ) + "$" + name ) : name ; String fqClassName = packageName == null ? className : packageName + "." + className ; BshClassManager bcm = interpreter . getClassManager ( ) ; // Race condition here... bcm . definingClass ( fqClassName ) ; // Create the class static namespace NameSpace classStaticNameSpace = new NameSpace ( enclosingNameSpace , className ) ; classStaticNameSpace . isClass = true ; callstack . push ( classStaticNameSpace ) ; // Evaluate any inner class class definitions in the block // effectively recursively call this method for contained classes first block . evalBlock ( callstack , interpreter , true /*override*/ , ClassNodeFilter . CLASSCLASSES ) ; // Generate the type for our class Variable [ ] variables = getDeclaredVariables ( block , callstack , interpreter , packageName ) ; DelayedEvalBshMethod [ ] methods = getDeclaredMethods ( block , callstack , interpreter , packageName , superClass ) ; callstack . pop ( ) ; // initialize static this singleton in namespace classStaticNameSpace . getThis ( interpreter ) ; // Create the class generator, which encapsulates all knowledge of the // structure of the class ClassGeneratorUtil classGenerator = new ClassGeneratorUtil ( modifiers , className , packageName , superClass , interfaces , variables , methods , classStaticNameSpace , type ) ; // Let the class generator install hooks relating to the structure of // the class into the class static namespace. e.g. the constructor // array. This is necessary whether we are generating code or just // reinitializing a previously generated class. classGenerator . initStaticNameSpace ( classStaticNameSpace , block /*instance initializer*/ ) ; // Check for existing class (saved class file) Class < ? > genClass = bcm . getAssociatedClass ( fqClassName ) ; // If the class isn't there then generate it. // Else just let it be initialized below. if ( genClass == null ) { // generate bytecode, optionally with static init hooks to // bootstrap the interpreter byte [ ] code = classGenerator . generateClass ( ) ; if ( Interpreter . getSaveClasses ( ) ) saveClasses ( className , code ) ; // Define the new class in the classloader genClass = bcm . defineClass ( fqClassName , code ) ; Interpreter . debug ( "Define " , fqClassName , " as " , genClass ) ; } // import the unqualified class name into parent namespace enclosingNameSpace . importClass ( fqClassName . replace ( ' ' , ' ' ) ) ; // Give the static space its class static import // important to do this after all classes are defined classStaticNameSpace . setClassStatic ( genClass ) ; Interpreter . debug ( classStaticNameSpace ) ; bcm . doneDefiningClass ( fqClassName ) ; if ( interpreter . getStrictJava ( ) ) ClassGeneratorUtil . checkAbstractMethodImplementation ( genClass ) ; return genClass ; }
Parse the BSHBlock for for the class definition and generate the class using ClassGenerator .