summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-05-27 12:23:54 +0000
committerMartin Odersky <odersky@gmail.com>2005-05-27 12:23:54 +0000
commit6e33a303fe231cd4e9ee2246bf4d59bb60db44bb (patch)
tree13c46c26cdff2a078ead170f79e10f9b0a71da9a /sources/scala/tools/nsc
parent08caefd4e04d42817c95e272bb3fb65770d6f015 (diff)
downloadscala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.tar.gz
scala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.tar.bz2
scala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc')
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Scanners.scala32
-rw-r--r--[-rwxr-xr-x]sources/scala/tools/nsc/ast/parser/TreeBuilder.scala (renamed from sources/scala/tools/nsc/ast/TreeBuilder.scala)4
-rwxr-xr-xsources/scala/tools/nsc/symtab/Definitions.scala29
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala6
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala2
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala51
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Namers.scala85
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala22
9 files changed, 162 insertions, 71 deletions
diff --git a/sources/scala/tools/nsc/ast/parser/Scanners.scala b/sources/scala/tools/nsc/ast/parser/Scanners.scala
index b17c8a6fe2..c9669488d9 100755
--- a/sources/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/sources/scala/tools/nsc/ast/parser/Scanners.scala
@@ -604,20 +604,26 @@ abstract class Scanners: ParserPhase {
}
token = INTLIT;
if (base <= 10 && in.ch == '.') {
- putChar(in.ch);
+ val lookahead = in.copy;
+ lookahead.next;
+ lookahead.ch match {
+ case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F' =>
+ putChar(in.ch);
+ in.next;
+ return getFraction
+ case _ =>
+ }
+ }
+ if (base <= 10 &&
+ (in.ch == 'e' || in.ch == 'E' ||
+ in.ch == 'f' || in.ch == 'F' ||
+ in.ch == 'd' || in.ch == 'D')) {
+ return getFraction
+ }
+ setName;
+ if (in.ch == 'l' || in.ch == 'L') {
in.next;
- getFraction
- } else if (base <= 10 &&
- (in.ch == 'e' || in.ch == 'E' ||
- in.ch == 'f' || in.ch == 'F' ||
- in.ch == 'd' || in.ch == 'D')) {
- getFraction
- } else {
- setName;
- if (in.ch == 'l' || in.ch == 'L') {
- in.next;
- token = LONGLIT;
- }
+ token = LONGLIT;
}
}
diff --git a/sources/scala/tools/nsc/ast/TreeBuilder.scala b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 96b79dc411..33215db36b 100755..100644
--- a/sources/scala/tools/nsc/ast/TreeBuilder.scala
+++ b/sources/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -3,7 +3,7 @@
* @author Martin Odersky
*/
// $Id$
-package scala.tools.nsc.ast;
+package scala.tools.nsc.ast.parser;
import symtab.Flags._;
import util.ListBuffer;
@@ -36,7 +36,7 @@ abstract class TreeBuilder {
val body1 = transform(body);
boundVars = boundVars.tail;
copy.Bind(tree, name, body1)
- case Sequence(_) | Alternative(_) =>
+ case Se quence(_) | Alternative(_) =>
super.transform(tree)
case _ =>
tree
diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala
index ecbf977d50..02c12ddf2c 100755
--- a/sources/scala/tools/nsc/symtab/Definitions.scala
+++ b/sources/scala/tools/nsc/symtab/Definitions.scala
@@ -67,14 +67,31 @@ abstract class Definitions: SymbolTable {
def TupleClass(i: int): Symbol = getClass("scala.Tuple" + i);
def FunctionClass(i: int): Symbol = getClass("scala.Function" + i);
- def tupleType(elems: List[Type]) = {
- val sym = TupleClass(elems.length);
- typeRef(sym.typeConstructor.prefix, sym, elems)
+ def tupleType(elems: List[Type]) =
+ if (elems.length <= MaxTupleArity) {
+ val sym = TupleClass(elems.length);
+ typeRef(sym.typeConstructor.prefix, sym, elems)
+ } else NoType;
+
+ def functionType(formals: List[Type], restpe: Type) =
+ if (formals.length <= MaxFunctionArity) {
+ val sym = FunctionClass(formals.length);
+ typeRef(sym.typeConstructor.prefix, sym, formals ::: List(restpe))
+ } else NoType;
+
+ def isTupleType(tp: Type): boolean = tp match {
+ case TypeRef(_, sym, elems) =>
+ elems.length <= MaxTupleArity && sym == TupleClass(elems.length);
+ case _ =>
+ false
}
- def functionType(formals: List[Type], restpe: Type) = {
- val sym = FunctionClass(formals.length);
- typeRef(sym.typeConstructor.prefix, sym, formals ::: List(restpe))
+ def isFunctionType(tp: Type): boolean = tp match {
+ case TypeRef(_, sym, args) =>
+ (args.length > 0) && (args.length - 1 <= MaxFunctionArity) &&
+ (sym == FunctionClass(args.length - 1))
+ case _ =>
+ false
}
def seqType(arg: Type) =
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index e50d92bbd2..19f5681913 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -40,6 +40,7 @@ object Flags {
val SYNTHETIC = 0x00200000; // symbol is compiler-generated
val STABLE = 0x00400000; // functions that are assumed to be stable
// (typically, access methods for valdefs)
+ val STATIC = 0x00800000; // static field, method or class
val ACCESSED = 0x01000000; // symbol was accessed at least once
val SELECTOR = 0x02000000; // symbol was used as selector in Select
@@ -72,10 +73,10 @@ object Flags {
PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE;
val PrintableFlags = // these modifiers appear in TreePrinter output.
ExplicitFlags | LOCAL | SYNTHETIC | STABLE | ACCESSOR |
- ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE;
+ ACCESS_METHOD | PARAMACCESSOR | LABEL | BRIDGE | STATIC;
val GenFlags = // these modifiers can be in generated trees
SourceFlags | PrintableFlags;
- val FieldFlags = MUTABLE | ACCESSED | PARAMACCESSOR;
+ val FieldFlags = MUTABLE | ACCESSED | PARAMACCESSOR | STATIC;
val AccessFlags = PRIVATE | PROTECTED;
val VARIANCES = COVARIANT | CONTRAVARIANT;
@@ -128,6 +129,7 @@ object Flags {
case JAVA => "<java>"
case SYNTHETIC => "<synthetic>"
case STABLE => "<stable>"
+ case STATIC => "<static>"
case ACCESSED => "<accessed>"
case SELECTOR => "<selector>"
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 000c7785f5..e4793071ab 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -124,7 +124,7 @@ abstract class Symbols: SymbolTable {
isConstructor && owner.primaryConstructor == this;
/** Is this symbol static (i.e. with no outer instance)? */
- final def isStatic: boolean = isRoot || owner.isStaticOwner;
+ final def isStatic: boolean = hasFlag(STATIC) || isRoot || owner.isStaticOwner;
/** Does this symbol denote a class that defines static symbols? */
final def isStaticOwner: boolean = isPackageClass || isStatic && isModuleClass;
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
index 2d18105e0c..b1027c77b1 100755
--- a/sources/scala/tools/nsc/symtab/Types.scala
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -181,11 +181,8 @@ abstract class Types: SymbolTable {
new SubstThisMap(from, to) apply this;
/** Does this type contain a reference to this symbol? */
- def contains(sym: Symbol): boolean = {
- val m = new ContainsMap(sym);
- m(this);
- m.result
- }
+ def contains(sym: Symbol): boolean =
+ new ContainsTraverser(sym).traverse(this).result;
/** Is this type a subtype of that type? */
def <:<(that: Type): boolean =
@@ -649,8 +646,7 @@ abstract class Types: SymbolTable {
return args(0).toString() + "*";
if (sym == ByNameParamClass && !args.isEmpty)
return "=> " + args(0).toString();
- if (args.length > 0 && args.length <= MaxFunctionArity - 1 &&
- sym == FunctionClass(args.length - 1))
+ if (isFunctionType(this))
return args.init.mkString("(", ", ", ")") + " => " + args.last;
}
pre.prefixString + sym.nameString +
@@ -931,6 +927,11 @@ abstract class Types: SymbolTable {
}
}
+ abstract class TypeTraverser extends TypeMap {
+ def traverse(tp: Type): TypeTraverser;
+ def apply(tp: Type): Type = { traverse(tp); tp }
+ }
+
/** A map to compute the asSeenFrom method */
class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
def apply(tp: Type): Type =
@@ -1039,9 +1040,9 @@ abstract class Types: SymbolTable {
}
/** A map to implement the contains method */
- class ContainsMap(sym: Symbol) extends TypeMap {
+ class ContainsTraverser(sym: Symbol) extends TypeTraverser {
var result = false;
- def apply(tp: Type): Type = {
+ def traverse(tp: Type): ContainsTraverser = {
if (!result) {
tp match {
case TypeRef(_, sym1, _) if (sym == sym1) => result = true
@@ -1049,7 +1050,7 @@ abstract class Types: SymbolTable {
case _ => mapOver(tp)
}
}
- tp
+ this
}
}
@@ -1058,24 +1059,22 @@ abstract class Types: SymbolTable {
object commonOwnerMap extends TypeMap {
var result: Symbol = _;
def init = { result = NoSymbol }
- def apply(tp: Type): Type = tp match {
- case ThisType(sym) =>
- register(sym);
- tp
- case TypeRef(NoPrefix, sym, args) =>
- register(sym.owner);
- for (val arg <- args) apply(arg);
- tp
- case SingleType(NoPrefix, sym) =>
- register(sym.owner);
- tp
- case _ =>
- mapOver(tp)
+ def apply(tp: Type): Type = {
+ tp match {
+ case ThisType(sym) =>
+ register(sym);
+ case TypeRef(NoPrefix, sym, args) =>
+ register(sym.owner); args foreach {arg => apply(arg); ()}
+ case SingleType(NoPrefix, sym) =>
+ register(sym.owner);
+ case _ =>
+ mapOver(tp)
+ }
+ tp
}
- private def register(sym: Symbol) = {
+ private def register(sym: Symbol): unit = {
while (result != NoSymbol && sym != result && !(sym isNestedIn result))
result = result.owner;
- result
}
}
@@ -1580,7 +1579,7 @@ abstract class Types: SymbolTable {
private def commonOwner(tps: List[Type]): Symbol = {
if (settings.debug.value) System.out.println("computing common owner of types " + tps);//debug
commonOwnerMap.init;
- List.mapConserve(tps)(commonOwnerMap);
+ tps foreach { tp => commonOwnerMap.apply(tp); () }
commonOwnerMap.result
}
diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 15aa4237f9..7f3a5e47ad 100755
--- a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -398,6 +398,8 @@ abstract class ClassfileParser {
res = res | TRAIT | INTERFACE | ABSTRACT;
if ((flags & JAVA_ACC_SYNTHETIC) != 0)
res = res | SYNTHETIC;
+ if ((flags & JAVA_ACC_STATIC) != 0)
+ res = res | STATIC;
res | JAVA;
}
}
diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala
index 2ca9c8813c..ce348ed796 100755
--- a/sources/scala/tools/nsc/typechecker/Namers.scala
+++ b/sources/scala/tools/nsc/typechecker/Namers.scala
@@ -12,6 +12,7 @@ import symtab.Flags._;
/** Methods to create symbols and to enter them into scopes. */
trait Namers: Analyzer {
import global._;
+ import definitions._;
class NamerPhase(prev: Phase) extends StdPhase(prev) {
val global: Namers.this.global.type = Namers.this.global;
@@ -219,7 +220,7 @@ trait Namers: Analyzer {
def setterTypeCompleter(tree: Tree) = new TypeCompleter(tree) {
override def complete(sym: Symbol): unit = {
if (settings.debug.value) log("defining " + sym);
- sym.setInfo(MethodType(List(typeSig(tree)), definitions.UnitClass.tpe));
+ sym.setInfo(MethodType(List(typeSig(tree)), UnitClass.tpe));
if (settings.debug.value) log("defined " + sym);
validate(sym);
}
@@ -280,7 +281,6 @@ trait Namers: Analyzer {
}
private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = {
- def checkContractive: unit = {}; //todo: complete
val meth = context.owner;
val tparamSyms = typer.reenterTypeParams(tparams);
val vparamSymss = enterValueParams(meth, vparamss);
@@ -292,11 +292,9 @@ trait Namers: Analyzer {
} else typer.typedType(tpt).tpe);
def mkMethodType(vparams: List[Symbol], restpe: Type) = {
val formals = vparams map (.tpe);
- if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) {
- if (settings.debug.value) System.out.println("create implicit");//debug
- checkContractive;
+ if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT))
new ImplicitMethodType(formals, restpe)
- } else MethodType(formals, restpe);
+ else MethodType(formals, restpe);
}
makePolyType(
tparamSyms,
@@ -304,6 +302,42 @@ trait Namers: Analyzer {
else (vparamSymss :\ restype)(mkMethodType))
}
+ /** If `sym' is an implicit value, check that its type signature `tp' is contractive.
+ * This means: The type of every implicit parameter is properly contained
+ * in the type that is obtained by removing all implicit parameters and converting
+ * the rest to a function type.
+ * If the check succeeds return `tp' itself, otherwise `ErrorType'.
+ */
+ private def checkContractive(sym: Symbol, tp: Type): Type = {
+ /* The type signature without implicit parameters converted to function type */
+ def provided(tp: Type): Type = tp match {
+ case PolyType(_, restpe) => provided(restpe);
+ case mt: ImplicitMethodType => mt.resultType;
+ case MethodType(formals, restpe) => functionType(formals, provided(restpe))
+ case _ => tp
+ }
+ /* The types of all implicit parameters */
+ def required(tp: Type): List[Type] = tp match {
+ case PolyType(_, restpe) => required(restpe);
+ case mt: ImplicitMethodType => mt.paramTypes;
+ case MethodType(formals, restpe) => required(restpe);
+ case _ => List()
+ }
+ var result = tp;
+ if (sym hasFlag IMPLICIT) {
+ val p = provided(tp);
+ for (val r <- required(tp)) {
+ if (!isContainedIn(r, p) || (r =:= p)) {
+ context.error(sym.pos, "implicit " + sym + " is not contractive," +
+ "\n because the implicit parameter type " + r +
+ "\n is not strictly contained in the signature " + p);
+ result = ErrorType;
+ }
+ }
+ }
+ result
+ }
+
private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type =
makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe);
@@ -320,7 +354,8 @@ trait Namers: Analyzer {
clazz.tpe;
case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
- new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs)
+ checkContractive(sym,
+ new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs))
case ValDef(_, _, tpt, rhs) =>
deconstIfNotFinal(sym,
@@ -387,7 +422,7 @@ trait Namers: Analyzer {
"\nit should be omitted for abstract members");
if (sym.hasFlag(OVERRIDE | ABSOVERRIDE) && sym.isClass)
context.error(sym.pos, "`override' modifier not allowed for classes");
- if (sym.info.symbol == definitions.FunctionClass(0) &&
+ if (sym.info.symbol == FunctionClass(0) &&
sym.isValueParameter && sym.owner.isClass && sym.owner.hasFlag(CASE))
context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
if ((sym.flags & DEFERRED) != 0) {
@@ -409,6 +444,40 @@ trait Namers: Analyzer {
}
}
+ /* Is type `tp1' properly contained in type `tp2'? */
+ def isContainedIn(tp1: Type, tp2: Type) = {
+ //System.out.println("is " + tp1 + " contained in " + tp2 + "?");//DEBUG
+ new ContainsTraverser(tp1).traverse(tp2).result;
+ }
+
+ /* Type `elemtp' is contained in type `tp' is one of the following holds:
+ * - elemtp and tp are the same
+ * - tp is a function type and elemtp is not
+ * - tp and elemtp are function types, and arity of tp is greater than arity of elemtp
+ * - tp and elemtp are both parameterized types with same type constructor and prefix,
+ * and each type argument of elemtp is contained in the corresponding type argument of tp.
+ */
+ private class ContainsTraverser(elemtp: Type) extends TypeTraverser {
+ var result = false;
+ def traverse(tp: Type): ContainsTraverser = {
+ if (!result) {
+ if (elemtp =:= tp)
+ result = true
+ else if (isFunctionType(tp) &&
+ (!isFunctionType(elemtp) || tp.typeArgs.length > elemtp.typeArgs.length))
+ result = true
+ else Pair(tp, elemtp) match {
+ case Pair(TypeRef(pre, sym, args), TypeRef(elempre, elemsym, elemargs)) =>
+ if ((sym == elemsym) && (pre =:= elempre) && (args.length == elemargs.length))
+ result = List.forall2(elemargs, args) (isContainedIn)
+ case _ =>
+ }
+ }
+ if (!result) mapOver(tp);
+ this
+ }
+ }
+
abstract class TypeCompleter(val tree: Tree) extends LazyType;
}
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index a413a75476..b5dbaab136 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -567,14 +567,14 @@ abstract class Typers: Analyzer {
}
def typedFunction(fun: Function, mode: int, pt: Type): Function = {
- val Triple(clazz, argpts, respt) = pt match {
- case TypeRef(_, sym, argtps)
- if (fun.vparams.length <= MaxFunctionArity && sym == FunctionClass(fun.vparams.length) ||
- sym == PartialFunctionClass && fun.vparams.length == 1 && fun.body.isInstanceOf[Match]) =>
- Triple(sym, argtps.init, argtps.last)
- case _ =>
- Triple(FunctionClass(fun.vparams.length), fun.vparams map (x => NoType), WildcardType)
- }
+ val Triple(clazz, argpts, respt) =
+ if (isFunctionType(pt)
+ ||
+ pt.symbol == PartialFunctionClass &&
+ fun.vparams.length == 1 && fun.body.isInstanceOf[Match])
+ Triple(pt.symbol, pt.typeArgs.init, pt.typeArgs.last)
+ else
+ Triple(FunctionClass(fun.vparams.length), fun.vparams map (x => NoType), WildcardType);
val vparamSyms = List.map2(fun.vparams, argpts) { (vparam, argpt) =>
vparam match {
case ValDef(_, _, tpt, _) =>
@@ -1212,11 +1212,7 @@ abstract class Typers: Analyzer {
}
def implicitsOfType(tp: Type): List[List[ImplicitInfo]] = {
- val tp1 =
- if (tp.typeArgs.length - 1 <= MaxFunctionArity &&
- tp.symbol == FunctionClass(tp.typeArgs.length - 1))
- intersectionType(tp.typeArgs.reverse)
- else tp;
+ val tp1 = if (isFunctionType(tp)) intersectionType(tp.typeArgs.reverse) else tp;
tp1.baseClasses map implicitsOfClass;
}