summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/CodeFactory.java
blob: ee501e692f36a24c9b8e2a13af0fab45125ca317 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                          




                                       
                                        
 

                                              
                       



                              

                                










                                                         
                                                           



                       
                                                             
                                          
                                                                  

       
                                          
                                        
                                           

     

                                                    
                                                                           

     






                                                                           


                                                         
                                                               

                                                                       

     
                                        
       

                                                                      
                                                           
 

                                                                                   
 







                                                              
                                                                

                        
                                      

                             
                                                                                   
         
 

     


                                    
                                                                     

     
                      
       
                                       
                                                                        



                      
                                           
                                                                             
     
 


                                        
                                                                      

       
                                                           

                                                                    


                                                            

                                                                    


     
                                                       
                                                                




                                   
                                                                

     

                                      



                                                                           
                                                                  
        
 

                                               

                                                                  

                        

                                                             
         
                                                                                      



                                              

                                                                  

                        

                                                              
         
                                                                                     


                                                  

                                                                       


                                                        
                             
                                                                    




                                                                       

     

                                            
                                                           


                                           
                                                                    

                                                                                    


     
 
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.transformer.matching;

import ch.epfl.lamp.util.Position;

import scalac.*;
import scalac.ast.*;
import scalac.util.*;
import scalac.symtab.*;
import PatternNode.*;
import Tree.*;

class CodeFactory extends PatternTool {

    public int pos = Position.FIRSTPOS ;

    public CodeFactory( Unit unit, int pos ) {
	super( unit );
	this.pos = pos;
    }

    // --------- these are new

    /** a faked switch statement
     */
    Tree Switch( Tree selector,
		 Tree condition[],
		 Tree body[],
		 Tree defaultBody ) {
	assert selector != null:"selector is null";
	assert condition != null:"cond is null";
	assert body != null:"body is null";
	assert defaultBody != null:"defaultBody is null";
	Tree result = defaultBody;

	for( int i = condition.length-1; i >= 0; i-- )
	    result = gen.If(condition[i], body[i], result);

	return result ;
    }

    /** returns  `List[ Tuple2[ scala.Int, <elemType> ] ]' */
      Type SeqTraceType( Type elemType ) {
          return defs.listType(pairType(defs.INT_TYPE, elemType));
      }

    /**  returns `Iterator[ elemType ]' */
    Type _seqIterType( Type elemType ) {
        return defs.iteratorType(elemType);
    }

    /**  returns `<seqObj.elements>' */
    Tree newIterator( Tree seqObj, Type elemType ) {
	return gen.mkApply__(gen.Select(seqObj, defs.ITERABLE_ELEMENTS()));
    }

    /** returns code `<seqObj>.elements'
     *  the parameter needs to have type attribute `Sequence[<elemType>]'
     */
    Tree newIterator( Tree seqObj ) {
	return newIterator( seqObj, getElemType_Sequence( seqObj.type() ));
    }

    // EXPERIMENTAL
    Tree newRef( Tree init ) {
	//System.out.println( "hello:"+refSym().type() );
	return gen.New(gen.mkPrimaryConstr(pos, defs.REF_CLASS,
			                    new Type[] { init.type() },
			                    new Tree[] { init } ));
    }

    /** returns A for T <: Sequence[ A ]
     */
    Type getElemType_Sequence( Type tpe ) {
	//System.err.println("getElemType_Sequence("+tpe.widen()+")");
	Type tpe1 = tpe.widen().baseType( defs.SEQ_CLASS );

	if( tpe1 == Type.NoType )
	    throw new ApplicationError("arg "+tpe+" not subtype of Sequence[ A ]");

	return tpe1.typeArgs()[ 0 ];
    }

    /** returns A for T <: Iterator[ A ]
     */
    Type getElemType_Iterator( Type tpe ) {
	//System.err.println("getElemType_Iterator("+tpe+")");

	Type tpe1 = tpe.widen().baseType( defs.ITERATOR_CLASS );

	switch( tpe1 ) {
	case TypeRef(_,_,Type[] args):
	    return args[ 0 ];
	default:
	    throw new ApplicationError("arg "+tpe+" not subtype of Iterator[ A ]");
	}

    }

    /** `it.next()'
     */
    public Tree _next( Tree iter ) {
	return gen.mkApply__(gen.Select(iter, defs.ITERATOR_NEXT()));
    }

    /** `it.hasNext()'
     */
    public Tree _hasNext( Tree iter ) {
	return gen.mkApply__(gen.Select(iter, defs.ITERATOR_HASNEXT()));
    }

    /** `!it.hasCur()'
     */
    public Tree _not_hasNext( Tree iter ) {
	return gen.mkApply__(gen.Select(_hasNext(iter), defs.BOOLEAN_NOT()));
    }

      /** `trace.isEmpty'
       */
      public Tree isEmpty( Tree iter ) {
          return gen.mkApply__(gen.Select(iter, defs.LIST_ISEMPTY()));
      }

    Tree SeqTrace_headElem( Tree arg ) { // REMOVE SeqTrace
	Tree t = gen.mkApply__(gen.Select(arg, defs.LIST_HEAD()));
	return gen.mkApply__(gen.Select(t, defs.TUPLE_FIELD(2, 2)));
    }

    Tree SeqTrace_headState( Tree arg ) { // REMOVE SeqTrace
	Tree t = gen.mkApply__(gen.Select(arg, defs.LIST_HEAD()));
	return gen.mkApply__(gen.Select(t, defs.TUPLE_FIELD(2, 1)));

    }

    Tree SeqTrace_tail( Tree arg ) { // REMOVE SeqTrace
	return gen.mkApply__(gen.Select(arg, defs.LIST_TAIL()));
    }

    /** `<seqlist>.head()'
     */
    Tree SeqList_head( Tree arg ) {
	return gen.mkApply__(gen.Select(arg, defs.LIST_HEAD()));
    }

     // unused
       public Tree Negate(Tree tree) {
       switch (tree) {
       case Literal(Object value):
       return gen.mkBooleanLit(tree.pos, !((Boolean)value).booleanValue());
       }
       return gen.mkApply__(gen.Select(tree, defs.BOOLEAN_NOT()));
       }

    protected Tree And(Tree left, Tree right) {
        switch (left) {
	case Literal(Object value):
	    return ((Boolean)value).booleanValue() ? right : left;
        }
        switch (right) {
	case Literal(Object value):
	    if (((Boolean)value).booleanValue()) return left;
        }
        return gen.mkApply_V(gen.Select(left, defs.BOOLEAN_AND()), new Tree[]{right});
    }

    protected Tree Or(Tree left, Tree right) {
        switch (left) {
	case Literal(Object value):
	    return ((Boolean)value).booleanValue() ? left : right;
        }
        switch (right) {
	case Literal(Object value):
	    if (!((Boolean)value).booleanValue()) return left;
        }
        return gen.mkApply_V(gen.Select(left, defs.BOOLEAN_OR()), new Tree[]{right});
    }

    protected Tree Equals(Tree left, Tree right) {
        Symbol fun = unit.global.definitions.EQEQ;
        return gen.mkApply_V(gen.Select(left, fun), new Tree[]{right});
    }

    protected Tree ThrowMatchError(int pos, Type type) {
        return gen.mkApplyTV(
			     gen.mkRef(pos, defs.MATCHERROR_FAIL()),
                             new Tree[]{gen.mkType(pos, type)},
                             new Tree[]{
                                 gen.mkStringLit(pos, unit.toString()),
                                 gen.mkIntLit(pos, Position.line(pos))
                             });
    }


    Type pairType( Type left, Type right ) {
	return defs.tupleType(new Type[] { left, right } );
    }

    Tree newPair( Tree left, Tree right ) {
 	return gen.New(gen.mkPrimaryConstr(pos, defs.TUPLE_CLASS[2],
			                   new Type[] { left.type(), right.type() },
			                   new Tree[] { left, right }));

    }

}