Large diffs are not rendered by default.

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

// $Id$

package scalac.ast.printer;

import java.io.OutputStream;

import scalac.Unit;
import scalac.ast.Tree;

/**
* Interface for all abstract tree printers.
*
* @author Michel Schinz
* @version 1.0
*/
public interface TreePrinter {
public void begin();
public void end();
public void flush();

public void beginSection(int level, String title);

public void print(Unit unit);

public TreePrinter print(Tree tree);
public TreePrinter print(String str);
public TreePrinter println();
}
@@ -0,0 +1,168 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac.checkers;

import scalac.util.*;
import scalac.ast.*;
import scalac.symtab.*;
import scalac.Global;
import scalac.util.Debug;
import Tree.*;

/**
* Check that the owner of symbols is set correctly.
*
* @author Michel Schinz
* @version 1.0
*/

public class CheckOwners extends Checker {
protected Symbol currentOwner;

public CheckOwners(Global global) {
super(global);
currentOwner = global.definitions.ROOT_CLASS;
}

protected void traverse(Tree tree, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
traverse(tree);
currentOwner = prevOwner;
}

protected void traverse(Tree[] array, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
traverse(array);
currentOwner = prevOwner;
}

protected void traverse(Tree[][] array, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
traverse(array);
currentOwner = prevOwner;
}

protected void traverse(Template templ, Symbol owner) {
Symbol prevOwner = currentOwner;
if (owner.kind == Kinds.CLASS)
currentOwner = owner.constructor();
traverse(templ.parents);
currentOwner = owner;

Symbol templSymbol = templ.symbol();
Tree[] body = templ.body;
for (int i = 0; i < body.length; ++i) {
switch (body[i]) {
case PackageDef(_,_):
case ClassDef(_,_,_,_,_,_):
case ModuleDef(_,_,_,_):
case DefDef(_,_,_,_,_,_):
case ValDef(_,_,_,_):
case TypeDef(_,_,_,_):
traverse(body[i], owner);
break;
default:
traverse(body[i], templSymbol);
}
}

currentOwner = prevOwner;
}

protected void checkOwner(Tree tree, Symbol sym) {
Symbol owner = sym.owner();
verify(tree,
owner == currentOwner,
"owner",
"incorrect owner for " + Debug.toString(sym) + ":\n"
+ " found: " + Debug.toString(owner) + "\n"
+ " required: " + Debug.toString(currentOwner));
}

public void traverse(Tree tree) {
switch(tree) {
case PackageDef(Tree packaged, Template impl):
check(tree);
traverse(packaged);
traverse(impl, packaged.symbol());
break;

case ClassDef(int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Template impl): {
check(tree);
traverse(tparams, tree.symbol());
traverse(vparams, tree.symbol());
traverse(tpe);
traverse(impl, tree.symbol());
} break;

case ModuleDef(int mods, Name name, Tree tpe, Template impl): {
check(tree);
traverse(tpe);
traverse(impl, tree.symbol());
} break;

case DefDef(int mods,
Name name,
TypeDef[] tparams,
ValDef[][] vparams,
Tree tpe,
Tree rhs): {
check(tree);
traverse(tparams, tree.symbol());
traverse(vparams, tree.symbol());
traverse(tpe, tree.symbol());
traverse(rhs, tree.symbol());
} break;

case ValDef(int mods, Name name, Tree tpe, Tree rhs): {
check(tree);
traverse(tpe);
traverse(rhs, tree.symbol());
} break;

case TypeDef(int mods, Name name, TypeDef[] tparams, Tree rhs): {
check(tree);
traverse(tparams, tree.symbol());
traverse(rhs, tree.symbol());
} break;

default:
super.traverse(tree);
}
}

public void check(Tree tree) {
switch (tree) {
case PackageDef(_,_):
case ClassDef(_,_,_,_,_,_):
case ModuleDef(_,_,_,_):
case DefDef(_,_,_,_,_,_):
case ValDef(_,_,_,_):
case TypeDef(_,_,_,_): {
Symbol sym = tree.symbol();
if (sym != null && sym != Symbol.NONE) {
checkOwner(tree, sym);
if (sym.kind == Kinds.CLASS)
checkOwner(tree, sym.constructor());
}
} break;

default:
; // nothing to do
}
}
}
@@ -0,0 +1,36 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac.checkers;

import scalac.ast.Tree;
import scalac.symtab.Symbol;
import scalac.Global;

/**
* Verify that all tree nodes for which hasSymbol() is true have a
* non-null symbol.
*
* @author Michel Schinz
* @version 1.0
*/

public class CheckSymbols extends Checker {
public CheckSymbols(Global global) { super(global); }

public void check(Tree tree) {
verify(tree,
implies(tree.hasSymbol(), tree.symbol() != null),
"symbol not null",
"hasSymbol => symbol not null");
verify(tree,
implies(tree.hasSymbol(), tree.symbol() != Symbol.NONE),
"symbol not NONE",
"hasSymbol => symbol not NONE");
}
}
@@ -0,0 +1,30 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac.checkers;

import scalac.ast.Tree;
import scalac.util.Name;
import scalac.symtab.Type;
import scalac.Global;
import scalac.util.Debug;

/**
* Check that all tree nodes have a type.
*
* @author Michel Schinz
* @version 1.0
*/

public class CheckTypes extends Checker {
public CheckTypes(Global global) { super(global); }

public void check(Tree tree) {
verify(tree, tree.type != null, "non-null type", "type of tree is not null");
}
}
@@ -0,0 +1,41 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac.checkers;

import scalac.ast.*;
import scalac.Global;

public abstract class Checker extends Traverser {
protected final Global global;

public Checker(Global global) {
this.global = global;
}

public boolean implies(boolean b1, boolean b2) {
return (!b1) | b2;
}

public void verify(Tree tree, boolean b, String name, String message) {
if (! b) {
System.err.println("ERROR: Condition '" + name + "' violated (after "
+ global.currentPhase + ")!");
System.err.println(message);
global.debugPrinter.print(tree);
System.err.println();
}
}

abstract public void check(Tree tree);

public void traverse(Tree tree) {
check(tree);
super.traverse(tree);
}
}

Large diffs are not rendered by default.

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

package scalac.symtab;


public interface Kinds {

/** kind of error symbol
*/
int ERROR = 0;

/** kind of non-existent symbol
*/
int NONE = 1;

/** definition kinds
*/
int ALIAS = 2;
int CLASS = 3;
int TYPE = 4;
int VAL = 5;
}
@@ -0,0 +1,135 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab;

public interface Modifiers {

// modifiers
int ABSTRACT = 0x00000001;
int FINAL = 0x00000002;
int PRIVATE = 0x00000004;
int PROTECTED = 0x00000008;

int QUALIFIED = 0x00000010;
int OVERRIDE = 0x00000020;
int CASE = 0x00000040;
int ABSTRACTCLASS = 0x00000080; // abstract class

int DEF = 0x00000100; // a def parameter
int SYNTHETIC = 0x00000200;
int DEPRECATED = 0x00000400;
int JAVA = 0x00000800; // symbol was defined by a Java class

int MODUL = 0x00001000; // symbol is module or class implementing a module
int MUTABLE = 0x00002000; // symbol is a mutable variable.
int PARAM = 0x00004000; // symbol is a (type) parameter to a method

int INITIALIZED = 0x00010000; // symbol's definition is complete
int LOCKED = 0x00020000; // temporary flag to catch cyclic dependencies
int ACCESSED = 0x00040000; // symbol was accessed at least once
int SELECTOR = 0x00080000; // symbol was used as selector in Select

int PACKAGE = 0x00100000; // symbol is a java packages.
int LABEL = 0x00200000; // symbol is a label symbol
int STATIC = 0x00400000; // "static" inner classes (i.e. after class norm.)
int STABLE = 0x00800000; // functions that are assumed to be stable
// (typically, access methods for valdefs)

int CAPTURED = 0x01000000; // variables is accessed from nested function.

int ACCESSOR = 0x04000000; // function is an access function for a
// value or variable
int BRIDGE = 0x0800000; // function is a bridge method.

int INTERFACE = 0x10000000; // symbol is a Java interface
int TRAIT = 0x20000000; // symbol is a Trait

int SNDTIME = 0x40000000; //debug

// masks
int SOURCEFLAGS = 0x00000077 | PARAM | TRAIT; // these modifiers can be set in source programs.
int ACCESSFLAGS = PRIVATE | PROTECTED;

public static class Helper {

public static boolean isAbstract(int flags) {
return (flags & (ABSTRACT | ABSTRACTCLASS)) != 0;
}

public static boolean isFinal(int flags) {
return (flags & FINAL) != 0;
}

public static boolean isPrivate(int flags) {
return (flags & PRIVATE) != 0;
}

public static boolean isProtected(int flags) {
return (flags & PROTECTED) != 0;
}

public static boolean isQualified(int flags) {
return (flags & QUALIFIED) != 0;
}

public static boolean isOverride(int flags) {
return (flags & OVERRIDE) != 0;
}

public static boolean isCase(int flags) {
return (flags & CASE) != 0;
}

public static boolean isInterface(int flags) {
return (flags & INTERFACE) != 0;
}

public static boolean isDef(int flags) {
return (flags & DEF) != 0;
}

public static boolean isModClass(int flags) {
return (flags & MODUL) != 0;
}

public static boolean isStatic(int flags) {
return (flags & STATIC) != 0;
}

public static boolean isJava(int flags) {
return (flags & JAVA) != 0;
}

public static boolean isNoVal(int flags) {
return (flags & PACKAGE) != 0;
}

public static String toString(int flags) {
StringBuffer buffer = new StringBuffer();
toString(buffer, flags);
return buffer.toString();
}

public static void toString(StringBuffer buffer, int flags) {
//buffer.append(flags).append(": ");//debug
int marker = buffer.length();
if (isPrivate(flags)) buffer.append("private ");
if (isProtected(flags)) buffer.append("protected ");
if (isAbstract(flags)) buffer.append("abstract ");
if (isFinal(flags)) buffer.append("final ");
if (isQualified(flags)) buffer.append("qualified ");
if (isInterface(flags)) buffer.append("interface ");
if (isCase(flags)) buffer.append("case ");
if (isDef(flags)) buffer.append("def ");
if (isOverride(flags)) buffer.append("override ");
int length = buffer.length();
buffer.setLength(length - (length == marker ? 0 : 1));
}
}
}
@@ -0,0 +1,33 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
**
** $Id$
\* */

package scalac.symtab;

import scalac.util.Name;
import java.util.HashMap;

public class NameMangler {

private HashMap/*<Symbol,HashMap<Symbol,int[]>>*/ mangleMap = new HashMap();

public void setMangledName(Symbol innerclazz) {
Symbol topclazz = innerclazz.enclToplevelClass();
HashMap map = (HashMap) mangleMap.get(topclazz);
if (map == null) {
map = new HashMap();
mangleMap.put(topclazz, map);
}
int[] ctr = (int[]) map.get(innerclazz);
if (ctr == null) {
ctr = new int[1];
map.put(innerclazz, ctr);
}
innerclazz.setMangledName(
Name.fromString(topclazz.name + "$" + (ctr[0]++) + innerclazz.name));
}
}
@@ -0,0 +1,306 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab;

import scalac.util.*;
import scalac.ApplicationError;

public class Scope {

public static abstract class SymbolIterator {
public abstract boolean hasNext();
public abstract Symbol next();
}

/** A symbol iterator that returns all alternatives of an overloaded symbol
* instead of the overloaded symbol itself.
*/
public static class UnloadIterator extends SymbolIterator {
private SymbolIterator iterator;
private Symbol[] alternatives;
private int index;

public UnloadIterator(SymbolIterator iterator) {
this.iterator = iterator;
this.alternatives = null;
this.index = -1;
}

public boolean hasNext() {
return index >= 0 || iterator.hasNext();
}
public Symbol next() {
if (index >= 0) {
Symbol symbol = alternatives[index++];
if (index == alternatives.length) {
alternatives = null;
index = -1;
}
return symbol;
} else {
Symbol symbol = iterator.next();
switch (symbol.type()) {
case OverloadedType(Symbol[] alts, _):
alternatives = alts;
index = 0;
return next();
default:
return symbol;
}
}
}
}

public static class Entry {

/** the absent entry
*/
public static final Entry NONE = new Entry();

/** the symbol of the entry (this is the symbol containing the name)
*/
public Symbol sym;

/** the next entry in the hash bucket
*/
Entry tail;

/** the next entry in this scope
*/
public Entry next;

/** The owner of the entry;
*/
public Scope owner;

Entry(Symbol sym, Scope owner) {
if (sym == null) throw new ApplicationError();
this.sym = sym;
this.owner = owner;
this.next = owner.elems;
owner.elems = this;
}

private Entry() {
this.sym = Symbol.NONE;
}

public Entry setSymbol(Symbol sym) {
this.sym = sym;
owner.elemsCache = null;
return this;
}

public int hashCode() {
return sym.name.index;
}

public String toString() {
return sym.toString();
}
}

/** all elements of this scope
*/
public Entry elems;

/** the hash table
*/
private Entry[] hashtable;

/** a cache for all elements, to be used by symbol iterator.
*/
private Symbol[] elemsCache = null;

/** size and mask of hash tables
* todo: make hashtables grow?
*/
private final int HASHSIZE = 0x80;
private final int HASHMASK = 0x7f;

/** the threshold number of entries from which a hashtable is constructed.
*/
private final int MIN_HASH = 6;

/** construct a new name space
*/
public Scope() {
this.elems = Entry.NONE;
}

public Scope(Entry elems) {
this.elems = elems;
if (size() >= MIN_HASH) createHash();
}

public Scope(Scope base) {
this.elems = base.elems;
if (base.hashtable != null) {
this.hashtable = new Entry[HASHSIZE];
for (int i = 0; i < HASHSIZE; i++)
hashtable[i] = base.hashtable[i];
}
}

public Scope(Symbol[] members) {
this();
for (int i = 0; i < members.length; i++)
enter(members[i]);
}

/** the number of entries in this scope
*/
int size() {
int s = 0;
for (Entry e = elems; e != Entry.NONE; e = e.next) s++;
return s;
}

private Scope enter(Entry e) {
elems = e;
elemsCache = null;
if (hashtable != null) {
int i = e.sym.name.index & HASHMASK;
elems.tail = hashtable[i];
hashtable[i] = elems;
} else if (size() >= MIN_HASH) {
createHash();
}
return this;
}

/** enter a symbol
*/
public Scope enter(Symbol sym) {
return enter(new Entry(sym, this));
}

public Scope enterOrOverload(Symbol sym) {
Entry e = lookupEntry(sym.name);
if (e.owner == this && (sym.flags & Modifiers.PRIVATE) == 0) {
e.setSymbol(e.sym.overloadWith(sym));
return this;
} else {
return enter(sym);
}
}

private void createHash() {
hashtable = new Entry[HASHSIZE];
for (int i = 0; i < HASHSIZE; i++)
hashtable[i] = Entry.NONE;
enterInHash(elems);
}

private void enterInHash(Entry e) {
if (e != Entry.NONE) {
enterInHash(e.next);
int i = e.sym.name.index & HASHMASK;
e.tail = hashtable[i];
hashtable[i] = e;
}
}

/** remove entry
*/
public void unlink(Entry e) {
Entry e1 = hashtable[e.sym.name.index & HASHMASK];
if (e1 == e) {
hashtable[e.sym.name.index & HASHMASK] = e.tail;
} else {
while (e1.tail != e) e1 = e1.tail;
}
if (elems == e) {
elems = e.next;
} else {
e1 = elems;
while (e1.next != e) e1 = e1.next;
e1.next = e.next;
}
elemsCache = null;
}

/** lookup a symbol
*/
public Symbol lookup(Name name) {
return lookupEntry(name).sym;
}

/** lookup a symbol entry.
*/
public Entry lookupEntry(Name name) {
Entry e;
if (hashtable != null) {
e = hashtable[name.index & HASHMASK];
while (e != Entry.NONE && e.sym.name != name) e = e.tail;
} else {
e = elems;
while (e != Entry.NONE && e.sym.name != name) e = e.next;
}
return e;
}

/** return all symbols as an array,
* in the order they were entered in this scope.
*/
public Symbol[] elements() {
if (elemsCache == null) {
int s = size();
elemsCache = new Symbol[s];
for (Entry e = elems; e != Entry.NONE; e = e.next)
elemsCache[--s] = e.sym;
}
return elemsCache;
}

/** return all symbols as an iterator,
* in the order they were entered in this scope.
*/
public SymbolIterator iterator() { return new MySymbols(); }

class MySymbols extends SymbolIterator {

private int index;
MySymbols() {
elements();
index = 0;
}

public boolean hasNext() {
return index < elemsCache.length;
}

public Symbol next() {
return elemsCache[index++];
}
}

public String toString() {
StringBuffer str = new StringBuffer("{");
SymbolIterator it = iterator();
while (it.hasNext()) {
str.append("\n " + it.next().defString());
}
str.append("}");
return str.toString();
}

public String simpleToString() {
StringBuffer str = new StringBuffer("{");
SymbolIterator it = iterator();
while (it.hasNext()) {
str.append("\n " + it.next().name);
}
str.append("}");
return str.toString();
}

public static Scope EMPTY = new Scope();
}

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

package scalac.symtab;

import scalac.*;
import scalac.ast.parser.*;
import scalac.typechecker.Analyzer;
import java.io.*;


public class SourceCompleter extends Type.LazyType {

/** the global compilation environment
*/
protected Global global;
protected String filename;
private boolean completed = false;

public SourceCompleter(Global global, String filename) {
this.global = global;
this.filename = filename;
}

/** complete class symbol c by loading the class
*/
public void complete(Symbol c) {
if (completed) {
c.setInfo(Type.ErrorType);
} else if (filename != null) {
try {
String fname = filename;
long msec = System.currentTimeMillis();
Unit unit = new Unit(global, new Sourcefile(filename, false));
filename = null;
global.PHASE.PARSER.createPhase(global).apply(unit);
((Analyzer)global.PHASE.ANALYZER.createPhase(global)).lateEnter(unit, c);
global.operation("added " + fname + " in " +
(System.currentTimeMillis() - msec) + "ms");
} catch (IOException e) {
e.printStackTrace();
global.error("i/o error while loading " + c);
c.setInfo(Type.ErrorType);
}
completed = true;
}
}
}
@@ -0,0 +1,89 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */

// $Id$

package scalac.symtab;

/** Sets of symbols, implemented as binary trees.
*/
public class SymSet {
private SymSet l, r;
private Symbol sym;

public SymSet() {}

private SymSet(Symbol sym, SymSet l, SymSet r) {
this.sym = sym; this.l = l; this.r = r;
}

/** Union of this set and `{sym}'.
*/
public SymSet incl(Symbol sym) {
if (this == EMPTY) {
return new SymSet(sym, EMPTY, EMPTY);
} else if (sym == this.sym) {
return this;
} else if (sym.isLess(this.sym)) {
return new SymSet(this.sym, l.incl(sym), r);
} else {
assert this.sym.isLess(sym);
return new SymSet(this.sym, l, r.incl(sym));
}
}

/** Is `sym' an element of this set?
*/
public boolean contains(Symbol sym) {
if (this == EMPTY) {
return false;
} else if (sym == this.sym) {
return true;
} else if (sym.isLess(this.sym)) {
return l.contains(sym);
} else {
assert this.sym.isLess(sym);
return r.contains(sym);
}
}

/** The number of elements in ths set.
*/
public int size() {
if (this == EMPTY) {
return 0;
} else {
return 1 + l.size() + r.size();
}
}

/** Copy elements of this set into `ss', starting at index `from'.
* Return index one past last element copied.
*/
public int copyToArray(Symbol[] ss, int from) {
if (this == EMPTY) {
return from;
} else {
from = l.copyToArray(ss, from);
ss[from] = sym;
return r.copyToArray(ss, from + 1);
}
}

/** Return all elements of this set as an array.
*/
public Symbol[] toArray() {
int s = size();
if (s == 0) return Symbol.EMPTY_ARRAY;
Symbol[] ss = new Symbol[s];
copyToArray(ss, 0);
return ss;
}

/** The empty set.
*/
public final static SymSet EMPTY = new SymSet();
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

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

package scalac.symtab;

public interface TypeTags {

/** unboxed type tags
*/
int BYTE = 10;
int CHAR = 11;
int SHORT = 12;
int INT = 13;
int LONG = 14;
int FLOAT = 15;
int DOUBLE = 16;
int BOOLEAN = 17;
int UNIT = 18;
int STRING = 19;

int FirstUnboxedTag = BYTE;
int LastUnboxedTag = UNIT;

/** other type tags (used for hashcodes and Pickling)
*/
int ERRORtpe = 20;
int NOtpe = 21;
int THIStpe = 22;
int NAMEDtpe = 23;
int SINGLEtpe = 24;
int COMPOUNDtpe = 25;
int METHODtpe = 26;
int POLYtpe = 27;
int CONSTRUCTORtpe = 28;
int COVARtpe = 29;
int OVERLOADEDtpe = 30;
int UNBOXEDtpe = 31;
int UNBOXEDARRAYtpe = 32;

int firstTypeTag = ERRORtpe;
int lastTypeTag = UNBOXEDARRAYtpe;
}

Large diffs are not rendered by default.

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

package scalac.symtab.classfile;

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


public class ClassParser extends Type.LazyType {

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

public ClassParser(Global global) {
this.global = global;
}

/** complete class symbol c by loading the class
*/
public void complete(Symbol c) {
//System.out.println("loading " + c);//DEBUG
try {
long msec = System.currentTimeMillis();
String filename = externalizeFileName(c.fullName()) + ".class";
AbstractFile f = global.classPath.openFile(filename);
if (f == null)
global.error("could not read class " + c);
else {
new ClassfileParser(global, new AbstractFileReader(f), c).parse();
global.operation("loaded " + f.getPath() + " in " +
(System.currentTimeMillis() - msec) + "ms");
//for (Definition e = c.locals().elems; e != null; e = e.sibling)
// if (e.def.kind == TYP)
// e.def.complete();
}
} catch (IOException e) {
e.printStackTrace();
global.error("i/o error while loading " + c);
c.setInfo(Type.ErrorType);
}
}

/** return external representation of file name s,
* converting '.' to File.separatorChar
*/
public String externalizeFileName(Name n) {
if ((n == null) || (n.length() == 0))
return ".";
byte[] ascii = n.toAscii();
String s = SourceRepresentation.ascii2string(
ascii, 0, ascii.length);
return s.replace('.', File.separatorChar);
}

public Type.LazyType staticsParser(Symbol clazz) {
return new StaticsParser(clazz);
}

public Type.LazyType aliasParser(Symbol alias) {
return new AliasParser(alias);
}

class StaticsParser extends Type.LazyType {
Symbol clazz;

StaticsParser(Symbol clazz) {
this.clazz = clazz;
}

public void complete(Symbol statics) {
ClassParser.this.complete(clazz);
}
}

class AliasParser extends Type.LazyType {
Symbol alias;

AliasParser(Symbol alias) {
this.alias = alias;
}

public void complete(Symbol c) {
try {
long msec = System.currentTimeMillis();
String filename = externalizeFileName(alias.fullName()) + ".class";
AbstractFile f = global.classPath.openFile(filename);
if (f == null)
global.error("could not read class " + c);
else {
new ClassfileParser(global, new AbstractFileReader(f), c).parse();
global.operation("loaded " + f.getPath() + " in " +
(System.currentTimeMillis() - msec) + "ms");
}
} catch (IOException e) {
e.printStackTrace();
global.error("i/o error while loading " + c);
c.setInfo(Type.ErrorType);
}
}
}
}

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

package scalac.symtab.classfile;

import scalac.util.Name;

public interface ClassfileConstants {

int JAVA_MAGIC = 0xCAFEBABE;
int JAVA_MAJOR_VERSION = 45;
int JAVA_MINOR_VERSION = 3;

int CONSTANT_UTF8 = 1;
int CONSTANT_UNICODE = 2;
int CONSTANT_INTEGER = 3;
int CONSTANT_FLOAT = 4;
int CONSTANT_LONG = 5;
int CONSTANT_DOUBLE = 6;
int CONSTANT_CLASS = 7;
int CONSTANT_STRING = 8;
int CONSTANT_FIELDREF = 9;
int CONSTANT_METHODREF = 10;
int CONSTANT_INTFMETHODREF = 11;
int CONSTANT_NAMEANDTYPE = 12;

int BAD_ATTR = 0x00000;
int SOURCEFILE_ATTR = 0x00001;
int SYNTHETIC_ATTR = 0x00002;
int DEPRECATED_ATTR = 0x00004;
int CODE_ATTR = 0x00008;
int EXCEPTIONS_ATTR = 0x00010;
int CONSTANT_VALUE_ATTR = 0x00020;
int LINE_NUM_TABLE_ATTR = 0x00040;
int LOCAL_VAR_TABLE_ATTR = 0x00080;
int INNERCLASSES_ATTR = 0x08000;
int META_ATTR = 0x10000;
int SCALA_ATTR = 0x20000;

Name SOURCEFILE_N = Name.fromString("SourceFile");
Name SYNTHETIC_N = Name.fromString("Synthetic");
Name DEPRECATED_N = Name.fromString("Deprecated");
Name CODE_N = Name.fromString("Code");
Name EXCEPTIONS_N = Name.fromString("Exceptions");
Name CONSTANT_VALUE_N = Name.fromString("ConstantValue");
Name LINE_NUM_TABLE_N = Name.fromString("LineNumberTable");
Name LOCAL_VAR_TABLE_N = Name.fromString("LocalVariableTable");
Name INNERCLASSES_N = Name.fromString("InnerClasses");
Name META_N = Name.fromString("JacoMeta");
Name SCALA_N = Name.fromString("ScalaSignature");
Name CONSTR_N = Name.fromString("<init>");
}
@@ -0,0 +1,239 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

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

//todo: don't keep statics module in scope.

public class ClassfileParser implements ClassfileConstants {

static final int CLASS_ATTR = SOURCEFILE_ATTR
| INNERCLASSES_ATTR
| SYNTHETIC_ATTR
| DEPRECATED_ATTR
| META_ATTR
| SCALA_ATTR;
static final int METH_ATTR = CODE_ATTR
| EXCEPTIONS_ATTR
| SYNTHETIC_ATTR
| DEPRECATED_ATTR
| META_ATTR;
static final int FIELD_ATTR = CONSTANT_VALUE_ATTR
| SYNTHETIC_ATTR
| DEPRECATED_ATTR
| META_ATTR;

protected Global global;
protected AbstractFileReader in;
protected Symbol c;
protected Type ctype;
protected Scope locals;
protected Scope statics;
protected Scope constr;
protected JavaTypeFactory make;
protected Signatures sigs;
protected ConstantPool pool;
protected AttributeParser attrib;
protected Definitions defs;
protected int phaseId;


public ClassfileParser(Global global, AbstractFileReader in, Symbol c) {
this.global = global;
this.in = in;
this.c = c;
this.ctype = Type.TypeRef(c.owner().thisType(), c, Type.EMPTY_ARRAY);
this.make = new JavaTypeCreator(global);
this.sigs = new Signatures(global, make);
this.pool = new ConstantPool(in, sigs);
this.attrib = new AttributeParser(in, pool, this);
this.defs = global.definitions;
this.phaseId = global.POST_ANALYZER_PHASE_ID;
}


/** parse the classfile and throw IO exception if there is an
* error in the classfile structure
*/
public void parse() throws IOException {
try {
if (in.nextInt() != JAVA_MAGIC)
throw new IOException("illegal start of class file");
int minorVersion = in.nextChar();
int majorVersion = in.nextChar();
if ((majorVersion < JAVA_MAJOR_VERSION) ||
((majorVersion == JAVA_MAJOR_VERSION) &&
(minorVersion < JAVA_MINOR_VERSION)))
throw new IOException("class file has wrong version " +
majorVersion + "." + minorVersion + ", should be " +
JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION);
pool.indexPool();
int flags = in.nextChar();
Name name = readClassName(in.nextChar());
if (c.fullName() != name)
throw new IOException("class file '" + c.fullName() +
"' contains wrong class " + name);
// todo: correct flag transition
c.flags = transFlags(flags);
if ((c.flags & Modifiers.ABSTRACT) != 0)
c.flags = c.flags & ~Modifiers.ABSTRACT | Modifiers.ABSTRACTCLASS;
Type supertpe = readClassType(in.nextChar());
Type[] basetpes = new Type[in.nextChar() + 1];
this.locals = new Scope();
this.statics = new Scope();
this.constr = new Scope();
// set type of class
Type classType = Type.compoundType(basetpes, locals, c);
c.setInfo(classType, phaseId);
// set type of statics
Symbol staticsClass = c.module().moduleClass();
Type staticsInfo = Type.compoundType(Type.EMPTY_ARRAY, statics, staticsClass);
staticsClass.setInfo(staticsInfo, phaseId);
c.module().setInfo(Type.TypeRef(staticsClass.owner().thisType(),
staticsClass, Type.EMPTY_ARRAY));
basetpes[0] = supertpe;
for (int i = 1; i < basetpes.length; i++)
basetpes[i] = readClassType(in.nextChar());
int fieldCount = in.nextChar();
for (int i = 0; i < fieldCount; i++)
parseField();
int methodCount = in.nextChar();
for (int i = 0; i < methodCount; i++)
parseMethod();
// set constructor type to the declared type
Symbol[] constrs = constr.elements();
if (constrs.length != 0) {
assert constrs.length == 1;
c.constructor().setInfo(constrs[0].info(), phaseId);
} else {
Type constrtype = ((c.flags & Modifiers.INTERFACE) != 0)
? Type.PolyType(Symbol.EMPTY_ARRAY, ctype)
: Type.MethodType(new Symbol[]{Symbol.NONE}, ctype);
c.constructor().setInfo(constrtype, phaseId);
}
attrib.readAttributes(c, classType, CLASS_ATTR);
//System.out.println("dynamic class: " + c);
//System.out.println("statics class: " + staticsClass);
//System.out.println("module: " + c.module());
//System.out.println("modules class: " + c.module().type().symbol());
} catch (RuntimeException e) {
e.printStackTrace();
throw new IOException("bad class file (" + e.getMessage() + ")");
}
}

/** convert Java modifiers into Scala flags
*/
public int transFlags(int flags) {
int res = 0;
if (((flags & 0x0007) == 0) ||
((flags & 0x0002) != 0))
res |= Modifiers.PRIVATE;
else if ((flags & 0x0004) != 0)
res |= Modifiers.PROTECTED;
if ((flags & 0x0400) != 0)
res |= Modifiers.ABSTRACT;
if ((flags & 0x0010) != 0)
res |= Modifiers.FINAL;
if ((flags & 0x0200) != 0)
res |= Modifiers.INTERFACE | Modifiers.ABSTRACTCLASS;
return res | Modifiers.JAVA;
}

/** read a class name
*/
protected Name readClassName(int i) {
return (Name)pool.readPool(i);
}

/** read a class name and return the corresponding class type
*/
protected Type readClassType(int i) {
if (i == 0)
return defs.ANY_TYPE;
Type res = defs.getJavaType((Name)pool.readPool(i));
if (res == Type.ErrorType)
global.error("unknown class reference " + pool.readPool(i));
if (res.symbol() == defs.JAVA_OBJECT_TYPE.symbol())
return defs.ANYREF_TYPE;
else
return res;
}

/** read a signature and return it as a type
*/
protected Type readType(int i) {
Name sig = pool.readExternal(i);
return sigs.sigToType(Name.names, sig.index, sig.length());
}

/** read a field
*/
protected void parseField() {
int flags = in.nextChar();
Name name = (Name)pool.readPool(in.nextChar());
Type type = readType(in.nextChar());
int mods = transFlags(flags);
if ((flags & 0x0010) == 0)
mods |= Modifiers.MUTABLE;
Symbol owner = c;
if ((flags & 0x0008) != 0)
owner = c.module().moduleClass();
Symbol s = new TermSymbol(Position.NOPOS, name, owner, mods);
s.setInfo(type, phaseId);
attrib.readAttributes(s, type, FIELD_ATTR);
((flags & 0x0008) != 0 ? statics : locals).enterOrOverload(s);
}

/** read a method
*/
protected void parseMethod() {
int flags = in.nextChar();
Name name = (Name)pool.readPool(in.nextChar());
Type type = readType(in.nextChar());
if (CONSTR_N.equals(name)) {
Symbol s = TermSymbol.newConstructor(c, transFlags(flags));
// kick out protected, package visible or
// private constructors
if (((flags & 0x0004) != 0) ||
((flags & 0x0002) != 0) ||
((flags & 0x0007) == 0)) {
attrib.readAttributes(s, type, METH_ATTR);
return;
}
switch (type) {
case MethodType(Symbol[] vparams, _):
if (c == defs.OBJECT_CLASS)
type = Type.PolyType(Symbol.EMPTY_ARRAY, ctype);
else
type = Type.MethodType(vparams, ctype);
break;
default:
throw new ApplicationError();
}
s.setInfo(type, phaseId);
attrib.readAttributes(s, type, METH_ATTR);
//System.out.println("-- enter " + s);
constr.enterOrOverload(s);
} else {
Symbol s = new TermSymbol(
Position.NOPOS, name,
((flags & 0x0008) != 0) ? c.module().moduleClass() : c,
transFlags(flags));
s.setInfo(type, phaseId);
attrib.readAttributes(s, type, METH_ATTR);
((flags & 0x0008) != 0 ? statics : locals).enterOrOverload(s);
}
}
}
@@ -0,0 +1,183 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

import scalac.*;
import scalac.symtab.*;
import scalac.util.*;

public class ConstantPool implements ClassfileConstants {

AbstractFileReader in;
Signatures sigparser;

/** the objects of the constant pool
*/
protected Object[] poolObj;

/** for every constant pool entry, an index into in.buf where the
* defining section of the entry is found
*/
protected int[] poolIdx;

/** constructor
*/
protected ConstantPool(AbstractFileReader in, Signatures sigparser) {
this.in = in;
this.sigparser = sigparser;
}

/** index all constant pool entries, writing their start
* addresses into poolIdx
*/
public void indexPool() {
poolIdx = new int[in.nextChar()];
poolObj = new Object[poolIdx.length];
int i = 1;
while (i < poolIdx.length) {
poolIdx[i++] = in.bp;
byte tag = in.nextByte();
switch (tag) {
case CONSTANT_UTF8:
case CONSTANT_UNICODE: {
int len = in.nextChar();
in.skip(len);
break;
}
case CONSTANT_CLASS:
case CONSTANT_STRING:
in.skip(2);
break;
case CONSTANT_FIELDREF:
case CONSTANT_METHODREF:
case CONSTANT_INTFMETHODREF:
case CONSTANT_NAMEANDTYPE:
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
in.skip(4);
break;
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
in.skip(8);
i++;
break;
default:
throw new RuntimeException("bad constant pool tag: " + tag +
" at " + (in.bp - 1));
}
}
}

/** if name is an array type or class signature, return the
* corresponding type; otherwise return a class definition with given name
*/
protected Object classOrType(Name name) {
if ((name.sub(0) == '[') || (name.sub(name.length() - 1) == ';')) {
byte[] ascii = name.toAscii();
return sigparser.sigToType(ascii, 0, ascii.length);
} else
return name;
}

/** read constant pool entry at start address i, use poolObj as a cache.
*/
public Object readPool(int i) {
if (poolObj[i] != null)
return poolObj[i];
int index = poolIdx[i];
if (index == 0)
return null;
switch (in.byteAt(index)) {
case CONSTANT_UTF8:
poolObj[i] = Name.fromAscii(in.buf, index + 3, in.getChar(index + 1));
break;

case CONSTANT_UNICODE:
throw new RuntimeException("can't read unicode strings in classfiles");

case CONSTANT_CLASS:
poolObj[i] = classOrType(readExternal(in.getChar(index + 1)));
break;

case CONSTANT_FIELDREF: {
//Symbol owner = (Symbol)readPool(in.getChar(index + 1));
//NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
//poolObj[i] = new TermSymbol(Kinds.VAR, Position.NOPOS, nt.name, owner, 0)
// .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
throw new RuntimeException("can't read constant_fieldrefs in classfiles");
}

case CONSTANT_METHODREF:
case CONSTANT_INTFMETHODREF: {
//Symbol owner = (Symbol)readPool(in.getChar(index + 1));
//NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
//poolObj[i] = new TermSymbol(Kinds.FUN, Position.NOPOS, nt.name, owner, 0)
// .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
throw new RuntimeException("can't read constant_methodrefs in classfiles");
}

case CONSTANT_NAMEANDTYPE:
poolObj[i] = new NameAndType((Name)readPool(in.getChar(index + 1)),
readExternal(in.getChar(index + 3)));
break;

case CONSTANT_STRING:
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
throw new RuntimeException("can't read constants in classfiles");

default:
throw new RuntimeException("bad constant pool tag: " + in.byteAt(index));
}
return poolObj[i];
}

/** return internal representation of buf[offset..offset+len-1],
* converting '/' to '.'
*/
public byte[] internalize(byte[] buf, int offset, int len) {
byte[] translated = new byte[len];
for (int j = 0; j < len; j++) {
byte b = buf[offset + j];
if (b == '/')
translated[j] = '.';
else
translated[j] = b;
}
return translated;
}

/** read a constant pool string and convert to internal representation.
*/
public Name readExternal(int i) {
if (poolObj[i] == null) {
int index = poolIdx[i];
if (in.byteAt(index) == CONSTANT_UTF8) {
int len = in.getChar(index + 1);
byte[] translated = internalize(in.buf, index + 3, len);
poolObj[i] = Name.fromAscii(translated, 0, len);
}
}
return (Name)poolObj[i];
}

/** the name and type signature of a method or field
*/
public static final class NameAndType {
public Name name;
public Name sig;

public NameAndType(Name name, Name sig) {
this.name = name;
this.sig = sig;
}
}
}
@@ -0,0 +1,82 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

import scalac.Global;
import scalac.util.*;
import scalac.symtab.*;
import Type.*;


public class JavaTypeCreator implements JavaTypeFactory {

protected Global global;

public JavaTypeCreator(Global global) {
this.global = global;
}

public Type byteType() {
return global.definitions.BYTE_TYPE;
}

public Type shortType() {
return global.definitions.SHORT_TYPE;
}

public Type charType() {
return global.definitions.CHAR_TYPE;
}

public Type intType() {
return global.definitions.INT_TYPE;
}

public Type longType() {
return global.definitions.LONG_TYPE;
}

public Type floatType() {
return global.definitions.FLOAT_TYPE;
}

public Type doubleType() {
return global.definitions.DOUBLE_TYPE;
}

public Type booleanType() {
return global.definitions.BOOLEAN_TYPE;
}

public Type voidType() {
return global.definitions.UNIT_TYPE;
}

public Type classType(Name classname) {
return global.definitions.getJavaType(classname);
}

public Type arrayType(Type elemtpe) {
return global.definitions.arrayType(elemtpe);
}

public Type methodType(Type[] argtpes, Type restpe, Type[] thrown) {
Symbol[] args = new Symbol[argtpes.length];
for (int i = 0; i < args.length; i++) {
args[i] = new TermSymbol(
Position.NOPOS, Name.fromString("x" + i), Symbol.NONE, Modifiers.PARAM);
args[i].setInfo(argtpes[i]);
}
return new MethodType(args, restpe);
}

public Type packageType(Name packagename) {
return null;
}
}
@@ -0,0 +1,28 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

import scalac.symtab.Type;
import scalac.util.Name;

public interface JavaTypeFactory {
Type byteType();
Type shortType();
Type charType();
Type intType();
Type longType();
Type floatType();
Type doubleType();
Type booleanType();
Type voidType();
Type classType(Name classname);
Type arrayType(Type elemtpe);
Type methodType(Type[] argtpes, Type restpe, Type[] thrown);
Type packageType(Name packagename);
}
@@ -0,0 +1,129 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

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

public class PackageParser extends Type.LazyType {

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

/** the class parser
*/
public ClassParser classCompletion;

public PackageParser(Global global) {
this.global = global;
this.classCompletion = new ClassParser(global);
}

/** complete package type symbol p by loading all package members
*/
public void complete(Symbol p) {
long msec = System.currentTimeMillis();
Scope members = new Scope();
String dirname = null;
Name name = p.fullName();
if (name.length() == 0) {
// includeMembers(AbstractFile.open(null, "."), p, members, false);
} else {
dirname = externalizeFileName(name);
assert !dirname.startsWith("com") : p;//debug
if (!dirname.endsWith("/"))
dirname += "/";
}
String[] base = global.classPath.components();
for (int i = 0; i < base.length; i++) {
includeMembers(
AbstractFile.open(base[i], dirname), p, members, dirname != null);
}
p.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, p));
if (dirname == null)
dirname = "anonymous package";
global.operation("scanned " + dirname + " in " +
(System.currentTimeMillis() - msec) + "ms");
}

/** read directory of a classpath directory and include members
* in package/module scope
*/
protected void includeMembers(AbstractFile dir, Symbol p, Scope locals,
boolean inclClasses) {
if (dir == null)
return;
String[] filenames = null;
try {
if ((filenames = dir.list()) == null)
return;
for (int j = 0; j < filenames.length; j++) {
String fname = filenames[j];
if (inclClasses && fname.endsWith(".class")) {
Name n = Name.fromString(fname.substring(0, fname.length() - 6))
.toTypeName();
ClassSymbol clazz = new ClassSymbol(n, p, classCompletion);
clazz.constructor().setInfo(
classCompletion.staticsParser(clazz));
// enter class
locals.enter(clazz);
locals.enter(clazz.constructor());
// enter module, except for scala.Object class
// todo: why not there also?.
if (!(n == Names.Object.toTypeName() &&
p.fullName().toTermName() == Names.scala)) {
Scope.Entry e = locals.lookupEntry(clazz.module().name);
if (e != Scope.Entry.NONE) {
// we already have a package of the same name; delete it
locals.unlink(e);
}
locals.enter(clazz.module());
}
} else if (fname.endsWith("/") && !fname.equals("META-INF/")) {
Name n = Name.fromString(fname.substring(0, fname.length() - 1));
if (locals.lookup(n) == Symbol.NONE) {
TermSymbol module = TermSymbol.newJavaPackageModule(n, p, this);
locals.enter(module);
}
} else if (fname.endsWith(".scala")) {
Name n = Name.fromString(fname.substring(0, fname.length() - 6))
.toTypeName();
if (locals.lookup(n) == Symbol.NONE) {
SourceCompleter completer = new SourceCompleter(global,
dir.getPath() + File.separatorChar + fname);
ClassSymbol clazz = new ClassSymbol(n, p, completer);
clazz.constructor().setInfo(completer);
clazz.module().setInfo(completer);
// enter class
locals.enter(clazz);
locals.enter(clazz.constructor());
locals.enter(clazz.module());
}
}
}
} catch (IOException e) {
}
}

/** return external representation of file name s,
* converting '.' to File.separatorChar
*/

public String externalizeFileName(Name n) {
if ((n == null) || (n.length() == 0))
return ".";
byte[] ascii = n.toAscii();
String s = SourceRepresentation.ascii2string(
ascii, 0, ascii.length);
return s.replace('.', File.separatorChar);
}
}
@@ -0,0 +1,122 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.symtab.classfile;

import scalac.*;
import scalac.symtab.*;
import scalac.util.*;
import java.util.*;
import Type.*;

public class Signatures {

/** signature constants
*/
Name BYTE_SIG = Name.fromString("B");
Name SHORT_SIG = Name.fromString("S");
Name CHAR_SIG = Name.fromString("C");
Name INT_SIG = Name.fromString("I");
Name LONG_SIG = Name.fromString("J");
Name FLOAT_SIG = Name.fromString("F");
Name DOUBLE_SIG = Name.fromString("D");
Name BOOLEAN_SIG = Name.fromString("Z");
Name VOID_SIG = Name.fromString("V");
Name CLASS_SIG = Name.fromString("L");
Name ARRAY_SIG = Name.fromString("[");
Name ARGBEGIN_SIG = Name.fromString("(");
Name ARGEND_SIG = Name.fromString(")");

Global global;
JavaTypeFactory make;


public Signatures(Global global, JavaTypeFactory make) {
this.make = make;
this.global = global;
}

/** the type represented by signature[offset..].
*/
protected byte[] signature;
protected int sigp;
protected int limit;

public Type sigToType(byte[] sig, int offset, int len) {
signature = sig;
sigp = offset;
limit = offset + len;
return sigToType();
}

protected Type sigToType() {
switch (signature[sigp]) {
case 'B':
sigp++;
return make.byteType();
case 'C':
sigp++;
return make.charType();
case 'D':
sigp++;
return make.doubleType();
case 'F':
sigp++;
return make.floatType();
case 'I':
sigp++;
return make.intType();
case 'J':
sigp++;
return make.longType();
case 'L':
sigp++;
int start = sigp;
while (signature[sigp] != ';')
sigp++;
return make.classType(Name.fromAscii(signature, start, (sigp++) - start));
case 'S':
sigp++;
return make.shortType();
case 'V':
sigp++;
return make.voidType();
case 'Z':
sigp++;
return make.booleanType();
case '[':
sigp++;
while (('0' <= signature[sigp]) && (signature[sigp] <= '9'))
sigp++;
return make.arrayType(sigToType());
case '(':
return make.methodType(sigToTypes(')'), sigToType(), Type.EMPTY_ARRAY);
default:
global.error("bad signature: " +
SourceRepresentation.ascii2string(signature, sigp, 1));
return Type.ErrorType;
}
}

protected Type[] sigToTypes(char terminator) {
sigp++;
return sigToTypes(terminator, 0);
}

protected Type[] sigToTypes(char terminator, int i) {
if (signature[sigp] == terminator) {
sigp++;
return new Type[i];
} else {
Type t = sigToType();
Type[] vec = sigToTypes(terminator, i+1);
vec[i] = t;
return vec;
}
}
}

Large diffs are not rendered by default.

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

// $Id$

package scalac.transformer;

import scalac.*;
import scalac.util.*;
import scalac.parser.*;
import scalac.symtab.*;
import scalac.checkers.*;

public class LambdaLiftPhase extends PhaseDescriptor implements Kinds, Modifiers {

private Global global;
int nextPhase;

public void initialize(Global global, int id) {
super.initialize(global, id);
this.global = global;
this.nextPhase = id + 1;
}

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

public String description () {
return "lambda lifter";
}

public String taskDescription() {
return "lambda lifting";
}

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

public Type transformInfo(Symbol sym, Type tp) {
Type tp1 = transform(tp, sym.owner());
if ((sym.flags & Modifiers.CAPTURED) != 0) return refType(tp1);
else return tp1;
}

/** Add proxies as type arguments for propagated type parameters.
*/
Type transform(Type tp, Symbol owner) {
return transformTypeMap.setOwner(owner).apply(tp);
}

private class TransformTypeMap extends Type.Map {
Symbol owner;
Type.Map setOwner(Symbol owner) { this.owner = owner; return this; }

public Type apply(Type tp) {
switch (tp) {
case TypeRef(Type pre, Symbol sym, Type[] targs):
switch (pre) {
case ThisType(_):
if (sym.constructor().isUpdated(nextPhase)) {
System.out.println("updated: " + sym.constructor());//debug
Symbol[] tparams =
sym.constructor().infoAt(nextPhase).typeParams();
int i = tparams.length;
while (i > 0 && (tparams[i-1].flags & SYNTHETIC) != 0)
i--;
if (i < tparams.length) {
Type[] targs1 = new Type[tparams.length];
System.arraycopy(map(targs), 0, targs1, 0, targs.length);
while (i < tparams.length) {
targs1[i] = proxy(tparams[i], owner).type();
}
return Type.TypeRef(pre, sym, targs1);
}
}
}
break;
}
return map(tp);
}

/** All symbols are mapped to themselves.
*/
public Scope map(Scope s) { return s; }
public Symbol map(Symbol s) { return s; }
public Symbol[] map(Symbol[] ss) { return ss; }
}

private TransformTypeMap transformTypeMap = new TransformTypeMap();

/** Return closest enclosing (type)parameter that has same name as `fv',
* or `fv' itself if this is the closest definition.
*/
Symbol proxy(Symbol fv, Symbol owner) {
if (global.debug)
global.log("proxy " + fv + " in " + LambdaLift.asFunction(owner));
Symbol o = owner;
while (o.kind != NONE) {
Symbol fowner = LambdaLift.asFunction(o);
if (fv.owner() == fowner) return fv;
Type ft = (fowner.isUpdated(nextPhase)) ? fowner.typeAt(nextPhase)
: fowner.type();
Symbol[] ownerparams = fv.isType() ? ft.typeParams()
: ft.firstParams();
for (int i = 0; i < ownerparams.length; i++) {
if (ownerparams[i].name == fv.name)
return ownerparams[i];
}
o = o.owner();
}
throw new ApplicationError("proxy " + fv + " in " + owner);
}

/** The type scala.Ref[tp]
*/
Type refType(Type tp) {
Symbol refClass = global.definitions.getClass(Names.scala_Ref);
assert refClass.kind == Kinds.CLASS;
return Type.TypeRef(global.definitions.SCALA_TYPE, refClass, new Type[]{tp});
}

public Checker[] postCheckers(Global global) {
return new Checker[] {
new CheckSymbols(global),
new CheckTypes(global),
new CheckOwners(global)
};
}
}
@@ -0,0 +1,132 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.transformer;

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


/** A default transformer class which also maintains owner information
*
* @author Martin Odersky
* @version 1.0
*/
public class OwnerTransformer extends Transformer {

protected Symbol currentOwner;

public OwnerTransformer(Global global, PhaseDescriptor descr) {
super(global, descr);
}

public void apply(Unit unit) {
currentOwner = global.definitions.ROOT_CLASS;
unit.body = transform(unit.body);
}

public Tree transform(Tree tree, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
Tree tree1 = transform(tree);
currentOwner = prevOwner;
return tree1;
}

public TypeDef[] transform(TypeDef[] params, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
TypeDef[] res = transform(params);
currentOwner = prevOwner;
return res;
}

public ValDef[][] transform(ValDef[][] params, Symbol owner) {
Symbol prevOwner = currentOwner;
currentOwner = owner;
ValDef[][] res = transform(params);
currentOwner = prevOwner;
return res;
}

public Template transform(Template templ, Symbol owner) {
Symbol prevOwner = currentOwner;
if (owner.kind == Kinds.CLASS)
currentOwner = owner.constructor();
Tree[] parents1 = transform(templ.parents);
currentOwner = owner;
Tree[] body1 = transformTemplateStats(templ.body, templ.symbol());
currentOwner = prevOwner;
return copy.Template(templ, parents1, body1);
}

public Tree[] transformTemplateStats(Tree[] ts, Symbol tsym) {
Tree[] ts1 = ts;
for (int i = 0; i < ts.length; i++) {
Tree t = transformTemplateStat(ts[i], tsym);
if (t != ts[i] && ts1 == ts) {
ts1 = new Tree[ts.length];
System.arraycopy(ts, 0, ts1, 0, i);
}
ts1[i] = t;
}
return ts1;
}

public Tree transformTemplateStat(Tree stat, Symbol tsym) {
return transform(stat, tsym);
}

public Tree transform(Tree tree) {
switch(tree) {
case PackageDef(Tree packaged, Template impl):
return copy.PackageDef(
tree, transform(packaged), transform(impl, packaged.symbol()));

case ClassDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
return copy.ClassDef(
tree, mods, name,
transform(tparams, tree.symbol()),
transform(vparams, tree.symbol()),
transform(tpe),
transform(impl, tree.symbol()));

case ModuleDef(int mods, Name name, Tree tpe, Template impl):
return copy.ModuleDef(
tree, mods, name, transform(tpe),
transform(impl, tree.symbol().moduleClass()));

case DefDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Tree rhs):
return copy.DefDef(
tree, mods, name,
transform(tparams, tree.symbol()),
transform(vparams, tree.symbol()),
transform(tpe, tree.symbol()),
transform(rhs, tree.symbol()));

case ValDef(int mods, Name name, Tree tpe, Tree rhs):
return copy.ValDef(
tree, mods, name, transform(tpe),
transform(rhs));

case TypeDef(int mods, Name name, TypeDef[] tparams, Tree rhs):
return copy.TypeDef(
tree, mods, name,
transform(tparams, tree.symbol()),
transform(rhs, tree.symbol()));

default:
return super.transform(tree);
}
}
}
@@ -0,0 +1,180 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.transformer;

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

/** Make all functions into one-argument functions
*/
public class UnCurry extends OwnerTransformer
implements Modifiers {

UnCurryPhase descr;

public UnCurry(Global global, UnCurryPhase descr) {
super(global, descr);
this.descr = descr;
}

/** (ps_1) ... (ps_n) => (ps_1, ..., ps_n)
*/
ValDef[][] uncurry(ValDef[][] params) {
int n = 0;
for (int i = 0; i < params.length; i++)
n = n + params[i].length;
ValDef[] ps = new ValDef[n];
int j = 0;
for (int i = 0; i < params.length; i++) {
System.arraycopy(params[i], 0, ps, j, params[i].length);
j = j + params[i].length;
}
return new ValDef[][]{ps};
}

/** tree of non-method type T ==> same tree with method type ()T
*/
Tree asMethod(Tree tree) {
switch (tree.type) {
case MethodType(_, _):
return tree;
default:
return tree.setType(Type.MethodType(Symbol.EMPTY_ARRAY, tree.type));
}
}

/** - uncurry all symbol and tree types (@see UnCurryPhase)
* - for every curried parameter list: (ps_1) ... (ps_n) ==> (ps_1, ..., ps_n)
* - for every curried application: f(args_1)...(args_n) ==> f(args_1, ..., args_n)
* - for every type application: f[Ts] ==> f[Ts]() unless followed by parameters
* - for every use of a parameterless function: f ==> f() and q.f ==> q.f()
* - for every def-parameter: def x: T ==> x: () => T
* - for every use of a def-parameter: x ==> x.apply()
* - for every argument to a def parameter `def x: T':
* if argument is not a reference to a def parameter:
* convert argument `e' to (expansion of) `() => e'
*/
public Tree transform(Tree tree) {
//uncurry type and symbol
if (tree.type != null) tree.type = descr.uncurry(tree.type);
switch (tree) {
case ClassDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl):
return copy.ClassDef(
tree, mods, name, tparams,
uncurry(transform(vparams, tree.symbol())),
tpe,
transform(impl, tree.symbol()));

case DefDef(int mods, Name name, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Tree rhs):
Tree rhs1 = transform(rhs, tree.symbol());
if (global.debug) global.log(name + ":" + rhs1.type);//debug
return copy.DefDef(
tree, mods, name, tparams,
uncurry(transform(vparams, tree.symbol())),
tpe, rhs1);

case ValDef(int mods, Name name, Tree tpe, Tree rhs):
if (tree.symbol().isDefParameter()) {
int mods1 = mods & ~ DEF;
Type newtype = global.definitions.functionType(Type.EMPTY_ARRAY, tpe.type);
Tree tpe1 = gen.mkType(tpe.pos, newtype);
return copy.ValDef(tree, mods1, name, tpe1, rhs).setType(newtype);
} else {
return tree;
}

case TypeApply(Tree fn, Tree[] args):
Tree tree1 = asMethod(super.transform(tree));
return gen.Apply(tree1, new Tree[0]);

case Apply(Tree fn, Tree[] args):
// f(x)(y) ==> f(x, y)
// argument to parameterless function e => ( => e)
Type ftype = fn.type;
Tree fn1 = transform(fn);
Tree[] args1 = transformArgs(args, ftype);
switch (fn1) {
case Apply(Tree fn2, Tree[] args2):
Tree[] newargs = new Tree[args1.length + args2.length];
System.arraycopy(args2, 0, newargs, 0, args2.length);
System.arraycopy(args1, 0, newargs, args2.length, args1.length);
return copy.Apply(tree, fn2, newargs);
default:
return copy.Apply(tree, fn1, args1);
}

case Select(_, _):
case Ident(_):
Tree tree1 = super.transform(tree);
switch (tree1.symbol().type()) {
case PolyType(Symbol[] tparams, Type restp):
if (tparams.length == 0 && !(restp instanceof Type.MethodType)) {
return gen.Apply(asMethod(tree1), new Tree[0]);
} else {
return tree1;
}
default:
if (tree1.symbol().isDefParameter()) {
tree1.type = global.definitions.functionType(
Type.EMPTY_ARRAY, tree1.type);
return gen.Apply(gen.Select(tree1, Names.apply), new Tree[0]);
} else {
return tree1;
}
}

default:
return super.transform(tree);
}
}

/** Transform arguments `args' to method with type `methtype'.
*/
private Tree[] transformArgs(Tree[] args, Type methtype) {
switch (methtype) {
case MethodType(Symbol[] params, _):
for (int i = 0; i < args.length; i++) {
args[i] = transformArg(args[i], params[i]);
}
return args;
case PolyType(_, Type restp):
return transformArgs(args, restp);
default:
throw new ApplicationError(methtype);
}
}

/** for every argument to a def parameter `def x: T':
* if argument is not a reference to a def parameter:
* convert argument `e' to (expansion of) `() => e'
*/
private Tree transformArg(Tree arg, Symbol formal) {
Tree arg1 = transform(arg);
if ((formal.flags & DEF) != 0) {
Symbol sym = arg.symbol();
if (sym != null && (sym.flags & DEF) != 0) {
switch (arg1) {
case Apply(Select(Tree qual, Name name), Tree[] args1):
assert name == Names.apply && args1.length == 0;
return qual;
default:
global.debugPrinter.print(arg);//debug
throw new ApplicationError();
}
}
return transform(gen.mkUnitFunction(
arg, descr.uncurry(arg.type), currentOwner));
} else return arg1;
}
}
@@ -0,0 +1,117 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
** **
** $Id$
\* */

package scalac.transformer;

import scalac.*;
import scalac.parser.*;
import scalac.symtab.*;
import scalac.typechecker.Infer;
import scalac.checkers.*;

public class UnCurryPhase extends PhaseDescriptor implements Modifiers {

private Global global;

public void initialize(Global global, int id) {
super.initialize(global, id);
this.global = global;
}

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

public String description () {
return "uncurry function types and applications";
}

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

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

/** - return symbol's transformed type,
* - if symbol is a def parameter with transformed type T, return () => T
*/
public Type transformInfo(Symbol sym, Type tp0) {
Type tp1 = uncurry(tp0);
if (sym.isDefParameter()) return global.definitions.functionType(Type.EMPTY_ARRAY, tp1);
else return tp1;
}

/** - (ps_1)...(ps_n)T ==> (ps_1,...,ps_n)T
*/
Type uncurry(Type tp) {
switch (tp) {
case MethodType(Symbol[] params, Type tp1):
Symbol[] uncurriedParams = uncurryParams(params);
Type uncurriedTp1 = uncurry(tp1);
switch (uncurriedTp1) {
case MethodType(Symbol[] params1, Type tp2):
Symbol[] newparams = new Symbol[uncurriedParams.length + params1.length];
System.arraycopy(uncurriedParams, 0, newparams, 0, uncurriedParams.length);
System.arraycopy(params1, 0, newparams, uncurriedParams.length, params1.length);
return Type.MethodType(newparams, tp2);
default:
if (uncurriedParams == params && uncurriedTp1 == tp1) return tp;
else return Type.MethodType(uncurriedParams, uncurriedTp1);
}
case PolyType(Symbol[] tparams, Type tp1):
if (tp instanceof Infer.VirtualPolyType)
return uncurry(tp1);
switch (tp1) {
case MethodType(_, _):
Type newtp1 = uncurry(tp1);
if (tp1 != newtp1) return Type.PolyType(tparams, newtp1);
else return tp;
default:
Type newtp1 = Type.MethodType(Symbol.EMPTY_ARRAY, tp1);
if (tparams.length == 0) return newtp1;
else return Type.PolyType(tparams, newtp1);
}
case OverloadedType(_, _):
return new Type.Map() {
public Type apply(Type t) { return uncurry(t); }
}.map(tp);
default:
return tp;
}
}

Symbol[] uncurryParams(Symbol[] params) {
Symbol[] params1 = params;
for (int i = 0; i < params.length; i++) {
Symbol param = params[i];
Symbol param1 = param;
Type tp = param.info();
Type tp1 = transformInfo(param, tp);
if (tp != tp1) {
if (params1 == params) {
params1 = new Symbol[params.length];
System.arraycopy(params, 0, params1, 0, i);
}
param1 = param.cloneSymbol().setType(tp1);
param1.flags &= ~DEF;
}
params1[i] = param1;
}
return params1;
}

public Checker[] postCheckers(Global global) {
return new Checker[] {
new CheckSymbols(global),
new CheckTypes(global),
new CheckOwners(global)
};
}
}

Large diffs are not rendered by default.

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

package scalac.typechecker;

import scalac.*;
import scalac.util.*;
import scalac.ast.*;
import scalac.symtab.*;
import scalac.checkers.*;
import java.util.HashMap;
import java.util.ArrayList;

public class AnalyzerPhase extends PhaseDescriptor {

/* final */ Context startContext;
HashMap/*<Unit,Context>*/ contexts = new HashMap();
ArrayList/*<Unit>*/ newSources = new ArrayList();

public void initialize(Global global, int id) {
super.initialize(global, id);
Definitions definitions = global.definitions;
this.startContext = new Context(
Tree.Empty,
definitions.ROOT_CLASS,
definitions.ROOT_CLASS.members(),
Context.NONE);
this.startContext.enclClass = this.startContext;

if (!global.noimports) {
TreeFactory make = global.make;

Tree java = make.Ident(Position.NOPOS, Names.java)
.setSymbol(definitions.JAVA)
.setType(Type.singleType(definitions.ROOT_TYPE, definitions.JAVA));
Tree javalang = make.Select(Position.NOPOS, java, Names.lang)
.setSymbol(definitions.JAVALANG)
.setType(Type.singleType(java.type, definitions.JAVALANG));
Tree importjavalang = make.Import(
Position.NOPOS, javalang, new Name[]{Names.WILDCARD})
.setSymbol(definitions.JAVALANG)
.setType(definitions.UNIT_TYPE);
startContext.imports = new ImportList(
importjavalang, startContext.scope, startContext.imports);

Tree scala = make.Ident(Position.NOPOS, Names.scala)
.setSymbol(definitions.SCALA)
.setType(Type.singleType(definitions.ROOT_TYPE, definitions.SCALA));
Tree importscala = make.Import(
Position.NOPOS, scala, new Name[]{Names.WILDCARD})
.setSymbol(definitions.SCALA)
.setType(definitions.UNIT_TYPE);
startContext.imports = new ImportList(
importscala, new Scope(), startContext.imports);

scala = make.Ident(Position.NOPOS, Names.scala)
.setSymbol(definitions.SCALA)
.setType(scala.type);
Symbol scalaPredefSym = definitions.getModule(Names.scala_Predef);
Tree scalaPredef = make.Select(Position.NOPOS, scala, Names.Predef)
.setSymbol(scalaPredefSym)
.setType(Type.singleType(scala.type, scalaPredefSym));

Tree importscalaPredef = make.Import(
Position.NOPOS, scalaPredef, new Name[]{Names.WILDCARD})
.setSymbol(scalaPredefSym)
.setType(definitions.UNIT_TYPE);
startContext.imports = new ImportList(
importscalaPredef, new Scope(), startContext.imports);
}
}

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

public String description () {
return "name and type analysis";
}

public String taskDescription() {
return "type checking";
}

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

public Checker[] postCheckers(Global global) {
return new Checker[] {
/* todo: uncomment
new CheckSymbols(global),
new CheckTypes(global),
new CheckOwners(global)
*/
};
}
}
@@ -0,0 +1,63 @@
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
**
** $Id$
\* */

package scalac.typechecker;

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

public class Context {
Tree tree; // Tree associated with this context
Symbol owner; // The current owner
Scope scope; // The current scope
ImportList imports; // The current import list
Context outer; // The next outer context
Context enclClass = this; // The next outer context whose tree
// is a class template
boolean delayArgs = false; // delay checking of type arguments

public Context() {}

public Context(Tree tree, Context outer) {
this(tree, outer.owner, outer.scope, outer);
}

public Context(Tree tree, Symbol owner, Scope scope, Context outer) {
this.tree = tree;
this.owner = owner;
this.scope = scope;
this.imports = outer.imports;
if (tree instanceof Tree.Template ||
tree instanceof Tree.CompoundType) this.enclClass = this;
else this.enclClass = outer.enclClass;
this.delayArgs = outer.delayArgs;
this.outer = outer;
}

public static Context NONE = new Context();

Context outerContext(Symbol clazz) {
Context c = this;
while (c != Context.NONE && c.owner != clazz) c = c.outer;
return c;
}

boolean isTopLevel() {
switch (tree) {
case Block(_):
return false;
case Template(_, _):
return outer.tree instanceof Tree.PackageDef;
case Empty:
return true;
default:
return outer.isTopLevel();
}
}
}