diff options
author | Martin Odersky <odersky@gmail.com> | 2004-01-08 15:52:45 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2004-01-08 15:52:45 +0000 |
commit | d8888a99cf2675e698744d1f21f90cdee42609b1 (patch) | |
tree | 621ef130c1e2d1fd21475f19036a2119cb2a4ba1 | |
parent | abdb5cc6bb86908c0a8a1d9e9ebd038e08c33964 (diff) | |
download | scala-d8888a99cf2675e698744d1f21f90cdee42609b1.tar.gz scala-d8888a99cf2675e698744d1f21f90cdee42609b1.tar.bz2 scala-d8888a99cf2675e698744d1f21f90cdee42609b1.zip |
*** empty log message ***
-rw-r--r-- | doc/reference/ScalaByExample.tex | 64 | ||||
-rw-r--r-- | doc/reference/ScalaReference.tex | 65 | ||||
-rw-r--r-- | sources/examples/parsers.scala | 12 | ||||
-rw-r--r-- | sources/scala/tools/scalac/typechecker/Analyzer.scala | 42 |
4 files changed, 92 insertions, 91 deletions
diff --git a/doc/reference/ScalaByExample.tex b/doc/reference/ScalaByExample.tex index b0aed6d462..cb75ba7ddd 100644 --- a/doc/reference/ScalaByExample.tex +++ b/doc/reference/ScalaByExample.tex @@ -6210,23 +6210,23 @@ A synchronized variable (or syncvar for short) offers \code{get} and block until the variable has been defined. An \code{unset} operation resets the variable to undefined state. -Synchronized variables can be implemented as follows. +Here's the standard implementation of synchronized variables. \begin{lstlisting} -class SyncVar[a] extends Monitor { - private val defined = new Signal; - private var isDefined: boolean = false; - private var value: a; +package scala.concurrent; +class SyncVar[a] with Monitor { + private var isDefined: Boolean = false; + private var value: a = _; def get = synchronized { - if (!isDefined) defined.wait; + if (!isDefined) wait(); value } def set(x: a) = synchronized { - value = x ; isDefined = true ; defined.send; + value = x ; isDefined = true ; notifyAll(); } - def isSet: boolean = + def isSet: Boolean = isDefined; - def unset = synchronized { - isDefined = false; + def unset = synchronized { + isDefined = false; } } \end{lstlisting} @@ -6240,18 +6240,20 @@ Futures are used in order to make good use of parallel processing resources. A typical usage is: \begin{lstlisting} +import scala.concurrent.ops._; +... val x = future(someLengthyComputation); anotherLengthyComputation; val y = f(x()) + g(x()); \end{lstlisting} -Futures can be implemented in Scala as follows. - +The \code{future} method is defined in object +\code{scala.concurrent.ops} as follows. \begin{lstlisting} def future[a](def p: a): unit => a = { val result = new SyncVar[a]; fork { result.set(p) } - (=> result.get) + (() => result.get) } \end{lstlisting} @@ -6275,31 +6277,33 @@ The next example presents a function \code{par} which takes a pair of computations as parameters and which returns the results of the computations in another pair. The two computations are performed in parallel. +The function is defined in object +\code{scala.concurrent.ops} as follows. \begin{lstlisting} -def par[a, b](def xp: a, def yp: b): (a, b) = { - val y = new SyncVar[a]; - fork { y.set(yp) } - (xp, y) -} + def par[a, b](def xp: a, def yp: b): Pair[a, b] = { + val y = new SyncVar[b]; + spawn { y set yp } + Pair(xp, y.get) + } \end{lstlisting} - -The next example presents a function \code{replicate} which performs a +Defined in the same place is a function \code{replicate} which performs a number of replicates of a computation in parallel. Each replication instance is passed an integer number which identifies it. - \begin{lstlisting} -def replicate(start: int, end: int)(def p: int => unit): unit = { - if (start == end) { - } else if (start + 1 == end) { - p(start) - } else { - val mid = (start + end) / 2; - par ( replicate(start, mid)(p), replicate(mid, end)(p) ) + def replicate(start: Int, end: Int)(p: Int => Unit): Unit = { + if (start == end) + () + else if (start + 1 == end) + p(start) + else { + val mid = (start + end) / 2; + spawn { replicate(start, mid)(p) } + replicate(mid, end)(p) + } } -} \end{lstlisting} -The next example shows how to use \code{replicate} to perform parallel +The next function uses \code{replicate} to perform parallel computations on all elements of an array. \begin{lstlisting} diff --git a/doc/reference/ScalaReference.tex b/doc/reference/ScalaReference.tex index fa5a795b65..c62e0f04b4 100644 --- a/doc/reference/ScalaReference.tex +++ b/doc/reference/ScalaReference.tex @@ -304,7 +304,7 @@ referenced entity in $T$. Type ::= Type1 `=>' Type | `(' [Types] `)' `=>' Type | Type1 - Type1 ::= SimpleType {with SimpleType} [Refinement] + Type1 ::= SimpleType {with SimpleType} SimpleType ::= StableId | SimpleType `#' id | Path `.' type @@ -318,14 +318,12 @@ take type parameters and yield types. A subset of first-order types called {\em value types} represents sets of (first-class) values. Value types are either {\em concrete} or {\em abstract}. Every concrete value type can be represented as a {\em class type}, i.e.\ a -type designator (\sref{sec:type-desig}) that refers to a -class\footnote{We assume that objects and packages also -implicitly define a class (of the same name as the object or package, -but inaccessible to user programs).} (\sref{sec:classes}), -or as a {\em compound type} (\sref{sec:compound-types}) -consisting of class types and possibly -also a refinement (\sref{sec:refinements}) that further constrains the -types of its members. +type designator (\sref{sec:type-desig}) that refers to a +class\footnote{We assume that objects and packages also implicitly +define a class (of the same name as the object or package, but +inaccessible to user programs).} (\sref{sec:classes}), or as a {\em +compound type} (\sref{sec:compound-types}) of class types. +\todo{verify whether operands need to be class types} A shorthand exists for denoting function types (\sref{sec:function-types}). Abstract value types are introduced by @@ -474,25 +472,14 @@ the following types are ill-formed: \label{sec:compound-types} \syntax\begin{lstlisting} - Type ::= SimpleType {with SimpleType} [Refinement] - Refinement ::= `{' [RefineStat {`;' RefineStat}] `}' - RefineStat ::= Dcl - | type TypeDef {`,' TypeDef} - | + Type ::= SimpleType {with SimpleType} \end{lstlisting} -A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~ represents -objects with members as given in the component types $T_1 \commadots -T_n$ and the refinement \lstinline@{$R\,$}@. Each component type $T_i$ must be a -class type and the base class sequence generated by types $T_1 -\commadots T_n$ must be well-formed (\sref{sec:basetypes-wf}). A -refinement \lstinline@{$R\,$}@ contains declarations and type -definitions. Each declaration or definition in a refinement must -override a declaration or definition in one of the component types -$T_1 \commadots T_n$. The usual rules for overriding (\sref{}) -apply. If no refinement is given, the empty refinement is implicitly -added, i.e. ~\lstinline@$T_1$ with $\ldots$ with $T_n$@~ is a shorthand for -~\lstinline@$T_1$ with $\ldots$ with $T_n$ {}@. +A compound type ~\lstinline@$T_1$ with $\ldots$ with $T_n$ {$R\,$}@~ +represents objects with members as given in the component types $T_1 +\commadots T_n$. Each component type $T_i$ must be a class type and +the base class sequence generated by types $T_1 \commadots T_n$ must +be well-formed (\sref{sec:basetypes-wf}). \subsection{Function Types} \label{sec:function-types} @@ -758,10 +745,7 @@ consisting only of package or object selectors and ending in $O$, then ~\lstinline@$O$.this.type $\equiv p$.type@. \item Two compound types are equivalent if their component types are -pairwise equivalent and their refinements are equivalent. Two -refinements are equivalent if they bind the same names and the -modifiers, types and bounds of every declared entity are equivalent in -both refinements. +pairwise equivalent. \item Two method types are equivalent if they have equivalent result types, both have the same number of parameters, and corresponding @@ -938,9 +922,8 @@ the expression is typed and evaluated is if it was \end{lstlisting} A {\em declaration} introduces names and assigns them types. It can -appear as one of the statements of a class definition -(\sref{sec:templates}) or as part of a refinement in a compound -type (\sref{sec:refinements}). +only appear as one of the statements of a class definition +(\sref{sec:templates}). A {\em definition} introduces names that denote terms or types. It can form part of an object or class definition or it can be local to a @@ -2720,13 +2703,7 @@ constructor invocations (of types $S, T_1 \commadots T_n$, say) and $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 -\lstinline@$S$ with $T_1$ with $\ldots$ with $T_n$ {$R\,$}@, -where \lstinline@{$R\,$}@ is -a refinement (\sref{sec:compound-types}) which declares exactly those -members of $stats$ that override a member of $S$ or $T_1 \commadots -T_n$. \todo{what about methods and overloaded defs?} For this type to -be well-formed, $R$ may not reference types defined in $stats$ which -do not themselves form part of $R$. +\lstinline@$S$ with $T_1$ with $\ldots$ with $T_n$@. The instance creation expression is evaluated by creating a fresh object, which is initialized by evaluating the expression template. @@ -3398,7 +3375,7 @@ Concretely, we distinguish the following kinds of patterns. A {\em wild-card pattern} \_ matches any value. A {\em typed pattern} $\_: T$ matches values of type $T$. The type $T$ may be - a class type or a compound type; it may not contain a refinement (\sref{sec:refinements}). + a class type or a compound type. This pattern matches any non-null value of type $T$. $T$ must conform to the pattern's expected type. A pattern $x:T$ is treated the same way as $x @ (_:T)$ @@ -4260,7 +4237,7 @@ grammar. Type ::= Type1 `=>' Type | `(' [Types] `)' `=>' Type | Type1 - Type1 ::= SimpleType {with SimpleType} [Refinement] + Type1 ::= SimpleType {with SimpleType} SimpleType ::= SimpleType TypeArgs | SimpleType `#' id | StableId @@ -4268,10 +4245,6 @@ grammar. | `(' Type ')' TypeArgs ::= `[' Types `]' Types ::= Type {`,' Type} - Refinement ::= `{' [RefineStat {`;' RefineStat}] `}' - RefineStat ::= Dcl - | type TypeDef {`,' TypeDef} - | Exprs ::= Expr {`,' Expr} Expr ::= Bindings `=>' Expr diff --git a/sources/examples/parsers.scala b/sources/examples/parsers.scala index 3112e0346d..bef1e960cb 100644 --- a/sources/examples/parsers.scala +++ b/sources/examples/parsers.scala @@ -1,5 +1,8 @@ package examples; -abstract class Parsers[intype] { + +abstract class Parsers { + + type intype; abstract class Parser { @@ -39,7 +42,7 @@ abstract class Parsers[intype] { def rep1(p: Parser): Parser = p &&& rep(p); // p+ = p p* } -abstract class ListParsers[intype] extends Parsers[intype] { +abstract class ListParsers extends Parsers { def chr(p: char => boolean): Parser; @@ -55,7 +58,8 @@ abstract class ListParsers[intype] extends Parsers[intype] { def expr : Parser = ident ||| number ||| list; } -class ParseString(s: String) extends Parsers[int] { +class ParseString(s: String) extends Parsers { + type intype = int; val input = 0; def chr(p: char => boolean) = new Parser { def apply(in: int): Parser#Result = @@ -68,7 +72,7 @@ object Test { def main(args: Array[String]): unit = if (args.length == 1) { - val ps = new ListParsers[int] with ParseString(args(0)); + val ps = new ListParsers with ParseString(args(0)); ps.exprs(input) match { case Some(n) => System.out.println("parsed: " + args(0).substring(0, n)); diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala index bfc9082add..c80cf712ab 100644 --- a/sources/scala/tools/scalac/typechecker/Analyzer.scala +++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala @@ -250,6 +250,7 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( if (isAccessible(sym, site, sitetype)) { symtype } else { + System.out.println(sym.flags & (PRIVATE | PROTECTED));//debug error(pos, "" + sym + " cannot be accessed in " + sitetype.widen()); Type.ErrorType } @@ -288,8 +289,9 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( accessWithin(owner) || ((sym.flags & PRIVATE) == 0) && - sitetype.symbol().isSubClass(owner) && - (site.isInstanceOf[Tree$Super] || isSubClassOfEnclosing(sitetype.symbol())) + (site.isInstanceOf[Tree$Super] || + (sitetype.symbol().isSubClass(owner) && + isSubClassOfEnclosing(sitetype.symbol()))) } } @@ -1021,9 +1023,10 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( var rhs = _rhs; var restype: Type = null; pushContext(tree, sym, new Scope(context.scope)); - if (name == Names.CONSTRUCTOR) + if (name == Names.CONSTRUCTOR) { context.enclClass.owner.flags = context.enclClass.owner.flags | INCONSTRUCTOR; + } val tparamSyms = enterParams(tparams); val vparamSyms = enterParams(vparams); if (tpe != Tree.Empty) { @@ -1031,8 +1034,10 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( (tree.asInstanceOf[Tree$DefDef]).tpe = tpe; restype = tpe.getType(); } else if (name == Names.CONSTRUCTOR) { - restype = context.enclClass.owner.getType().subst( - context.enclClass.owner.typeParams(), tparamSyms); + if (context.enclClass.owner.typeParams().length != 0) + error(tree.pos, "secondary constructors for parameterized classes not yet implemented"); + restype = context.enclClass.owner.getType();/*.subst( + context.enclClass.owner.typeParams(), tparamSyms)*/; context.enclClass.owner.flags = context.enclClass.owner.flags & ~INCONSTRUCTOR; } else { @@ -2449,14 +2454,29 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer( val constr: Symbol = c.allConstructors(); val fn0: Tree = fn1; fn1 = gen.mkRef(fn1.pos, pre, constr); - fn1 match { - case Tree$Select(fn1qual, _) => + if (constr.owner().isPackage()) { + var c = context; + while (c != Context.NONE && + !c.tree.isInstanceOf[Tree$ClassDef] && + !c.tree.isInstanceOf[Tree$Template]) + c = c.outer; + if (c.owner.isConstructor()) + // we are in a superclass constructor call + fn1.setType(checkAccessible( + fn1.pos, constr, fn1.getType(), make.Super(tree.pos, Names.EMPTY.toTypeName(), Names.EMPTY.toTypeName()), c.owner.constructorClass().typeConstructor())); + else fn1.setType(checkAccessible( - fn1.pos, constr, fn1.getType(), fn1qual, fn1qual.getType())); - case _ => - if (constr.owner().isPackage()) + fn1.pos, constr, fn1.getType(), c.tree, c.owner.typeConstructor())); + } else { + fn1 match { + case Tree$Select(fn1qual, _) => fn1.setType(checkAccessible( - fn1.pos, constr, fn1.getType(), Tree.Empty, constr.owner().getType())); + fn1.pos, constr, fn1.getType(), fn1qual, fn1qual.getType())); + case _ => + if (constr.owner().isPackage()) + fn1.setType(checkAccessible( + fn1.pos, constr, fn1.getType(), Tree.Empty, constr.owner().getType())); + } } if (tsym == c) { fn0 match { |