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

package scalac;

import ch.epfl.lamp.util.Position;
import ch.epfl.lamp.util.SourceFile;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import scalac.ast.*;
import scalac.ast.parser.*;
import scalac.ast.printer.*;
import scalac.backend.Primitives;
// !!! <<< Interpreter stuff
import scalac.symtab.*;
// !!! >>> Interpreter stuff
import scalac.symtab.Definitions;
import scalac.util.*;

/** The global environment of a compiler run
 *
 *  @author     <NAME>
 *  @version    1.0
 */
public 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 explaintypes;
    public final boolean uniqid;

    public final boolean printtypes;
    public final boolean printtokens;

    public final String outpath;
    public final String target;

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

    /** a stack for maintaining timestamps
     */
    private final Stack startTimes = new Stack();

    /** all compilation units
     */
    public Unit[] units;

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

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

    /** the fresh name creator
     */
    public final FreshNameCreator freshNameCreator;

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

    /** the unique-id generator
     */
    public final UniqueID uniqueID;

    /** the global tree printer
     */
    public final TreePrinter printer;
    public OutputStream printStream;
    public final TreePrinter debugPrinter;

    /** documentation comments of trees
     */
    public final Map/*<Tree, String>*/ mapTreeComment = new HashMap();

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

    public final Map/*<FullName, Pickle>*/ symdata = new HashMap();

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

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

    /** the first phase
     */
    private final Phase firstPhase;

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

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

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

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

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

    public static final String[] TARGETS = new String[] {
        TARGET_INT      = "int".intern(),
        TARGET_JVM      = "jvm".intern(),
        TARGET_JVM_BCEL = "jvm-bcel".intern(),
        TARGET_MSIL     = "msil".intern(),
    };

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

    public static final String[] PRINTERS = new String[] {
        PRINTER_TEXT = "text".intern(),
        PRINTER_HTML = "html".intern(),
    };

    /**
     * Creates an instance variable.
     *
     * @param args
     */
    public Global(CompilerCommand args) {
        this(args, false);
    }

    /**
     * Creates an instance variable.
     *
     * @param args
     * @param interpret
     */
    public Global(CompilerCommand args, boolean interpret) {
        if (Global.instance != null) { // jaco bug: can't use assert here
            new Error("Duplicate creation of Global").printStackTrace();
            System.exit(1);
        };
        Global.instance = this;
        this.args = args;
        this.reporter = args.reporter();
        this.start(); // timestamp to compute the total time
        this.noimports = args.noimports.value;
        this.nopredefs = args.nopredefs.value;
        //this.optimize = args.optimize.optimize;
        this.debug = args.debug.value;
        this.uniqid = args.uniqid.value;
        this.explaintypes = args.explaintypes.value;
        this.printtypes = args.types.value;
        this.printtokens = args.print.tokens;
        this.classPath = args.classpath();
        this.outpath = args.outpath();
        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);
        this.uniqueID = new UniqueID();
        String printFile = args.printfile.value;
        try {
            this.printStream = "-".equals(printFile)
                ? System.out
                : new FileOutputStream(printFile);
        } catch (FileNotFoundException e) {
            error("unable to open file " + printFile + ". Printing on console");
            this.printStream = System.out;
        }
        String printerName = args.printer.value.intern();
        if (printerName == PRINTER_TEXT)
            this.printer = new TextTreePrinter(printStream);
        else
            this.printer = new HTMLTreePrinter(printStream);
        this.debugPrinter = new TextTreePrinter(System.err, true);
        this.freshNameCreator = new FreshNameCreator();
        this.make = new DefaultTreeFactory();
        this.PHASE = args.phases;
        // if (!optimize) PHASE.remove(args.phases.OPTIMIZE);
	// TODO: Enable TailCall for other backends when they handle LabelDefs
        if (target != TARGET_JVM) args.phases.TAILCALL.addSkipFlag();
        if (target != TARGET_MSIL) args.phases.GENMSIL.addSkipFlag();
        if (target != TARGET_JVM) args.phases.GENJVM.addSkipFlag();
        if (target != TARGET_JVM_BCEL) args.phases.GENJVM_BCEL.addSkipFlag();
        PHASE.freeze();
        PhaseDescriptor[] descriptors = PHASE.phases();
        this.firstPhase = descriptors[0].create(this);
        this.definitions = new Definitions(this);
        this.primitives = new Primitives(this);
        this.treeGen = new TreeGen(this, make);
        assert !descriptors[0].hasSkipFlag();
        for (int i = 1; i < descriptors.length; i++)
            if (!descriptors[i].hasSkipFlag()) descriptors[i].create(this);
        this.currentPhase = firstPhase;
    }

    /** Returns the first compilation phase. */
    public Phase getFirstPhase() {
        return firstPhase;
    }

    /**
     * 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;
    }

    /** the top-level compilation process
     */
    public void compile(String[] files, boolean console) {
        reporter.resetCounters();
        // parse files
        List units = new ArrayList(files.length);
        for (int i = 0; i < files.length; i++) {
            String file = files[i];
            try {
                units.add(new Unit(this, new SourceFile(file), console));
            } catch (FileNotFoundException e) {
                error("file " + file + " not found");
            } catch (IOException e) {
                error(e.toString());
            }
        }
        this.units = (Unit[])units.toArray(new Unit[units.size()]);
        compile();
    }

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

    /** compile all compilation units
     */
    private void compile() {
        printer.begin();

        currentPhase = firstPhase;
        // apply successive phases and pray that it works
        while (currentPhase.next != null && reporter.errors() == 0) {
            currentPhase = currentPhase.next;
            start();
            currentPhase.apply(units);
            stop(currentPhase.descriptor.taskDescription());
            if (currentPhase.descriptor.hasPrintFlag())
                currentPhase.print(this);
            if (currentPhase.descriptor.hasGraphFlag())
                currentPhase.graph(this);
            if (currentPhase.descriptor.hasCheckFlag())
                currentPhase.check(this);
            if (currentPhase == PHASE.PARSER.phase()) fix1();
            if (currentPhase == PHASE.ANALYZER.phase()) fix2();
        }
        if (reporter.errors() != 0) {
            imports.clear();
            for (Iterator it = compiledNow.keySet().iterator(); it.hasNext();) {
                Symbol sym = (Symbol) it.next();
                sym.reset(new SourceCompleter(this));
            }
        }
	symdata.clear();
        compiledNow.clear();
        printer.end();
    }

    /** transform a unit and stop at the current compilation phase
     */
    public void transformUnit(Unit unit) {
       	Phase oldCurrentPhase = currentPhase;
        currentPhase = PHASE.ANALYZER.phase().next; // or REFCHECK.next?
        while ((currentPhase.id < oldCurrentPhase.id) && (reporter.errors() == 0)) {
            start();
            currentPhase.apply(new Unit[] {unit}); // !!! pb with Analyzer
            stop(currentPhase.descriptor.taskDescription());
            if (currentPhase.descriptor.hasPrintFlag())
                currentPhase.print(this);
            if (currentPhase.descriptor.hasGraphFlag())
                currentPhase.graph(this);
            if (currentPhase.descriptor.hasCheckFlag())
                currentPhase.check(this);
            currentPhase = currentPhase.next;
        }
        currentPhase = oldCurrentPhase;
    }

    // !!! <<< Interpreter stuff
    public static final String CONSOLE_S = "$console$";
    private static final Name
        CONSOLE_N               = Name.fromString(CONSOLE_S),
        INTERPRETER_N           = Name.fromString("scala.runtime.InterpreterSupport"),
        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() {<commit_msg>- Added a phase change before printing to get r...<commit_after>/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac;

import ch.epfl.lamp.util.Position;
import ch.epfl.lamp.util.SourceFile;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import scalac.ast.*;
import scalac.ast.parser.*;
import scalac.ast.printer.*;
import scalac.backend.Primitives;
// !!! <<< Interpreter stuff
import scalac.symtab.*;
// !!! >>> Interpreter stuff
import scalac.symtab.Definitions;
import scalac.util.*;

/** The global environment of a compiler run
 *
 *  @author     <NAME>
 *  @version    1.0
 */
public 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 explaintypes;
    public final boolean uniqid;

    public final boolean printtypes;
    public final boolean printtokens;

    public final String outpath;
    public final String target;

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

    /** a stack for maintaining timestamps
     */
    private final Stack startTimes = new Stack();

    /** all compilation units
     */
    public Unit[] units;

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

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

    /** the fresh name creator
     */
    public final FreshNameCreator freshNameCreator;

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

    /** the unique-id generator
     */
    public final UniqueID uniqueID;

    /** the global tree printer
     */
    public final TreePrinter printer;
    public OutputStream printStream;
    public final TreePrinter debugPrinter;

    /** documentation comments of trees
     */
    public final Map/*<Tree, String>*/ mapTreeComment = new HashMap();

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

    public final Map/*<FullName, Pickle>*/ symdata = new HashMap();

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

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

    /** the first phase
     */
    private final Phase firstPhase;

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

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

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

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

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

    public static final String[] TARGETS = new String[] {
        TARGET_INT      = "int".intern(),
        TARGET_JVM      = "jvm".intern(),
        TARGET_JVM_BCEL = "jvm-bcel".intern(),
        TARGET_MSIL     = "msil".intern(),
    };

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

    public static final String[] PRINTERS = new String[] {
        PRINTER_TEXT = "text".intern(),
        PRINTER_HTML = "html".intern(),
    };

    /**
     * Creates an instance variable.
     *
     * @param args
     */
    public Global(CompilerCommand args) {
        this(args, false);
    }

    /**
     * Creates an instance variable.
     *
     * @param args
     * @param interpret
     */
    public Global(CompilerCommand args, boolean interpret) {
        if (Global.instance != null) { // jaco bug: can't use assert here
            new Error("Duplicate creation of Global").printStackTrace();
            System.exit(1);
        };
        Global.instance = this;
        this.args = args;
        this.reporter = args.reporter();
        this.start(); // timestamp to compute the total time
        this.noimports = args.noimports.value;
        this.nopredefs = args.nopredefs.value;
        //this.optimize = args.optimize.optimize;
        this.debug = args.debug.value;
        this.uniqid = args.uniqid.value;
        this.explaintypes = args.explaintypes.value;
        this.printtypes = args.types.value;
        this.printtokens = args.print.tokens;
        this.classPath = args.classpath();
        this.outpath = args.outpath();
        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);
        this.uniqueID = new UniqueID();
        String printFile = args.printfile.value;
        try {
            this.printStream = "-".equals(printFile)
                ? System.out
                : new FileOutputStream(printFile);
        } catch (FileNotFoundException e) {
            error("unable to open file " + printFile + ". Printing on console");
            this.printStream = System.out;
        }
        String printerName = args.printer.value.intern();
        if (printerName == PRINTER_TEXT)
            this.printer = new TextTreePrinter(printStream);
        else
            this.printer = new HTMLTreePrinter(printStream);
        this.debugPrinter = new TextTreePrinter(System.err, true);
        this.freshNameCreator = new FreshNameCreator();
        this.make = new DefaultTreeFactory();
        this.PHASE = args.phases;
        // if (!optimize) PHASE.remove(args.phases.OPTIMIZE);
	// TODO: Enable TailCall for other backends when they handle LabelDefs
        if (target != TARGET_JVM) args.phases.TAILCALL.addSkipFlag();
        if (target != TARGET_MSIL) args.phases.GENMSIL.addSkipFlag();
        if (target != TARGET_JVM) args.phases.GENJVM.addSkipFlag();
        if (target != TARGET_JVM_BCEL) args.phases.GENJVM_BCEL.addSkipFlag();
        PHASE.freeze();
        PhaseDescriptor[] descriptors = PHASE.phases();
        this.firstPhase = descriptors[0].create(this);
        this.definitions = new Definitions(this);
        this.primitives = new Primitives(this);
        this.treeGen = new TreeGen(this, make);
        assert !descriptors[0].hasSkipFlag();
        for (int i = 1; i < descriptors.length; i++)
            if (!descriptors[i].hasSkipFlag()) descriptors[i].create(this);
        this.currentPhase = firstPhase;
    }

    /** Returns the first compilation phase. */
    public Phase getFirstPhase() {
        return firstPhase;
    }

    /**
     * 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;
    }

    /** the top-level compilation process
     */
    public void compile(String[] files, boolean console) {
        reporter.resetCounters();
        // parse files
        List units = new ArrayList(files.length);
        for (int i = 0; i < files.length; i++) {
            String file = files[i];
            try {
                units.add(new Unit(this, new SourceFile(file), console));
            } catch (FileNotFoundException e) {
                error("file " + file + " not found");
            } catch (IOException e) {
                error(e.toString());
            }
        }
        this.units = (Unit[])units.toArray(new Unit[units.size()]);
        compile();
    }

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

    /** compile all compilation units
     */
    private void compile() {
        printer.begin();

        currentPhase = firstPhase;
        // apply successive phases and pray that it works
        while (currentPhase.next != null && reporter.errors() == 0) {
            currentPhase = currentPhase.next;
            start();
            currentPhase.apply(units);
            stop(currentPhase.descriptor.taskDescription());
            if (currentPhase.descriptor.hasPrintFlag()) {
                // go to next phase to print symbols with their new type
                boolean next = currentPhase.next != null;
                if (next) currentPhase = currentPhase.next;
                currentPhase.print(this);
                if (next) currentPhase = currentPhase.prev;
            }
            if (currentPhase.descriptor.hasGraphFlag())
                currentPhase.graph(this);
            if (currentPhase.descriptor.hasCheckFlag())
                currentPhase.check(this);
            if (currentPhase == PHASE.PARSER.phase()) fix1();
            if (currentPhase == PHASE.ANALYZER.phase()) fix2();
        }
        if (reporter.errors() != 0) {
            imports.clear();
            for (Iterator it = compiledNow.keySet().iterator(); it.hasNext();) {
                Symbol sym = (Symbol) it.next();
                sym.reset(new SourceCompleter(this));
            }
        }
	symdata.clear();
        compiledNow.clear();
        printer.end();
    }

    /** transform a unit and stop at the current compilation phase
     */
    public void transformUnit(Unit unit) {
       	Phase oldCurrentPhase = currentPhase;
        currentPhase = PHASE.ANALYZER.phase().next; // or REFCHECK.next?
        while ((currentPhase.id < oldCurrentPhase.id) && (reporter.errors() == 0)) {
            start();
            currentPhase.apply(new Unit[] {unit}); // !!! pb with Analyzer
            stop(currentPhase.descriptor.taskDescription());
            if (currentPhase.descriptor.hasPrintFlag()) {
                // go to next phase to print symbols with their new type
                boolean next = currentPhase.next != null;
                if (next) currentPhase = currentPhase.next;
                currentPhase.print(this);
                if (next) currentPhase = currentPhase.prev;
            }
            if (currentPhase.descriptor.hasGraphFlag())
                currentPhase.graph(this);
            if (currentPhase.descriptor.hasCheckFlag())
                currentPhase.check(this);
            currentPhase = currentPhase.next;
        }
        currentPhase = oldCurrentPhase;
    }

    // !!! <<< Interpreter stuff
    public static final String CONSOLE_S = "$console$";
    private static final Name
        CONSOLE_N               = Name.fromString(CONSOLE_S),
        INTERPRETER_N           = Name.fromString("scala.runtime.InterpreterSupport"),
        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() {
{'fraction_non_alphanumeric': 0.11057425065207166, 'fraction_numerical': 0.0013682815239235472, 'mean_word_length': 2.091197462331483, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7360894', 'n_tokens_mistral': 6418, 'n_tokens_neox': 6207, 'n_words': 1609}