@@ -0,0 +1,354 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac;

import java.io.*;
import java.util.*;
import scalac.util.*;
import scalac.ast.*;
import scalac.ast.parser.*;
import scalac.symtab.Definitions;
import scalac.ast.printer.*;


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

public static Global instance;

/** global options
*/
public final boolean noimports;
//public final boolean optimize;
public final boolean debug;
public final boolean uniqid;

public final boolean printtypes;
public final boolean printtokens;

public final String outpath;
public final String target;

public final String jacoDebug;

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

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

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

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

/** compilation phases.
*/
public final PhaseRepository PHASE;
public final PhaseDescriptor[] phases;

public final int POST_ANALYZER_PHASE_ID = 3;

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

public static final String[] TARGETS = new String[] {
TARGET_INT = "int".intern(),
TARGET_JAVA = "java".intern(),
TARGET_JVM = "jvm".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(),
};

public Global(CompilerCommand args) {
this(args, false);
}

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.reporter = args.reporter();
this.start(); // timestamp to compute the total time
this.noimports = args.noimports.value;
//this.optimize = args.optimize.optimize;
this.debug = args.debug.value;
this.uniqid = args.uniqid.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.jacoDebug = args.jaco.value;
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);
this.freshNameCreator = new FreshNameCreator();
this.make = new TreeCreator();
this.currentPhase = PhaseDescriptor.INITIAL;
this.definitions = new Definitions(this);
//this.primitives = new Primitives(this);
this.treeGen = new TreeGen(this, make);
this.PHASE = args.phases;
List phases = new ArrayList();
phases.add(PHASE.INITIAL);
phases.add(PHASE.PARSER);
phases.add(PHASE.ANALYZER);
phases.add(PHASE.REFCHECK);
phases.add(PHASE.UNCURRY);
/*
if (optimize) {
phases.add(PHASE.OPTIMIZE);
}
phases.add(PHASE.TRANSMATCH);
*/
//phases.add(PHASE.LAMBDALIFT);
/*
phases.add(PHASE.EXPLICITOUTER);
phases.add(PHASE.ADDACCESSORS);
phases.add(PHASE.ADDINTERFACES);
phases.add(PHASE.EXPANDMIXIN);
phases.add(PHASE.ERASURE);
if (target == TARGET_INT || target == TARGET_MSIL || target == TARGET_JVM) {
phases.add(PHASE.ADDCONSTRUCTORS);
}
if (target == TARGET_JAVA) phases.add(PHASE.GENJAVA);
if (target == TARGET_MSIL) phases.add(PHASE.GENMSIL);
if (target == TARGET_JVM) phases.add(PHASE.GENJVM);
*/
phases.add(PHASE.TERMINAL);
this.phases = new PhaseDescriptor[phases.size()];
for (int i = 0; i < phases.size(); i++) {
PhaseDescriptor phase = (PhaseDescriptor)phases.get(i);
this.phases[i] = phase;
if (i > 0) this.phases[i - 1].flags |= phase.flags >>> 16;
phase.initialize(this, i);
assert phase.id == i;
}
assert PHASE.ANALYZER.id + 1 == POST_ANALYZER_PHASE_ID;
}

/** Move to next phase
*/
public void nextPhase() {
currentPhase = phases[currentPhase.id + 1];
}

/** Move to previous phase
*/
public void prevPhase() {
currentPhase = phases[currentPhase.id - 1];
}

/** 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
*/
public void compile(String input, boolean console) {
reporter.resetCounters();
Sourcefile source = new Sourcefile(input.getBytes(), console);
units = new Unit[]{new Unit(this, source)};
compile();
}

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

// apply successive phases and pray that it works
for (int i = 0; i < phases.length && reporter.errors() == 0; ++i) {
currentPhase = phases[i];
if ((currentPhase.flags & PhaseDescriptor.SKIP) != 0) {
operation("skipping phase " + currentPhase.name());
} else {
currentPhase.apply(this);
}
if ((currentPhase.flags & PhaseDescriptor.PRINT) != 0)
currentPhase.print(this);
if ((currentPhase.flags & PhaseDescriptor.GRAPH) != 0)
currentPhase.graph(this);
if ((currentPhase.flags & PhaseDescriptor.CHECK) != 0)
currentPhase.check(this);
if ((currentPhase.flags & PhaseDescriptor.STOP) != 0) {
operation("stopped after phase " + currentPhase.name());
break;
}
}

printer.end();
}

/** stop the compilation process immediately
*/
public Error fail() {
throw new ApplicationError();
}

/** stop the compilation process immediately
*/
public Error fail(String message) {
throw new ApplicationError(message);
}

/** stop the compilation process immediately
*/
public Error fail(String message, Object object) {
throw new ApplicationError(message, object);
}

/** stop the compilation process immediately
*/
public Error fail(Object value) {
throw new ApplicationError(value);
}

/** issue a global error
*/
public void error(String message) {
reporter.error("error: " + message);
}

/** issue a global warning
*/
public void warning(String message) {
reporter.warning("warning: " + message);
}

/** issue a global note (if in verbose mode)
*/
public void note(String message) {
reporter.note("note: " + message);
}

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

/** 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.report("[log " + currentPhase.name() + "] " + message);
}
return true;
}

/** return true if logging is switched on for the current phase
*/
public boolean log() {
return (currentPhase.flags & PhaseDescriptor.LOG) != 0;
}

/** start a new timer
*/
public void start() {
startTimes.push(new Long(System.currentTimeMillis()));
}

/** issue timing information
*/
public void stop(String message) {
long start = ((Long)startTimes.pop()).longValue();
reporter.inform("[" + message + " in " +
(System.currentTimeMillis() - start) + "ms]");
}
}
@@ -0,0 +1,38 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac;

import scalac.util.Reporter;

/** The main class for SoCoS, a compiler for the programming
* language Scala.
*
* @author Matthias Zenger
* @version 1.0
*/
public class Main {

public static final String PRODUCT =
System.getProperty("scala.product", "socos");
public static final String VERSION =
System.getProperty("scala.version", "unknown version");

public static void main(String[] args) {
Reporter reporter = new Reporter();
CompilerCommand command = new CompilerCommand(
PRODUCT, VERSION, reporter, new PhaseRepository());
if (command.parse(args) && command.files.list.size() > 0) {
Global global = new Global(command);
global.compile(command.files.toArray(), false);
global.stop("total");
global.reporter.printSummary();
}
System.exit((reporter.errors() > 0) ? -1 : 0);
}
}
@@ -0,0 +1,45 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac;

/** Representation of a compiler phase. PhaseDescriptors create
* phase. Phases operate subsequently on all compilation units.
*
* @author Matthias Zenger
* @version 1.0
*/
public abstract class Phase {

/** the global environment
*/
public final Global global;

/** the descriptor for this phase
*/
public final PhaseDescriptor descr;

/** constructor
*/
public Phase(Global global, PhaseDescriptor descr) {
this.global = global;
this.descr = descr;
}

/** apply this phase to all compilation units
*/
public void apply() {
for (int i = 0; i < global.units.length; i++) {
apply(global.units[i]);
}
}

/** apply this phase to the given compilation unit
*/
public abstract void apply(Unit unit);
}
@@ -0,0 +1,169 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac;

import java.util.*;
import scalac.ast.printer.*;
import scalac.ast.*;
import scalac.symtab.*;
import scalac.checkers.*;
import java.io.PrintWriter;

/**
* Information about a compiler phase.
*
* @author Michel Schinz
*/

public abstract class PhaseDescriptor {

private static class InitialPhaseDescriptor extends PhaseDescriptor {

public String name() {
return "initial";
}

public String description() {
return "initializing compiler";
}

public Phase createPhase(Global global) {
return null;
}

/** apply phase to all compilation units
*/
public void apply(Global global) {}
}

private static class TerminalPhaseDescriptor extends PhaseDescriptor {

public String name() {
return "terminal";
}

public String description() {
return "compilation terminated ";
}

public Phase createPhase(Global global) {
return null;
}

/** apply phase to all compilation units
*/
public void apply(Global global) {}
}

public static PhaseDescriptor INITIAL = new InitialPhaseDescriptor();
public static PhaseDescriptor TERMINAL = new TerminalPhaseDescriptor();

public static final int SKIP = 0x0001;
public static final int CHECK = 0x0002;
public static final int PRINT = 0x0004;
public static final int GRAPH = 0x0008;
public static final int STOP = 0x0010;
public static final int LOG = 0x0020;

public int flags;
public int id;

/** return a short, one-word name for the phase.
*/
public abstract String name();

/** return a one-line description for the phase.
*/
public abstract String description();

/** a one-line task description of this phase
*/
public String taskDescription() {
return description();
}

/** initialize the phase
*/
public final void initialize(Global global) {
throw new Error();
}
public void initialize(Global global, int id) {
this.id = id;
}

/** create a phase
*/
public abstract Phase createPhase(Global global);

/** Assume that `tp' is the info of symbol `sym' before this phase.
* Return the info of `sym' after the phase.
*/
public Type transformInfo(Symbol sym, Type tp) {
return tp;
}

/** apply phase to all compilation units
*/
public void apply(Global global) {
global.start();
createPhase(global).apply();
global.stop(taskDescription());
}

/** check all compilation units
*/
public void check(Global global) {
for (int i = 0; i < global.units.length; i++)
check(global.units[i]);
}

/** print all compilation units
*/
public void print(Global global) {
TreePrinter printer = global.printer;

printer.beginSection(1, "Trees after phase " + name());
for (int i = 0; i < global.units.length; i++)
printer.print(global.units[i]);
}

/** graph all compilation units
*/
public void graph(Global global) {
for (int i = 0; i < global.units.length; i++)
graph(global.units[i]);
}

/** return an array of checkers which can be applied after the phase
*/
public Checker[] postCheckers(Global global) {
return new Checker[0];
}

/** check the result of this phase for the given compilation unit
*/
public void check(Unit unit) {
Checker[] checkers = postCheckers(unit.global);
for (int i = 0; i < checkers.length; i++)
checkers[i].traverse(unit);
}

/** graph the result of this phase for the given compilation unit
*/
public void graph(Unit unit) {
/* todo: uncomment
new scala.compiler.gdl.TreePrinter().printInFile(
unit, unit.source + "-" + name() + ".gdl");
*/
}

public String toString() {
return name();
}
}
@@ -0,0 +1,96 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac;

import scalac.ast.parser.ParserPhase;
import scalac.typechecker.AnalyzerPhase;
import scalac.typechecker.RefCheckPhase;
import scalac.transformer.UnCurryPhase;
/*
import scalac.transformer.TransMatchPhase;
*/
import scalac.transformer.LambdaLiftPhase;
/*
import scalac.transformer.ExplicitOuterClassesPhase;
import scalac.transformer.AddInterfacesPhase;
import scalac.transformer.AddAccessorsPhase;
import scalac.transformer.ExpandMixinsPhase;
import scalac.transformer.ErasurePhase;
import scalac.optimizer.OptimizePhase;
import scalac.backend.AddConstructorsPhase;
import scalac.backend.msil.GenMSILPhase;
import scalac.backend.jvm.GenJVMPhase;
import scalac.jaco.GenJavaPhase;
*/

public class PhaseRepository {

//########################################################################
// Private state

public final PhaseDescriptor[] phases;

//########################################################################
// Reporter constructors

public PhaseRepository() {
this.phases = new PhaseDescriptor[] {
INITIAL = PhaseDescriptor.INITIAL,
PARSER = new ParserPhase(),
ANALYZER = new AnalyzerPhase(),
REFCHECK = new RefCheckPhase(),
UNCURRY = new UnCurryPhase(),
/*
OPTIMIZE = new OptimizePhase(),
TRANSMATCH = new TransMatchPhase(),
*/
LAMBDALIFT = new LambdaLiftPhase(),
/*
EXPLICITOUTER = new ExplicitOuterClassesPhase(),
ADDACCESSORS = new AddAccessorsPhase(),
ADDINTERFACES = new AddInterfacesPhase(),
EXPANDMIXIN = new ExpandMixinsPhase(),
ERASURE = new ErasurePhase(),
ADDCONSTRUCTORS = new AddConstructorsPhase(),
GENMSIL = new GenMSILPhase(),
GENJAVA = new GenJavaPhase(),
GENJVM = new GenJVMPhase(),
*/
TERMINAL = PhaseDescriptor.TERMINAL,
};
}

//########################################################################
// Reporter interface

public final PhaseDescriptor INITIAL;
public final ParserPhase PARSER;
public final AnalyzerPhase ANALYZER;
public final RefCheckPhase REFCHECK;
public final UnCurryPhase UNCURRY;
/*
public final OptimizePhase OPTIMIZE;
public final TransMatchPhase TRANSMATCH;
*/
public final LambdaLiftPhase LAMBDALIFT;
/*
public final ExplicitOuterClassesPhase EXPLICITOUTER;
public final AddAccessorsPhase ADDACCESSORS;
public final AddInterfacesPhase ADDINTERFACES;
public final ExpandMixinsPhase EXPANDMIXIN;
public final ErasurePhase ERASURE;
public final AddConstructorsPhase ADDCONSTRUCTORS;
public final GenMSILPhase GENMSIL;
public final GenJavaPhase GENJAVA;
public final GenJVMPhase GENJVM;
*/
public final PhaseDescriptor TERMINAL;

//########################################################################
}
@@ -0,0 +1,123 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac;

import scalac.util.*;
import scalac.symtab.NameMangler;
import scalac.ast.parser.Sourcefile;
import scalac.ast.Tree;
import scala.compiler.typechecker.*;
import java.io.*;
import java.util.*;


/** A representation for a compilation unit in scala
*
* @author Matthias Zenger
* @version 1.0
*/
public class Unit {

/** the global compilation environment
*/
public Global global;

/** the associated source code file
*/
public Sourcefile source;

/** the content of the compilation unit in tree form
*/
public Tree[] body;

/** the generated symbol data; Symbol -> byte[]
public SymData symdata;
*/

/** the name mangler
*/
public NameMangler mangler = new NameMangler();

/** number of errors issued for this compilation unit
*/
public int errors;

/** number of warnings issued for this compilation unit
*/
public int warnings;

/** number of notes issued for this compilation unit
*/
public int notes;

public Unit(Global global, Sourcefile source) {
this.global = global;
this.source = source;
}
/*
public void print(String message) {
print(System.out, message);
}
public void print(PrintStream out, String message) {
out.println("[[begin " + message + "]]");
new Printer(out).printCompilationUnit(this);
out.println();
out.println("[[end " + message + "]]");
}
*/
/** issue an error in this compilation unit
*/
public void error(String message) {
error(Position.NOPOS, message);
}

/** issue an error in this compilation unit at a specific location
*/
public void error(int pos, String message) {
boolean hidden = source.testAndSetLog(pos, message);
if (!hidden) errors++;
global.reporter.error(source.getMessage(pos, message), hidden);
}

/** issue a warning in this compilation unit
*/
public void warning(String message) {
warning(Position.NOPOS, message);
}

/** issue a warning in this compilation unit at a specific location
*/
public void warning(int pos, String message) {
if (global.reporter.nowarn) return;
message = "warning: " + message;
boolean hidden = source.testAndSetLog(pos, message);
if (!hidden) warnings++;
global.reporter.warning(source.getMessage(pos, message), hidden);
}

/** issue a note in this compilation unit
*/
public void note(String message) {
note(Position.NOPOS, message);
}

/** issue a note in this compilation unit at a specific location
*/
public void note(int pos, String message) {
global.reporter.note(source.getMessage(pos, message));
notes++;
}

/** return a string representation
*/
public String toString() {
return source.toString();
}
}
@@ -0,0 +1,30 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
\* */

// $Id$

package scalac.ast;

import scalac.ast.*;

/**
* Abstract superclass for all TreeCopyFactories, which provides only
* the code to copy the attribution from the "old" to the "new" tree.
*
* @author Michel Schinz
* @version 1.0
*/

public abstract class AbstractTreeCopyFactory implements TreeCopyFactory {
public void attribute(Tree newTree, Tree oldTree) {
if (newTree != oldTree) {
newTree.type = oldTree.type;
if (newTree.hasSymbol())
newTree.setSymbol(oldTree.symbol());
}
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,215 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
\* */

// $Id$

package scalac.ast;

import java.io.*;
import java.util.*;
import scalac.*;
import scalac.util.*;
import Tree.*;


/** Class to traverse a tree without modifying it.
*
* @author Michel Schinz
*/

public class Traverser {
public Traverser() {}

// this should be removed in the future
public Traverser(Global global) {}

public void traverse(Unit unit) {
traverse(unit.body);
}

public void traverse(Tree tree) {
switch (tree) {
case Bad():
case Empty:
case Ident(_):
case Literal(_):
return;

case ClassDef(int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Template impl):
traverse(tparams);
traverse(vparams);
traverse(tpe);
traverse(impl);
return;

case PackageDef(Tree packaged, Template impl) :
traverse(packaged);
traverse(impl);
return;

case ModuleDef(int mods, Name name, Tree tpe, Template impl):
traverse(tpe);
traverse(impl);
return;

case ValDef(int mods, Name name, Tree tpe, Tree rhs):
traverse(tpe);
traverse(rhs);
return;

case PatDef(int mods, Tree pat, Tree rhs):
traverse(pat);
traverse(rhs);
return;

case DefDef(int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Tree rhs):
traverse(tparams);
traverse(vparams);
traverse(tpe);
traverse(rhs);
return;

case TypeDef(int mods, Name name, TypeDef[] tparams, Tree rhs):
traverse(tparams);
traverse(rhs);
return;

case Import(Tree expr, Name[] selectors):
traverse(expr);
return;

case CaseDef(Tree pat, Tree guard, Tree body):
traverse(pat);
traverse(guard);
traverse(body);
return;

case Template(Tree[] baseClasses, Tree[] body):
traverse(baseClasses);
traverse(body);
return;

case LabelDef(Tree[] params,Tree rhs):
traverse(params);
traverse(rhs);
return;

case Block(Tree[] stats):
traverse(stats);
return;

case Tuple(Tree[] trees):
traverse(trees);
return;

case Visitor(CaseDef[] cases):
traverse(cases);
return;

case Function(ValDef[] vparams, Tree body):
traverse(vparams);
traverse(body);
return;

case Assign(Tree lhs, Tree rhs):
traverse(lhs);
traverse(rhs);
return;

case If(Tree cond, Tree thenp, Tree elsep):
traverse(cond);
traverse(thenp);
traverse(elsep);
return;

case New(Template templ):
traverse(templ);
return;

case Typed(Tree expr, Tree tpe):
traverse(expr);
traverse(tpe);
return;

case TypeApply(Tree fun, Tree[] tparams):
traverse(fun);
traverse(tparams);
return;

case Apply(Tree fun, Tree[] vparam):
traverse(fun);
traverse(vparam);
return;

case Super(Tree tpe):
traverse(tpe);
return;

case This(Tree qualifier):
traverse(qualifier);
return;

case Select(Tree qualifier, Name selector):
traverse(qualifier);
return;

case SingletonType(Tree ref):
traverse(ref);
return;

case SelectFromType(Tree qualifier, Name selector):
traverse(qualifier);
return;

case FunType(Tree[] argtpes, Tree restpe):
traverse(argtpes);
traverse(restpe);
return;

case CompoundType(Tree[] baseTypes, Tree[] refinements):
traverse(baseTypes);
traverse(refinements);
return;

case TupleType(Tree[] types):
traverse(types);
return;

case AppliedType(Tree tpe, Tree[] args):
traverse(tpe);
traverse(args);
return;

case CovariantType(Tree tpe):
traverse(tpe);
return;

default:
throw new ApplicationError("unknown node " + tree);
}
}

public void traverse(Tree[] array) {
for (int i = 0; i < array.length; ++i)
traverse(array[i]);
}

public void traverse(Tree[][] array) {
for (int i = 0; i < array.length; ++i)
traverse(array[i]);
}
}

Large diffs are not rendered by default.

@@ -0,0 +1,165 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast;

import scalac.util.Name;
import Tree.*;

/**
* Interface for a kind of factory which, for each node constructor,
* takes an original node from which some data will be copied or shared.
*
* @author Michel Schinz
* @version 1.1
*/
public interface TreeCopyFactory {

public void attribute(Tree newTree, Tree oldTree);

public Tree Bad(Tree tree);

public Tree ClassDef(Tree tree,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Template impl);

public Tree PackageDef(Tree tree,
Tree packaged,
Template impl);

public Tree ModuleDef(Tree tree,
int mods,
Name name,
Tree tpe,
Template impl);

public Tree ValDef(Tree tree,
int mods,
Name name,
Tree tpe,
Tree rhs);

public Tree PatDef(Tree tree,
int mods,
Tree pat,
Tree rhs);

public Tree DefDef(Tree tree,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Tree rhs);

public Tree TypeDef(Tree tree,
int mods,
Name name,
TypeDef[] tparams,
Tree rhs);

public Tree Import(Tree tree,
Tree expr,
Name[] selectors);

public Tree CaseDef(Tree tree,
Tree pat,
Tree guard,
Tree body);

public Template Template(Tree tree,
Tree[] baseClasses,
Tree[] body);

public Tree LabelDef(Tree tree,
Tree[] params,
Tree rhs);

public Tree Block(Tree tree,
Tree[] stats);

public Tree Tuple(Tree tree,
Tree[] trees);

public Tree Visitor(Tree tree,
CaseDef[] cases);

public Tree Function(Tree tree,
ValDef[] vparams,
Tree body);

public Tree Assign(Tree tree,
Tree lhs,
Tree rhs);

public Tree If(Tree tree,
Tree cond,
Tree thenp,
Tree elsep);

public Tree New(Tree tree,
Template templ);

public Tree Typed(Tree tree,
Tree expr,
Tree tpe);

public Tree TypeApply(Tree tree,
Tree fun,
Tree[] args);

public Tree Apply(Tree tree,
Tree fun,
Tree[] args);

public Tree Super(Tree tree,
Tree tpe);

public Tree This(Tree tree,
Tree qualifier);

public Tree Select(Tree tree,
Tree qualifier,
Name selector);

public Tree Ident(Tree tree,
Name name);

public Tree Literal(Tree tree,
Object value);

public Tree SingletonType(Tree tree,
Tree ref);

public Tree SelectFromType(Tree tree,
Tree qualifier,
Name selector);

public Tree FunType(Tree tree,
Tree[] argtpes,
Tree restpe);

public Tree CompoundType(Tree tree,
Tree[] baseTypes,
Tree[] refinements);

public Tree TupleType(Tree tree,
Tree[] types);

public Tree AppliedType(Tree tree,
Tree tpe,
Tree[] args);

public Tree CovariantType(Tree tree,
Tree tpe);

}
@@ -0,0 +1,293 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast;

import Tree.*;
import scalac.util.Name;


public class TreeCreator implements TreeFactory {

public Tree Bad(int pos) {
Tree t = new ExtBad();
t.pos = pos;
return t;
}

public Tree ClassDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Template impl) {
Tree t = new ExtClassDef(mods, name, tparams, vparams, tpe, impl);
t.pos = pos;
return t;
}

public Tree PackageDef(int pos,
Tree packaged,
Template impl) {
Tree t = new PackageDef(packaged, impl);
t.pos = pos;
return t;
}

public Tree ModuleDef(int pos,
int mods,
Name name,
Tree tpe,
Template body) {
Tree t = new ExtModuleDef(mods, name, tpe, body);
t.pos = pos;
return t;
}

public Tree ValDef(int pos,
int mods,
Name name,
Tree tpe,
Tree rhs) {
Tree t = new ExtValDef(mods, name, tpe, rhs);
t.pos = pos;
return t;
}

public Tree PatDef(int pos,
int mods,
Tree pat,
Tree rhs) {
Tree t = new PatDef(mods, pat, rhs);
t.pos = pos;
return t;
}

public Tree DefDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Tree rhs) {
Tree t = new ExtDefDef(mods, name, tparams, vparams, tpe, rhs);
t.pos = pos;
return t;
}


public Tree TypeDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
Tree rhs) {
Tree t = new ExtTypeDef(mods, name, tparams, rhs);
t.pos = pos;
return t;
}

public Tree Import(int pos,
Tree expr,
Name[] selectors) {
Tree t = new ExtImport(expr, selectors);
t.pos = pos;
return t;
}

public CaseDef CaseDef(int pos,
Tree pat,
Tree guard,
Tree body) {
CaseDef t = new CaseDef(pat, guard, body);
t.pos = pos;
return t;
}

public Template Template(int pos,
Tree[] baseClasses,
Tree[] body) {
Template t = new ExtTemplate(baseClasses, body);
t.pos = pos;
return t;
}

public Tree LabelDef(int pos,
Tree[] params,
Tree body) {
Tree t = new ExtLabelDef(params,body);
t.pos = pos;
return t;
}

public Tree Block(int pos,
Tree[] stats) {
Tree t = new Block(stats);
t.pos = pos;
return t;
}

public Tree Tuple(int pos,
Tree[] trees) {
Tree t = new Tuple(trees);
t.pos = pos;
return t;
}

public Tree Visitor(int pos,
CaseDef[] cases) {
Tree t = new Visitor(cases);
t.pos = pos;
return t;
}

public Tree Function(int pos,
ValDef[] vparams,
Tree body) {
Tree t = new Function(vparams, body);
t.pos = pos;
return t;
}

public Tree Assign(int pos,
Tree lhs,
Tree rhs) {
Tree t = new Assign(lhs, rhs);
t.pos = pos;
return t;
}

public Tree If(int pos,
Tree cond,
Tree thenp,
Tree elsep) {
Tree t = new If(cond, thenp, elsep);
t.pos = pos;
return t;
}

public Tree New(int pos,
Template templ) {
Tree t = new New(templ);
t.pos = pos;
return t;
}

public Tree Typed(int pos,
Tree expr,
Tree tpe) {
Tree t = new Typed(expr, tpe);
t.pos = pos;
return t;
}

public Tree TypeApply(int pos,
Tree fun,
Tree[] tparams) {
Tree t = new TypeApply(fun, tparams);
t.pos = pos;
return t;
}

public Tree Apply(int pos,
Tree fun,
Tree[] vparam) {
Tree t = new Apply(fun, vparam);
t.pos = pos;
return t;
}

public Tree Super(int pos,
Tree tpe) {
Tree t = new Super(tpe);
t.pos = pos;
return t;
}

public Tree This(int pos,
Tree qualifier) {
Tree t = new This(qualifier);
t.pos = pos;
return t;
}

public Tree Select(int pos,
Tree qualifier,
Name selector) {
Tree t = new ExtSelect(qualifier, selector);
t.pos = pos;
return t;
}

public Tree Ident(int pos,
Name name) {
Tree t = new ExtIdent(name);
t.pos = pos;
return t;
}

public Tree Literal(int pos,
Object value) {
Tree t = new Literal(value);
t.pos = pos;
return t;
}


public Tree SingletonType(int pos, Tree ref) {
Tree t = new SingletonType(ref);
t.pos = pos;
return t;
}

public Tree SelectFromType(int pos,
Tree qualifier,
Name selector) {
Tree t = new ExtSelectFromType(qualifier, selector);
t.pos = pos;
return t;
}

public Tree FunType(int pos,
Tree[] argtpes,
Tree restpe) {
Tree t = new FunType(argtpes, restpe);
t.pos = pos;
return t;
}

public Tree CompoundType(int pos,
Tree[] mixins,
Tree[] fields) {
Tree t = new CompoundType(mixins, fields);
t.pos = pos;
return t;
}

public Tree TupleType(int pos,
Tree[] types) {
Tree t = new TupleType(types);
t.pos = pos;
return t;
}

public Tree AppliedType(int pos,
Tree tpe,
Tree[] args) {
Tree t = new AppliedType(tpe, args);
t.pos = pos;
return t;
}

public Tree CovariantType(int pos,
Tree tpe) {
Tree t = new CovariantType(tpe);
t.pos = pos;
return t;
}
}
@@ -0,0 +1,155 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast;

import scalac.util.Name;
import Tree.*;

public interface TreeFactory {

public Tree Bad(int pos);

public Tree ClassDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Template impl);

public Tree PackageDef(int pos,
Tree packaged,
Template impl);

public Tree ModuleDef(int pos,
int mods,
Name name,
Tree tpe,
Template impl);

public Tree ValDef(int pos,
int mods,
Name name,
Tree tpe,
Tree rhs);

public Tree PatDef(int pos,
int mods,
Tree pat,
Tree rhs);

public Tree DefDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Tree rhs);

public Tree TypeDef(int pos,
int mods,
Name name,
TypeDef[] tparams,
Tree rhs);

public Tree Import(int pos,
Tree expr,
Name[] selectors);

public CaseDef CaseDef(int pos,
Tree pat,
Tree guard,
Tree body);

public Template Template(int pos,
Tree[] baseClasses,
Tree[] body);

public Tree LabelDef(int pos,
Tree[] params,
Tree rhs);

public Tree Block(int pos,
Tree[] stats);

public Tree Tuple(int pos,
Tree[] trees);

public Tree Visitor(int pos,
CaseDef[] cases);

public Tree Function(int pos,
ValDef[] vparams,
Tree body);

public Tree Assign(int pos,
Tree lhs,
Tree rhs);

public Tree If(int pos,
Tree cond,
Tree thenp,
Tree elsep);

public Tree New(int pos,
Template templ);

public Tree Typed(int pos,
Tree expr,
Tree tpe);

public Tree TypeApply(int pos,
Tree fun,
Tree[] tparams);

public Tree Apply(int pos,
Tree fun,
Tree[] vparam);

public Tree Super(int pos,
Tree tpe);

public Tree This(int pos,
Tree qualifier);

public Tree Select(int pos,
Tree qualifier,
Name selector);

public Tree Ident(int pos,
Name name);

public Tree Literal(int pos,
Object value);

public Tree SingletonType(int pos,
Tree ref);

public Tree SelectFromType(int pos,
Tree qualifier,
Name selector);

public Tree FunType(int pos,
Tree[] argtpes,
Tree restpe);

public Tree CompoundType(int pos,
Tree[] baseTypes,
Tree[] refinements);

public Tree TupleType(int pos,
Tree[] types);

public Tree AppliedType(int pos,
Tree tpe,
Tree[] args);

public Tree CovariantType(int pos,
Tree tpe);
}

Large diffs are not rendered by default.

@@ -0,0 +1,136 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast;

import scalac.ApplicationError;
import scalac.util.Name;
import scalac.symtab.Type;
import scalac.symtab.Symbol;
import scalac.symtab.Modifiers;

public class TreeInfo {

public static boolean isTerm(Tree tree) {
return tree.isTerm();
}

public static boolean isType(Tree tree) {
return tree.isType();
}

public static boolean isOwnerDefinition(Tree tree) {
switch (tree) {
case PackageDef(_, _):
case ClassDef(_, _, _, _, _, _):
case ModuleDef(_, _, _, _):
case DefDef(_, _, _, _, _, _):
case Import(_, _):
return true;
default:
return false;
}
}

public static boolean isDefinition(Tree tree) {
switch (tree) {
case PackageDef(_, _):
case ClassDef(_, _, _, _, _, _):
case ModuleDef(_, _, _, _):
case DefDef(_, _, _, _, _, _):
case ValDef(_, _, _, _):
case TypeDef(_, _, _, _):
case Import(_, _):
return true;
default:
return false;
}
}

public static boolean isDeclaration(Tree tree) {
switch (tree) {
case DefDef(_, _, _, _, _, Tree rhs):
return rhs == Tree.Empty;
case ValDef(_, _, _, Tree rhs):
return rhs == Tree.Empty;
case TypeDef(_, _, _, _):
return true;
default:
return false;
}
}

/** Is tree a pure definition?
*/
public static boolean isPureDef(Tree tree) {
switch (tree) {
case ClassDef(_, _, _, _, _, _):
case ModuleDef(_, _, _, _):
case DefDef(_, _, _, _, _, _):
case TypeDef(_, _, _, _):
case Import(_, _):
return true;
case ValDef(int mods, _, _, Tree rhs):
return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs);
default:
return false;
}
}

/** Is tree a stable & pure expression?
*/
public static boolean isPureExpr(Tree tree) {
switch (tree) {
case Empty:
case This(_):
case Super(_):
return true;
case Ident(_):
return tree.type.isStable();
case Select(Tree qual, _):
return tree.type.isStable() && isPureExpr(qual);
case Typed(Tree expr, _):
return isPureExpr(expr);
case Literal(_):
return true;
default:
return false;
}
}

/** Is tree a pure constructor?
* //todo: update
*/
public static boolean isPureConstr(Tree tree) {
switch (tree) {
case Ident(_):
return tree.symbol() != null && tree.symbol().isPrimaryConstructor();
case Select(Tree qual, _):
return isPureExpr(qual) &&
tree.symbol() != null && tree.symbol().isPrimaryConstructor();
case TypeApply(Tree constr, _):
return isPureConstr(constr);
default:
return false;
}
}

/** The method symbol of an application node, or Symbol.NONE, if none exists.
*/
public static Symbol methSymbol(Tree tree) {
switch (tree) {
case Apply(Tree fn, _):
return methSymbol(fn);
case TypeApply(Tree fn, _):
return methSymbol(fn);
default:
if (tree.hasSymbol()) return tree.symbol();
else return Symbol.NONE;
}
}
}
@@ -0,0 +1,71 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id
\* */

package scalac.ast;


public final class TreeList {
Tree[] trees;
int len;

public TreeList(Tree[] ts) {
trees = ts;
len = ts.length;
}

public TreeList() {
this(new Tree[4]);
len = 0;
}

public void append(Tree tree) {
if (len == trees.length) {
Tree[] ts = new Tree[len * 2];
System.arraycopy(trees, 0, ts, 0, len);
trees = ts;
}
trees[len++] = tree;
}

public void append(Tree[] ts) {
for (int j = 0; j < ts.length; j++)
append(ts[j]);
}

public void append(TreeList tl) {
for (int j = 0; j < tl.len; j++)
append(tl.trees[j]);
}

public int length() {
return len;
}

public Tree get(int i) {
return trees[i];
}

public Tree first() {
return trees[0];
}

public Tree removeLast() {
return trees[--len];
}

public Tree[] toArray() {
Tree[] ts = new Tree[len];
System.arraycopy(trees, 0, ts, 0, len);
return ts;
}

public Tree[] copyTo(Tree[] ts) {
System.arraycopy(trees, 0, ts, 0, len);
return ts;
}
}

Large diffs are not rendered by default.

@@ -0,0 +1,63 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
**
** $Id$
\* */

package scalac.ast.parser;

import java.io.*;
import scalac.*;

public class ParserPhase extends PhaseDescriptor {

public String name() {
return "parse";
}

public String description () {
return "parse source files";
}

public String taskDescription() {
return "parsed";
}

public Phase createPhase(Global global) {
return new ParserWorker(global, this);
}
}

public class ParserWorker extends Phase {

/** constructor
*/
public ParserWorker(Global global, PhaseDescriptor descr) {
super(global, descr);
}

/** apply this phase to all compilation units
*/
public void apply() {
super.apply();
int count = 0;
for (int i = 0; i < global.units.length; i++) {
if (global.units[i].body != null) count++;
}
Unit[] units = new Unit[count];
for (int i = 0, j = 0; i < global.units.length; i++) {
if (global.units[i].body != null) units[j++] = global.units[i];
}
global.units = units;
}

/** apply this phase to the given compilation unit
*/
public void apply(Unit unit) {
global.start();
unit.body = new Parser(unit).parse();
global.stop("parsed " + unit.source);
}
}

Large diffs are not rendered by default.

@@ -0,0 +1,205 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id
\* */

package scalac.ast.parser;

public final class SourceRepresentation {

public static int digit2int(byte ch, int base) {
if ('0' <= ch && ch <= '9' && ch < '0' + base)
return ch - '0';
else if ('A' <= ch && ch < 'A' + base - 10)
return ch - 'A' + 10;
else if ('a' <= ch && ch < 'a' + base - 10)
return ch - 'a' + 10;
else
return -1;
}

public static byte int2digit(int x) {
if (x <= 9)
return (byte)(x + '0');
else
return (byte)(x - 10 + 'A');
}

/* the next 4 functions convert between three fundamental name
* representations:
* - string each character 16 bit,
* - source characters outside 0..127 are represented by
* unicode escapes, \ u X X X X
* - ascii characters outside 0..127 are represented by two or three
* byte sequences with high bit set (as in class file format).
*/

/** convert source bytes in source[offset..offset+len-1] to ascii.
*/
public static int source2ascii(byte source[], int offset, int len, byte ascii[]) {
int j = 0;
int i = 0;
while (i < len) {
if (source[offset + i] == '\\' && i + 1 < len) {
i++;
switch (source[offset + i]) {
case 'n':
ascii[j++] = (byte)'\n'; i++; continue;
case 't':
ascii[j++] = (byte)'\t'; i++; continue;
case 'b':
ascii[j++] = (byte)'\b'; i++; continue;
case 'r':
ascii[j++] = (byte)'\r'; i++; continue;
case 'f':
ascii[j++] = (byte)'\f'; i++; continue;
case 'u':
if (i + 4 < len) {
int code = 0;
int k = 1;
int d = 0;
while (k <= 4 && d >= 0) {
d = digit2int(source[offset + i + k], 16);
code = code * 16 + d;
k++;
}
if (d >= 0) {
if (code <= 0x7F)
ascii[j++] = (byte)code;
else
if (code <= 0x3FF) {
ascii[j++] = (byte)(0xC0 | (code >> 6));
ascii[j++] = (byte)(0x80 | (code & 0x3F));
} else {
ascii[j++] = (byte)(0xE0 | (code >> 12));
ascii[j++] = (byte)(0x80 |
((code >> 6) & 0x3F));
ascii[j++] = (byte)(0x80 | (code & 0x3F));
}
i = i + 5;
continue;
}
}
}
}
byte b = source[offset + i++];
if (b >= 0)
ascii[j++] = b;
else {
ascii[j++] = (byte)(0xC0 | ((b >> 6) & 0x3));
ascii[j++] = (byte)(0x80 | (b & 0x3F));
}
}
return j;
}

/** convert ascii bytes in ascii[offset..offset+len-1] to a string
*/
public static String ascii2string(byte ascii[], int offset, int len) {
char cs[] = new char[len];
int i = offset;
int j = 0;
len += offset;
while (i < len) {
int b = ascii[i++] & 0xFF;
if (b >= 0xE0) {
b = ((b & 0x0F) << 12) | (ascii[i++] & 0x3F) << 6;
b = b | (ascii[i++] & 0x3F);
}
else
if (b >= 0xC0)
b = ((b & 0x1F) << 6) | (ascii[i++] & 0x3F);
cs[j++] = (char)b;
}
return new String(cs, 0, j);
}

/** convert string to array of source bytes
*/
public static byte[] string2source(String s) {
byte[] source = new byte[s.length() * 6];
int j = 0;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
switch (ch) {
case '\n':
source[j++] = (byte)'\\';
source[j++] = (byte)'n';
break;
case '\t':
source[j++] = (byte)'\\';
source[j++] = (byte)'t';
break;
case '\b':
source[j++] = (byte)'\\';
source[j++] = (byte)'b';
break;
case '\r':
source[j++] = (byte)'\\';
source[j++] = (byte)'r';
break;
case '\f':
source[j++] = (byte)'\\';
source[j++] = (byte)'f';
break;
case '\"':
source[j++] = (byte)'\\';
source[j++] = (byte)'\"';
break;
case '\'':
source[j++] = (byte)'\\';
source[j++] = (byte)'\'';
break;
case '\\':
source[j++] = (byte)'\\';
source[j++] = (byte)'\\';
break;
default:
if ((' ' <= ch) && (ch <= 127))
source[j++] = (byte)ch;
else {
source[j++] = (byte)'\\';
source[j++] = (byte)'u';
source[j++] = int2digit((ch >> 12) & 0xF);
source[j++] = int2digit((ch >> 8) & 0xF);
source[j++] = int2digit((ch >> 4) & 0xF);
source[j++] = int2digit(ch & 0xF);
}
}
}
byte[] res = new byte[j];
System.arraycopy(source, 0, res, 0, j);
return res;
}

/** convert string to array of ascii bytes
*/
public static byte[] string2ascii(String s) {
byte[] source = string2source(s);
byte[] ascii = new byte[source.length * 2];
int alen = source2ascii(source, 0, source.length, ascii);
byte[] res = new byte[alen];
System.arraycopy(ascii, 0, res, 0, alen);
return res;
}

/** escape all characters outside 32..127 in string s
*/
public static String escape(String s) {
try {
return new String(string2source(s), "8859_1");
} catch (java.io.UnsupportedEncodingException e) {
throw new InternalError(e.getMessage());
}
}

/** escape character c, if outside 32..127.
*/
public static String escape(char c) {
char[] s = {c};
return escape(new String(s));
}
}
@@ -0,0 +1,304 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast.parser;

import java.io.*;
import java.util.Hashtable;
import scalac.util.AbstractFile;
import scalac.util.Name;
import scalac.util.Position;


/** This class represents a single scala source file. It provides
* functionality to read the file and to output error messages on
* a given line and column. Error messages are logged to
* decouple the time where an error message is issued from the
* time where the error messages are displayed.
*
* @author Matthias Zenger
* @version 1.0
*/
public class Sourcefile {

/** the id management
*/
public static int numIds = 1;
public static String[] files = new String[]{"console", null, null, null};
public static Sourcefile[] sources = new Sourcefile[]{null, null, null, null};
public int id;

/** the filename
*/
public final boolean console;
protected String filename;
public String shortname;
public String pathname;

/** the encoding of the file
*/
protected String encoding;

/** a log of all errors generated so far; used to avoid printing an
* error message more than once
*/
protected Hashtable recorded = new Hashtable();

/** the buffer containing the file that is currently translated
*/
protected byte[] buf = null;

/** the last error position
*/
protected int lastLine = 0;
protected int lastPos = 0;
protected int lineEnd = 0;
protected int newPos = 0;

/** constants used for source parsing
*/
final static byte LF = 0xA;
final static byte FF = 0xC;
final static byte CR = 0xD;
final static byte SU = 0x1A;

/** set col to NO_COLUMN, if the printLine method should not mark
* the column
*/
final static int NO_COLUMN = -1;

/** number of lines and bytes (not used internally)
*/
public int lines; // set externally
public int bytes;

/** prompt after error?
*/
public boolean prompt;

/** constructors
*/
public Sourcefile(String filename, boolean console) throws IOException, FileNotFoundException {
this.console = console;
if (filename == null) {
this.filename = "(sourcefile not available)";
this.shortname = "?";
this.pathname = "?";
buf = new byte[]{SU};
} else {
File f = new File(filename);
this.filename = filename;
this.shortname = f.getName();
this.pathname = f.getAbsoluteFile().getParentFile().
getCanonicalPath();
fillBuffer(new FileInputStream(f));
}
if (numIds == files.length) {
String[] newfiles = new String[numIds * 2];
System.arraycopy(files, 0, newfiles, 0, numIds);
files = newfiles;
Sourcefile[] newsources = new Sourcefile[numIds * 2];
System.arraycopy(sources, 0, newsources, 0, numIds);
sources = newsources;
}
sources[numIds] = this;
files[id = numIds++] = shortname;
}

public Sourcefile(AbstractFile abs) throws IOException, FileNotFoundException {
this.console = false;
if (filename == null) {
this.filename = "(sourcefile not available)";
this.shortname = "?";
this.pathname = "?";
buf = new byte[]{SU};
} else {
this.filename = abs.getPath();
this.shortname = abs.getName();
this.pathname = abs.getPath();
fillBuffer(abs.getInputStream());
}
if (numIds == files.length) {
String[] newfiles = new String[numIds * 2];
System.arraycopy(files, 0, newfiles, 0, numIds);
files = newfiles;
Sourcefile[] newsources = new Sourcefile[numIds * 2];
System.arraycopy(sources, 0, newsources, 0, numIds);
sources = newsources;
}
sources[numIds] = this;
files[id = numIds++] = shortname;
}

public Sourcefile(byte[] input, boolean console) {
this.console = console;
if (input == null) {
this.filename = "(sourcefile not available)";
this.shortname = "?";
this.pathname = "?";
buf = new byte[]{SU};
} else {
this.filename = "console";
this.shortname = "console";
this.pathname = "console";
buf = new byte[input.length + 2];
System.arraycopy(input, 0, buf, 0, input.length);
buf[input.length] = Scanner.LF;
buf[input.length + 1] = SU;
}
sources[0] = this;
id = 0;
}

/** fill the buffer using the InputStream
*/
private void fillBuffer(InputStream in) throws IOException {
try {
buf = new byte[(bytes = in.available()) + 1];
if (in.read(buf) != (buf.length - 1))
throw new IOException();
in.close();
buf[buf.length - 1] = SU;
} catch (IOException e) {
throw new IOException("cannot read '" + filename + "'");
}
}

/** return filename as a string
*/
public String toString() {
return filename;
}

/** return filename as a name
*/
public Name getName() {
return Name.fromString(filename);
}

/** return the shortname without the suffix
*/
public String getShortnameWithoutSuffix() {
int idx = shortname.lastIndexOf('.');
if (idx < 0)
return shortname;
else
return shortname.substring(0, idx);
}

/** return the source buffer of this file
*/
public byte[] getBuffer() {
return buf;
}

/** number of logged entries
*/
public int logged() {
return recorded.size();
}

/** is there already an entry at position 'pos'
*/
public boolean isLogged(int pos) {
return (recorded.get(new Integer(pos)) != null);
}

/** enter entry into log table
*/
public void log(int pos, String message) {
recorded.put(new Integer(pos), message);
}

/** set encoding of the file
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}

/** return true if there is an entry for this position,
* otherwise return false and enter message into log
*/
public boolean testAndSetLog(int pos, String message) {
if (!isLogged(pos)) {
log(pos, message);
return false;
}
return true;
}

/** get error message with line from sourcefile
*/
public String getMessage(int pos, String message) {
if (pos == Position.NOPOS)
return filename + ": " + message;
else {
int fileId = Position.file(pos);
String filename = files[fileId];
int line = Position.line(pos);
int col = Position.column(pos);
String main = filename + ":" + line + ": " + message;
if ((fileId > 0) &&
(fileId < numIds) &&
(sources[fileId] != null))
return main + '\n' + sources[fileId].getLine(line, col);
else
return main;
//else
// System.out.println("(source file not available anymore)");
}
}

/** get source line
*/
public String getLine(int line, int col) {
int pos = 0;
if (lastLine > line)
lastLine = 0;
else
pos = newPos;
while ((pos < buf.length) && (lastLine < line))
{
lastPos = pos;
while ((pos < buf.length) && (buf[pos] != CR) &&
(buf[pos] != LF) && (buf[pos] != FF))
pos++;
lineEnd = pos;
if (pos < buf.length)
pos++;
if ((pos < buf.length) && (buf[pos-1] == CR) && (buf[pos] == LF))
pos++;
lastLine++;
}
newPos = pos;
try
{
String errline = (encoding != null) ?
new String(buf, lastPos, lineEnd - lastPos, encoding) :
new String(buf, lastPos, lineEnd - lastPos);
if (col != NO_COLUMN)
{
byte[] ptr = new byte[col];
for (int i = col - 2; i >= 0; i--)
ptr[i] = (byte)' ';
ptr[col - 1] = (byte)'^';
return errline + '\n' + new String(ptr);
} else
return errline;
} catch (UnsupportedEncodingException e) {
throw new InternalError(e.getMessage());
}
}

/** release all sourcefile objects
*/
public static void flushSources() {
for (int i = 0; i < sources.length; i++)
sources[i] = null;
}
}
@@ -0,0 +1,44 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast.parser;

import scalac.util.Name;

/** A class for representing a token's data.
*
* @author Matthias Zenger
* @version 1.0
*/
public class TokenData implements Tokens {

/** the next token
*/
public int token = EMPTY;

/** the token's position. pos = line << Position.LINESHIFT + col
*/
public int pos = 0;

/** the name of an identifier or token
*/
public Name name;

/** the value of a number
*/
public long intVal;
public double floatVal;

public void copyFrom(TokenData td) {
this.token = td.token;
this.pos = td.pos;
this.name = td.name;
this.intVal = td.intVal;
this.floatVal = td.floatVal;
}
}
@@ -0,0 +1,84 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.ast.parser;

public interface Tokens {
byte EMPTY = -3,
UNDEF = -2,
ERROR = -1,
EOF = 0,

/* literals */
CHARLIT = 1,
INTLIT = 2,
LONGLIT = 3,
FLOATLIT = 4,
DOUBLELIT = 5,
STRINGLIT = 6,

/* identifier */
IDENTIFIER = 10,

/* keywords */
IF = 20,
FOR = 21,
ELSE = 22,
THIS = 23,
NULL = 24,
NEW = 25,
WITH = 26,
SUPER = 27,
CASE = 28,
CASECLASS = 29,
VAL = 30,
ABSTRACT = 31,
FINAL = 32,
PRIVATE = 33,
PROTECTED = 34,
QUALIFIED = 35,
OVERRIDE = 36,
VAR = 37,
DEF = 38,
TYPE = 39,
EXTENDS = 40,
LET = 41,
MODULE = 43,
CLASS = 44,
CONSTR = 45,
IMPORT = 46,
PACKAGE = 47,
AS = 48,
IS = 49,
YIELD = 50,
DO = 51,
TRAIT = 52,

/* special symbols */
COMMA = 61,
SEMI = 62,
DOT = 63,
USCORE = 64,
COLON = 65,
EQUALS = 66,
LARROW = 57,
ARROW = 68,
SUBTYPE = 69,
AT = 70,
HASH = 71,

/* parenthesis */
LPAREN = 90,
RPAREN = 91,
LBRACKET = 92,
RBRACKET = 93,
LBRACE = 94,
RBRACE = 95;
}


@@ -0,0 +1,173 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
\* */

// $Id$

package scalac.ast.printer;

import scalac.Unit;
import scalac.symtab.Symbol;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.Math;
import java.util.HashMap;

/**
* HTML pretty printer for Scala abstract syntax trees.
*
* @author Michel Schinz
* @version 1.0
*/

public class HTMLTreePrinter extends TextTreePrinter {
protected int outSectionLevel = 1;
protected boolean started = false;

public HTMLTreePrinter(OutputStream stream) {
super(stream);
}

public void begin() {
assert !started;

super.begin();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<html>");
out.println("<head>");
out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">");
out.println("<link rel=\"stylesheet\" href=\"scala.css\" type=\"text/css\">");
out.println("<title>Scala tree</title>");
out.println("</head>");
out.println("<body>");

started = true;
}

public void end() {
assert started;

out.println("</body>");
out.println("</html>");
super.end();

started = false;
}

public void beginSection(int level, String title) {
outSectionLevel = Math.min(level, 4);
beginSection1(outSectionLevel, title);
}

protected void beginSection1(int level, String title) {
if (level == 1)
out.println("<hr/>");
String tag = "h" + level;
startTag(tag);
print(Text.Simple(title));
endTag(tag);
}

protected void startTag(String tag) {
out.print('<'); out.print(tag); out.print('>');
}

protected void startTag(String tag, String attr1, String val1) {
out.print('<');
out.print(tag);
out.print(' ');
out.print(attr1);
out.print("=\"");
out.print(val1);
out.print("\">");
}

protected void endTag(String tag) {
out.print("</"); out.print(tag); out.print(">");
}

protected void startSpan(String cls) {
startTag("span", "class", cls);
}

protected void endSpan() {
endTag("span");
}

protected void printString(String str) {
StringBuffer buf = null;
int strLen = str.length();

for (int i = 0; i < strLen; ++i) {
String entity;
char c = str.charAt(i);
switch (c) {
case '<': entity = "lt"; break;
case '>': entity = "gt"; break;
case '&': entity = "amp"; break;
default: entity = null; break;
}
if (entity != null) {
out.print('&');
out.print(entity);
out.print(';');
} else
out.print(c);
}
}

protected static HashMap/*<Symbol,Integer>*/ symAnchors = new HashMap();
protected String symbolAnchor(Symbol sym, SymbolUsage usage) {
Integer anchorId = (Integer)symAnchors.get(sym);
if (anchorId == null) {
anchorId = new Integer(symAnchors.size());
symAnchors.put(sym, anchorId);
}
if (usage == SymbolUsage.Definition)
return anchorId.toString();
else
return "#" + anchorId.toString();
}

protected void print(Text text) {
switch (text) {
case Keyword(String name):
startSpan("kw");
printString(name);
endSpan();
break;
case Literal(String str):
startSpan("lit");
printString(str);
endSpan();
break;
case Identifier(Symbol symbol, String name, SymbolUsage usage):
boolean defined = (usage == SymbolUsage.Definition);
if (defined) startSpan("idDef");
if (symbol != null) {
String attr = (defined ? "name" : "href");
startTag("a", attr, symbolAnchor(symbol, usage));
}
printString(name);
if (symbol != null)
endTag("a");
if (defined) endSpan();
break;
default:
super.print(text);
}
}

protected void printUnitHeader(Unit unit) {
beginSection1(outSectionLevel + 1, unit.source.toString());
startTag("pre");
}

protected void printUnitFooter(Unit unit) {
endTag("pre");
}
}