diff options
author | Martin Odersky <odersky@gmail.com> | 2003-07-04 14:06:34 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2003-07-04 14:06:34 +0000 |
commit | 00abd39f96ee40da727ccc735d25ca3d96ce01ce (patch) | |
tree | 6d7314cd14761335c0dd99d149d8934ef45d4115 | |
parent | bf8fd4c5b3e1df5b249f7fa2d765913cf662fd51 (diff) | |
download | scala-00abd39f96ee40da727ccc735d25ca3d96ce01ce.tar.gz scala-00abd39f96ee40da727ccc735d25ca3d96ce01ce.tar.bz2 scala-00abd39f96ee40da727ccc735d25ca3d96ce01ce.zip |
*** empty log message ***
-rw-r--r-- | doc/reference/reference.verb.tex | 320 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Parser.java | 16 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Scanner.java | 1 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Tokens.java | 1 | ||||
-rw-r--r-- | sources/scalac/ast/printer/TextTreePrinter.java | 9 | ||||
-rw-r--r-- | sources/scalac/symtab/Modifiers.java | 10 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 18 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 6 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 69 | ||||
-rw-r--r-- | sources/scalac/util/Names.java | 1 | ||||
-rw-r--r-- | support/latex/verbfilterScala.java | 5 | ||||
-rw-r--r-- | test/files/neg/S6.check | 2 | ||||
-rw-r--r-- | test/files/neg/seqtest.check | 3 | ||||
-rw-r--r-- | test/files/pos/imports.scala | 2 | ||||
-rw-r--r-- | test/neg/S6.check | 2 | ||||
-rw-r--r-- | test/neg/seqtest.check | 3 | ||||
-rw-r--r-- | test/pos/imports.scala | 2 |
17 files changed, 228 insertions, 242 deletions
diff --git a/doc/reference/reference.verb.tex b/doc/reference/reference.verb.tex index f179555f5d..cca510c3aa 100644 --- a/doc/reference/reference.verb.tex +++ b/doc/reference/reference.verb.tex @@ -10,7 +10,7 @@ \newcommand{\iffinaltype}[1]{} \newcommand{\ifpackaging}[1]{} \newcommand{\ifnewfor}[1]{} -\renewcommand{\todo}[1]{#1} +\renewcommand{\todo}[1]{{$\clubsuit$\bf todo: #1$\spadesuit$}} \newcommand{\notyet}{\footnote{not yet implemented.}} \title{Report on the Programming Language Scala} @@ -256,9 +256,9 @@ abstract as case class constr def do else extends final false for if is import new null object override package -private protected super this trait -true type val var with -yield +private protected sealed super this +trait true type val var +with yield _ : = => <- <: >: # @ \end{verbatim} @@ -1368,29 +1368,36 @@ entity, of type \verb@T_1 \overload \ldots \overload T_n@ \label{sec:import} \syntax\begin{verbatim} - Import \=::=\> import ImportExpr {`,' ImportExpr} + Import \=::=\= import ImportExpr {`,' ImportExpr} ImportExpr \>::=\> StableId `.' (Id | `_' | ImportSelectors) ImportSelectors \>::=\> `{' {ImportSelector `,'} (ImportSelector | `_') `}' ImportSelector \>::=\> Id [`=>' Id | `=>' `_'] \end{verbatim} -An import clause has the form $import;e.I$ where \verb@e@ is a stable +An import clause has the form \verb@import p.I@ where \verb@p@ is a stable identifier (\sref{sec:paths}) and \verb@I@ is an import expression. -The import expression determines a set of names of members of \verb@e@ +The import expression determines a set of names of members of \verb@p@ which are made available without qualification. The most general form of an import expression is a list of {\em import selectors} \begin{verbatim} { x$_1$ => y$_1$, ..., x$_n$ => y$_n$, _ } \end{verbatim} for $n \geq 0$, where the final wildcard `\verb@_@' may be absent. It -makes available each member \verb@e.x$_i$@ under the unqualified name -\verb@y$_i$. I.e.\ every import selector \verb@x$_i$ => y$_i$@ renames -\verb@e.x$_i$@ to -\verb@y$_i$. If a final wildcard is present, all members \verb@z@ of -\verb@e@ other than \verb@x$_1$, ..., x$_n$@ are also made available +makes available each member \verb@p.x$_i$@ under the unqualified name +\verb@y$_i$@. I.e.\ every import selector \verb@x$_i$ => y$_i$@ renames +\verb@p.x$_i$@ to +\verb@y$_i$@. If a final wildcard is present, all members \verb@z@ of +\verb@p@ other than \verb@x$_1$, ..., x$_n$@ are also made available under their own unqualfied names. -If destination in an import selector is a wildcard, the import +Import selectors work in the same way for members in all three name +spaces. For instance, an import clause \verb@import p.{x => y}@ +renames the term name \verb@p.x@ to the term name \verb@y@, the type +name \verb@p.x@ to the type name \verb@y@, and the constructor name +\verb@p.x@ to the type name \verb@y@. At least one of these three +names must reference a member of \verb@p@. + +If the destination in an import selector is a wildcard, the import selector hides access to the source member. For instance, the import selector \verb@x => _@ ``renames'' \verb@x@ to the wildcard symbol (which is unaccessible as a name in user programs), and thereby @@ -1398,119 +1405,40 @@ effectively prevents unqualified access to \verb@x@. This is useful if there is a final wildcard in the same import selector list, which imports all members not mentioned in previous import selectors. - - -The import selector \verb@x$_i$ - - - - - - -\begin{itemize} -\item -An import selet -If the import selector is an identifier, as in \verb@import e.x@, then -\verb@x@ can be accessed without qualification. -\item -If the import selector is - - - , an clause makes members - -expression $e$ available without qualification. The expression $e$ -must be a stable identifier $r$, possibly followed by an explicit type -$T$. If no type is given, the type of $r$ is assumed. For every -simple name $x$ of a non-private member of $T$, the simple name $x$ is -introduced as an alias for $r.x$ in the remainder of the block or -template that follows the import clause. - -An import clause with multiple expressions $\IMPORT;e_1 -\commadots e_n$ is interpreted as a sequence of import clauses -$\IMPORT;e_1 \ldots \IMPORT;e_n$. - -\example Consider the module definition: -\begin{verbatim} -module M with { def z = 0; def inc(x: Int): Int = x + 1 } +Several shorthands exist. An import selector may be just a simple name +\verb@x@. In this case, \verb@x@ is imported without renaming, so the +import selector is equivalent to \verb@x => x@. Furthermore, it is +possible to replace the whole import selector list by a single +identifier or wildcard. The import clause \verb@import p.x@ is +equivalent to \verb@import p.{x}@, i.e.\ it makes available without +qualification the member \verb@x@ of \verb@p@. The import clause +\verb@import p._@ is equivalent to +\verb@import p.{_}@, +i.e.\ it makes available without qualification all members of \verb@p@ +(this is analogous to \verb@import p.*@ in Java). + +An import clause with multiple import expressions +\verb@import p$_1$.I$_1$, ..., p$_n$.I$_n$@ is interpreted as a +sequence of import clauses +\verb@import p$_1$.I$_1$; ..., import p$_n$.I$_n$@. + +\example Consider the object definition: +\begin{verbatim} +object M { + def z = 0, one = 1; + def add(x: Int, y: Int): Int = x + y +} \end{verbatim} Then the block -\verb@{ import M; inc(z) }@ -is equivalent to the block \verb@{ M.inc(M.z) }@. - -\comment{ -The compiler expands the import clause to a sequence of definitions as -is described below. Assume first that the imported expression $e$ is a -stable identifier $r$. For every simple name $x$ of a member of $r$, -the compiler generates an alias definition (\sref{sec:aliasing}) of -$x$ for $r.x$. If there are several members of $r$ that have the same -simple name $x$ but different qualified names, only the member -identified (\sref{sec:names}) by the simple name $x$ is imported. - - -\subsection*{Alias Definitions} -\label{sec:aliasing} - -With the exception of guards (which are never members of classes or -objects) it is always possible to define aliases for defined -entities. An alias definition of the \ifqualified{(possibly qualified)} name $X$ for -the entity $Y$ takes one of the following forms. - -If $Y$ defines a type, then the alias definition is \verb@type X = Y@ -(or the parameterized analogue if $Y$ is a type constructor). - -If $Y$ defines a parameterless method of type $[]T$, then the alias definition is -\bda{l} -\DEF;X: T = Y \enspace.\eda - -If $Y$ defines a monomorpic method of type $(ps_1)\ldots(ps_n)T$, -then the alias definition is -\bda{l} -\DEF;X(ps_1) \ldots (ps_n): T = Y(ps_1)\ldots (ps_n) \enspace.\eda - -If $Y$ defines a polymorphic method of type $[a_1 \extends S_1 \commadots a_m \extends S_m](ps_1)\ldots(ps_n) T$, -then the alias definition is -\bda{l} -\DEF;X[a_1 \extends S_1 \commadots a_m \extends S_m](ps_1) \ldots (ps_n): T = -Y[a_1 \commadots a_m](ps_1)\ldots (ps_n) \enspace. -\eda - -If $Y$ defines an overloaded function of type $T_1 \overload \ldots -\overload T_n$, then the alias definition consists of $n$ function -definitions, which correspond to the alternatives $T_1 \commadots T_n$ -of the overloaded type. - -If $Y$ is defined by a value (\sref{sec:valdef}), -let (\sref{sec:letdef}) or module (\sref{sec:modules}) definition, then the alias -definition is $\VAL;X = Y$. - -If $Y$ defines a parameterless class, then the alias definition is -$\CLASS;X = Y$. If $Y$ defines a class with parameters $[a_1 -\extends S_1 \commadots a_m \extends S_m](ps_1) \ldots (ps_n)$, -then the alias definition is -\bda{l} -\CLASS;X;[a_1\extends S_1 \commadots a_m \extends S_m](ps_1) \ldots (ps_n) = Y[a_1 \commadots a_m](ps_1) \ldots (ps_n) -\enspace. -\eda - -\example Some alias definitions are: - -\begin{verbatim} -module L = scala.lang; -type T = L.List[Int]; -def println(s: String) = L.System.println(s); -val out = L.System.out; -class IntList = L.List[Int]; -class Nil[a] = L.Nil[a]; -\end{verbatim} -} - +\verb@{ import M.{one, z => zero, _}; add(zero, one) }@ +is equivalent to the block \verb@{ M.add(M.z, M.one) }@. \chapter{Classes and Modules} \label{sec:globaldefs} \syntax\begin{verbatim} - PureDef \=::= \= [case] class ClassDef {`,' ClassDef} - \> | \> module ModuleDef {`,' ModuleDef} + ClsDef \>::=\> ([case] class | trait) ClassDef {`,' ClassDef} + \> |\> [case] object ObjectDef {`,' ObjectDef} \end{verbatim} Classes (\sref{sec:classes}) and modules @@ -1520,28 +1448,34 @@ Classes (\sref{sec:classes}) and modules \label{sec:templates} \syntax\begin{verbatim} - Template \=::= \= Constr {$\WITH$ Constr} [$\WITH$ `(' {TemplateStat `;'} `)'] -\end{verbatim} - -Templates define the type signature, behavior and initial state of a -class of objects. They form part of instance creation expressions, -class definitions, and module definitions. A template -$sc;\WITH;mc_1;\WITH;\ldots;\WITH;mc_n;\WITH;(stats)$ consists of a -constructor invocation $sc$ which defines the template's {\em -superclass}, constructor invocations $mc_1 \commadots mc_n$ $(n \geq -0)$, which define the template's {\em mixin classes}, and a statement -sequence $stats$ which contains additional member definitions for the -template. The {\em least proper supertype} of a template is the class -type or compound type (\sref{sec:compound-types}) consisting of its -superclass and mixin classes. The superclass of a template must be a -subtype of the superclass of each mixin class. + Template \=::=\= Constr {`with' Constr} [TemplateBody] + TemplateBody \>::=\> `{' [TemplateStat {`;' TemplateStat}] `}' +\end{verbatim} + +A template defines the type signature, behavior and initial state of a +class of objects or of a single object. Templates form part of +instance creation expressions, class definitions, and module +definitions. A template +\verb@sc with mc$_1$ with ... with mc$_n$ {stats}@ consists of a +constructor invocation \verb@sc@ which defines the template's {\em +superclass}, constructor invocations \verb@mc$_1$ \commadots mc$_n$@ +$(n \geq 0)$, which define the template's {\em mixin classes}, and a +statement sequence \verb@stats@ which contains additional member +definitions for the template. The superclass of a template must be a +subtype of the superclass of each mixin class. The {\em least proper +supertype} of a template is the class type or compound type +(\sref{sec:compound-types}) consisting of its superclass and mixin +classes. Member definitions define new members or overwrite members in the superclass and the mixin classes. If the template forms part of a -class definition, $stats$ may also contain declarations of abstract -members. The type of each non-private definition or declaration of a -template must be equivalent to a type which does not refer to any -private members of that template. +class definition, \verb@stats@ may also contain declarations of abstract +members. +%The type of each non-private definition or declaration of a +%template must be equivalent to a type which does not refer to any +%private members of that template. + +\paragraph{Connection with Java} \subsection{Constructor Invocations} \label{sec:constr-invoke} @@ -1564,18 +1498,18 @@ sequences of class types: the {\em base classes} and {\em mixin base classes}. Their definitions are as follows. The {\em mixin base classes} of a template -$sc;\WITH;mc_1;\WITH;mc_n;\WITH;(stats)$ are obtained by +\verb@sc;\WITH;mc_1;\WITH;mc_n;\WITH;(stats)@ are obtained by concatenating, for each $i = 1 \commadots n$, the mixin base classes -of the mixin $mc_i$. The mixin base classes of a class type $C$ are -the mixin base classes of the template represented by $C$, followed by -$C$ itself. The mixin base classes of a constructor invocation of type +of the mixin \verb@mc_i@. The mixin base classes of a class type \verb@C@ are +the mixin base classes of the template represented by \verb@C@, followed by +\verb@C@ itself. The mixin base classes of a constructor invocation of type \verb@class T@ are the mixin base classes of class \verb@T@. The {\em base classes} of a template consist of the base classes of its superclass, followed by the template's mixin base classes. The base classes of class \verb@scala.Any@ consist of just the -class itself. The base classes of some other class type $C$ are the -base classes of the template represented by $C$, followed by $C$ +class itself. The base classes of some other class type \verb@C@ are the +base classes of the template represented by \verb@C@, followed by \verb@C@ itself. The base classes of a constructor invocation of type \verb@class T@ are the base classes of \verb@T@. @@ -1597,25 +1531,25 @@ determination of the meaning of \verb@super@ (\sref{sec:this-super}). We therefore define two notions of template evaluation: (Plain) evaluation (as a defining template or superclass) and mixin evaluation -with a given superclass $sc$. These notions are defined for templates +with a given superclass \verb@sc@. These notions are defined for templates and constructor invocations as follows. -A {\em mixin evaluation with superclass $sc$} of a template -$sc';\WITH;mc_1;\WITH;mc_n;\WITH;(stats)$ consists of mixin -evaluations with superclass $sc$ of the mixin constructor invocations -$mc_1 \commadots mc_n$ in the order they are given, followed by an -evaluation of the statement sequence $stats$. Within $stats$ the -actual superclass refers to $sc$. A mixin evaluation with superclass -$sc$ of a class constructor invocation $ci$ consists of an evaluation +A {\em mixin evaluation with superclass \verb@sc@} of a template +\verb@sc';\WITH;mc_1;\WITH;mc_n;\WITH;(stats)@ consists of mixin +evaluations with superclass \verb@sc@ of the mixin constructor invocations +\verb@mc_1 \commadots mc_n@ in the order they are given, followed by an +evaluation of the statement sequence \verb@stats@. Within \verb@stats@ the +actual superclass refers to \verb@sc@. A mixin evaluation with superclass +\verb@sc@ of a class constructor invocation \verb@ci@ consists of an evaluation of the constructor function and its arguments in the order they are -given, followed by a mixin evaluation with superclass $sc$ of the +given, followed by a mixin evaluation with superclass \verb@sc@ of the template represented by the constructor invocation. An {\em evaluation} of a template -$sc;\WITH;mc_1;\WITH;mc_n;\WITH;(stats)$ consists of an evaluation of -the superclass constructor invocation $sc$ (of type $S$, say), -followed by a mixin evaluation with superclass $sc$ of the template. An -evaluation of a class constructor invocation $ci$ consists of an +\verb@sc;\WITH;mc_1;\WITH;mc_n;\WITH;(stats)@ consists of an evaluation of +the superclass constructor invocation \verb@sc@ (of type \verb@S@, say), +followed by a mixin evaluation with superclass \verb@sc@ of the template. An +evaluation of a class constructor invocation \verb@ci@ consists of an evaluation of the constructor function and its arguments in the order they are given, followed by an evaluation of the template represented by the constructor invocation. @@ -1635,27 +1569,27 @@ member is called {\em abstract} if it is introduced by a declaration, {\em concrete} otherwise. \item A {\em concrete inherited} member is a non-private, concrete member of -one of the template's base classes $B$, except if a member with the +one of the template's base classes \verb@B@, except if a member with the same \ifqualified{qualified} name is already directly bound in the template, or is directly bound in a base class of the template which is a subclass of -$B$, or is a directly bound, non-private, concrete member of a base -class which succeeds $B$ in the base class sequence of the template. +\verb@B@, or is a directly bound, non-private, concrete member of a base +class which succeeds \verb@B@ in the base class sequence of the template. \item An {\em abstract inherited} member is a non-private, abstract member -of one of the template's base classes $B$, except if a member with the +of one of the template's base classes \verb@B@, except if a member with the same \ifqualified{qualified} name is already directly bound in the template, or is a concrete inherited member, or is a directly bound, non-private member -of a base class which succeeds $b$ in the base class sequence of the +of a base class which succeeds \verb@b@ in the base class sequence of the template. \end{enumerate} -The type of a member $m$ is determined as follows: If $m$ is defined -in $stats$, then its type is the type as given in the member's -declaration or definition. Otherwise, if $m$ is inherited from the -base class $B[T1 \commadots T_n]$, $B$'s class declaration has formal -parameters $[a_1 \commadots a_n]$, and $M$'s type in $B$ is $U$, then -$M$'s type in $C$ is $U[a_1 := T_1 -\commadots a_n := T_n]$. +The type of a member \verb@m@ is determined as follows: If \verb@m@ is defined +in \verb@stats@, then its type is the type as given in the member's +declaration or definition. Otherwise, if \verb@m@ is inherited from the +base class \verb@B[T1 \commadots T_n]@, \verb@B@'s class declaration has formal +parameters \verb@[a_1 \commadots a_n]@, and \verb@M@'s type in \verb@B@ is \verb@U@, then +\verb@M@'s type in \verb@C@ is \verb@U[a_1 := T_1 +\commadots a_n := T_n]@. \ifqualified{ Members of templates have internally qualified names $Q\qex x$ where @@ -1715,28 +1649,28 @@ in addition to the members inherited from class \verb@Any@. \subsection{Overriding} \label{sec:overriding} -A template member $M$ that has the same \ifqualified{qualified} name as a -non-private member $M'$ of a base class (and that belongs to the same +A template member \verb@M$ that has the same \ifqualified{qualified} name as a +non-private member \verb@M'$ of a base class (and that belongs to the same namespace) is said to {\em override} that member. In this case the -binding of the overriding member $M$ must be more specific -(\sref{sec:subtyping}) than the binding of the overridden member $M'$. +binding of the overriding member \verb@M$ must be more specific +(\sref{sec:subtyping}) than the binding of the overridden member \verb@M'$. Furthermore, the overridden definition may not be a class or module definition or a type alias. Method definitions may only override other method definitions (or the methods implicitly defined by a variable definition). They may not override value or let definitions. -Finally, the following restrictions on modifiers apply to $M$ and -$M'$: +Finally, the following restrictions on modifiers apply to \verb@M$ and +\verb@M'$: \begin{itemize} \item -$M$ must not be labelled \verb@private@. +\verb@M$ must not be labelled \verb@private@. \item -If $M'$ is not abstract, then $M$ must be labelled \verb@override@. +If \verb@M'$ is not abstract, then \verb@M$ must be labelled \verb@override@. \item -If $M'$ is labelled \verb@protected@, then $M$ must also be +If \verb@M'$ is labelled \verb@protected@, then \verb@M$ must also be labelled \verb@protected@. \iffinaltype{ \item -$M'$ may be labelled \verb@final@ only if it is an abstract type +\verb@M'$ may be labelled \verb@final@ only if it is an abstract type binding. } \end{itemize} @@ -1822,22 +1756,22 @@ Protected members can be accessed from within the template of the defining class as well as in all templates that have the defining class as a base class. Furthermore, accesses from the template of the defining class are not permitted in packagings other than the one -containing the definition. A protected identifier $x$ may be used as -a member name in a selection $r.x$ only if $r$ is one of the reserved +containing the definition. A protected identifier \verb@x$ may be used as +a member name in a selection \verb@r.x$ only if \verb@r$ is one of the reserved words \verb@this@ and -\verb@super@, or if $r$'s type conforms to a type-instance of a class +\verb@super@, or if \verb@r$'s type conforms to a type-instance of a class which contains the access. \item The \verb@override@ modifier applies to member definitions. If a -definition of a simple name $x$ is preceded by +definition of a simple name \verb@x$ is preceded by \verb@override@, the definition is taken to override (\sref{sec:overriding}) a member in the least proper supertype -(\sref{sec:templates}) which is identified by the simple name $x$. +(\sref{sec:templates}) which is identified by the simple name \verb@x$. The \verb@override@ modifier may be followed by a qualified name. If -a definition of a simple name $x$ is preceded by -\verb@override $Q$@, the definition is taken to override -a member in the base class referenced by the qualified name $Q$ which -is identified by the simple name $x$. In both cases, there must exist +a definition of a simple name \verb@x$ is preceded by +\verb@override \verb@Q$@, the definition is taken to override +a member in the base class referenced by the qualified name \verb@Q$ which +is identified by the simple name \verb@x$. In both cases, there must exist such a member according to the rules of (\sref{sec:names}). \verb@override@ may not be combined in one modifier list with \verb@private@. @@ -1845,8 +1779,8 @@ such a member according to the rules of (\sref{sec:names}). \item The \verb@qualified@ modifier applies to class or module definitions. When present, all non-overriding member definitions of -the class or module (named $M$, say) introduce names which are -qualified by $M$. When absent, non-overriding member definitions of +the class or module (named \verb@M$, say) introduce names which are +qualified by \verb@M$. When absent, non-overriding member definitions of the class or module introduce names which are qualified by the empty string $\epsilon$. } @@ -1864,7 +1798,7 @@ abstract final class C (x: Int) with { val empty = new C(0) with {} \end{verbatim} For instance, in the code above clients can create instances of class -$C$ only by calling the \verb@nextC@ method of an existing \verb@C@ +\verb@C$ only by calling the \verb@nextC@ method of an existing \verb@C@ object; it is not possible for clients to create objects of class \verb@C@ directly. Indeed the following two lines are both in error: @@ -4368,13 +4302,13 @@ grammar. \> |\> Binding \>::=\> Id [`:' Type] - Modifier \>::=\> abstract - \> |\> final + Modifier \>::=\> LocalModifier \> |\> private \> |\> protected \> |\> override LocalModifier \>::=\> abstract \> |\> final + \> |\> sealed Template \>::=\> Constr {`with' Constr} [TemplateBody] TemplateBody \>::=\> `{' [TemplateStat {`;' TemplateStat}] `}' diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index 0ec6de68b0..51d926afdf 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -115,15 +115,16 @@ public class Parser implements Tokens { boolean isModifier() { return (s.token == ABSTRACT) || (s.token == FINAL) + || (s.token == SEALED) || (s.token == PRIVATE) || (s.token == PROTECTED) -// || (s.token == QUALIFIED) || (s.token == OVERRIDE); } boolean isLocalModifier() { return (s.token == ABSTRACT) - || (s.token == FINAL); + || (s.token == FINAL) + || (s.token == SEALED); } boolean isDefIntro() { @@ -921,6 +922,9 @@ public class Parser implements Tokens { convertToConstr(stats[stats.length - 1])); else syntaxError(res.pos, "class constructor expected", false); + break; + default: + res = applyConstr(convertToConstr(res)); } accept(RBRACE); return res; @@ -1190,6 +1194,9 @@ public class Parser implements Tokens { case FINAL: mod = Modifiers.FINAL; break; + case SEALED: + mod = Modifiers.SEALED; + break; case PRIVATE: mod = Modifiers.PRIVATE; break; @@ -1224,6 +1231,9 @@ public class Parser implements Tokens { case FINAL: mod = Modifiers.FINAL; break; + case SEALED: + mod = Modifiers.SEALED; + break; default: return mods; } @@ -1386,9 +1396,11 @@ public class Parser implements Tokens { t = make.Select(pos, t, name); pos = accept(DOT); } else { + /* if (name == Names.ASTERISK) s.unit.warning( pos, "this imports only the identifier `*';\nuse `import xyz._' to import all members of `xyz'."); + */ return make.Import(startpos, t, new Name[]{name, name}); } } diff --git a/sources/scalac/ast/parser/Scanner.java b/sources/scalac/ast/parser/Scanner.java index 82b41f6e3a..5573ce3e05 100644 --- a/sources/scalac/ast/parser/Scanner.java +++ b/sources/scalac/ast/parser/Scanner.java @@ -816,6 +816,7 @@ public class Scanner extends TokenData { enterKeyword("package", PACKAGE); enterKeyword("private", PRIVATE); enterKeyword("protected", PROTECTED); + enterKeyword("sealed", SEALED); enterKeyword("super", SUPER); enterKeyword("this", THIS); enterKeyword("trait", TRAIT); diff --git a/sources/scalac/ast/parser/Tokens.java b/sources/scalac/ast/parser/Tokens.java index cad7a2da8b..f2e3bc39ad 100644 --- a/sources/scalac/ast/parser/Tokens.java +++ b/sources/scalac/ast/parser/Tokens.java @@ -60,6 +60,7 @@ public interface Tokens { YIELD = 50, DO = 51, TRAIT = 52, + SEALED = 53, /* special symbols */ COMMA = 61, diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java index 39e8f1edcf..a56fb1a656 100644 --- a/sources/scalac/ast/printer/TextTreePrinter.java +++ b/sources/scalac/ast/printer/TextTreePrinter.java @@ -154,6 +154,7 @@ public class TextTreePrinter implements TreePrinter { protected static final Text KW_ELSE = Text.Keyword("else"); protected static final Text KW_EXTENDS = Text.Keyword("extends"); protected static final Text KW_FINAL = Text.Keyword("final"); + protected static final Text KW_SEALED = Text.Keyword("sealed"); protected static final Text KW_FOR = Text.Keyword("for"); protected static final Text KW_IF = Text.Keyword("if"); protected static final Text KW_IMPORT = Text.Keyword("import"); @@ -643,6 +644,10 @@ public class TextTreePrinter implements TreePrinter { print(KW_FINAL); print(Text.Space); } + if ((flags & Modifiers.SEALED) != 0) { + print(KW_SEALED); + print(Text.Space); + } if ((flags & Modifiers.PRIVATE) != 0) { print(KW_PRIVATE); print(Text.Space); @@ -651,10 +656,6 @@ public class TextTreePrinter implements TreePrinter { print(KW_PROTECTED); print(Text.Space); } - if ((flags & Modifiers.QUALIFIED) != 0) { - print(KW_QUALIFIED); - print(Text.Space); - } if ((flags & Modifiers.OVERRIDE) != 0) { print(KW_OVERRIDE); print(Text.Space); diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index 9c6f12c115..00509ad16b 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -16,7 +16,7 @@ public interface Modifiers { int PRIVATE = 0x00000004; int PROTECTED = 0x00000008; - int QUALIFIED = 0x00000010; + int SEALED = 0x00000010; int OVERRIDE = 0x00000020; int CASE = 0x00000040; int ABSTRACTCLASS = 0x00000080; // abstract class @@ -36,7 +36,7 @@ public interface Modifiers { int ACCESSED = 0x00040000; // symbol was accessed at least once int SELECTOR = 0x00080000; // symbol was used as selector in Select - int PACKAGE = 0x00100000; // symbol is a java packages. + int PACKAGE = 0x00100000; // symbol is a java package. int LABEL = 0x00200000; // symbol is a label symbol int STATIC = 0x00400000; // "static" inner classes (i.e. after class norm.) int STABLE = 0x00800000; // functions that are assumed to be stable @@ -79,8 +79,8 @@ public interface Modifiers { return (flags & PROTECTED) != 0; } - public static boolean isQualified(int flags) { - return (flags & QUALIFIED) != 0; + public static boolean isSealed(int flags) { + return (flags & SEALED) != 0; } public static boolean isOverride(int flags) { @@ -132,7 +132,7 @@ public interface Modifiers { if (isProtected(flags)) buffer.append("protected "); if (isAbstract(flags)) buffer.append("abstract "); if (isFinal(flags)) buffer.append("final "); - if (isQualified(flags)) buffer.append("qualified "); + if (isSealed(flags)) buffer.append("qualified "); if (isInterface(flags)) buffer.append("interface "); if (isCase(flags)) buffer.append("case "); if (isDef(flags)) buffer.append("def "); diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 23b062800f..5e4e7e2801 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -211,6 +211,13 @@ public abstract class Symbol implements Modifiers, Kinds { return isInitializedMethod(); } + /* + public final boolean caseClassOfFactory() { + if (isMethod() && !isConstructor() && (flags & CASE) != 0) + return owner.info().lookup(name.toTypeName()).constructor(); + } + */ + public final boolean isAbstractClass() { return (flags & ABSTRACTCLASS) != 0 && this != Global.instance.definitions.ARRAY_CLASS; @@ -542,7 +549,7 @@ public abstract class Symbol implements Modifiers, Kinds { throw new CyclicReference(this, info); } flags |= LOCKED; - //System.out.println("completing " + this);//DEBUG + //System.out.println("completing " + this.name);//DEBUG info.complete(this); flags = flags & ~LOCKED; if (info instanceof SourceCompleter && (flags & SNDTIME) == 0) { @@ -553,7 +560,7 @@ public abstract class Symbol implements Modifiers, Kinds { assert !(rawInfoAt(id) instanceof Type.LazyType) : this; flags |= INITIALIZED; } - //System.out.println("done: " + this);//DEBUG + //System.out.println("done: " + this.name);//DEBUG } return rawInfoAt(id); } @@ -741,6 +748,7 @@ public abstract class Symbol implements Modifiers, Kinds { closurePos(c) >= 0 || this == Global.instance.definitions.ALL_CLASS || (this == Global.instance.definitions.ALLREF_CLASS && + c != Global.instance.definitions.ALL_CLASS && c.isSubClass(Global.instance.definitions.ANYREF_CLASS)); } @@ -914,8 +922,10 @@ public abstract class Symbol implements Modifiers, Kinds { owner.thisType().memberType(that)); } + /** Reset symbol to initial state + */ public void reset(Type completer) { - this.flags &= (FINAL | MODUL); + this.flags &= SOURCEFLAGS; this.pos = 0; this.infos = TypeIntervalList.EMPTY; this.setInfo(completer); @@ -942,7 +952,7 @@ public class TermSymbol extends Symbol { } public static TermSymbol newJavaConstructor(Symbol clazz) { - return newConstructor(clazz, clazz.flags & (ACCESSFLAGS | QUALIFIED | JAVA)); + return newConstructor(clazz, clazz.flags & (ACCESSFLAGS | JAVA)); } public static TermSymbol newModule(int pos, Name name, Symbol owner, int flags) { diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 471c206b9c..33d509c55c 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -305,6 +305,7 @@ public class Type implements Modifiers, Kinds, TypeTags { lb = pre.memberLoBound(sym); } if (lb.symbol() == Global.instance.definitions.ALL_CLASS && + this.symbol() != Global.instance.definitions.ALL_CLASS && this.isSubType(Global.instance.definitions.ANYREF_TYPE)) { lb = Global.instance.definitions.ALLREF_TYPE; } @@ -1389,8 +1390,9 @@ public class Type implements Modifiers, Kinds, TypeTags { return that.isSubType(Global.instance.definitions.ANY_TYPE); else if (sym == Global.instance.definitions.ALLREF_CLASS) return - that.isSameAs(Global.instance.definitions.ANY_TYPE) || - that.isSubType(Global.instance.definitions.ANYREF_TYPE); + that.symbol() == Global.instance.definitions.ANY_CLASS || + (that.symbol() != Global.instance.definitions.ALL_CLASS && + that.isSubType(Global.instance.definitions.ANYREF_TYPE)); break; case OverloadedType(Symbol[] alts, Type[] alttypes): diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 03377ef78c..abb6b7067f 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -9,12 +9,11 @@ // todo: (0) propagate target type in cast. // todo: eliminate Typed nodes. // todo: use SELECTOR flag to avoid access methods for privates -// todo: drop requirement that only abstract classes can have abstract -// type members. // todo: use mangled name or drop. // todo: emit warnings for unchecked. // todo: qualified super. // todo: pattern definitions with 0 or 1 bound variable. +// todo: phase sync package scalac.typechecker; @@ -259,6 +258,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { void validate(Symbol sym) { checkNoConflict(sym, DEFERRED, PRIVATE); checkNoConflict(sym, FINAL, PRIVATE); + checkNoConflict(sym, FINAL, SEALED); checkNoConflict(sym, PRIVATE, PROTECTED); checkNoConflict(sym, PRIVATE, OVERRIDE); checkNoConflict(sym, DEFERRED, FINAL); @@ -331,6 +331,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { " does not conform to " + parents[i] + "'s supertype"); } if ((bsym.flags & FINAL) != 0) { + error(constrs[i].pos, "illegal inheritance from final class"); + } else if ((bsym.flags & SEALED) != 0) { // are we in same scope as base type definition? Scope.Entry e = context.scope.lookupEntry(bsym.name); if (e.sym != bsym || e.owner != context.scope) { @@ -339,7 +341,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { while (c != Context.NONE && c.owner != bsym) c = c.outer; if (c == Context.NONE) { - error(constrs[i].pos, "illegal inheritance from final class"); + error(constrs[i].pos, "illegal inheritance from sealed class"); } } } @@ -880,6 +882,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.mode = EXPRmode; Type savedPt = this.pt; this.pt = Type.AnyType; + int savedId = global.currentPhase.id; + global.currentPhase.id = descr.id; try { Symbol sym = tree.symbol(); @@ -942,8 +946,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } popContext(); } + //checkNonCyclic(tree.pos, tpe.type); owntype = tpe.type; - checkNonCyclic(tree.pos, owntype); break; case DefDef(int mods, Name name, Tree.TypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs): @@ -959,7 +963,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } Type restype = checkNoEscape(tpe.pos, tpe.type); popContext(); - checkNonCyclic(tree.pos, restype); + //checkNonCyclic(tree.pos, tpe.type); owntype = makeMethodType(tparamSyms, vparamSyms, restype); //System.out.println("methtype " + name + ":" + owntype);//DEBUG break; @@ -978,13 +982,21 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { owntype = rhs.type; popContext(); } - checkNonCyclic(tree.pos, owntype); + //checkNonCyclic(tree.pos, owntype); break; case Import(Tree expr, Name[] selectors): ((Import) tree).expr = expr = transform(expr, EXPRmode | QUALmode); checkStable(expr); owntype = expr.type; + Type tp = owntype.widen(); + for (int i = 0; i < selectors.length; i = i + 2) { + if (selectors[i] != Names.WILDCARD && + tp.lookup(selectors[i]) == Symbol.NONE && + tp.lookup(selectors[i].toTypeName()) == Symbol.NONE && + tp.lookup(selectors[i].toConstrName()) == Symbol.NONE) + error(tree.pos, selectors[i] + " is not a member of " + expr); + } break; default: @@ -1003,6 +1015,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { this.context = savedContext; this.mode = savedMode; this.pt = savedPt; + global.currentPhase.id = savedId; } /** Definition phase for a template. This enters all symbols in template @@ -1660,6 +1673,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { rhs1 = transform(rhs, EXPRmode, tpe.type); popContext(); } + sym.flags |= LOCKED; + checkNonCyclic(tree.pos, tpe.type); + sym.flags &= ~LOCKED; return copy.ValDef(tree, sym, tpe, rhs1) .setType(definitions.UNIT_TYPE); @@ -1673,10 +1689,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (rhs != Tree.Empty) rhs1 = transform(rhs, EXPRmode, tpe.type); popContext(); + sym.flags |= LOCKED; + checkNonCyclic(tree.pos, tpe.type); + sym.flags &= ~LOCKED; return copy.DefDef(tree, sym, tparams1, vparams1, tpe, rhs1) .setType(definitions.UNIT_TYPE); case TypeDef(_, _, _, _): + checkNonCyclic(tree.pos, sym.type()); return tree .setType(definitions.UNIT_TYPE); @@ -2073,23 +2093,30 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { infer.applyErrorMsg( "", fn1, " cannot be applied to ", argtypes, pt)); - case Super(Tree tpe): - Symbol enclClazz = context.enclClass.owner; - if (enclClazz != null) { - // we are in a class or module - Tree tpe1 = transform(tpe, TYPEmode); // ignored for now. - switch (enclClazz.info()) { - case CompoundType(Type[] parents, _): - return copy.Super(tree, tpe1) - .setType(Type.compoundType(parents, Scope.EMPTY).symbol().thisType()); - case ErrorType: - return tree.setType(Type.ErrorType); - default: - throw new ApplicationError(); + case Super(Tree qual): + Symbol clazz; + Tree qual1; + if (qual == Tree.Empty) { + clazz = context.enclClass.owner; + if (clazz != null) { + qual1 = gen.Ident(tree.pos, clazz); + } else { + return error( + tree.pos, + "super can be used only in a class, object, or template"); } } else { - return error(tree.pos, - "super can be used only in a class, object, or template"); + qual1 = transform(qual, TYPEmode | FUNmode); + clazz = qual1.symbol(); + } + switch (clazz.info()) { + case CompoundType(Type[] parents, _): + return copy.Super(tree, qual1) + .setType(Type.compoundType(parents, Scope.EMPTY).symbol().thisType()); + case ErrorType: + return tree.setType(Type.ErrorType); + default: + return error(qual.pos, "class identifier expected"); } case This(Tree qual): diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index 0b224b9758..9e338d9d4d 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -21,7 +21,6 @@ public class Names { public static final Name _EQ = encode("_="); public static final Name MINUS = encode("-"); public static final Name PLUS = encode("+"); - public static final Name ASTERISK = encode("*"); public static final Name TILDE = encode("~"); public static final Name EQEQ = encode("=="); public static final Name BANG = encode("!"); diff --git a/support/latex/verbfilterScala.java b/support/latex/verbfilterScala.java index 5c8cf85d13..b8db2fb6e9 100644 --- a/support/latex/verbfilterScala.java +++ b/support/latex/verbfilterScala.java @@ -8,8 +8,9 @@ public class verbfilterScala { "abstract", "as", "case", "class", "constr", "def", "do", "else", "extends", "false", "final", "for", "if", "import", "is", "new", "null", "object", "override", "package", - "private", "protected", "super", "this", "trait", - "true", "type", "val", "var", "with", "yield"}; + "private", "protected", "sealed", "super", "this", + "trait", "true", "type", "val", "var", + "with", "yield"}; static final int TABINC = 8; diff --git a/test/files/neg/S6.check b/test/files/neg/S6.check index 6303e4c8e2..0647138103 100644 --- a/test/files/neg/S6.check +++ b/test/files/neg/S6.check @@ -1,4 +1,4 @@ -S6.scala:11: illegal cyclic reference involving type S +S6.scala:11: cyclic aliasing or subtyping involving type S type S <: T; ^ one error found diff --git a/test/files/neg/seqtest.check b/test/files/neg/seqtest.check index d3a04e8e51..42d3a71a9c 100644 --- a/test/files/neg/seqtest.check +++ b/test/files/neg/seqtest.check @@ -1,6 +1,7 @@ seqtest.scala:11: ambiguous reference to overloaded definition, both method L: [a](scala.Seq[a])scala.Seq[a] -and method L: [a](a*)scala.Seq[a] match. +and method L: [a](a*)scala.Seq[a] +match argument types (scala.Seq[scala.Int]) val c = L(a); ^ one error found diff --git a/test/files/pos/imports.scala b/test/files/pos/imports.scala index 32b7aace62..65ea090436 100644 --- a/test/files/pos/imports.scala +++ b/test/files/pos/imports.scala @@ -1,7 +1,5 @@ package test; - - import java.lang.{System => S} object test { diff --git a/test/neg/S6.check b/test/neg/S6.check index 6303e4c8e2..0647138103 100644 --- a/test/neg/S6.check +++ b/test/neg/S6.check @@ -1,4 +1,4 @@ -S6.scala:11: illegal cyclic reference involving type S +S6.scala:11: cyclic aliasing or subtyping involving type S type S <: T; ^ one error found diff --git a/test/neg/seqtest.check b/test/neg/seqtest.check index d3a04e8e51..42d3a71a9c 100644 --- a/test/neg/seqtest.check +++ b/test/neg/seqtest.check @@ -1,6 +1,7 @@ seqtest.scala:11: ambiguous reference to overloaded definition, both method L: [a](scala.Seq[a])scala.Seq[a] -and method L: [a](a*)scala.Seq[a] match. +and method L: [a](a*)scala.Seq[a] +match argument types (scala.Seq[scala.Int]) val c = L(a); ^ one error found diff --git a/test/pos/imports.scala b/test/pos/imports.scala index 32b7aace62..65ea090436 100644 --- a/test/pos/imports.scala +++ b/test/pos/imports.scala @@ -1,7 +1,5 @@ package test; - - import java.lang.{System => S} object test { |