diff options
author | Martin Odersky <odersky@gmail.com> | 2005-05-27 12:23:54 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-05-27 12:23:54 +0000 |
commit | 6e33a303fe231cd4e9ee2246bf4d59bb60db44bb (patch) | |
tree | 13c46c26cdff2a078ead170f79e10f9b0a71da9a /sources | |
parent | 08caefd4e04d42817c95e272bb3fb65770d6f015 (diff) | |
download | scala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.tar.gz scala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.tar.bz2 scala-6e33a303fe231cd4e9ee2246bf4d59bb60db44bb.zip |
*** empty log message ***
Diffstat (limited to 'sources')
-rwxr-xr-x | sources/scala/tools/nsc/ast/parser/Scanners.scala | 32 | ||||
-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-x | sources/scala/tools/nsc/symtab/Definitions.scala | 29 | ||||
-rw-r--r-- | sources/scala/tools/nsc/symtab/Flags.scala | 6 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/symtab/Symbols.scala | 2 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/symtab/Types.scala | 51 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 2 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Namers.scala | 85 | ||||
-rwxr-xr-x | sources/scala/tools/nsc/typechecker/Typers.scala | 22 |
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; } |