diff options
author | paltherr <paltherr@epfl.ch> | 2003-12-10 15:26:11 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2003-12-10 15:26:11 +0000 |
commit | d0ffbd24122f69ded774ffd89cd0146a3d9cc15d (patch) | |
tree | 734aa6f97879a2b92ebb023456a0eccbb379d986 /sources | |
parent | 904d31853dda3e962c503f48113b2f96c9305f13 (diff) | |
download | scala-d0ffbd24122f69ded774ffd89cd0146a3d9cc15d.tar.gz scala-d0ffbd24122f69ded774ffd89cd0146a3d9cc15d.tar.bz2 scala-d0ffbd24122f69ded774ffd89cd0146a3d9cc15d.zip |
- Added context and scope management
Diffstat (limited to 'sources')
-rw-r--r-- | sources/scalac/checkers/TreeChecker.java | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/sources/scalac/checkers/TreeChecker.java b/sources/scalac/checkers/TreeChecker.java index 433d170c97..4f6e7c56e8 100644 --- a/sources/scalac/checkers/TreeChecker.java +++ b/sources/scalac/checkers/TreeChecker.java @@ -8,8 +8,15 @@ package scalac.checkers; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + import scalac.Unit; +import scalac.ast.Tree; import scalac.symtab.Definitions; +import scalac.symtab.Symbol; +import scalac.util.Debug; /** * This checker checks that trees are well-formed. It checks both the @@ -23,6 +30,30 @@ public class TreeChecker { /** The global definitions */ private final Definitions definitions; + /** The stack of current units */ + private final Stack/*<Unit>*/ units = new Stack(); + + /** The stack of current classes */ + private final Stack/*<Symbol>*/ classes = new Stack(); + + /** The stack of current members */ + private final Stack/*<Symbol>*/ members = new Stack(); + + /** The stack of current owners */ + private final Stack/*<Symbol>*/ owners = new Stack(); + + /** The currently visible type variables */ + private final Set/*<Symbol>*/ tvars = new HashSet(); + + /** The currently visible value variables */ + private final Set/*<Symbol>*/ vvars = new HashSet(); + + /** The currently visible labels */ + private final Set/*<Symbol>*/ labels = new HashSet(); + + /** The currently defined symbols */ + private final Set/*<Symbol>*/ symbols = new HashSet(); + //######################################################################## // Public Constructors @@ -40,4 +71,201 @@ public class TreeChecker { } //######################################################################## + // Private Methods - Declaring symbols + + /** Do the trees contain the given symbols? */ + private boolean containSymbols(Tree[] trees, Symbol[] symbols) { + if (trees.length != symbols.length) return false; + for (int i = 0; i < trees.length; i++) + if (trees[i].symbol() != symbols[i]) return false; + return true; + } + + /** Remove parameters of symbol from current scope. */ + private void scopeInsertParametersOf(Symbol symbol) { + Symbol[] tparams = symbol.typeParams(); + for (int i = 0; i < tparams.length; i++) + scopeInsertTVariable(tparams[i], true); + Symbol[] vparams = symbol.valueParams(); + for (int i = 0; i < vparams.length; i++) + scopeInsertVVariable(vparams[i], true); + } + + /** Adds the type variable to the current scope. */ + private void scopeInsertTVariable(Symbol symbol, boolean isParameter) { + assert !symbol.owner().isClass(): show(symbol); + assert symbol.isParameter() == isParameter: show(symbol); + registerSymbol(symbol); + tvars.add(symbol); + } + + /** Adds the value variable to the current scope. */ + private void scopeInsertVVariable(Symbol symbol, boolean isParameter) { + assert !symbol.owner().isClass(): show(symbol); + assert symbol.isParameter() == isParameter: show(symbol); + registerSymbol(symbol); + vvars.add(symbol); + } + + /** Adds the label to current scope. */ + private void scopeInsertLabel(Symbol symbol) { + assert !symbol.owner().isClass(): show(symbol); + registerSymbol(symbol); + labels.add(symbol); + } + + /** Remove parameters of symbol from current scope. */ + private void scopeRemoveParametersOf(Symbol symbol) { + Symbol[] tparams = symbol.typeParams(); + for (int i = 0; i < tparams.length; i++) + scopeRemoveTVariable(tparams[i]); + Symbol[] vparams = symbol.valueParams(); + for (int i = 0; i < vparams.length; i++) + scopeRemoveVVariable(vparams[i]); + } + + /** Removes the type variable from current scope. */ + private void scopeRemoveTVariable(Symbol symbol) { + boolean removed = tvars.remove(symbol); + assert removed: show(symbol); + } + + /** Removes the value variable from current scope. */ + private void scopeRemoveVVariable(Symbol symbol) { + boolean removed = vvars.remove(symbol); + assert removed: show(symbol); + } + + /** Removes the label symbol from current scope. */ + private void scopeRemoveLabel(Symbol symbol) { + boolean removed = labels.remove(symbol); + assert removed: show(symbol); + } + + /** Registers the symbol. */ + private void registerSymbol(Symbol symbol) { + boolean added = symbols.add(symbol); + assert added: show(symbol); + } + + //######################################################################## + // Private Methods - Managing current context + + /** Returns the current unit. */ + private Unit currentUnit() { + return units.size() > 0 ? (Unit)units.peek() : null; + } + + /** Returns the current class. */ + private Symbol currentClass() { + return classes.size() > 0 ? (Symbol)classes.peek() : null; + } + + /** Returns the current member. */ + private Symbol currentMember() { + return members.size() > 0 ? (Symbol)members.peek() : null; + } + + /** Returns the current owner. */ + private Symbol currentOwner() { + return owners.size() > 0 ? (Symbol)owners.peek() : null; + } + + /** Sets the current unit to the given one. */ + private void pushUnit(Unit unit) { + assert units.size() == 0: showPush(unit); + assert classes.size() == 0: showPush(unit); + assert members.size() == 0: showPush(unit); + units.push(unit); + } + + /** Sets the current class to the given one. */ + private void pushClass(Symbol clasz) { + assert clasz.isClass(): showPush(clasz); + assert members.size() == 0: showPush(clasz); + classes.push(clasz); + pushOwner(clasz); + } + + /** Sets the current member to the given one. */ + private void pushMember(Symbol member) { + assert member.isTerm(): showPush(member); + assert members.size() == 0: showPush(member); + assert member.owner() == currentClass(): showPush(member); + members.push(member); + pushOwner(member); + } + + /** Sets the current owner to the given one. */ + private void pushOwner(Symbol owner) { + owners.push(owner); + } + + /** Sets the current unit to the previous one. */ + private void popUnit() { + assert units.size() > 0: show(); + units.pop(); + } + + /** Sets the current class to the previous one. */ + private void popClass() { + assert members.size() == 0: show(); + assert classes.size() > 0: show(); + popOwner(); + classes.pop(); + } + + /** Sets the current member to the previous one. */ + private void popMember() { + assert members.size() > 0: show(); + popOwner(); + members.pop(); + } + + /** Sets the current owner to the previous one. */ + private void popOwner() { + assert owners.size() > 0: show(); + owners.pop(); + } + + //######################################################################## + // Private Methods - Showing errors + + /** Returns the current position. */ + private String show() { + return + format("unit", currentUnit()) + + format("clasz", currentClass()) + + format("member", currentMember()) + + format("owner", currentOwner()); + } + + /** Returns the current position and given header and value. */ + private String show(String header, Object value) { + return show() + format(header, value); + } + + /** Returns the current position and given symbol. */ + private String show(Symbol symbol) { + return show("symbol", symbol); + } + + /** Returns the current position and given pushed value. */ + private String showPush(Object value) { + return show("pushing", value); + } + + /** Returns a string with the given header and value. */ + private String format(String header, Object value) { + while (header.length() < 10) header = header + ' '; + return "\n" + header + ": " + toString(value); + } + + /** Returns a string representation of the given value. */ + private String toString(Object value) { + if (value instanceof Symbol) return Debug.show(value); + return String.valueOf(value); + } + + //######################################################################## } |