Nice/src/bossa/syntax niceclass.nice,1.23,1.24 enum.nice,1.17,1.18 defaultconstructor.nice,1.5,1.6

Daniel Bonniot <[email protected]>
Newsgroups gmane.comp.lang.nice.cvs
Message-ID <[email protected]>
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();
    }
  



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.