[Nice-commit] Nice/src/bossa/syntax niceclass.nice,1.23,1.24 enum.nice,1.17,1.18 defaultconstructor.
Brought to you by:
bonniot
|
From: Daniel B. <bo...@us...> - 2005-03-01 17:37:03
|
Update of /cvsroot/nice/Nice/src/bossa/syntax In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27179/src/bossa/syntax Modified Files: niceclass.nice enum.nice defaultconstructor.nice Log Message: Make sure that constructors with defaults omitted are compiled first so they get unmangled names, in case they clash with ones with all values. Cleaned up DefaultConstructor by creating a class CompiledConstructor to handle the details of bytecode generation. Index: defaultconstructor.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/defaultconstructor.nice,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** defaultconstructor.nice 13 Jan 2005 14:06:15 -0000 1.5 --- defaultconstructor.nice 1 Mar 2005 17:36:36 -0000 1.6 *************** *** 30,46 **** ?MethodDeclaration parent; ! /** Call the constructor, with all the arguments. */ ! private ?gnu.expr.Expression initialize = null; ! /** Call the constructor, with all the arguments, with an implicit this argument. */ ! private ?gnu.expr.Expression initializeFromConstructor = null; ! /** Call the constructor, with only non-default arguments. */ ! private ?gnu.expr.Expression initializeOmitDefaults = null; ! /** Instantiate the class, calling the constructor with all the arguments. */ ! private ?gnu.expr.Expression instantiate = null; getInitializationCode(implicitThis) { this.getCode(); ! return notNull(initializeFromConstructor); } --- 30,40 ---- ?MethodDeclaration parent; ! private CompiledConstructor compiledFull = cast(null); ! private ?CompiledConstructor compiledMini = null; getInitializationCode(implicitThis) { this.getCode(); ! return notNull(compiledFull.initialization); } *************** *** 49,124 **** this.getCode(); return ! // lambdaOmitDefaults is null if the two versions are identical ! omitDefaults && initializeOmitDefaults != null ! ? notNull(initializeOmitDefaults) : notNull(initialize); } ! computeCode() { ! if (classe.getDefinition().inInterfaceFile()) ! throw new Error("Constructors are loaded from the compiled package"); ! this.createBytecode(true); ! this.createBytecode(false); ! return notNull(instantiate); } ! /** ! @param omitDefaults if true, do not take the value of fields with ! default values as parameters, but use that default instead. ! */ ! private void createBytecode(boolean omitDefaults) { ! gnu.bytecode.ClassType thisType = cast(this.javaReturnType()); ! let thisDecl = new gnu.expr.Declaration("this"); ! thisDecl.setType(thisType); ! let thisExp = new gnu.expr.ThisExp(thisDecl); ! ! let fullArgs = notNull(parameters).getMonoSymbols(); ! let fullArgTypes = this.javaArgTypes(); ! ! List<MonoSymbol> args = new LinkedList(); ! List<gnu.bytecode.Type> argTypes = new LinkedList(); ! ! for (int i = 0; i < notNull(parameters).size; i++) ! { ! if (omitDefaults && notNull(parameters).hasDefaultValue(i)) ! continue; ! ! args.add(fullArgs[i]); ! argTypes.add(fullArgTypes[i]); ! } ! ! // Do not create a second constructor omiting defaults if there is ! // no default to omit! ! if (omitDefaults && args.size() == fullArgs.length) ! return; ! let argTypesArray = argTypes.toArray(); ! let argsArray = args.toArray(); ! let lambda = generateConstructor ! (thisDecl, argTypesArray, argsArray); ! lambda.setSuperCall(this.callSuper(thisExp, fullArgs, omitDefaults)); ! nice.tools.code.Gen.setMethodBody(lambda, this.body(thisExp, fullArgs, omitDefaults)); ! classe.getClassExp().addMethod(lambda); ! if (! omitDefaults) ! { ! initialize = new gnu.expr.QuoteExp(new gnu.expr.InitializeProc(lambda)); ! initializeFromConstructor = new gnu.expr.QuoteExp(new gnu.expr.InitializeProc(lambda, true)); ! instantiate = new gnu.expr.QuoteExp(new gnu.expr.InstantiateProc(lambda)); ! // Add attributes useful for the nice compiler. These are not needed ! // for the version omitting defaults, since that one is only there for ! // Java users' sake. ! lambda.addBytecodeAttribute(notNull(parameters).asBytecodeAttribute()); ! lambda.addBytecodeAttribute(new gnu.bytecode.MiscAttr("default")); ! } ! else ! { ! initializeOmitDefaults = new gnu.expr.QuoteExp(new gnu.expr.InitializeProc(lambda)); ! } } --- 43,86 ---- this.getCode(); return ! // compiledMini is null if the two versions are identical ! omitDefaults && compiledMini != null ! ? notNull(compiledMini).invoke : compiledFull.invoke; } ! void createFirstPass() { ! // We want to create bytecode methods in two passes to guarantee a ! // consistent behaviour in case versions with and without defaults omitted ! // clash. ! // Create the full version first. At the moment class methods are created ! // in reverse order, so they don't get the priority for unmangled names. ! compiledFull = new CompiledConstructor(constructor: this); ! compiledFull.createMethod(false); } ! computeCode() { ! if (classe.getDefinition().inInterfaceFile()) ! throw new Error("Constructors are loaded from the compiled package"); ! compiledMini = new CompiledConstructor(constructor: this).createMethod(true); ! // Add attributes useful for the nice compiler. These are not needed ! // for the version omitting defaults, since that one is only there for ! // Java users' sake. ! compiledFull.lambda.addBytecodeAttribute(notNull(parameters).asBytecodeAttribute()); ! compiledFull.lambda.addBytecodeAttribute(new gnu.bytecode.MiscAttr("default")); ! return notNull(compiledFull.instantiate); ! } ! compile() ! { ! this.getCode(); ! if (compiledMini != null) ! notNull(compiledMini).compileBody(true); ! compiledFull.compileBody(false); } *************** *** 180,181 **** --- 142,226 ---- (new gnu.expr.InitializeProc( notNull(gnu.bytecode.Type.pointer_type).getDeclaredMethod("<init>", 0))); + + /** + A wrapper for a bytecode version of this constructor. + + One instance of this class is used to hold the version with all parameters, + another one holds the version where fields with default values are omitted. + */ + private class CompiledConstructor + { + DefaultConstructor constructor; + + /** Call the constructor. */ + private gnu.expr.Expression invoke = cast(null); + + /** Call the constructor with an implicit this argument. */ + private ?gnu.expr.Expression initialization = null; + + /** Instantiate the class then call the constructor. */ + private ?gnu.expr.Expression instantiate = null; + + // Things that need to be remembered from the method constructor + // to the compilation of the body. + + gnu.expr.ConstructorExp lambda = cast(null); + + private MonoSymbol[] fullArgs = cast(null); + + /** + @param omitDefaults if true, do not take the value of fields with + default values as parameters, but use that default instead. + */ + private ?CompiledConstructor createMethod(boolean omitDefaults) + { + gnu.bytecode.ClassType thisType = cast(constructor.javaReturnType()); + let thisDecl = new gnu.expr.Declaration("this"); + thisDecl.setType(thisType); + + let parameters = constructor.parameters; + + fullArgs = notNull(parameters).getMonoSymbols(); + let fullArgTypes = constructor.javaArgTypes(); + + List<MonoSymbol> args = new LinkedList(); + List<gnu.bytecode.Type> argTypes = new LinkedList(); + + for (int i = 0; i < notNull(parameters).size; i++) + { + if (omitDefaults && notNull(parameters).hasDefaultValue(i)) + continue; + + args.add(fullArgs[i]); + argTypes.add(fullArgTypes[i]); + } + + // Do not create a second constructor omiting defaults if there is + // no default to omit! + if (omitDefaults && args.size() == fullArgs.length) + return null; + + lambda = generateConstructor(thisDecl, argTypes.toArray(), args.toArray()); + constructor.classe.getClassExp().addMethod(lambda); + + invoke = new gnu.expr.QuoteExp(new gnu.expr.InitializeProc(lambda)); + + if (! omitDefaults) + { + initialization = new gnu.expr.QuoteExp(new gnu.expr.InitializeProc(lambda, true)); + instantiate = new gnu.expr.QuoteExp(new gnu.expr.InstantiateProc(lambda)); + } + + return this; + } + + private void compileBody(boolean omitDefaults) + { + let thisExp = new gnu.expr.ThisExp(lambda.getThisDecl()); + + lambda.setSuperCall(constructor.callSuper(thisExp, fullArgs, omitDefaults)); + + nice.tools.code.Gen.setMethodBody + (lambda, constructor.body(thisExp, fullArgs, omitDefaults)); + } + } Index: niceclass.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/niceclass.nice,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** niceclass.nice 28 Feb 2005 14:00:58 -0000 1.23 --- niceclass.nice 1 Mar 2005 17:36:36 -0000 1.24 *************** *** 47,51 **** /** List of symbols for calling constructors of this class. */ private List<MethodSymbol> constructors = new ArrayList(); ! private Constructor[?] constructorMethod = null; // Used to resolve fields, and constructor constraint. --- 47,51 ---- /** List of symbols for calling constructors of this class. */ private List<MethodSymbol> constructors = new ArrayList(); ! private DefaultConstructor[?] constructorMethod = null; // Used to resolve fields, and constructor constraint. *************** *** 559,563 **** cst = mlsub.typing.Constraint.True; ! constructorMethod = cast(new Constructor[allConstructorParams.size()]); for (int i = 0; i < allConstructorParams.size(); i++) { --- 559,563 ---- cst = mlsub.typing.Constraint.True; ! constructorMethod = cast(new DefaultConstructor[allConstructorParams.size()]); for (int i = 0; i < allConstructorParams.size(); i++) { *************** *** 597,600 **** --- 597,608 ---- for (field : fields) field.createField(); + + // Creating constructor methods needs to be done even if we don't recompile + // since classes are always regenerated. + // We want to do it in two passes to guarantee a consistent behaviour + // in case versions with and without defaults omitted clash. + if (constructorMethod != null) + for (cm : notNull(constructorMethod)) + cm.createFirstPass(); } *************** *** 614,618 **** if (constructorMethod != null) for (cm : notNull(constructorMethod)) ! cm.getCode(); // Take into account external interface implementations, which --- 622,626 ---- if (constructorMethod != null) for (cm : notNull(constructorMethod)) ! cm.compile(); // Take into account external interface implementations, which Index: enum.nice =================================================================== RCS file: /cvsroot/nice/Nice/src/bossa/syntax/enum.nice,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** enum.nice 16 Jan 2005 21:51:15 -0000 1.17 --- enum.nice 1 Mar 2005 17:36:36 -0000 1.18 *************** *** 55,58 **** --- 55,60 ---- for (symbol : symbols) symbol.compileValue(); + + classDef.compile(); } |