From e1d1b2d9b8797b2af95c247f840ccb11b1857dc7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 Aug 2003 16:41:30 +0000 Subject: *** empty log message *** --- doc/reference/reference.verb.tex | 567 ++++++++++++--------- sources/scalac/CompilerCommand.java | 8 +- sources/scalac/Global.java | 3 +- sources/scalac/symtab/Symbol.java | 21 +- sources/scalac/symtab/Type.java | 2 +- .../scalac/symtab/classfile/AttributeParser.java | 19 +- sources/scalac/symtab/classfile/ClassParser.java | 3 +- .../scalac/symtab/classfile/ClassfileParser.java | 9 +- sources/scalac/symtab/classfile/PackageParser.java | 41 +- sources/scalac/symtab/classfile/Pickle.java | 40 -- sources/scalac/symtab/classfile/UnPickle.java | 3 +- sources/scalac/typechecker/Analyzer.java | 16 +- sources/scalac/typechecker/Infer.java | 2 + sources/scalac/util/AbstractFile.java | 32 ++ sources/scalac/util/AbstractFileReader.java | 5 + 15 files changed, 434 insertions(+), 337 deletions(-) diff --git a/doc/reference/reference.verb.tex b/doc/reference/reference.verb.tex index ecc43834dd..56bdbbb9b1 100644 --- a/doc/reference/reference.verb.tex +++ b/doc/reference/reference.verb.tex @@ -993,13 +993,6 @@ parameters (\sref{sec:parameters}) of type $[]T$, because its result would violate the well-formedness rules for anonymous functions (\sref{sec:closures}). Hence, methods with call-by-name parameters always need to be applied to arguments immediately. -\item -If $p$ is a path (\sref{sec:paths}), then $p$ is implicitly converted to a -value of type \verb@p.type@ if the context requires it. -\item If an integer literal appears in a context which requires -one of the types \ver@byte@, \verb@short@, or \verb@char@, it -is implicity converted to that type, provided the value of the literal fits in -the numeric range described by the type. \end{itemize} \chapter{Basic Declarations and Definitions} @@ -1178,9 +1171,6 @@ inference (\sref{sec:local-type-inf}). VarDef \>::=\> Id [`:' Type] `=' Expr \> |\> Id `:' Type `=' `_' \end{verbatim} -\ifundefvar{ - PureDef \>::= \> $\VAR$ ValDcl {`,' ValDcl} -} A variable declaration \verb@var x: T@ is equivalent to declarations of a {\em getter function} \verb@x@ and a {\em setter function} @@ -1213,11 +1203,11 @@ The default value depends on the type \verb@T@ as follows: \verb@null@ & for all other types $T$. \end{tabular}\end{quote} -Both forms of variable defintion also introduce a getter function -\verb@x@ which returns the value currently assigned to the variable, -as well as a setter function \verb@x_=@ which changes the value -currently assigned to the variable. The functions have the same -signatures as for a variable declaration. +When they occur as members of a template, both forms of variable +defintion also introduce a getter function \verb@x@ which returns the +value currently assigned to the variable, as well as a setter function +\verb@x_=@ which changes the value currently assigned to the variable. +The functions have the same signatures as for a variable declaration. \example The following example shows how {\em properties} can be simulated in Scala. It defines a class \verb@TimeOfDayVar@ of time @@ -1227,7 +1217,7 @@ values to be assigned to these fields. The user code, on the other hand, accesses these fields just like normal variables. \begin{verbatim} -class TimeOfDayVar with { +class TimeOfDayVar { private var h: int = 0, m: int = 0, s: int = 0; def hours \== h; def hours_= (h: int) \>= \=if (0 <= h && h < 24) this.h = h @@ -1520,9 +1510,10 @@ definition. A constructor invocation is a function application \sref{sec:stable-ids}), \verb@c@ is a type name which either designates a class or defines an alias type for one, and \verb@(args)@ is an argument list, which matches one of the constructors of that -class. The prefix \verb@x.@ can be omitted. The argument list -\verb@(args)@ can also be omitted, in which case an empty argument -list \verb@()@ is implicitly added. +class. The prefix \verb@x.@ can be omitted. The class \verb@c@ must +conform to \verb@scala.AnyRef@, i.e.\ it may not be a value type. The +argument list \verb@(args)@ can also be omitted, in which case an +empty argument list \verb@()@ is implicitly added. \subsection{Base Classes} \label{sec:base-classes} @@ -2216,24 +2207,49 @@ module FileSystem with { \> |\> Id `#' Id \> |\> SimpleExpr TypeArgs \> |\> SimpleExpr ArgumentExpr + ArgumentExpr \>::=\> `(' Expr ')' + \> |\> BlockExpr + BlockExpr \>::=\> `{' CaseClause {CaseClause} `}' + \> |\> `{' Block `}' + Block \>::=\> {BlockStat `;'} [Expr] Exprs \>::= \> Expr {`,' Expr} \end{verbatim} Expressions are composed of operators and operands. Expression forms are -discussed subsequently in decreasing order of precedence. +discussed subsequently in decreasing order of precedence. \section{Literals} \syntax\begin{verbatim} SimpleExpr \=::= \= literal + literal \>::= \> intLit + \> |\> floatLit + \> |\> charLit + \> |\> stringLit + \> |\> symbolLit \end{verbatim} -Typing and evaluation of literals are analogous to Java. +Typing and evaluation of literals are generally as in Java. +An integer literal denotes an integer number. Its type is normally +\verb@int@. However, if the expected type \verb@pt@ of the expression +is either \verb@byte@, \verb@short@, or \verb@char@ and the integer +number fits in the numeric range defined by the type, then the number +is converted to \verb@pt@ and the expression's type is \verb@pt@. A +floating point literal denotes a single-precision or double precision +IEEE floating point number. A character literal denotes a Unicode +character. A string literal denotes a member of +\verb@java.lang.String@. + +A symbol literal \verb@'id@ is a shorthand for the expression +\verb@scala.Symbol("id")@. If the symbol literal is followed by an +actual parameters, as in \verb@'id(args)@, then the whole expression +is taken to be a shorthand for +\verb@scala.Labelled(scala.Symbol("id"), args)@. \section{Boolean constants} \begin{verbatim} - SimpleExpr \=::= \= true | false + SimpleExpr \=::= \= true | false \end{verbatim} The boolean truth values are denoted by the reserved words \verb@true@ @@ -2279,6 +2295,12 @@ it was $(\VAL;y=e\semi y.x)$ for some fresh name $y$. The typing rules for blocks implies that in that case $x$'s type may not refer to any abstract type member of \verb@e@. +The type of a designator is normally the type of the entity it refers +to. However, if the designator is a path \sref{sec:paths} \verb@p@ +it's type is \verb@p.type@, provided the expression's expected type is +a singleton type, or \verb@p@ occurs as the prefix of a selection, +type selection, or mixin super expression. + The selection $e.x$ is evaluated by first evaluating the qualifier expression $e$. The selection's result is then the value to which the selector identifier is bound in the selected object designated by $e$. @@ -2292,27 +2314,28 @@ selector identifier is bound in the selected object designated by $e$. \end{verbatim} The expression \verb@this@ can appear in the statement part of a -template or compound typw. It stands for the object being defined by +template or compound type. It stands for the object being defined by the innermost template or compound type enclosing the reference. If -this is a template forming part of a module or class definition, the -type of \verb@this@ is the self type of the definition; otherwise the -type of \verb@this@ is the type of the innermost enclosing template or -compund type itself. +this is a compound type, the type of \verb@this@ is the compount type. +If it is a template of an instance creation expression, the type of +\verb@this@ is the type of that template. If it is a template of a +class or object definition with simple name \verb@C@, the type of this +is the same as the type of \verb@C.this@. The expression \verb@C.this@ is legal in the statement part of an enclosing class or object definition with simple name \verb@C@. It stands for the object being defined by the innermost such definition. -Its type is the self type of that definition. +Its type is the self type of that definition if one is given; +otherwise its type is \verb@C.this.type@. A reference \verb@super.$m$@ in a template refers to the definition of \verb@m@ in the actual superclass (\sref{sec:base-classes}) of the template. A reference \verb@C.super.m@ refers to the definition of \verb@m@ in the actual superclass of the innermost enclosing class or -object definition enclosing the reference. The referred-to definition -of \verb@m@ must be concrete, or the template containing the reference -must contain a definition which has an \verb@override@ modifier and -which overrides \verb@m@. - +object definition enclosing the reference. The definition referred to +by \verb@super@ or \verb@C.super@ must be concrete, or the template +containing the reference must contain a definition which has an +\verb@override@ modifier and which overrides \verb@m@. \example\label{ex:super} Consider the following class definitions @@ -2344,8 +2367,8 @@ depending on whether \verb@B@ is used as defining class or as a mixin class. \end{verbatim} In the statement part of a template -the reference \verb@M # m@ refers to the definition of the member \verb@m@ in -the mixin parent class of the template with simple name \verb@@M. +the reference \verb@M#m@ refers to the definition of the member \verb@m@ in +the mixin parent class of the template with simple name \verb@M@. \example Consider the following class definitions: \begin{verbatim} @@ -2371,7 +2394,8 @@ trait Colored extends Shape { } \end{verbatim} -All three definitions of \verb@equals@ are combined in the class below, which makes use of \verb@super@ as well as mixin +All three definitions of \verb@equals@ are combined in the class +below, which makes use of \verb@super@ as well as mixin super references. \begin{verbatim} class BorderedColoredShape extends Shape with Bordered with Colored { @@ -2411,7 +2435,7 @@ of evaluating the rewritten right-hand side is finally converted to the function's declared result type, if one is given. The case where of a formal \verb@def@-parameter with a parameterless -method type \verb@[\,]T@ is treated specially. In this case, the +method type \verb@[]T@ is treated specially. In this case, the corresponding actual argument expression is not evaluated before the application. Instead, every use of the formal parameter on the right-hand side of the rewrite rule entails a re-evaluation of the @@ -2433,7 +2457,33 @@ will never produce a division-by-zero error at run-time, since the expression \verb@(y = 1/x)@ will be evaluated in the body of \verb@while@ only if the condition parameter is false. -\subsection{References to Overloaded Bindings} +\section{Type Applications} +\label{sec:type-app} +\syntax\begin{verbatim} + SimpleExpr \=::= \= SimpleExpr `[' Types `]' +\end{verbatim} + +A type application \verb@f[T$_1$, ..., T$_n$]@ instantiates a +polymorphic value \verb@f@ of type +\verb@[a$_1$ >: L$_1$ <: U$_1$, ..., a$_n$ >: L$_n$ <: U$_n$]S@ with +argument types \verb@T$_1$, ..., T$_n$@. Every argument type +\verb@T$_i$@ must obey corresponding bounds \verb@L$_i$@ and +\verb@U$_i$@. That is, for each \verb@i = 1 \commadots n@, we must +have \verb@L$_i \sigma$ <: T$_i$ <: U$_i \sigma$@, where $\sigma$ is the +substitution \verb@[a$_1$ := T$_1$, ..., a$_n$ := T$_n$]@. The type +of the application is \verb@S$\sigma$@. + +The function part \verb@f@ may also have some value type. In this case +the type application is taken to be equivalent to +\verb@f.apply[\verb@T$_1$, ..., T$_n$]@, i.e.\ the +application of an \verb@apply@ function defined by \verb@f@. + +Type applications can be omitted if local type inference +(\sref{sec:local-type-inf}) can infer best type parameters for a +polymorphic functions from the types of the actual function arguments +and the expected result type. + +\section{References to Overloaded Bindings} \label{sec:overloaded-refs} If a name \verb@f@ referenced in an identifier or selection is @@ -2443,137 +2493,89 @@ way this is done depends on whether or not \verb@f@ is used as a function. Let $\AA$ be the set of all type alternatives of \verb@f@. -Assume first that \verb@f@ is used as a function, as in -\verb@f(args)@. If there is precisely one alternative in \verb@\AA@ -which is a (possibly polymorphic) method type whose arity matches the -number of arguments given, that alternative is chosen. +Assume first that \verb@f@ appears as a function in an application, as +in \verb@f(args)@. If there is precisely one alternative in +\verb@\AA@ which is a (possibly polymorphic) method type whose arity +matches the number of arguments given, that alternative is chosen. Otherwise, let \verb@argtypes@ be the vector of types obtained by typing each argument with an undefined prototype. One determines first -the set of applicable alternatives. A method type alternative is -applicable if each type in \verb@argtypes@ conforms to the +the set of applicable alternatives. A method type alternative is {\em +applicable} if each type in \verb@argtypes@ is compatible with the corresponding formal parameter type in the alternative, and, if a -prototype is given, the method's result type conforms to it. A +prototype is given, the method's result type is compatible to it. A polymorphic method type is applicable if local type inference can determine type arguments so that the instantiated method type is -applicable. - -Let $\BB$ be the set of applicable alternatives. It is an error of -$\BB$ is empty. Otherwise, one chooses the most specific alternative - - - - +applicable. +Here, a type \verb@T@ is {\em compatible} to a type \verb@U@ if one of the +following three clauses applies: +\begin{enumerate} +\item +\verb@T@ conforms to \verb@U@. +\item +\verb@T@ is a parameterless method type \verb@[]T'@ and \verb@T'@ +conforms to \verb@U@. +\item +\verb@T@ is a monomorphic method type \verb@(ps$_1$) ... (ps$_n$)S@ which +can be converted to a function type \verb@T'@ by using the rules for +implicit conversions \sref{sec:impl-conv} and \verb@T'@ conforms to +\verb@U@. +\end{enumerate} - - - -and let \veeb@pt@ be the expected (result-) type of the expression. - - - - - -Let \verb@n $\geq$ 0@ be maximal such that there is a method -type of arity \verb@\geq n@ in \verb@\AA@, and \verb@f@ is a applied -to at least \verb@n@ argument lists, e.g.\ it is used as in -\verb@f;(args$_1$) \ldots (args$_n$)@. Let \verb@T$_p$@ be the -expected type of \verb@f;(args$_1$) \ldots (args$_n$)@ (which may be -partially undefined). For \verb@i \in 1 \commadots n@ let -\verb@{ts$_i$}@ be the list of types of \verb@{args$_i$}@ which are -obtained by typing each argument in \verb@{args$_i$}@ with a -completely undefined prototype. - -Among all {\em applicable} alternative types in \verb@\AA@ the compiler -selects one which {\em specializes} all others. - -A method type alternative of arity \verb@m \geq n@ is {\em applicable} if a -non-overloaded function of that type could legally be applied to -stable identifier lists \verb@{xs$_1$} \commadots xs$_n$@ of the argument types -\verb@{ts$_1$} -\commadots {ts$_n$}@, and the application's result type would match -\verb@T$_p$@. - -\comment{ -Method types which do not have a class constructor -\verb@class T@ as their result type always specialize -method types which do. For other pairs of method types, the -following applies: } -A parameterized method type \verb@(ps$_1$) -\ldots (ps$_m$) T@ where \verb@m > 0@ {\em specializes} some other -type \verb@U@ if \verb@U@ is applicable to arguments \verb@(ps$_1$)@ \ldots \verb@(ps$_m$)@. -A polymorphic method type \verb@[a$_1$ -\extends S$_1$ -\commadots a$_k$ \extends S$_k$] (ps$_1$) \ldots (ps$_m$) T@ specializes -a type \verb@U@ if \verb@(ps$_1$) \ldots (ps$_m$) T@ is more -specific than \verb@U@ under the assumption that for \verb@i = 1 \commadots k@ -each \verb@a$_i$@ is an abstract type name bounded by \verb@S$_i$@. - -If there is no applicable signature which specializes all other -applicable signatures, or if there is more than one, the application -is rejected for being ambiguous. +Let $\BB$ be the set of applicable alternatives. It is an error if +$\BB$ is empty. Otherwise, one chooses the {\em most specific} +alternative among the alternatives in $\BB$, according to the +following definition of being ``more specific''. +\begin{itemize} +\item +A method type \verb@(ps)T@ is more specific than some other +type \verb@S@ if \verb@S@ is applicable to arguments \verb@(ps)@. +\item +A polymorphic method type +\verb@[a$_1$ >: L$_1$ <: U$_1$, ..., a$_n$ >: L$_n$ <: U$_n$](ps)T@ is +more specific than some other type \verb@S@ if \verb@(ps)T@ is more +specific than \verb@S@ under the assumption that for +\verb@i = 1 \commadots n@ each \verb@a$_i$@ is an abstract type name +bounded from below by \verb@L$_i$@ and from above by \verb@U$_i$@. +\item +Any other type is always more specific than a parameterized method +type or a polymorphic type. +\end{itemize} +It is an error if there is no unique alternative in $\BB$ which is +more specific than all other alternatives in $\BB$. + +Assume next that \verb@f@ appears as a function in a type +application, as in \verb@f[targs]@. Then we choose an alternative in +$\AA$ which takes the same number of type parameters as there are +type arguments in \verb@targs@. It is an error if no such alternative +exists, or if it is not unique. + +Assume finally that \verb@f@ does not appear as a function in either +an application or a type application. If an expected type is given, +let \verb@BB@ be the set of those alternatives in \verb@AA@ which are +compatible to it. Otherwise, let \verb@BB@ be the same as \verb@AA@. +We choose in this case the most specific alternative among all +alternatives in \verb@BB@. It is an error if there is no unique +alternative in $\BB$ which is more specific than all other +alternatives in $\BB$. \example Consider the following definitions: \begin{verbatim} - class S extends B with {} - def f(x: S)(y: B) = ... - def f(x: B)(y: B) = ... - val s: S, b: B + class A extends B {} + def f(x: B, y: B) = ... + def f(x: A, y: B) = ... + val a: A, b: B \end{verbatim} -Then the application \verb@f(s)(s)@ refers to the first -definition of \verb@f@ whereas the application \verb@f(b)(b)@ +Then the application \verb@f(b, b)@ refers to the first +definition of \verb@f@ whereas the application \verb@f(a, a)@ refers to the second. Assume now we add a third overloaded definition \begin{verbatim} - def f(x: B)(y: S) = ... -\end{verbatim} -Then the application \verb@f(s)(s)@ is rejected for being ambiguous, since - no most specific applicable signature exists. - -\comment{ -\example Consider the following definitions - -\begin{verbatim} - class Point() with { ... } - module Point with { val origin = 0.0 } + def f(x: B, y: A) = ... \end{verbatim} - -Then the term namespace contains the overloaded binding -\verb@Point: ()constr Point \verb@\overload@ Point\verb@\Dollar@class@ -where \verb@C_{Point}@ stands for the (invisible) type of the module -\verb@Point@. Therefore the name \verb@Point@ identifies the -\verb@Point@ module, the expression \verb@Point.origin@ selects its \verb@origin@ -field, but \verb@Point()@ is an invocation of the \verb@Point@ -constructor. -} - -\section{Type Applications} -\label{sec:type-app} -\syntax\begin{verbatim} - SimpleExpr \=::= \= SimpleExpr `[' Types `]' -\end{verbatim} - -A type application \verb@f[T$_1$\commadots T$_n$]@ instantiates a polymorphic -value \verb@f@ of type \verb@[a$_1$ \extends B$_1$ \commadots a$_n$ \extends B$_n$] U@ with -argument types \verb@T$_1$ \commadots T$_n$@. Every argument type \verb@T$_i$@ must -conform to the corresponding bound type \verb@B$_i$@. That is, for each \verb@i = 1 -\commadots n@, we must have \verb@T$_i$ \conforms B$_i$\sigma@, where \verb@\sigma@ is -the substitution \verb@[a$_1$ := T$_1$, ..., a$_n$ := T$_n$]@. The type of the -application is \verb@U\sigma@. If the function part \verb@f@ has an overloaded -type \verb@T$_1$ \overload \ldots \overload T$_n$@ then excatly one alternative -\verb@T$_i$@ must have an \verb@n@-ary type parameter list, and this alternative -will be instantiated. - -The function part \verb@f@ may also have some value type. In this case the -type application is taken to be equivalent to -\verb@\verb@f@.apply[\verb@T$_1$\commadots T$_n$@]@, -i.e.\ the application of an \verb@apply@ function defined by \verb@f@. - -Type applications can be omitted if local type inference -(\sref{sec:local-type-inf}) can infer best type parameters for a -polymorphic functions from the types of the actual function arguments -and the expected result type. +Then the application \verb@f(a, a)@ is rejected for being ambiguous, since +no most specific applicable signature exists. \section{Instance Creation Expressions} \label{sec:inst-creation} @@ -2582,75 +2584,105 @@ and the expected result type. Expr4 \=::= \= new Template \end{verbatim} -A simple instance creation expression is \verb@\NEW;c@ where \verb@c@ is a -constructor invocation (\sref{sec:constr-invoke}). If \verb@c@ has type -\verb@class T@, then \verb@new c@ has type \verb@T@. -This type must conform to -type \verb@scala.AnyRef@. -The expression -is evaluated by creating a fresh object of type \verb@T@, which is is -initialized by evaluating \verb@c@. +A simple instance creation expression is \verb@new c@ where \verb@c@ +is a constructor invocation (\sref{sec:constr-invoke}). Let \verb@T@ +be the type of \verb@c@. Then \verb@T@ must denote a (a type instance +of) a reference class which is non-abstract, and which conforms to its self +type. The expression is evaluated by creating a fresh object of the +type \verb@T@, which is is initialized by evaluating \verb@c@. The +type of the expression is \verb@T@'s self type (which might be less +specific than \verb@T@). A general instance creation expression is -\verb@@\NEW;sc;\WITH;mc$_1$;\WITH;\ldots;\WITH;mc$_n$;\WITH;(stats)\verb@@ where \verb@n \geq -0@, \verb@sc@ as well as \verb@mc$_1$ \commadots mc$_n$@ are constructor invocations -(of types \verb@\CLASS;S, \CLASS;T$_1$ \commadots \CLASS;T$_n$@, say) and +\verb@new sc with mc$_1$ with ... with mc$_n$ {stats}@ where +\verb@n $\geq$ 0@, \verb@sc@ as well as \verb@mc$_1$, ..., mc$_n$@ are +constructor invocations (of types \verb@S, T$_1$, ...,T$_n$@, say) and \verb@stats@ is a statement sequence containing initializer statements and member definitions (\sref{sec:members}). The type of such an instance creation expression is then the compound type -\verb@S;\WITH;T$_1$;\WITH;\ldots;\WITH;T$_n$;\WITH;R@, where \verb@R@ is a -refinement (\sref{sec:refinements}) which declares exactly those -members of \verb@stats@ that override a member of \verb@S@ or \verb@T$_1$ \commadots -T$_n$@. This type must conform to -type \verb@scala.AnyRef@. -For this type to be well-formed, \verb@R@ may not reference types -defined in \verb@stats@ which do not themselves form part of \verb@R@. +\verb@S with T$_1$ with ... with T$_n$ {R}@, where \verb@{R}@ is a +refinement (\sref{sec:compound-types}) which declares exactly those +members of \verb@stats@ that override a member of \verb@S@ or +\verb@T$_1$, ..., T$_n$@. For this type to be well-formed, \verb@R@ +may not reference types defined in \verb@stats@ which do not +themselves form part of \verb@R@. The instance creation expression is evaluated by creating a fresh object, which is initialized by evaluating the expression template. \example Consider the class \begin{verbatim} -abstract class C with { - type T - val x: T - def f(x: T): Object +abstract class C { + type T; val x: T; def f(x: T): Object } \end{verbatim} and the instance creation expression \begin{verbatim} -C with { - type T = Int - val x: T = 1 - def f(x: T): T = y - val y: T = 2 -} +C { type T = Int; val x: T = 1; def f(x: T): T = y; val y: T = 2 } \end{verbatim} Then the created object's type is: \begin{verbatim} -C with { - type T = Int - val x: T - def f(x: T): T -} +C { type T = Int; val x: T; def f(x: T): T } \end{verbatim} The value \verb@y@ is missing from the type, since \verb@y@ does not override a member of \verb@C@. +\section{Blocks} +\label{sec:blocks} + +\syntax\begin{verbatim} + BlockExpr \=::= \= `{' Block `}' + Block \>::= \> [{BlockStat `;'} Expr] +\end{verbatim} + +A block expression +\verb@{s$_1$; ...; s$_n$; e} is constructed from a sequence of block statements \verb@s$_1$ +, ..., s$_n$@ and a final expression \verb@e@. The final expression +can be omitted, in which case the unit value \verb@()@ is assumed. + +%Whether or not the scope includes the statement itself +%depends on the kind of definition. + +The expected type of the final expression \verb@e@ is the expected +type of the block. The expected type of all preceding statements is +undefined. + +The type of a block \verb@s$_1$; ...; s$_n$; e@ is usually the type of +\verb@e@. That type must be equivalent to a type which does not refer +to an entity defined locally in the block. If this condition is +violated, but a fully defined expected type is given, the type of the +block is instead assumed to be the expected type. + +Evaluation of the block entails evaluation of its statement sequence, +followed by an evaluation of the final expression \verb@e@, which +defines the result of the block. + +\example +Written in isolation, +the block \verb@{ class C extends B {...} ; new C }@ is illegal, since its type +refers to class \verb@C@, which is defined locally in the block. + +However, when used in a definition such as +\begin{verbatim} +val x: B = { class C extends B {...} ; new C } +\end{verbatim} +the block is well-formed, since the problematic type \verb@C@ can be +replaced by the expected type \verb@B@. + \section{Prefix, Infix, and Postfix Operations} \label{sec:infix-operations} \syntax\begin{verbatim} - Expr2 \=::= \= Expr3 [id] - Expr3 \>::= \> Expr4 - \> | \> Expr3 Id Expr3 - Expr4 \>::= \> SimpleExpr - \> |\> (`+' | `-' | `!') Expr4 + PostfixExpr \>::=\> InfixExpr [Id] + InfixExpr \>::=\> PrefixExpr + \> |\> InfixExpr Id InfixExpr + PrefixExpr \>::=\> [`-' | `+' | `!' | `~'] SimpleExpr \end{verbatim} Expressions can be constructed from operands and operators. A prefix -operation \verb@op;e@ consists of a prefix operator \verb@op@, which must be one -of \verb@+@, \verb@-@, \verb@!@, and a simple expression \verb@e@. The +operation \verb@op e@ consists of a prefix operator \verb@op@, +which must be one of \verb@+@, \verb@-@, \verb@!@, or \verb@~@, +and a simple expression \verb@e@. The expression is equivalent to the postfix method application \verb@e.op@. Prefix operators are different from normal function applications in @@ -2681,10 +2713,9 @@ precedence, with characters on the same line having the same precedence. That is, operators starting with a letter have lowest precedence, followed by operators starting with `\verb@|@', etc. -The {\em associativity} of an operator -is also determined by the operator's first character. - Operators starting with a colon -`\verb@:@' are right-associative. All other operators are left-associative. +The {\em associativity} of an operator is determined by the operator's +last character. Operators ending with a colon `\verb@:@' are +right-associative. All other operators are left-associative. Precedence and associativity of operators determine the grouping of parts of an expression as follows. @@ -2693,40 +2724,42 @@ parts of an expression as follows. expression, then operators with higher precedence bind more closely than operators with lower precedence. \item If there are consecutive infix -operations \verb@e$_0$;op$_1$;e$_1$;op$_2$\ldots;op$_n$;e$_n$@ with operators \verb@op$_1$ -\commadots op$_n$@ of the same precedence, then all these operators must +operations \verb@e$_0$ op$_1$ e$_1$ op$_2$ ... op$_n$ e$_n$@ +with operators \verb@op$_1$, ..., op$_n$@ of the same precedence, +then all these operators must have the same associativity. If all operators are left-associative, -the sequence is interpreted as \verb@(\ldots(e$_0$;op$_1$;e$_1$);op$_2$;\ldots); -op$_n$;e$_n$@. Otherwise, if all operators are right-associative, the +the sequence is interpreted as +\verb@(...(e$_0$ op$_1$ e$_1$) op$_2$...) op$_n$ e$_n$@. +Otherwise, if all operators are right-associative, the sequence is interpreted as -\verb@e$_0$;op$_1$;(e$_1$;op$_2$;(\ldots;op$_n$;e$_n$)\ldots)@. +\verb@e$_0$ op$_1$ (e$_1$ op$_2$ (... op$_n$ e$_n$)...)@. \item Postfix operators always have lower precedence than infix -operators. E.g.\ \verb@e$_1$;op$_1$;e$_2$;op$_2$@ is always equivalent to -\verb@(e$_1$;op$_1$;e$_2$);op$_2$@. +operators. E.g.\ \verb@e$_1$ op$_1$ e$_2$ op$_2$@ is always equivalent to +\verb@(e$_1$ op$_1$ e$_2$) op$_2$@. \end{itemize} A postfix operation \verb@e;op@ is interpreted as \verb@e.op@. A -left-associative binary operation \verb@e$_1$;op;e$_2$@ is interpreted as +left-associative binary operation \verb@e$_1$ op e$_2$@ is interpreted as \verb@e$_1$.op(e$_2$)@. If \verb@op@ is right-associative, the same operation is -interpreted as \verb@(\VAL;x=e$_1$ -\semi e$_2$.op(x))@, where \verb@x@ is a fresh name. +interpreted as \verb@(val x=e$_1$; e$_2$.op(x))@, +where \verb@x@ is a fresh name. \section{Typed Expressions} \syntax\begin{verbatim} - Expr1 \=::= \= Expr2 [`:' Type] + Expr \=::= \= PostfixExpr [`:' Type1] \end{verbatim} -The typed expression \verb@e: T@ has type \verb@T@. The type of expression \verb@e@ -is required to conform to \verb@T@. The result of the expression is the -value of \verb@e@ converted to type \verb@T@. +The typed expression \verb@e: T@ has type \verb@T@. The type of +expression \verb@e@ is expected to conform to \verb@T@. The result of +the expression is the value of \verb@e@ converted to type \verb@T@. \example Here are examples of well-typed and illegal typed expressions. \begin{verbatim} - 1: Int \=// legal, of type Int - 1: Long \>// legal, of type Long - // 1: String \>// illegal + 1: int \=// legal, of type int + 1: long \>// legal, of type long + // 1: string \>// illegal \end{verbatim} \section{Assignments} @@ -2737,15 +2770,83 @@ value of \verb@e@ converted to type \verb@T@. \end{verbatim} An assignment to a simple variable \verb@x = e@ is interpreted as the invocation -\verb@\verb@x@$_=$(\verb@e@)@ of the setter function for variable +\verb@x_=(e)@ of the setter function for variable \verb@x@ (\sref{sec:vardef}). -Analogously, an assignment \verb@f.a = e@ to a field \verb@a@ is interpreted -as the invocation \verb@\verb@f.a@_=(\verb@e@)@. +Analogously, an assignment \verb@f.x = e@ to a field \verb@x@ is interpreted +as the invocation \verb@f.x_=(e)@. -An assignment \verb@f(is) = e@ with a function application to the -left of the ``\verb@=@' operator is interpreted as \verb@\verb@f@.update(\verb@is, e@)@, i.e.\ +An assignment \verb@f(args) = e@ with a function application to the +left of the ``\verb@=@' operator is interpreted as +\verb@f.update(args, e)@, i.e.\ the invocation of an \verb@update@ function defined by \verb@f@. +\example Here is the usual imperative code for matrix multiplication. + +\begin{verbatim} +def matmul(xs: Array[Array[double]], ys: Array[Array[double]]) = { + val zs: Array[Array[double]] = new Array(xs.length, ys.length); + var i = 0; + while (i < xs.length) { + var j = 0; + while (j < ys(0).length) { + var acc = 0.0; + var k = 0; + while (k < ys.length) { + acc = acc + xs(i)(k) * ys(k)(j); + k = k + 1 + } + zs(i)(j) = acc; + j = j + 1 + } + i = i + 1 + } + zs +} +\end{verbatim} +Desugaring the array accesses and assignments yields the following +expanded version: +\begin{verbatim} +def matmul(xs: Array[Array[double]], ys: Array[Array[double]]) = { + val zs: Array[Array[double]] = new Array(xs.length, ys.length); + var i = 0; + while (i < xs.length) { + var j = 0; + while (j < ys(0).length) { + var acc = 0.0; + var k = 0; + while (k < ys.length) { + acc = acc + xsa.apply(i).apply(k) * ys.apply(k).apply(j); + k = k + 1 + } + zs.apply(i).update(j, acc); + j = j + 1 + } + i = i + 1 + } + zs +} +\end{verbatim} + +\begin{verbatim} +def matmul(xss: Array[Array[double]], yss: Array[Array[double]]) = { + val ysst = transpose(yss); + for (val xs <- xs) yield + for (val ys <- ysst) yield + scalprod(xs, ys) +} + +def transpose[a](xss: Array[Array[a]]) { + for (val i <- Array.range(0, xss(0).length)) yield + Array(for (val xs <- xss) yield xs(i)) + +def scalprod(xs: Array[double], ys: Array[double]) { + var acc = 0.0; + for (val Pair(x, y) <- xs zip ys) do acc = acc + x * y; + acc +} +\end{verbatim} + + \section{Conditional Expressions} \syntax\begin{verbatim} @@ -3049,31 +3150,6 @@ $(T_1 \commadots T_n) U$. The expression is interpreted as \>// variable count and returns the new value. \end{verbatim} -\section{Blocks} -\label{sec:blocks} - -\syntax\begin{verbatim} - Block \=::= \= [{BlockStat `;'} Expr] -\end{verbatim} - -A block $s_1 \semi\ldots\semi s_n \semi e$ -is constructed from a sequence of block statements $s_1 \commadots s_n$ -and a final expression $e$. The final expression can be omitted, in -which case the unit value $()$ is assumed. - -Block statements may be definitions which bind local names in the -block. No modifiers are allowed in block-local definitions. - -%Whether or not the scope includes the statement itself -%depends on the kind of definition. - -The type of a block $s_1 \semi\ldots\semi s_n \semi e$ is the type of $e$. That -type must be equivalent to a type which does not refer to an entity -defined locally in the block. -Evaluation of the block entails -evaluation of its statement sequence, followed by an evaluation of the final expression -$e$, which defines the result of the block. - \section{Statements} \label{sec:statements} @@ -3097,6 +3173,9 @@ declarations. An expression that is used as a statement can have an arbitrary value type. An expression statement $e$ is evaluated by evaluating $e$ and discarding the result of the evaluation. +Block statements may be definitions which bind local names in the +block. No modifiers are allowed in block-local definitions. + With the exception of overloaded definitions (\sref{sec:overloaded-defs}), a statement sequence making up a block or template may not contain two definitions or declarations that bind diff --git a/sources/scalac/CompilerCommand.java b/sources/scalac/CompilerCommand.java index 5b87d72b46..3eb8a1d117 100644 --- a/sources/scalac/CompilerCommand.java +++ b/sources/scalac/CompilerCommand.java @@ -40,7 +40,7 @@ public class CompilerCommand extends CommandParser { public final BooleanOptionParser uniqid; public final BooleanOptionParser types; public final BooleanOptionParser prompt; - public final BooleanOptionParser separate; + public final ChoiceOptionParser separate; //public final OptimizeOptionParser optimize; public final StringOptionParser classpath; public final StringOptionParser sourcepath; @@ -109,9 +109,9 @@ public class CompilerCommand extends CommandParser { "prompt", "Display a prompt after each error (debugging option)", false), - this.separate = new BooleanOptionParser(this, - "separate", "read symbol files for separate compilation", - false), + this.separate = new ChoiceOptionParser(this, + "separate", "read symbol files for separate compilation: (yes, no)", + "separate", new String[]{"yes", "no"}, "default"), //this.optimize = new OptimizeOptionParser(this, // "optimize", "optimize bytecode (-optimize:help for option list)", diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java index 4860eb9402..44636ff982 100644 --- a/sources/scalac/Global.java +++ b/sources/scalac/Global.java @@ -164,7 +164,6 @@ public class Global { this.start(); // timestamp to compute the total time this.noimports = args.noimports.value; this.nopredefs = args.nopredefs.value; - this.separate = args.separate.value; //this.optimize = args.optimize.optimize; this.debug = args.debug.value; this.uniqid = args.uniqid.value; @@ -174,6 +173,8 @@ public class Global { this.classPath = args.classpath(); this.outpath = args.outpath(); this.target = interpret ? TARGET_INT : args.target.value.intern(); + this.separate = args.separate.value.equals("yes") || + args.separate.value.equals("default") && !this.target.equals(TARGET_INT); this.uniqueID = new UniqueID(); String printFile = args.printfile.value; try { diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 280d3f73e6..55bb65b6ac 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -148,15 +148,13 @@ public abstract class Symbol implements Modifiers, Kinds { || info instanceof Type.PolyType && ((Type.PolyType)info).result instanceof Type.MethodType : "illegal type for " + this + ": " + info; - //if ((flags & (INITIALIZED | LOCKED)) != (INITIALIZED | LOCKED)) { - if (infos == TypeIntervalList.EMPTY) { - infos = new TypeIntervalList(TypeIntervalList.EMPTY); - } - infos.limit = limit; - infos.info = info; - if (info instanceof Type.LazyType) flags &= ~INITIALIZED; - else flags |= INITIALIZED; - //} + if (infos == TypeIntervalList.EMPTY) { + infos = new TypeIntervalList(TypeIntervalList.EMPTY); + } + infos.limit = limit; + infos.info = info; + if (info instanceof Type.LazyType) flags &= ~INITIALIZED; + else flags |= INITIALIZED; return this; } @@ -205,6 +203,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Does this symbol denote a value? */ public final boolean isValue() { + preInitialize(); return kind == VAL && !(isModule() && isJava()) && !isPackage(); } @@ -615,7 +614,8 @@ public abstract class Symbol implements Modifiers, Kinds { public final void preInitialize() { //todo: clean up if (infos.info instanceof ClassParser || - infos.info instanceof SourceCompleter) + infos.info instanceof SourceCompleter || + infos.info instanceof ClassParser.StaticsParser) infos.info.complete(this); } @@ -627,6 +627,7 @@ public abstract class Symbol implements Modifiers, Kinds { * its baseclasses and members. */ public Type info() { + //if (isModule()) moduleClass().initialize(); int id = currentPhaseId(); if ((flags & INITIALIZED) == 0) { Type info = rawInfoAt(FIRST_ID); diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 7b27647e22..10578d02de 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -53,7 +53,7 @@ public class Type implements Modifiers, Kinds, TypeTags, EntryTags { */ public case TypeRef(Type pre, Symbol sym, Type[] args) { assert pre.isLegalPrefix() || pre == ErrorType : pre + "#" + sym; - assert sym.kind == ERROR || sym.isType() : pre + "#" + sym; + assert sym.kind == ERROR || sym.isType() : pre + " # " + sym; } /** parts_1 with ... with parts_n { members } diff --git a/sources/scalac/symtab/classfile/AttributeParser.java b/sources/scalac/symtab/classfile/AttributeParser.java index 4df2529b2d..a4cfc6fec6 100644 --- a/sources/scalac/symtab/classfile/AttributeParser.java +++ b/sources/scalac/symtab/classfile/AttributeParser.java @@ -81,18 +81,8 @@ public class AttributeParser implements ClassfileConstants { switch (attr) { // class attributes case SCALA_ATTR: - in.skip(attrLen); - /* not yet - Name sourcefile = (Name)pool.readPool(in.nextChar()); - new UnPickle( - (JavaClassSymbol) sym, in.nextBytes(attrLen - 2), sourcefile); - */ - return; - - case SOURCEFILE_ATTR: - // ((ClassDef)def).sourcefile = (Name)reader.readPool(in.nextChar()); - in.skip(attrLen); - return; + new UnPickle(sym, in.nextBytes(attrLen), Name.fromString(in.path)); + return; case INNERCLASSES_ATTR: /* int n = in.nextChar(); @@ -154,8 +144,11 @@ public class AttributeParser implements ClassfileConstants { new MetaParser(meta, tvars, sym, type).parse(), Symbol.FIRST_ID); return; + + default: + in.skip(attrLen); + return; } - throw new RuntimeException("unknown classfile attribute"); } Scope tvars = new Scope(); diff --git a/sources/scalac/symtab/classfile/ClassParser.java b/sources/scalac/symtab/classfile/ClassParser.java index 19eb931f3b..0dc29c87bb 100644 --- a/sources/scalac/symtab/classfile/ClassParser.java +++ b/sources/scalac/symtab/classfile/ClassParser.java @@ -28,6 +28,7 @@ public class ClassParser extends Type.LazyType { /** complete class symbol c by loading the class */ public void complete(Symbol c) { + c.owner().initialize(); //System.out.println("loading " + c);//DEBUG try { long msec = System.currentTimeMillis(); @@ -59,7 +60,7 @@ public class ClassParser extends Type.LazyType { return new AliasParser(alias); } - class StaticsParser extends Type.LazyType { + public class StaticsParser extends Type.LazyType { Symbol clazz; StaticsParser(Symbol clazz) { diff --git a/sources/scalac/symtab/classfile/ClassfileParser.java b/sources/scalac/symtab/classfile/ClassfileParser.java index 098be96b06..da5300cb42 100644 --- a/sources/scalac/symtab/classfile/ClassfileParser.java +++ b/sources/scalac/symtab/classfile/ClassfileParser.java @@ -97,11 +97,12 @@ public class ClassfileParser implements ClassfileConstants { c.setInfo(classType, Symbol.FIRST_ID); // set type of statics Symbol staticsClass = c.module().moduleClass(); - Type staticsInfo = Type.compoundType(Type.EMPTY_ARRAY, statics, staticsClass); - staticsClass.setInfo(staticsInfo, Symbol.FIRST_ID); - c.module().setInfo(Type.TypeRef(staticsClass.owner().thisType(), + if (staticsClass.isModuleClass()) { + Type staticsInfo = Type.compoundType(Type.EMPTY_ARRAY, statics, staticsClass); + staticsClass.setInfo(staticsInfo, Symbol.FIRST_ID); + 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()); diff --git a/sources/scalac/symtab/classfile/PackageParser.java b/sources/scalac/symtab/classfile/PackageParser.java index 9fdbe797ed..1b29c7a0ef 100644 --- a/sources/scalac/symtab/classfile/PackageParser.java +++ b/sources/scalac/symtab/classfile/PackageParser.java @@ -8,10 +8,12 @@ package scalac.symtab.classfile; +import ch.epfl.lamp.util.*; import scalac.*; import scalac.symtab.*; import scalac.util.*; import java.io.*; +import java.util.HashMap; public class PackageParser extends Type.LazyType { @@ -39,18 +41,19 @@ public class PackageParser extends Type.LazyType { Scope members = new Scope(); String dirname = null; Name name = p.fullName(); + HashMap/**/ symFile = new HashMap(); if (name.length() == 0) { // includeMembers(AbstractFile.open(null, "."), p, members, false); } else { dirname = SourceRepresentation.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); + AbstractFile.open(base[i], dirname), + p, members, dirname != null, symFile); } p.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, p)); if (dirname == null) @@ -59,11 +62,24 @@ public class PackageParser extends Type.LazyType { (System.currentTimeMillis() - msec) + "ms"); } + private boolean isMostRecent(AbstractFile f, Symbol previous, HashMap symFile) { + if (previous == Symbol.NONE || previous.isPackage()) return true; + if (previous.pos != Position.NOPOS) return false; + AbstractFile pf = (AbstractFile) symFile.get(previous); + if (!global.separate) { + if (f.getName().endsWith(".scala") && + pf.getName().endsWith(".class")) return true; + if (f.getName().endsWith(".class") && + pf.getName().endsWith(".scala")) return false; + } + return f.lastModified() > pf.lastModified(); + } + /** read directory of a classpath directory and include members * in package/module scope */ protected void includeMembers(AbstractFile dir, Symbol p, Scope locals, - boolean inclClasses) { + boolean inclClasses, HashMap symFile) { if (dir == null) return; String[] filenames = null; @@ -72,14 +88,17 @@ public class PackageParser extends Type.LazyType { return; for (int j = 0; j < filenames.length; j++) { String fname = filenames[j]; + AbstractFile f = dir.open(fname); if (inclClasses && fname.endsWith(".class")) { Name n = Name.fromString(fname.substring(0, fname.length() - 6)) .toTypeName(); - if (locals.lookup(n) == Symbol.NONE) { + if (isMostRecent(f, locals.lookup(n), symFile)) { ClassSymbol clazz = new ClassSymbol(n, p, classCompletion); // todo: needed? clazz.allConstructors().setInfo( classCompletion.staticsParser(clazz)); + clazz.module().setInfo( + classCompletion.staticsParser(clazz)); // enter class locals.enter(clazz); // enter module, except for scala.Object class @@ -93,14 +112,18 @@ public class PackageParser extends Type.LazyType { } locals.enter(clazz.module()); } + symFile.put(clazz, f); } } 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); + //todo: moduleClass needs to be entered? locals.enter(module.moduleClass()); - } + } + +/* } else if (inclClasses && fname.endsWith(".symbl")) { //todo: compare dates between symbl and scala. Name n = Name.fromString(fname.substring(0, fname.length() - 6)) @@ -117,14 +140,11 @@ public class PackageParser extends Type.LazyType { locals.enter(clazz); locals.enter(clazz.module()); } +*/ } else if (inclClasses && fname.endsWith(".scala")) { Name n = Name.fromString(fname.substring(0, fname.length() - 6)) .toTypeName(); - Symbol sym = locals.lookup(n); - if (sym == Symbol.NONE || - sym.isPackage() || - sym.rawInfoAt(Symbol.FIRST_ID) instanceof ClassParser && - !(sym.rawInfoAt(Symbol.FIRST_ID) instanceof SymblParser)) { + if (isMostRecent(f, locals.lookup(n), symFile)) { SourceCompleter completer = new SourceCompleter(global); ClassSymbol clazz = new ClassSymbol(n, p, completer); //todo: needed? @@ -133,6 +153,7 @@ public class PackageParser extends Type.LazyType { // enter class locals.enter(clazz); locals.enter(clazz.module()); + symFile.put(clazz, f); } } } diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java index fe41289f8f..bae101668d 100644 --- a/sources/scalac/symtab/classfile/Pickle.java +++ b/sources/scalac/symtab/classfile/Pickle.java @@ -72,46 +72,6 @@ public class Pickle implements Kinds, Modifiers, EntryTags { return bp; } - /** Create output file with given extension for given class. - */ - public File outputFile(Name fullname, String extension) { - if (Global.instance.outpath != null) { - return new File( - Global.instance.outpath, - SourceRepresentation.externalizeFileName(fullname) + extension); - } else { - String s = fullname.toString(); - int i = s.length(); - while (i > 0 && s.charAt(i - 1) != '.') i--; - return new File(s.substring(i) + extension); - } - } - - private void createPath(File f) { - try { - f.createNewFile(); - } catch (IOException ex) { - f.getParentFile().mkdirs(); - try { - f.createNewFile(); - } catch (IOException ex1) { - } - } - } - - public void writeFile(Name fullname) { - File outfile = outputFile(fullname, ".symbl"); - try { - createPath(outfile); - FileOutputStream out = new FileOutputStream(outfile); - out.write(bytes, 0, bp); - out.close(); - Global.instance.operation("wrote " + outfile); - } catch (IOException ex) { - System.err.println("error writing " + outfile); - } - } - /* ************************************************** * Phase 1: Build entry table ************************************************* */ diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java index de755fd7fd..07c30a60c4 100644 --- a/sources/scalac/symtab/classfile/UnPickle.java +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -35,7 +35,6 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { Global global; UnPickle(Symbol root, byte[] data, Name sourceName) { - assert !root.isInitialized(); global = Global.instance; if (root.isConstructor()) { this.classroot = root.primaryConstructorClass(); @@ -70,6 +69,8 @@ public class UnPickle implements Kinds, Modifiers, EntryTags { if (global.debug) global.log("unpickled " + root + ":" + root.rawInfo());//debug if (!root.isInitialized()) throw new BadSignature(this, "it does not define " + root); + if (moduleroot.isModule() && !moduleroot.moduleClass().isInitialized()) + moduleroot.setInfo(Type.NoType); } Type setOwner(Type tp, Symbol owner) { diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 9a9803691f..3c3812c573 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -129,7 +129,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { pickle.add(sym.owner().info().lookup(sym.name.toTermName())); pickle.add(sym.owner().info().lookup(sym.name.toTypeName())); pickle.pickle(); - pickle.writeFile(fullname); global.symdata.put(fullname, pickle); } break; @@ -270,12 +269,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { * - symbols with `override' modifier override some other symbol. */ void validate(Symbol sym) { - checkNoConflict(sym, DEFERRED, PRIVATE); - checkNoConflict(sym, FINAL, SEALED); - checkNoConflict(sym, FINAL, PRIVATE); - checkNoConflict(sym, PRIVATE, PROTECTED); - checkNoConflict(sym, PRIVATE, OVERRIDE); - checkNoConflict(sym, DEFERRED, FINAL); if ((sym.flags & ABSTRACTCLASS) != 0 && sym.kind != CLASS) { error(sym.pos, "`abstract' modifier can be used only for classes; " + "\nit should be omitted for abstract members"); @@ -317,6 +310,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { sym.flags &= ~OVERRIDE; } } + checkNoConflict(sym, DEFERRED, PRIVATE); + checkNoConflict(sym, FINAL, SEALED); + checkNoConflict(sym, FINAL, PRIVATE); + checkNoConflict(sym, PRIVATE, PROTECTED); + checkNoConflict(sym, PRIVATE, OVERRIDE); + checkNoConflict(sym, DEFERRED, FINAL); } /** Check that @@ -712,8 +711,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { tree.pos, name.toTermName(), owner, mods & ACCESSFLAGS | CASE, context.scope); enterInScope(cf); - if (!cf.isInitialized()) + if (!cf.isInitialized() || cf.info().symbol().isModuleClass()) { cf.setInfo(new LazyConstrMethodType(tree)); + } } } return enterSym(tree, clazz); diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index 6690855ec6..b3a6babae5 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -926,11 +926,13 @@ public class Infer implements Modifiers, Kinds { if (i == alts.length) throw new Type.Error("missing arguments for " + alts[0]); } + /* // then catch the case of a single alternative. if (alts.length == 1) { tree.setSymbol(alts[0]).setType(alttypes[0]); return; } + */ // finally, do the normal case. int best = -1; for (int i = 0; i < alttypes.length; i++) { diff --git a/sources/scalac/util/AbstractFile.java b/sources/scalac/util/AbstractFile.java index 2487e07ca3..7069df868b 100644 --- a/sources/scalac/util/AbstractFile.java +++ b/sources/scalac/util/AbstractFile.java @@ -39,6 +39,10 @@ public abstract class AbstractFile { */ public abstract boolean isDirectory(); + /** date file was last modified + */ + public abstract long lastModified(); + /** read content of the file into a byte[] buffer */ public abstract byte[] read() throws IOException; @@ -129,6 +133,10 @@ class PlainFile extends AbstractFile { return f.isDirectory(); } + public long lastModified() { + return f.lastModified(); + } + public byte[] read() throws IOException { FileInputStream in = new FileInputStream(f); int rest = (int)f.length(); @@ -196,6 +204,10 @@ class ZippedFile extends AbstractFile { return zipEntry.isDirectory(); } + public long lastModified() { + return zipEntry.getTime(); + } + public byte[] read() throws IOException { InputStream in = dir.zipFile.getInputStream(zipEntry); int rest = (int)zipEntry.getSize(); @@ -254,6 +266,10 @@ class ZipDir extends AbstractFile { return (zipFile != null); } + public long lastModified() { + return -1; + } + public byte[] read() throws IOException { throw new IOException("cannot read directory"); } @@ -322,6 +338,10 @@ final class JarArchive extends AbstractFile { return jarFile != null; } + public long lastModified() { + return -1; + } + public byte[] read() throws IOException { throw new IOException("cannot read archive"); } @@ -443,6 +463,10 @@ final class JarArchive extends AbstractFile { return true; } + public long lastModified() { + return -1; + } + public String[] list() throws IOException { throw new IOException("not a directory"); } @@ -510,6 +534,10 @@ final class JarArchive extends AbstractFile { return false; } + public long lastModified() { + return -1; + } + public String[] list() throws IOException { throw new IOException("not a directory"); } @@ -537,6 +565,10 @@ final class JarArchive extends AbstractFile { return true; } + public long lastModified() { + return jarFile.getJarEntry(name).getTime(); + } + public byte[] read() throws IOException { JarEntry jarEntry = jarFile.getJarEntry(name); if (jarEntry == null) diff --git a/sources/scalac/util/AbstractFileReader.java b/sources/scalac/util/AbstractFileReader.java index 0d18292838..2f7d0e1e21 100644 --- a/sources/scalac/util/AbstractFileReader.java +++ b/sources/scalac/util/AbstractFileReader.java @@ -21,11 +21,16 @@ public class AbstractFileReader { */ public int bp; + /** the file path name + */ + public final String path; + /** constructor */ public AbstractFileReader(AbstractFile f) throws IOException { buf = f.read(); bp = 0; + path = f.getPath(); } /** return byte at offset 'pos' -- cgit v1.2.3