summaryrefslogblamecommitdiff
path: root/sources/scalac/Global.java
blob: 801883ad25601538bc1f0ae1105a7821054eae45 (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                          
                                     
 

                                     

                            

                            



                                                    
                   
 
                                     
                                  

                                   
                                     
                                 


                                      
 

                           
                                      
                              
                                 
                                 
                            
                       
                            
                                 
                                             
                                                
                                        
                                
                                     
                     





                                            
                              





                                   
                                   
                                  

                                    
                                   
                                      
                                
                                  
                                       
                                      




                                     
                                 

                               



                                   
                 
       
                             
 











                                         







                                     



                                 

                               

                                         
 



                                                                          

                             
                                                                                 
 





                                                                         
                                                                 
 
 
                                      
       
                                      
 
                                                       
       
                                                                      
 

                                               
                                                                  
 

                         
                              






                                   
                                       


                           
                                      
 


                                               


                                          

                                           
                                                   

                                                         



                                            





                                            
                                             

                                                          

                              
                                

      
                                                     
                                 

                                                

     

                                     


                                                                       
                                                                        
 





                                    
                                                                         


                                                                       
                               
                         
                                        
                           
                                              
                                              

                                                 
                                              
                                        
                                             
                                                    
                                                     
                                                    


                                             
                                                               
                                      
















                                                                           
                                                                          
                                                            
                                                                                     
                                                
                            
             
                                          



                                                                                




                                                          


                                                              


                                                                      
         
                                             
                                 
                                                   
                                                             
                                                                              
                                                                           

                                                       

                                             
                                                                           

                                                                 
                                                                   
                                               
                                           
                                                                           




                                                                     
                                                  

     

                           

                             

                                         




                              

                                         

     

                                                                        
                                                                 



                                                                         
                                                           


                                                                 



                                                                           
                                                       




                                                                      

                                                                              

                                                                


                                   

                                          


                                                             

     

                                         
                                                                       



                                                 
                 
                                                            
                                                                      
                                          
                                             

                                                                                  

             

                                                                    

     





                                         
       
                                                                                      
                                 
                                                           
                                  

                                                                               



                                     
                                                                
                                                  
                            



                                              
                                     
                            




                                                                                


                            
                          
                                                   
                     
     
 

                                            

                                                                   
                                    

                                              
                                                                                       
                              
         

     






                                                                                 




                                                                  

     



                                                                                 



                                                       

                                             





                                                              

                                                



                                                     










                                                                      



                                                        

                                                       
                                         





                                                                             
                                      

                                                       
                                                         
                                       

                                                                   
 

                                                       
                                                                      

                                                       



                                                                    
                                     
                                                       
         

     

                                                       
                             

                                                                         
                                                                         
                               
                           
                              
                                         

                                         
 

                                  
                                                                                    














                                                                                  





                                                                                  
                           
                                           
                          
 
                                        


                                                 
                    

                                                   
                                                                                                
         
                    

     
                                             
                                





                                                                       
                                                       
                                      


                                 
 
                                        




                                                 
                                             


                                                    

                                                        
                                                                         
                                 
                                                 
                                                   
                                                            
                                                          
                                                     

                                                    
                                                                             
                                                         

                                        

                                                                      
                 


















                                                                     

                                      
                                                 
                        

                                            
                                                                     
                                           
                                
                                                                              

                                
                                                 
                        

                                            
                                                                     
                                                 
                                
                                                                           
                                                                  




                   



                                             

                                        
                                                                          

     
                                    














                                                                   

     
                                
 


                                       
                                      




                                         
                                        

     


                                           
                                                        





                                                                            
                    
                                                                               






                                                                   
                                                    

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

package scalac;

import ch.epfl.lamp.util.CodePrinter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.*;

import scala.tools.util.AbstractFile;
import scala.tools.util.ClassPath;
import scala.tools.util.Position;
import scala.tools.util.SourceFile;
import scala.tools.util.SourceReader;
import scala.tools.util.Reporter;
import scala.tools.util.Timer;
import scala.tools.util.DummyTimer;
import scala.tools.util.ReporterTimer;

import scalac.ast.*;
import scalac.ast.parser.*;
import scalac.ast.printer.TreePrinter;
import scalac.atree.AConstant;
import scalac.atree.ATreePrinter;
import scalac.backend.Primitives;
// !!! <<< Interpreter stuff
import scalac.symtab.*;
// !!! >>> Interpreter stuff
import scalac.symtab.Definitions;
import scalac.symtab.classfile.PackageParser;
import scalac.symtab.classfile.CLRPackageParser;
import scalac.typechecker.AnalyzerPhase;
import scalac.typechecker.Infer;
import scalac.transformer.ICodePhase;
import scalac.util.*;

/** The global environment of a compiler run
 *
 *  @author     Matthias Zenger
 *  @version    1.0
 */
public abstract class Global {

    public static Global instance;

    /** global options
     */
    public final boolean noimports;
    public final boolean nopredefs;
    public final boolean separate;
    //public final boolean optimize;
    public final boolean debug;
    public final boolean debuginfo;
    public final boolean explaintypes;
    public final boolean uniqid;
    public final boolean newMatch;
    public final boolean xmlPreserveWS;
    public final boolean runTimeTypes;

    public final boolean printtypes;
    public final boolean printtokens;

    public final String outpath;
    public final String encoding;
    public final String target;

    /** the message reporter
     */
    public final Reporter reporter;

    /** the timer
     */
    public final Timer timer;

    /** the source file charset
     */
    private final Charset charset;

    /** the source file decoder
     */
    private final CharsetDecoder decoder;

    /** the source file reader
     */
    private final SourceReader reader;

    /** the class path
     */
    public final ClassPath classPath;

    /** the global tree factory
     */
    public final TreeFactory make;

    /** the tree generator
     */
    public final TreeGen treeGen;

    /** the global tree printer
     */
    public final PrintWriter writer;
    public final TreePrinter treePrinter;

    /** documentation comments of symbols
     */
    public final Map/*<Symbol, String>*/ mapSymbolComment = new HashMap();

    /** attributes of symbols
     */
    protected final Map/*<Symbol, AttributeInfo>*/ mapSymbolAttr = new HashMap();

    /** views associated with (upper-bounded) type parameters
     */
    public final Map/*<Symbol, Symbol>*/ viewOfTypeParam = new HashMap();

    /** Pickled info of top-level symbols
     */
    public final Map/*<Symbol, Pickle>*/ symdata = new HashMap();


    /** The compiler command arguments
     */
    public final CompilerCommand args;

    /** The set of currently compiled top-level symbols
     */
    public HashMap/*<Symbol,Sourcefile>*/ compiledNow = new HashMap();

    /** The set of already compiled sourcefiles
     */
    private HashSet/*<SourceFile>*/ compiledUnits = new HashSet();

    /** the current phase
     */
    public Phase currentPhase;

    /** the global definitions
     */
    public Definitions definitions;

    /** the global primitives
     */
    public final Primitives primitives;

    /** compilation phases.
     */
    public final CompilerPhases PHASE;

    /** The current compilation loop or null */
    private CompilationLoop loop;

    /** compilation targets
     */
    public static final String TARGET_INT;
    public static final String TARGET_JVM;
    public static final String TARGET_MSIL;
    public static final String TARGET_JVMFROMICODE;

    public static final String[] TARGETS = new String[] {
        TARGET_INT          = "int",
        TARGET_JVM          = "jvm",
        TARGET_MSIL         = "msil",
	TARGET_JVMFROMICODE = "jvmfromicode"
    };

    /** tree printers
     */
    public static final String PRINTER_TEXT;
    public static final String PRINTER_HTML;
    public static final String PRINTER_SWING;

    public static final String[] PRINTERS = new String[] {
        PRINTER_TEXT = "text",
        PRINTER_HTML = "html",
	PRINTER_SWING = "swing",
    };

    public static Timer getTimer(Reporter reporter) {
        return reporter.verbose()
            ? (Timer)new ReporterTimer(reporter)
            : (Timer)DummyTimer.object;
    }

    /** hooks for installing printers
     */
    public abstract Infer newInfer();
    public abstract TreePrinter newTextTreePrinter(PrintWriter writer);
    public abstract TreePrinter newHTMLTreePrinter(PrintWriter writer);
    public abstract TreePrinter newSwingTreePrinter(PrintWriter writer);

    /**
     * Creates an instance variable.
     *
     * @param args
     * @param interpret
     */
    public Global(CompilerCommand args, Timer timer, boolean interpret) {
        assert Debug.initialize() || true;
        if (Global.instance != null) // jaco bug: can't use assert here
            /* throw */ Debug.abort("duplicate creation of Global");
        Global.instance = this;
        this.args = args;
        this.reporter = args.reporter();
        this.timer = timer;
        this.noimports = args.noimports.value;
        this.nopredefs = args.nopredefs.value;
        //this.optimize = args.optimize.optimize;
        this.debug = args.debug.value;
        this.debuginfo = args.debuginfo.value;
        this.uniqid = args.uniqid.value;
        this.newMatch = args.Xnewmatch.value;
        this.xmlPreserveWS = args.XpreserveWS.value;
        this.runTimeTypes = args.XrunTimeTypes.value;
        this.explaintypes = args.explaintypes.value;
        this.printtypes = args.types.value;
        this.printtokens = args.print.tokens;
        this.classPath = args.classpath();
	reporter.info(null, "classpath = " + classPath, false);
        this.outpath = args.outpath();
        String encoding = args.encoding.value;
        Charset charset = null;
        try {
            charset = Charset.forName(encoding);
        } catch (IllegalCharsetNameException exception) {
            args.encoding.error("illegal charset name '" + encoding + "'");
        } catch (UnsupportedCharsetException exception) {
            args.encoding.error("unsupported charset '" + encoding + "'");
        }
        if (charset == null) {
            encoding = "ISO-8859-1"; // A mandatory charset
            charset = Charset.forName(encoding);
        }
        this.encoding = encoding;
        this.charset = charset;
        this.decoder = charset.newDecoder();
        this.reader = new SourceReader(decoder);
        this.target = interpret ? TARGET_INT : args.target.value.intern();
        this.separate = args.separate.value.equals("yes") ||
            args.separate.value.equals("default") && !this.target.equals(TARGET_INT);
        String printFile = args.printfile.value;
        OutputStream stream;
        try {
            stream = "-".equals(printFile)
                ? System.out
                : new FileOutputStream(printFile);
        } catch (FileNotFoundException e) {
            error("unable to open file " + printFile + ". Printing on console");
            stream = System.out;
        }
        this.writer = new PrintWriter(stream, debug);
        if (args.printer.value.equals(PRINTER_HTML)) {
            this.treePrinter = newHTMLTreePrinter(writer);
	} else if (args.printer.value.equals(PRINTER_SWING)) {
	    this.treePrinter = newSwingTreePrinter(writer);
	} else {
            if (!args.printer.value.equals(PRINTER_TEXT))
                error("unknown printer kind: " +  args.printer.value);
            this.treePrinter = newTextTreePrinter(writer);
        }
        this.make = new DefaultTreeFactory();
        this.PHASE = args.phases;
        args.phases.WHOLEPROG.addSkipFlag(); // !!!
        // if (!optimize) PHASE.remove(args.phases.OPTIMIZE);
        // TODO: Enable TailCall for other backends when they handle LabelDefs
	if (target != TARGET_JVMFROMICODE) args.phases.ICODE.addSkipFlag();
        PHASE.freeze();
        PhaseDescriptor[] descriptors = PHASE.phases();
        int i = 0;
        for (; i < descriptors.length; i++) {
            if (!descriptors[i].hasSkipFlag()) descriptors[i].create(this);
            if (descriptors[i] == PHASE.ANALYZER) { i++; break; }
        }
        this.treeGen = ((AnalyzerPhase)PHASE.ANALYZER.phase()).gen;
        this.primitives = new Primitives(this);
        for (; i < descriptors.length; i++)
            if (!descriptors[i].hasSkipFlag()) descriptors[i].create(this);
        assert descriptors.length >= 2
            && descriptors[0] == PHASE.INITIAL
            && descriptors[descriptors.length - 1] == PHASE.TERMINAL:
            Debug.show(descriptors);
        assert !PHASE.INITIAL.hasSkipFlag();
        this.currentPhase = PHASE.INITIAL.phase();
    }

    /**
     * Moves to next phase.
     */
    public void nextPhase() {
        assert currentPhase.next != null;
        currentPhase = currentPhase.next;
    }

    /** Move to previous phase
     */
    public void prevPhase() {
        assert currentPhase.prev != null;
        currentPhase = currentPhase.prev;
    }

    /** Creates a virtual source file with given name and content. */
    public SourceFile getSourceFile(String sourcename, String content) {
        return new SourceFile(sourcename, content.toCharArray());
    }

    /** Reads and returns the source file in file with given name. */
    public SourceFile getSourceFile(String filename) throws IOException {
        AbstractFile file = AbstractFile.getFile(filename);
        if (file == null) throw new FileNotFoundException(
            "source file '" + filename + "' could not be found");
        return getSourceFile(file);
    }

    /** Reads and returns the source file in given abstract file. */
    public SourceFile getSourceFile(AbstractFile file) throws IOException {
        return new SourceFile(file, reader.read(file));
    }

    /** Reads and returns the source file of given clasz. */
    public SourceFile getSourceFile(Symbol clasz) throws IOException {
        assert clasz.isClass() && clasz.isStatic(): Debug.show(clasz);
        AbstractFile file = classPath.getRoot().lookupPath(
            SourceRepresentation.externalizeFileName(clasz, ".scala"), false);
        if (file == null) throw new FileNotFoundException(
            "source file for " + clasz + " could not be found");
        return getSourceFile(file);
    }

    /** Returns the root symbol loader. */
    public SymbolLoader getRootLoader() {
        return target == TARGET_MSIL
            ? new CLRPackageParser(this, classPath.getRoot())
            : new PackageParser(this, classPath.getRoot());
    }

    /** the top-level compilation process
     */
    public CompilationUnit[] compile(String[] files, boolean console) {
        reporter.resetCounters();
        // parse files
        List units = new ArrayList(files.length);
        for (int i = 0; i < files.length; i++) {
            try {
		SourceFile source = getSourceFile(files[i]);
                units.add(new CompilationUnit(this, source, console));
		compiledUnits.add(source);
            } catch (IOException exception) {
                error("IO problem (encoding problem?) with file "+files[i]
                                    +"\n exception was: "+exception.getMessage());
            }
        }
        CompilationUnit[] array = new CompilationUnit[units.size()];
        return compile((CompilationUnit[])units.toArray(array));
    }

    /**
     * The top-level compilation process.
     *
     * @param filename
     * @param input
     * @param console
     */
    public CompilationUnit[] compile(String filename, String input, boolean console) {
        reporter.resetCounters();
        SourceFile source = getSourceFile(filename, input);
	compiledUnits.add(source);
        CompilationUnit[] units = {new CompilationUnit(this, source, console)};
        return compile(units);
    }

    /** compile all compilation units
     */
    private CompilationUnit[] compile(CompilationUnit[] units) {
        this.currentPhase = PHASE.INITIAL.phase();
        treePrinter.begin();
        this.loop = new CompilationLoop(this);
        loadFunctions();
        units = loop.compile(units);
        this.loop = null;
        if (reporter.errors() != 0) {
            imports.clear();
            for (Iterator i = compiledNow.entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry)i.next();
                Symbol clasz = (Symbol)entry.getKey();
                AbstractFile file = ((SourceFile)entry.getValue()).getFile();
                clasz.reset(new SourceCompleter(this, file));
            }
        }
        compiledNow.clear();
        treePrinter.end();
        this.currentPhase = PHASE.TERMINAL.phase();
        return units;
    }

    protected abstract void loadFunctions();

    /** Compiles an additional source file. */
    public void compileLate(SourceFile source, boolean mixinOnly) {
        assert loop != null: source;
	if (!compiledUnits.contains(source)) {
	    compiledUnits.add(source);
	    CompilationUnit unit = new CompilationUnit(this, source, false, mixinOnly);
            loop.insert(unit);
	}
    }


    /** Add attribute for a symbol
     *  @param sym - symbol of the defininition to which the attribute is applied
     *  @param aSym - symbol of the constructor of the attribute class
     *  @param args - arguments to the attribute constructor
     */
    public void addAttribute(Symbol sym, Symbol aSym, AConstant[] args) {
        if (aSym != null && ! (aSym.isNone() || aSym.isError())) {
            AttributeInfo attr = getAttributes(sym);
            attr = new AttributeInfo(aSym, args, attr);
            setAttribute(sym, attr);
        }
    }

    /** Add attribute with no arguments
     *  @param sym - symbol of the defininition to which the attribute is applied
     *  @param aSym - symbol of the constructor of the attribute class
     */
    public void addAttribute(Symbol sym, Symbol aSym) {
        addAttribute(sym, aSym, AConstant.EMPTY_ARRAY);
    }

    /** Set the attributes for a given symbol
     */
    public void setAttribute(Symbol sym, AttributeInfo attr) {
        mapSymbolAttr.put(sym, attr);
        if (sym.isModule() && !sym.isModuleClass())
            mapSymbolAttr.put(sym.moduleClass(), attr);
    }

    /** Return all attributes for a given symbol
     */
    public AttributeInfo getAttributes(Symbol sym) {
        return (AttributeInfo)mapSymbolAttr.get(sym);
    }

    /** Return attribute arguments
     *  @param sym - symbol of the definition
     *  @param aSym - symbol of the constructor of the attribute class
     */
    public AConstant[] getAttrArguments(Symbol sym, Symbol aSym) {
        AttributeInfo attrs = getAttributes(sym);
        return attrs == null ? null : attrs.getAttrArguments(aSym);
    }

    /** Remove the attributes for a given symbol
     */
    public AttributeInfo removeAttributes(Symbol sym) {
        return (AttributeInfo)mapSymbolAttr.remove(sym);
    }

    public abstract void dump(CompilationUnit[] units);

    void print(CompilationUnit[] units) {
        if (currentPhase.id == PHASE.MAKEBOXINGEXPLICIT.id()) {
            boolean html = args.printer.value.equals(PRINTER_HTML);
            if (html) writer.println("<pre>");
            ATreePrinter printer = new ATreePrinter(new CodePrinter(writer));
            boolean next = currentPhase.next != null;
            if (next) currentPhase = currentPhase.next;
            printer.printUnits(units);
            if (next) currentPhase = currentPhase.prev;
            if (html) writer.println("</pre>");
        } else if (currentPhase.id == PHASE.ICODE.id()) {
            Phase phase = currentPhase;
            boolean html = args.printer.value.equals(PRINTER_HTML);
            if (html) writer.println("<pre>");

            boolean next = currentPhase.next != null;
            if (next) currentPhase = currentPhase.next;
            ((ICodePhase)phase).print(units, new CodePrinter(writer));
            if (next) currentPhase = currentPhase.prev;
            if (html) writer.println("</pre>");
        } else {
            // go to next phase to print symbols with their new type
            boolean next = currentPhase.next != null;
            if (next) currentPhase = currentPhase.next;
            treePrinter.print(units);
            if (next) currentPhase = currentPhase.prev;
        }
    }

    // !!! <<< Interpreter stuff
    public static final String CONSOLE_S = "$console$";
    private static final Name
        SHOW_DEFINITION_N       = Name.fromString("showDefinition"),
        SHOW_VALUE_DEFINITION_N = Name.fromString("showValueDefinition"),
        SET_EVALUATION_RESULT_N = Name.fromString("setEvaluationResult");
    private Symbol INTERPRETER;
    private Symbol PRINTER;
    private Symbol SHOW_VALUE;
    private Symbol SET_EVALUATION_RESULT;
    private Symbol SHOW_DEFINITION;
    private Symbol SHOW_VALUE_DEFINITION;

    private Symbol INTERPRETER() {
        if (INTERPRETER == null)
            INTERPRETER = definitions.getModule("scala.runtime.InterpreterSupport");
        return INTERPRETER;
    }

    private Symbol SHOW_DEFINITION() {
        if (SHOW_DEFINITION == null)
            SHOW_DEFINITION = INTERPRETER().lookup(SHOW_DEFINITION_N);
        return SHOW_DEFINITION;
    }

    private Symbol SHOW_VALUE_DEFINITION() {
        if (SHOW_VALUE_DEFINITION == null)
            SHOW_VALUE_DEFINITION = INTERPRETER().lookup(SHOW_VALUE_DEFINITION_N);
        return SHOW_VALUE_DEFINITION;
    }

    private Symbol SET_EVALUATION_RESULT() {
        if (SET_EVALUATION_RESULT == null)
            SET_EVALUATION_RESULT = INTERPRETER().lookup(SET_EVALUATION_RESULT_N);
        return SET_EVALUATION_RESULT;
    }

    private int module = 0;
    private List imports = new ArrayList();
    public Symbol console;

    void fix1(CompilationUnit[] units) {
        for (int i = 0; i < units.length; i++) {
            if (units[i].console) fix1(units[i]);
        }
        nextPhase();
        for (int i = 0; i < imports.size(); i++) {
            Symbol module = (Symbol)imports.get(i);
            ((scalac.typechecker.AnalyzerPhase)PHASE.ANALYZER.phase()).addConsoleImport(module);
        }
        prevPhase();
    }

    private void fix1(CompilationUnit unit) {
        unit.body = new Tree[] {
            make.ModuleDef(Position.FIRSTPOS,
                0, Name.fromString(CONSOLE_S+module), Tree.Empty,
                make.Template(Position.FIRSTPOS, new Tree[]{
                    make.Apply(Position.FIRSTPOS,
                        make.Select(Position.FIRSTPOS,
                            make.Ident(Position.FIRSTPOS, Names.scala),
                            Names.AnyRef.toTypeName()),
                        new Tree[0])},
                    unit.body))};
        module++;
    }

    void fix2(CompilationUnit[] units) {
        for (int i = 0; i < units.length; i++) {
            if (units[i].console) fix2(units[i]);
        }
    }

    private void fix2(CompilationUnit unit) {
        imports.clear();
        for (int i = 0; i < unit.body.length; i++) {
            switch (unit.body[i]) {
            case ModuleDef(_, _, _, Tree.Template impl):
                Symbol symbol = unit.body[i].symbol();
                if (!symbol.name.toString().startsWith(CONSOLE_S)) break;
                console = symbol;
                if (impl.body.length <= 0) break;
                imports.add(unit.body[i].symbol());
                Tree last = impl.body[impl.body.length - 1];
                if (last != Tree.Empty && last.isTerm()) {
                    impl.body[impl.body.length - 1] =
                        treeGen.Apply(last.pos,
                            treeGen.Select(last.pos,
                                treeGen.mkGlobalRef(last.pos, INTERPRETER()),
                                SET_EVALUATION_RESULT()),
                            new Tree[] {
                                last,
                                treeGen.mkStringLit(
                                    last.pos, show(last.getType()))});
                }
                TreeList body = new TreeList();
                for (int j = 0; j < impl.body.length; j++)
                    fix2(body, impl.body[j]);
                impl.body = body.toArray();
                break;
            }
        }
    }

    private void fix2(TreeList body, Tree tree) {
        body.append(tree);
        switch (tree) {
        case PatDef(_, _, _): // !!! impossible (removed by analyzer)
            assert false : Debug.show(tree);
            return;
        case ClassDef(_, _, _, _, _, _):
        case PackageDef(_, _):
        case ModuleDef(_, _, _, _):
        case DefDef(_, _, _, _, _, _):
        case AbsTypeDef(_, _, _, _):
        case AliasTypeDef(_, _, _, _):
            if (!mustShow(tree.symbol())) return;
            body.append(
                treeGen.Apply(tree.pos,
                    treeGen.Select(tree.pos,
                        treeGen.mkGlobalRef(tree.pos, INTERPRETER()),
                        SHOW_DEFINITION()),
                    new Tree[] {
                        treeGen.mkStringLit(tree.pos, show(tree.symbol()))}));
            return;
        case ValDef(_, _, _, _):
            if (!mustShow(tree.symbol())) return;
            body.append(
                treeGen.Apply(tree.pos,
                    treeGen.Select(tree.pos,
                        treeGen.mkGlobalRef(tree.pos, INTERPRETER()),
                        SHOW_VALUE_DEFINITION()),
                    new Tree[] {
                        treeGen.mkStringLit(tree.pos, show(tree.symbol())),
                        treeGen.Ident(tree.pos, tree.symbol())}));
            return;
        default:
            return;
        }
    }

    private boolean mustShow(Symbol symbol) {
        return !symbol.isAccessor();
    }

    private String show(Symbol symbol) {
        return new InterpreterPrinter().printSignature(symbol).toString();
    }

    private String show(Type type) {
        return new InterpreterPrinter().printType(type).toString();
    }

    private class InterpreterPrinter extends SymbolTablePrinter {
        public InterpreterPrinter() {
            super("  ");
        }
        public String getSymbolName(Symbol symbol) {
            String string = super.getSymbolName(symbol);
            if (!debug) {
                int index = string.indexOf('$');
                if (index > 0) string = string.substring(0, index);
            }
            return string;
        }
    }

    // !!! >>> Interpreter stuff

    /** issue a global error
     */
    public void error(String message) {
        reporter.error(null, message);
    }

    /** issue a global warning
     */
    public void warning(String message) {
        reporter.warning(null, message);
    }

    /** issue an operation note
     */
    public void operation(String message) {
        reporter.info(null, "[" + message + "]", false);
    }

    /** issue a debug message from currentPhase
     */
    // the boolean return value is here to let one write "assert log( ... )"
    public boolean log(String message) {
        if (log()) {
            reporter.info(null, "[log " + currentPhase + "] " + message, true);
        }
        return true;
    }

    /** return true if logging is switched on for the current phase
     */
    public boolean log() {
        return currentPhase.descriptor.hasLogFlag();
    }

}