summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2005-12-16 18:44:33 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2005-12-16 18:44:33 +0000
commit53a3cc7b17f4cf97075b7e71720777fd84109696 (patch)
tree0cc784e0b47ea49cc151a136d19f20bfa8ee2197 /docs
parentdf50e05006b43b007c2587549030d24b5c154398 (diff)
downloadscala-53a3cc7b17f4cf97075b7e71720777fd84109696.tar.gz
scala-53a3cc7b17f4cf97075b7e71720777fd84109696.tar.bz2
scala-53a3cc7b17f4cf97075b7e71720777fd84109696.zip
Created proper 'docs' folder for new layout.
Diffstat (limited to 'docs')
-rw-r--r--docs/LICENSE35
-rw-r--r--docs/README62
-rw-r--r--docs/devel/nscNodes.dot104
-rw-r--r--docs/devel/nscTypes.dot73
-rw-r--r--docs/development/nscNodes.dot104
-rw-r--r--docs/development/nscTypes.dot73
-rw-r--r--docs/examples/Parsers.scala108
-rw-r--r--docs/examples/auction.scala133
-rw-r--r--docs/examples/boundedbuffer.scala36
-rw-r--r--docs/examples/computeserver.scala42
-rw-r--r--docs/examples/expressions/expressions-current.scala67
-rw-r--r--docs/examples/fors.scala114
-rw-r--r--docs/examples/futures.scala17
-rw-r--r--docs/examples/iterators.scala29
-rw-r--r--docs/examples/jolib/Ref.scala56
-rw-r--r--docs/examples/jolib/parallelOr.scala59
-rw-r--r--docs/examples/maps.scala192
-rw-r--r--docs/examples/mobile/sort.scala17
-rw-r--r--docs/examples/monads/callccInterpreter.scala84
-rw-r--r--docs/examples/monads/directInterpreter.scala55
-rw-r--r--docs/examples/monads/errorInterpreter.scala86
-rw-r--r--docs/examples/monads/simpleInterpreter.scala75
-rw-r--r--docs/examples/monads/stateInterpreter.scala86
-rw-r--r--docs/examples/oneplacebuffer.scala47
-rw-r--r--docs/examples/parsers1.scala118
-rw-r--r--docs/examples/parsers2.scala63
-rw-r--r--docs/examples/patterns.scala35
-rw-r--r--docs/examples/pilib/elasticBuffer.scala77
-rw-r--r--docs/examples/pilib/handover.scala190
-rw-r--r--docs/examples/pilib/mobilePhoneProtocol.scala172
-rw-r--r--docs/examples/pilib/piNat.scala92
-rw-r--r--docs/examples/pilib/rwlock.scala331
-rw-r--r--docs/examples/pilib/scheduler.scala149
-rw-r--r--docs/examples/pilib/semaphore.scala72
-rw-r--r--docs/examples/pilib/twoPlaceBuffer.scala67
-rw-r--r--docs/examples/sort.scala48
-rw-r--r--docs/examples/sort1.scala22
-rw-r--r--docs/examples/sort2.scala25
-rw-r--r--docs/examples/typeinf.scala244
-rw-r--r--docs/man/man1/scala.1133
-rw-r--r--docs/man/man1/scalac.1299
-rw-r--r--docs/man/man1/scaladoc.1119
-rw-r--r--docs/man/man1/scalaint.1127
-rw-r--r--docs/man/man1/scalarun.1123
44 files changed, 4260 insertions, 0 deletions
diff --git a/docs/LICENSE b/docs/LICENSE
new file mode 100644
index 0000000000..e2ab255c55
--- /dev/null
+++ b/docs/LICENSE
@@ -0,0 +1,35 @@
+SCALA LICENSE
+
+Copyright (c) 2002-2005 EPFL, Lausanne.
+All rights reserved.
+
+This software was developed by the Programming Methods Laboratory of the
+Swiss Federal Institute of Technology (EPFL), Lausanne, Switzerland.
+
+Permission to use, copy, modify, and distribute this software in source
+or binary form for any purpose with or without fee is hereby granted,
+provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the EPFL nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/docs/README b/docs/README
new file mode 100644
index 0000000000..26b4db9cdd
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,62 @@
+
+Scala Software Distributions
+----------------------------
+
+- scala-YYYYMMDD-hhmmss.tar.gz Unix distribution
+- scala-YYYYMMDD-hhmmss.zip Windows distribution
+
+The standard distributions require Java 1.4.x or above. If you don't
+know which version of Java you have, run the command "java -version".
+
+
+Scala Tools
+-----------
+
+- scalac Scala compiler
+- scaladoc Scala API documentation generator
+- scalaint Scala interactive interpreter
+- scalarun Scala interpreter
+- scalap Scala profiler
+
+Run the command "scalac -help" to display the list of available
+compiler options.
+
+NB. socos, siris and surus are deprecated commands starting from
+version 20030811-115735 of the Scala distribution, please use
+respectively scalac, scalaint and scalarun instead.
+
+
+Install on Unix
+---------------
+
+Untar the archive. All Scala tools are located in the directory "bin".
+
+You may test the distribution by running the script "scala-test"
+located in the subdirectory "share/scala/test/bin".
+
+
+Install on Windows
+------------------
+
+Unzip the archive. All Scala tools are located in the "bin"
+directory. Before running any of these tools, you must define the
+environment variable SCALA_HOME to point to the home directory of the
+scala distribution.
+
+On Windows 95/98/Me, this can be done by adding the following command
+to your AUTOEXEC.BAT file and then rebooting your machine.
+
+set SCALA_HOME=<install-directory>\scala-YYYYMMDD-hhmmss
+
+On Windows NT/2000/XP, open the "Control Panel", open the "System"
+applet, select the "Advanced" tab, click on "Environment Variables",
+click on "New..." in the user variable section and enter the following
+informations:
+
+Variable Name : SCALA_HOME
+Variable Value: <install-directory>\scala-YYYYMMDD-hhmmss
+
+If you have Administrator privileges, you may install the tools for
+all users of your machine by creating a new system variable instead of
+a new user variable.
+
diff --git a/docs/devel/nscNodes.dot b/docs/devel/nscNodes.dot
new file mode 100644
index 0000000000..eb0b792451
--- /dev/null
+++ b/docs/devel/nscNodes.dot
@@ -0,0 +1,104 @@
+digraph SQLTypes {
+
+ size="4,4"
+ rankdir=BT
+ rank=max
+ ratio=compress
+
+ node [shape = record]
+
+ Tree
+
+ SymTree -> Tree
+
+ DefTree -> SymTree
+
+ TermTree -> Tree
+
+ TypTree -> Tree
+
+ EmptyTree -> TermTree
+
+ PackageDef -> DefTree
+
+ ClassDef -> DefTree
+
+ ModuleDef -> DefTree
+
+ ValDef -> DefTree
+
+ DefDef -> DefTree
+
+ AbsTypeDef -> DefTree
+
+ AliasTypeDef -> DefTree
+
+ LabelDef -> DefTree
+ LabelDef -> TermTree
+
+ Import -> SymTree
+
+ Attributed -> Tree
+
+ DocDef -> Tree
+
+ Template -> SymTree
+
+ Block -> TermTree
+
+ CaseDef -> Tree
+
+ Sequence -> TermTree
+
+ Alternative -> TermTree
+
+ Star -> TermTree
+
+ Bind -> DefTree
+
+ ArrayValue -> TermTree
+
+ Function -> TermTree
+
+ Assign -> TermTree
+
+ If -> TermTree
+
+ Match -> TermTree
+
+ Return -> TermTree
+
+ Try -> TermTree
+
+ Throw -> TermTree
+
+ New -> TermTree
+
+ TypeApply -> TermTree
+
+ Apply -> TermTree
+
+ Super -> TermTree
+ Super -> SymTree
+
+ This -> TermTree
+ This -> SymTree
+
+ Select -> SymTree
+
+ Ident -> SymTree
+
+ Literal -> TermTree
+
+ TypeTree -> TypTree
+
+ SingletonTypeTree -> TypTree
+
+ SelectFromTypeTree -> TypTree
+ SelectFromTypeTree -> SymTree
+
+ CompoundTypeTree -> TypTree
+
+ AppliedTypeTree -> TypTree
+
+} \ No newline at end of file
diff --git a/docs/devel/nscTypes.dot b/docs/devel/nscTypes.dot
new file mode 100644
index 0000000000..8e4e531aa6
--- /dev/null
+++ b/docs/devel/nscTypes.dot
@@ -0,0 +1,73 @@
+digraph SQLTypes {
+
+ size="4,4"
+ rankdir=BT
+ rank=max
+ ratio=compress
+
+ node [shape = record]
+
+ Type
+
+ SubType -> Type
+
+ SingletonType -> SubType
+
+ ErrorType -> Type
+
+ WildcardType -> Type
+
+ NoType -> Type
+
+ NoPrefix -> Type
+
+ ThisType [label = "{ThisType|sym: Symbol}"]
+ ThisType -> SingletonType
+
+ SingleType [label = "{SingleType|pre: Type\nsym: Symbol}"]
+ SingleType -> SingletonType
+
+ SuperType [label = "{SuperType|thistpe: Type\nsupertp: Type}"]
+ SuperType -> SingletonType
+
+ TypeBounds [label = "{TypeBounds|lo: Type\nhi: Type}"]
+ TypeBounds -> SubType
+
+ CompoundType -> Type
+
+ RefinedType[label = "{RefinedType|parents: List[Type]\ndecls: Scope}"]
+ RefinedType -> CompoundType
+
+ ClassInfoType[label = "{ClassInfoType|parents: List[Type]\ndecls: Scope\nsymbol: Symbol}"]
+ ClassInfoType -> CompoundType
+
+ PackageClassInfoType[label = "{PackageClassInfoType|decls: Scope\nclazz: Symbol}"]
+ PackageClassInfoType -> ClassInfoType
+
+ ConstantType[label = "{ConstantType|value: Constant}"]
+ ConstantType -> SingletonType
+
+ TypeRef[label = "{TypeRef|pre: Type\nsym: Symbol\nargs: List[Type]}"]
+ TypeRef -> Type
+
+ MethodType[label = "{MethodType|paramTypes: List[Type]\nresultType: Type}"]
+ MethodType -> Type
+
+ PolyType[label = "{PolyType|typeParams: List[Symbol]\nresultType: Type}"]
+ PolyType -> Type
+
+ OverloadedType[label = "{OverloadedType|pre: Type\nalternatives: List[Symbol]}"]
+ OverloadedType -> Type
+
+ AntiPolyType[label = "{AntiPolyType|pre: Type\ntargs: List[Type]}"]
+ AntiPolyType -> Type
+
+ TypeVar[label = "{TypeVar|origin: Type\nconstr: TypeConstraint}"]
+ TypeVar -> Type
+
+ LazyType -> Type
+
+ LazyPolyType[label = "{LazyPolyType|typeParams: List[Symbol]\nrestp: Type}"]
+ LazyPolyType -> LazyType
+
+} \ No newline at end of file
diff --git a/docs/development/nscNodes.dot b/docs/development/nscNodes.dot
new file mode 100644
index 0000000000..eb0b792451
--- /dev/null
+++ b/docs/development/nscNodes.dot
@@ -0,0 +1,104 @@
+digraph SQLTypes {
+
+ size="4,4"
+ rankdir=BT
+ rank=max
+ ratio=compress
+
+ node [shape = record]
+
+ Tree
+
+ SymTree -> Tree
+
+ DefTree -> SymTree
+
+ TermTree -> Tree
+
+ TypTree -> Tree
+
+ EmptyTree -> TermTree
+
+ PackageDef -> DefTree
+
+ ClassDef -> DefTree
+
+ ModuleDef -> DefTree
+
+ ValDef -> DefTree
+
+ DefDef -> DefTree
+
+ AbsTypeDef -> DefTree
+
+ AliasTypeDef -> DefTree
+
+ LabelDef -> DefTree
+ LabelDef -> TermTree
+
+ Import -> SymTree
+
+ Attributed -> Tree
+
+ DocDef -> Tree
+
+ Template -> SymTree
+
+ Block -> TermTree
+
+ CaseDef -> Tree
+
+ Sequence -> TermTree
+
+ Alternative -> TermTree
+
+ Star -> TermTree
+
+ Bind -> DefTree
+
+ ArrayValue -> TermTree
+
+ Function -> TermTree
+
+ Assign -> TermTree
+
+ If -> TermTree
+
+ Match -> TermTree
+
+ Return -> TermTree
+
+ Try -> TermTree
+
+ Throw -> TermTree
+
+ New -> TermTree
+
+ TypeApply -> TermTree
+
+ Apply -> TermTree
+
+ Super -> TermTree
+ Super -> SymTree
+
+ This -> TermTree
+ This -> SymTree
+
+ Select -> SymTree
+
+ Ident -> SymTree
+
+ Literal -> TermTree
+
+ TypeTree -> TypTree
+
+ SingletonTypeTree -> TypTree
+
+ SelectFromTypeTree -> TypTree
+ SelectFromTypeTree -> SymTree
+
+ CompoundTypeTree -> TypTree
+
+ AppliedTypeTree -> TypTree
+
+} \ No newline at end of file
diff --git a/docs/development/nscTypes.dot b/docs/development/nscTypes.dot
new file mode 100644
index 0000000000..8e4e531aa6
--- /dev/null
+++ b/docs/development/nscTypes.dot
@@ -0,0 +1,73 @@
+digraph SQLTypes {
+
+ size="4,4"
+ rankdir=BT
+ rank=max
+ ratio=compress
+
+ node [shape = record]
+
+ Type
+
+ SubType -> Type
+
+ SingletonType -> SubType
+
+ ErrorType -> Type
+
+ WildcardType -> Type
+
+ NoType -> Type
+
+ NoPrefix -> Type
+
+ ThisType [label = "{ThisType|sym: Symbol}"]
+ ThisType -> SingletonType
+
+ SingleType [label = "{SingleType|pre: Type\nsym: Symbol}"]
+ SingleType -> SingletonType
+
+ SuperType [label = "{SuperType|thistpe: Type\nsupertp: Type}"]
+ SuperType -> SingletonType
+
+ TypeBounds [label = "{TypeBounds|lo: Type\nhi: Type}"]
+ TypeBounds -> SubType
+
+ CompoundType -> Type
+
+ RefinedType[label = "{RefinedType|parents: List[Type]\ndecls: Scope}"]
+ RefinedType -> CompoundType
+
+ ClassInfoType[label = "{ClassInfoType|parents: List[Type]\ndecls: Scope\nsymbol: Symbol}"]
+ ClassInfoType -> CompoundType
+
+ PackageClassInfoType[label = "{PackageClassInfoType|decls: Scope\nclazz: Symbol}"]
+ PackageClassInfoType -> ClassInfoType
+
+ ConstantType[label = "{ConstantType|value: Constant}"]
+ ConstantType -> SingletonType
+
+ TypeRef[label = "{TypeRef|pre: Type\nsym: Symbol\nargs: List[Type]}"]
+ TypeRef -> Type
+
+ MethodType[label = "{MethodType|paramTypes: List[Type]\nresultType: Type}"]
+ MethodType -> Type
+
+ PolyType[label = "{PolyType|typeParams: List[Symbol]\nresultType: Type}"]
+ PolyType -> Type
+
+ OverloadedType[label = "{OverloadedType|pre: Type\nalternatives: List[Symbol]}"]
+ OverloadedType -> Type
+
+ AntiPolyType[label = "{AntiPolyType|pre: Type\ntargs: List[Type]}"]
+ AntiPolyType -> Type
+
+ TypeVar[label = "{TypeVar|origin: Type\nconstr: TypeConstraint}"]
+ TypeVar -> Type
+
+ LazyType -> Type
+
+ LazyPolyType[label = "{LazyPolyType|typeParams: List[Symbol]\nrestp: Type}"]
+ LazyPolyType -> LazyType
+
+} \ No newline at end of file
diff --git a/docs/examples/Parsers.scala b/docs/examples/Parsers.scala
new file mode 100644
index 0000000000..10512ab2fd
--- /dev/null
+++ b/docs/examples/Parsers.scala
@@ -0,0 +1,108 @@
+package examples;
+
+abstract class Parsers {
+
+ type inputType;
+
+ trait Parser[a] {
+
+ type Result = Option[Pair[a, inputType]];
+
+ def apply(in: inputType): Result;
+
+ def filter(pred: a => boolean) = new Parser[a] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => if (pred(x)) Some(Pair(x, in1)) else None
+ }
+ }
+
+ def map[b](f: a => b) = new Parser[b] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
+ }
+ }
+
+ def flatMap[b](f: a => Parser[b]) = new Parser[b] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => f(x).apply(in1)
+ }
+ }
+
+ def ||| (p: => Parser[a]) = new Parser[a] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => p(in)
+ case s => s
+ }
+ }
+
+ def &&& [b](p: => Parser[b]): Parser[b] =
+ for (val _ <- this; val x <- p) yield x;
+ }
+
+ def succeed[a](x: a) = new Parser[a] {
+ def apply(in: inputType): Result = Some(Pair(x, in))
+ }
+
+ def rep[a](p: Parser[a]): Parser[List[a]] =
+ rep1(p) ||| succeed(List());
+
+ def rep1[a](p: Parser[a]): Parser[List[a]] =
+ for (val x <- p; val xs <- rep(p)) yield x :: xs;
+
+ def opt[a](p: Parser[a]): Parser[List[a]] =
+ (for (val x <- p) yield List(x)) ||| succeed(List());
+}
+
+class Tokenizer(in: Iterator[char], delimiters: String) extends Iterator[String] {
+
+ val EOI: char = 0;
+
+ def nextChar() =
+ if (in.hasNext) in.next else EOI;
+
+ private var ch = nextChar();
+
+ def isDelimiter(ch: Char) = {
+ var i = 0;
+ while (i < delimiters.length() && delimiters.charAt(i) != ch) { i = i + 1 }
+ i < delimiters.length()
+ }
+
+ def hasNext: boolean = ch != EOI;
+
+ private val buf = new StringBuffer;
+
+ def next: String = {
+ while (ch <= ' ' && ch != EOI) nextChar();
+ if (ch == EOI) ""
+ else {
+ if (isDelimiter(ch)) ch.toString()
+ else {
+ buf.setLength(0); buf append ch;
+ while (ch > ' ' && ch != EOI && !isDelimiter(ch)) {
+ buf append ch; nextChar();
+ }
+ buf.toString()
+ }
+ }
+ }
+}
+
+abstract class TokenParsers extends Parsers {
+ type inputType = Stream[String];
+ def nextToken() = new Parser[String] {
+ def apply(in: inputType): Result =
+ if (in.isEmpty) None else Some(Pair(in.head, in.tail));
+ }
+}
+
+abstract class CharParsers extends Parsers {
+ def any: Parser[char];
+ def chr(ch: char) =
+ for (val c <- any; c == ch) yield c;
+ def chr(p: char => boolean) =
+ for (val c <- any; p(c)) yield c;
+}
diff --git a/docs/examples/auction.scala b/docs/examples/auction.scala
new file mode 100644
index 0000000000..c6ab223375
--- /dev/null
+++ b/docs/examples/auction.scala
@@ -0,0 +1,133 @@
+package examples;
+
+import java.util.Date;
+import scala.concurrent._;
+
+/** A simple demonstrator program implementing an online auction service
+ * The example uses the actor abstraction defined in the API of
+ * package scala.concurrent.
+ */
+trait AuctionMessage;
+case class
+ Offer(bid: int, client: Actor), // make a bid
+ Inquire(client: Actor) extends AuctionMessage; // inquire status
+
+trait AuctionReply;
+case class
+ Status(asked: int, expiration: Date), // asked sum, expiration date
+ BestOffer(), // yours is the best offer
+ BeatenOffer(maxBid: int), // offer beaten by maxBid
+ AuctionConcluded(seller: Actor, client: Actor), // auction concluded
+ AuctionFailed(), // failed with no bids
+ AuctionOver() extends AuctionReply; // bidding is closed
+
+class Auction(seller: Actor, minBid: int, closing: Date) extends Actor {
+
+ val timeToShutdown = 3600000; // msec
+ val bidIncrement = 10;
+
+ override def run() = {
+ var maxBid = minBid - bidIncrement;
+ var maxBidder: Actor = null;
+ var running = true;
+
+ while (running) {
+ receiveWithin (closing.getTime() - new Date().getTime()) {
+
+ case Offer(bid, client) =>
+ if (bid >= maxBid + bidIncrement) {
+ if (maxBid >= minBid)
+ maxBidder send BeatenOffer(bid);
+ maxBid = bid;
+ maxBidder = client;
+ client send BestOffer()
+ } else {
+ client send BeatenOffer(maxBid)
+ }
+
+ case Inquire(client) =>
+ client send Status(maxBid, closing)
+
+ case TIMEOUT() =>
+ if (maxBid >= minBid) {
+ val reply = AuctionConcluded(seller, maxBidder);
+ maxBidder send reply;
+ seller send reply
+ } else {
+ seller send AuctionFailed()
+ }
+ receiveWithin(timeToShutdown) {
+ case Offer(_, client) => client send AuctionOver()
+ case TIMEOUT() => running = false
+ }
+
+ }
+ }
+ }
+}
+
+// ---- Test -------------------------------------------------------------
+
+object auction {
+
+ val random = new java.util.Random();
+
+ val minBid = 100;
+ val closing = new Date(new Date().getTime() + 60000);
+
+ val seller = new Actor {
+ override def run() = {}
+ }
+ val auction = new Auction(seller, minBid, closing);
+
+ def client(i: int, increment: int, top: int) = new Actor {
+ val name = "Client " + i;
+ def log(msg: String) = Console.println(name + ": " + msg);
+ var running = true;
+ var max: int = _;
+ var current: int = 0;
+ override def run() = {
+ log("started");
+ auction send Inquire(this);
+ receive {
+ case Status(maxBid, _) => {
+ log("status(" + maxBid + ")");
+ max = maxBid
+ }
+ }
+ while (running) {
+ if (max >= top)
+ log("too high for me")
+ else if (current < max) {
+ current = max + increment;
+ Thread.sleep(1 + random.nextInt(1000));
+ auction send Offer(current, this);
+ }
+ receive {
+ case BestOffer() => {
+ log("bestOffer(" + current + ")");
+ }
+ case BeatenOffer(maxBid) => {
+ log("beatenOffer(" + maxBid + ")");
+ max = maxBid;
+ }
+ case AuctionConcluded(seller, maxBidder) => {
+ log("auctionConcluded");
+ }
+ case AuctionOver() => {
+ running = false;
+ log("auctionOver");
+ }
+ }
+ }
+ }
+ }
+
+ def main(args: Array[String]) = {
+ seller.start();
+ auction.start();
+ client(1, 20, 200).start();
+ client(2, 10, 300).start();
+ }
+
+}
diff --git a/docs/examples/boundedbuffer.scala b/docs/examples/boundedbuffer.scala
new file mode 100644
index 0000000000..983a3a7bf5
--- /dev/null
+++ b/docs/examples/boundedbuffer.scala
@@ -0,0 +1,36 @@
+package examples;
+
+object boundedbuffer {
+
+ import concurrent.ops._;
+
+ class BoundedBuffer[a](N: Int) {
+ var in, out, n = 0;
+ val elems = new Array[a](N);
+
+ def await(cond: => Boolean) = while (!cond) { wait() }
+
+ def put(x: a) = synchronized {
+ await (n < N);
+ elems(in) = x; in = (in + 1) % N; n = n + 1;
+ if (n == 1) notifyAll();
+ }
+
+ def get: a = synchronized {
+ await (n != 0);
+ val x = elems(out); out = (out + 1) % N ; n = n - 1;
+ if (n == N - 1) notifyAll();
+ x
+ }
+ }
+
+ def main(args: Array[String]) = {
+ val buf = new BoundedBuffer[String](10);
+ var cnt = 0;
+ def produceString = { cnt = cnt + 1; cnt.toString() }
+ def consumeString(ss: String) = System.out.println(ss);
+ spawn { while (true) { val ssss = produceString; buf.put(ssss) } }
+ spawn { while (true) { val s = buf.get; consumeString(s) } }
+ }
+
+}
diff --git a/docs/examples/computeserver.scala b/docs/examples/computeserver.scala
new file mode 100644
index 0000000000..acc4a0b93e
--- /dev/null
+++ b/docs/examples/computeserver.scala
@@ -0,0 +1,42 @@
+package examples;
+
+import concurrent._, concurrent.ops._;
+
+class ComputeServer(n: Int) {
+
+ private trait Job {
+ type t;
+ def task: t;
+ def ret(x: t): Unit;
+ }
+
+ private val openJobs = new Channel[Job]();
+
+ private def processor(i: Int): Unit = {
+ while (true) {
+ val job = openJobs.read;
+ Console.println("read a job");
+ job.ret(job.task)
+ }
+ }
+
+ def future[a](p: => a): () => a = {
+ val reply = new SyncVar[a]();
+ openJobs.write{
+ new Job {
+ type t = a;
+ def task = p;
+ def ret(x: a) = reply.set(x);
+ }
+ }
+ () => reply.get
+ }
+
+ spawn(replicate(0, n) { processor })
+}
+
+object computeserver with Application {
+ val server = new ComputeServer(1);
+ val f = server.future(42);
+ Console.println(f())
+}
diff --git a/docs/examples/expressions/expressions-current.scala b/docs/examples/expressions/expressions-current.scala
new file mode 100644
index 0000000000..91e5df02ae
--- /dev/null
+++ b/docs/examples/expressions/expressions-current.scala
@@ -0,0 +1,67 @@
+package examples.expressions;
+
+abstract class Lang {
+ trait Visitor {
+ def caseNum(n: int): unit;
+ }
+
+ abstract class Exp {
+ def visit(v: visitor): unit;
+ }
+
+ type visitor <: Visitor;
+
+ class Num(n: int) extends Exp {
+ def visit(v: visitor): unit = v.caseNum(n);
+ }
+
+ class Eval(result: Ref[int]): visitor extends Visitor {
+ def caseNum(n: int) = result.elem = n;
+ }
+}
+
+abstract class Lang2 extends Lang {
+ abstract class Visitor2 extends Visitor {
+ def casePlus(left: Exp, right: Exp): unit;
+ }
+
+ type visitor <: Visitor2;
+
+ class Plus(l: Exp, r: Exp) extends Exp {
+ def visit(v: visitor): unit = v.casePlus(l, r);
+ }
+
+ class Eval2(result: Ref[int]): visitor extends Eval(result) with Visitor2 {
+ def casePlus(l: Exp, r: Exp) =
+ result.elem = { l.visit(this); result.elem } + { r.visit(this); result.elem }
+ }
+
+ class Show2(result: Ref[String]): visitor extends Visitor2 {
+ def caseNum(n: int) = result.elem = n.toString();
+ def casePlus(l: Exp, r: Exp) =
+ result.elem =
+ "(" + { l.visit(this); result.elem } +
+ "+" + { r.visit(this); result.elem } + ")";
+ }
+}
+
+object Main {
+
+ def main(args: Array[String]) = {
+ //val l1 = new Lang { type visitor = Visitor } // not yet implemented
+ object l1 extends Lang { type visitor = Visitor } // workaround
+ val e1: l1.Exp = new l1.Num(42);
+ val iref = new Ref(0);
+ Console.println("eval: " + { e1.visit(new l1.Eval(iref)); iref.elem });
+
+ //val l2 = new Lang2 { type visitor = Visitor2 } // not yet implemented
+ object l2 extends Lang2 { type visitor = Visitor2 } // workaround
+ val e2: l2.Exp = new l2.Plus(new l2.Num(5), new l2.Num(37));
+ val sref = new Ref("");
+ Console.println("eval: " + { e2.visit(new l2.Eval2(iref)); iref.elem });
+ Console.println("show: " + { e2.visit(new l2.Show2(sref)); sref.elem });
+ e1.visit(new l1.Eval(iref));
+ e2.visit(new l2.Show2(sref));
+ }
+}
+
diff --git a/docs/examples/fors.scala b/docs/examples/fors.scala
new file mode 100644
index 0000000000..6c969d3519
--- /dev/null
+++ b/docs/examples/fors.scala
@@ -0,0 +1,114 @@
+package examples;
+
+import scala.xml._;
+
+
+object fors {
+
+ val e = Node.NoAttributes ;
+
+ class Person(_name: String, _age: Int) {
+ val name = _name;
+ val age = _age;
+ }
+
+ def printOlderThan20(xs: Seq[Person]): Iterator[String] =
+ printOlderThan20(xs.elements);
+
+ def printOlderThan20(xs: Iterator[Person]): Iterator[String] =
+ for (val p <- xs; p.age > 20) yield p.name;
+
+ val persons = List(
+ new Person("John", 40),
+ new Person("Richard", 68)
+ );
+
+ def divisors(n: Int): List[Int] =
+ for (val i <- List.range(1, n+1); n % i == 0) yield i;
+
+ def isPrime(n: Int) = divisors(n).length == 2;
+
+ def findNums(n: Int): Iterator[Pair[Int, Int]] =
+ for (val i <- Iterator.range(1, n);
+ val j <- Iterator.range(1, i-1);
+ isPrime(i+j)) yield Pair(i, j);
+
+ def sum(xs: List[Double]): Double =
+ xs.foldLeft(0.0) { (x, y) => x + y }
+
+ def scalProd(xs: List[Double], ys: List[Double]) =
+ sum(for(val Pair(x, y) <- xs zip ys) yield x * y);
+
+ type Lst = List[Any];
+
+ val prefix = null;
+ val scope = TopScope;
+
+ val books = List(
+ Elem(prefix, "book", e, scope,
+ Elem(prefix, "title", e, scope,
+ Text("Structure and Interpretation of Computer Programs")),
+ Elem(prefix, "author", e, scope,
+ Text("Abelson, Harald")),
+ Elem(prefix, "author", e, scope,
+ Text("Sussman, Gerald J."))),
+ Elem(prefix, "book", e, scope,
+ Elem(prefix, "title", e, scope,
+ Text("Principles of Compiler Design")),
+ Elem(prefix, "author", e, scope,
+ Text("Aho, Alfred")),
+ Elem(prefix, "author", e, scope,
+ Text("Ullman, Jeffrey"))),
+ Elem(prefix, "book", e, scope,
+ Elem(prefix, "title", e, scope,
+ Text("Programming in Modula-2")),
+ Elem(prefix, "author", e, scope,
+ Text("Wirth, Niklaus")))
+ );
+
+ def findAuthor(books: Lst) =
+ for (val Elem(_, "book", _, scope, book @ _*) <- books;
+ val Elem(_, "title", _, scope, Text(title)) <- book;
+ (title indexOf "Program") >= 0;
+ val Elem(_, "author", _, scope, Text(author)) <- book) yield author;
+
+ for (val Elem(_, "book", _, scope, b @ _*) <- books;
+ val Elem(_, "author", _, scope, Text(author)) <- b;
+ author startsWith "Ullman";
+ val Elem(_, "title", _, scope, Text(title)) <- b) yield title;
+
+ removeDuplicates(
+ for (val Elem(_, "book", _, scope, b1 @ _* ) <- books;
+ val Elem(_, "book", _, scope, b2 @ _*) <- books;
+ b1 != b2;
+ val Elem(_, "author", _, scope, Text(a1)) <- b1;
+ val Elem(_, "author", _, scope, Text(a2)) <- b2;
+ a1 == a2) yield Pair(a1, a2));
+
+ def removeDuplicates[a](xs: List[a]): List[a] =
+ if (xs.isEmpty)
+ xs
+ else
+ xs.head :: removeDuplicates(for (val x <- xs.tail; x != xs.head) yield x);
+
+ def main(args: Array[String]) = {
+ Console.print("Persons over 20:");
+ printOlderThan20(persons) foreach { x => Console.print(" " + x) };
+ Console.println;
+
+ Console.println("divisors(34) = " + divisors(34));
+
+ Console.print("findNums(15) =");
+ findNums(15) foreach { x => Console.print(" " + x); };
+ Console.println;
+
+ val xs = List(3.5, 5.0, 4.5);
+ Console.println("average(" + xs + ") = "
+ + sum(xs) / xs.length);
+
+ val ys = List(2.0, 1.0, 3.0);
+ Console.println("scalProd(" + xs + ", " + ys +") = "
+ + scalProd(xs, ys));
+ }
+
+}
diff --git a/docs/examples/futures.scala b/docs/examples/futures.scala
new file mode 100644
index 0000000000..905d360612
--- /dev/null
+++ b/docs/examples/futures.scala
@@ -0,0 +1,17 @@
+package examples;
+
+import concurrent.ops._;
+
+object futures {
+ def someLengthyComputation = 1;
+ def anotherLengthyComputation = 2;
+ def f(x: Int) = x + x;
+ def g(x: Int) = x * x;
+
+ def main(args: Array[String]): Unit = {
+ val x = future(someLengthyComputation);
+ anotherLengthyComputation;
+ val y = f(x()) + g(x());
+ Console.println(y)
+ }
+} \ No newline at end of file
diff --git a/docs/examples/iterators.scala b/docs/examples/iterators.scala
new file mode 100644
index 0000000000..5f951156cf
--- /dev/null
+++ b/docs/examples/iterators.scala
@@ -0,0 +1,29 @@
+package examples;
+
+object iterators {
+
+ def Array(elems: Double*): Array[Double] = {
+ val ar = new Array[Double](elems.length);
+ for (val i <- Iterator.range(0, elems.length))
+ ar(i) = elems(i);
+ ar
+ }
+
+ def printArray(xs: Array[Double]) =
+ Iterator.fromArray(xs) foreach { x => Console.println(x) };
+
+ def findGreater(xs: Array[Double], limit: Double) =
+ Iterator.fromArray(xs)
+ .zip(Iterator.from(0))
+ .filter{case Pair(x, i) => x > limit }
+ .map{case Pair(x, i) => i}
+
+ def main(args: Array[String]) = {
+ val ar = Array/*[Double]*/(6, 2, 8, 5, 1);
+ printArray(ar);
+ Console.println("Elements greater than 3.0:");
+ findGreater(ar, 3.0) foreach { x => Console.println(ar(x)) }
+ }
+
+}
+
diff --git a/docs/examples/jolib/Ref.scala b/docs/examples/jolib/Ref.scala
new file mode 100644
index 0000000000..73cc167307
--- /dev/null
+++ b/docs/examples/jolib/Ref.scala
@@ -0,0 +1,56 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package examples.jolib;
+/*
+import concurrent.SyncVar;
+import concurrent.jolib._;
+
+class Ref[a](init: a) extends Join {
+
+ object get extends Synchr[a](this) { case class C() extends SyncVar[a]; }
+ object set extends Synchr[unit](this) { case class C(x: a) extends SyncVar[unit]; }
+ object state extends Asynchr(this) { case class C(x: a); }
+
+ rules (
+ Pair(List(get, state), { case List(g @ get.C(), state.C(x) ) =>
+ { g.set(x); state(state.C(x)) } }),
+ Pair(List(set, state), { case List(s @ set.C(x), state.C(y) ) =>
+ { s.set(()); state(state.C(x)) } })
+ );
+
+ state(state.C(init));
+
+ def Get: a = get(get.C());
+ def Set(x: a): unit = set(set.C(x));
+}
+*/
+object RefTest {
+
+ def main(args: Array[String]) = {
+ System.out.println("Started.");
+/*
+ concurrent.ops.spawn({
+ val r1 = new Ref(0);
+ System.out.println("Reference r1 created.");
+ System.out.println("Value r1 (first time) = " + r1.Get);
+ r1.Set(42);
+ System.out.println("Value r1 (second time) = " + r1.Get);
+ });
+ concurrent.ops.spawn({
+ val r2 = new Ref(100);
+ System.out.println("Reference r2 created.");
+ System.out.println("Value r2 (first time) = " + r2.Get);
+ r2.Set(89);
+ System.out.println("Value r2 (second time) = " + r2.Get);
+ });
+*/
+ }
+
+}
diff --git a/docs/examples/jolib/parallelOr.scala b/docs/examples/jolib/parallelOr.scala
new file mode 100644
index 0000000000..bff4dcd87a
--- /dev/null
+++ b/docs/examples/jolib/parallelOr.scala
@@ -0,0 +1,59 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package examples.jolib;
+/*
+import concurrent.jolib._;
+import concurrent.SyncVar;
+
+/** Implementation in the join-calculus of a parallel OR. */
+object or extends Join {
+
+ object res extends Synchr[boolean](this) { case class C() extends SyncVar[boolean] };
+ object res1 extends Asynchr(this) { case class C(b: boolean); }
+ object res2 extends Asynchr(this) { case class C(b: boolean); }
+ object res1False extends Synchr[boolean](this) { case class C() extends SyncVar[boolean] };
+ object res2False extends Synchr[boolean](this) { case class C() extends SyncVar[boolean] };
+
+ rules(
+ Pair(List(res, res1), { case List(r @ res.C(), res1.C(b)) =>
+ if (b) r.set(b) else r.set(res1False(res1False.C())) }),
+
+ Pair(List(res, res2), { case List(r @ res.C(), res2.C(b)) =>
+ if (b) r.set(b) else r.set(res2False(res2False.C())) }),
+
+ Pair(List(res1False, res2), { case List(r @ res1False.C(), res2.C(b)) =>
+ r.set(b) }),
+
+ Pair(List(res2False, res1), { case List(r @ res2False.C(), res1.C(b)) =>
+ r.set(b) })
+ );
+
+ def apply(b1: => boolean, b2: => boolean): boolean = {
+ concurrent.ops.spawn(res1(res1.C(b1)));
+ concurrent.ops.spawn(res2(res2.C(b2)));
+ res(res.C())
+ }
+}
+*/
+object parallelOr {
+
+ def main(args: Array[String]): unit = {
+ def loop: boolean = { while (true) {}; true };
+/*
+ System.out.println("true || true = " + or(true, true));
+ System.out.println("false || false = " + or(false, false));
+ System.out.println("false || true = " + or(false, true));
+ System.out.println("true || false = " + or(true, false));
+ System.out.println("true || loop = " + or(true, loop));
+ System.out.println("loop || true = " + or(loop, true));
+*/
+ }
+
+}
diff --git a/docs/examples/maps.scala b/docs/examples/maps.scala
new file mode 100644
index 0000000000..87489d496d
--- /dev/null
+++ b/docs/examples/maps.scala
@@ -0,0 +1,192 @@
+package examples;
+
+object maps {
+
+ import scala.collection.immutable._;
+
+ trait MapStruct[kt, vt] {
+ trait Map with Function1[kt, vt] {
+ def extend(key: kt, value: vt): Map;
+ def remove(key: kt): Map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ type map <: Map;
+ val empty: map;
+ }
+
+ class AlgBinTree[kt <: Ordered[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = AlgMap;
+
+ val empty: AlgMap = Empty();
+
+ private case class
+ Empty(),
+ Node(key: kt, value: vt, l: map, r: map) extends AlgMap {}
+
+ trait AlgMap extends Map {
+ def apply(key: kt): vt = this match {
+ case Empty() => null
+ case Node(k, v, l, r) =>
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v
+ }
+
+ def extend(key: kt, value: vt): map = this match {
+ case Empty()=> Node(key, value, empty, empty)
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.extend(key, value), r)
+ else if (key > k) Node(k, v, l, r.extend(key, value))
+ else Node(k, value, l, r)
+ }
+
+ def remove(key: kt): map = this match {
+ case Empty()=> empty
+ case Node(k, v, l, r) =>
+ if (key < k) Node(k, v, l.remove(key), r)
+ else if (key > k) Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ Node(midKey, r.apply(midKey), l, r.remove(midKey))
+ }
+ }
+
+ def domain: Stream[kt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.domain append Stream.cons(k, r.domain)
+ }
+
+ def range: Stream[vt] = this match {
+ case Empty()=> Stream.empty
+ case Node(k, v, l, r) => l.range append Stream.cons(v, r.range)
+ }
+ }
+ }
+
+ class OOBinTree[kt <: Ordered[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = OOMap;
+
+ trait OOMap extends Map {
+ def apply(key: kt): vt;
+ def extend(key: kt, value: vt): map;
+ def remove(key: kt): map;
+ def domain: Stream[kt];
+ def range: Stream[vt];
+ }
+ val empty: OOMap = new OOMap {
+ def apply(key: kt): vt = null;
+ def extend(key: kt, value: vt) = new Node(key, value, empty, empty);
+ def remove(key: kt) = empty;
+ def domain: Stream[kt] = Stream.empty;
+ def range: Stream[vt] = Stream.empty;
+ }
+ private class Node(k: kt, v: vt, l: map, r: map) extends OOMap {
+ def apply(key: kt): vt =
+ if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+ def extend(key: kt, value: vt): map =
+ if (key < k) new Node(k, v, l.extend(key, value), r)
+ else if (key > k) new Node(k, v, l, r.extend(key, value))
+ else new Node(k, value, l, r);
+ def remove(key: kt): map =
+ if (key < k) new Node(k, v, l.remove(key), r)
+ else if (key > k) new Node(k, v, l, r.remove(key))
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ val midKey = r.domain.head;
+ new Node(midKey, r(midKey), l, r.remove(midKey))
+ }
+ def domain: Stream[kt] = l.domain append Stream.cons(k, r.domain);
+ def range: Stream[vt] = l.range append Stream.cons(v, r.range);
+ }
+ }
+
+ class MutBinTree[kt <: Ordered[kt], vt <: AnyRef]() extends MapStruct[kt, vt] {
+ type map = MutMap;
+ class MutMap(key: kt, value: vt) extends Map {
+ val k = key;
+ var v = value;
+ var l, r = empty;
+
+ def apply(key: kt): vt =
+ if (this == empty) null
+ else if (key < k) l.apply(key)
+ else if (key > k) r.apply(key)
+ else v;
+
+ def extend(key: kt, value: vt): map =
+ if (this == empty) new MutMap(key, value)
+ else {
+ if (key < k) l = l.extend(key, value)
+ else if (key > k) r = r.extend(key, value)
+ else v = value;
+ this
+ }
+
+ def remove(key: kt): map =
+ if (this == empty) this
+ else if (key < k) { l = l.remove(key) ; this }
+ else if (key > k) { r = r.remove(key) ; this }
+ else if (l == empty) r
+ else if (r == empty) l
+ else {
+ var mid = r;
+ while (!(mid.l == empty)) { mid = mid.l }
+ mid.r = r.remove(mid.k);
+ mid.l = l;
+ mid
+ }
+
+ def domain: Stream[kt] =
+ if (this == empty) Stream.empty;
+ else l.domain append Stream.cons(k, r.domain);
+
+ def range: Stream[vt] =
+ if (this == empty) Stream.empty;
+ else l.range append Stream.cons(v, r.range);
+ }
+ val empty = new MutMap(null, null);
+ }
+
+ class Date(y: Int, m: Int, d: Int) with Ordered[Date] {
+ def year = y;
+ def month = m;
+ def day = d;
+
+ def compareTo[b >: Date <% Ordered[b]](that: b): int = that match {
+ case other: Date =>
+ if ((year == other.year) &&
+ (month == other.month) &&
+ (day == other.day))
+ 0
+ else if ((year < other.year) ||
+ (year == other.year && month < other.month) ||
+ (month == other.month && day < other.day))
+ -1
+ else
+ 1
+ case _ =>
+ -(that compareTo this)
+ }
+
+ override def equals(that: Any): Boolean =
+ that.isInstanceOf[Date] && {
+ val o = that.asInstanceOf[Date];
+ day == o.day && month == o.month && year == o.year
+ }
+ }
+
+ def main(args: Array[String]) = {
+ val t = new OOBinTree[Date, String]();
+ ()
+ }
+
+}
+
+
+
diff --git a/docs/examples/mobile/sort.scala b/docs/examples/mobile/sort.scala
new file mode 100644
index 0000000000..62818467fa
--- /dev/null
+++ b/docs/examples/mobile/sort.scala
@@ -0,0 +1,17 @@
+package examples.mobile;
+
+import java.net._;
+import scala.mobile._;
+
+
+object sort with Application {
+ val url = new URL("http://scala.epfl.ch/classes/examples.jar");
+
+ val location = new Location(url);
+ val obj = location create "examples.sort";
+ val ar = Array(6, 2, 8, 5, 1);
+ obj[Array[Int], Unit]("println")(ar);
+ obj[Array[Int], Unit]("sort")(ar);
+ obj[Array[Int], Unit]("println")(ar);
+ Console.println
+}
diff --git a/docs/examples/monads/callccInterpreter.scala b/docs/examples/monads/callccInterpreter.scala
new file mode 100644
index 0000000000..934fce1a9e
--- /dev/null
+++ b/docs/examples/monads/callccInterpreter.scala
@@ -0,0 +1,84 @@
+object callccInterpreter {
+
+ type Answer = Value;
+
+ case class M[A](in: (A => Answer) => Answer) {
+ def bind[B](k: A => M[B]) = M[B](c => in (a => k(a) in c));
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A) = M[A](c => c(a));
+
+ def showM(m: M[Value]): String = (m in id).toString();
+
+ def callCC[A](h: (A => M[A]) => M[A]) =
+ M[A](c => h(a => M[A](d => c(a))) in c);
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+ case class Ccc(x: Name, t: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => unitM(Wrong)
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => unitM(Wrong)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => unitM(Wrong)
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ case Ccc(x, t) => callCC(k => interp(t, Pair(x, Fun(k)) :: e))
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+ val term2 = Add(Con(1), Ccc("k", Add(Con(2), App(Var("k"), Con(4)))));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ System.out.println(test(term2));
+ }
+}
+
diff --git a/docs/examples/monads/directInterpreter.scala b/docs/examples/monads/directInterpreter.scala
new file mode 100644
index 0000000000..0e2aae4a7b
--- /dev/null
+++ b/docs/examples/monads/directInterpreter.scala
@@ -0,0 +1,55 @@
+object directInterpreter {
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value;
+ case class Num(n: int) extends Value;
+ case class Fun(f: Value => Value)extends Value;
+
+ def showval(v: Value): String = v match {
+ case Wrong => "<wrong>"
+ case Num(n) => n.toString()
+ case Fun(f) => "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): Value = e match {
+ case List() => Wrong
+ case Pair(y, b) :: e1 => if (x == y) b else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): Value = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => Num(m + n)
+ case _ => Wrong
+ }
+
+ def apply(a: Value, b: Value) = a match {
+ case Fun(k) => k(b)
+ case _ => Wrong
+ }
+
+ def interp(t: Term, e: Environment): Value = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => Num(n)
+ case Add(l, r) => add(interp(l, e), interp(r, e))
+ case Lam(x, t) => Fun(a => interp(t, Pair(x, a) :: e))
+ case App(f, t) => apply(interp(f, e), interp(t, e))
+ }
+
+ def test(t: Term): String =
+ showval(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+
+ def main(args: Array[String]) =
+ System.out.println(test(term0));
+}
diff --git a/docs/examples/monads/errorInterpreter.scala b/docs/examples/monads/errorInterpreter.scala
new file mode 100644
index 0000000000..05dc979621
--- /dev/null
+++ b/docs/examples/monads/errorInterpreter.scala
@@ -0,0 +1,86 @@
+object errorInterpreter {
+
+ trait M[A] {
+ def show: String;
+ def bind[B](k: A => M[B]);
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A): M[A] = new Suc(a);
+ def errorM[A](msg: String): M[A] = new Err(msg);
+
+ def showM(m: M[Value]): String = m.show;
+
+ class Suc[A](x: T) extends M[A] {
+ def bind[A](k: A => M[B]): M[B] = k(x);
+ def show: String = "Success: " + x;
+ }
+ class Err[T](msg: String) extends M[T] {
+ def bind[A](k: A => M[B]): M[B] = new Err(msg);
+ def show: String = "Error: " + msg;
+ }
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => errorM("unbound variable: " + x);
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => errorM("should be numbers: " + a + "," + b)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => errorM("should be function: " + a);
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ }
+}
+
diff --git a/docs/examples/monads/simpleInterpreter.scala b/docs/examples/monads/simpleInterpreter.scala
new file mode 100644
index 0000000000..d728c620cf
--- /dev/null
+++ b/docs/examples/monads/simpleInterpreter.scala
@@ -0,0 +1,75 @@
+object simpleInterpreter {
+
+ case class M[A](value: A) {
+ def bind[B](k: A => M[B]): M[B] = k(value);
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A): M[A] = M(a);
+
+ def showM(m: M[Value]): String = m.value.toString();
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => unitM(Wrong)
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => unitM(Num(m + n))
+ case _ => unitM(Wrong)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => k(b)
+ case _ => unitM(Wrong)
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ }
+}
+
diff --git a/docs/examples/monads/stateInterpreter.scala b/docs/examples/monads/stateInterpreter.scala
new file mode 100644
index 0000000000..593f2d9e3e
--- /dev/null
+++ b/docs/examples/monads/stateInterpreter.scala
@@ -0,0 +1,86 @@
+package examples.monads;
+
+object stateInterpreter {
+
+ type State = int;
+
+ val tickS = new M(s => Pair((), s + 1));
+
+ case class M[A](in: State => Pair[A, State]) {
+ def bind[B](k: A => M[B]) = M[B]{ s0 =>
+ val Pair(a, s1) = this in s0; k(a) in s1
+ }
+ def map[B](f: A => B): M[B] = bind(x => unitM(f(x)));
+ def flatMap[B](f: A => M[B]): M[B] = bind(f);
+ }
+
+ def unitM[A](a: A) = M[A](s => Pair(a, s));
+
+ def showM(m: M[Value]): String = {
+ val Pair(a, s1) = m in 0;
+ "Value: " + a + "; Count: " + s1
+ }
+
+ type Name = String;
+
+ trait Term;
+ case class Var(x: Name) extends Term;
+ case class Con(n: int) extends Term;
+ case class Add(l: Term, r: Term) extends Term;
+ case class Lam(x: Name, body: Term) extends Term;
+ case class App(fun: Term, arg: Term) extends Term;
+
+ trait Value;
+ case object Wrong extends Value {
+ override def toString() = "wrong"
+ }
+ case class Num(n: int) extends Value {
+ override def toString() = n.toString();
+ }
+ case class Fun(f: Value => M[Value]) extends Value {
+ override def toString() = "<function>"
+ }
+
+ type Environment = List[Pair[Name, Value]];
+
+ def lookup(x: Name, e: Environment): M[Value] = e match {
+ case List() => unitM(Wrong)
+ case Pair(y, b) :: e1 => if (x == y) unitM(b) else lookup(x, e1)
+ }
+
+ def add(a: Value, b: Value): M[Value] = Pair(a, b) match {
+ case Pair(Num(m), Num(n)) => for (val _ <- tickS) yield Num(m + n)
+ case _ => unitM(Wrong)
+ }
+
+ def apply(a: Value, b: Value): M[Value] = a match {
+ case Fun(k) => for (val _ <- tickS; val c <- k(b)) yield c
+ case _ => unitM(Wrong)
+ }
+
+ def interp(t: Term, e: Environment): M[Value] = t match {
+ case Var(x) => lookup(x, e)
+ case Con(n) => unitM(Num(n))
+ case Add(l, r) => for (val a <- interp(l, e);
+ val b <- interp(r, e);
+ val c <- add(a, b))
+ yield c
+ case Lam(x, t) => unitM(Fun(a => interp(t, Pair(x, a) :: e)))
+ case App(f, t) => for (val a <- interp(f, e);
+ val b <- interp(t, e);
+ val c <- apply(a, b))
+ yield c
+ }
+
+ def test(t: Term): String =
+ showM(interp(t, List()));
+
+ val term0 = App(Lam("x", Add(Var("x"), Var("x"))), Add(Con(10), Con(11)));
+ val term1 = App(Con(1), Con(2));
+
+ def main(args: Array[String]) = {
+ System.out.println(test(term0));
+ System.out.println(test(term1));
+ }
+}
+
diff --git a/docs/examples/oneplacebuffer.scala b/docs/examples/oneplacebuffer.scala
new file mode 100644
index 0000000000..7fa2ae8dba
--- /dev/null
+++ b/docs/examples/oneplacebuffer.scala
@@ -0,0 +1,47 @@
+package examples;
+
+object oneplacebuffer {
+
+ import scala.concurrent._;
+
+ class OnePlaceBuffer {
+ private val m = new MailBox() {}; // An internal mailbox
+ private case class Empty(), Full(x: Int); // Types of messages we deal with
+
+ m send Empty(); // Initialization
+
+ def write(x: Int): Unit = m receive {
+ case Empty() =>
+ Console.println("put " + x);
+ m send Full(x)
+ }
+
+ def read: Int = m receive {
+ case Full(x) =>
+ Console.println("get " + x);
+ m send Empty() ; x
+ }
+ }
+
+ def main(args: Array[String]) = {
+ val buf = new OnePlaceBuffer;
+ val random = new java.util.Random();
+
+ def producer(n: int): unit = {
+ Thread.sleep(random.nextInt(1000));
+ buf.write(n);
+ producer(n + 1)
+ }
+
+ def consumer: unit = {
+ Thread.sleep(random.nextInt(1000));
+ val n = buf.read;
+ consumer
+ }
+
+ ops.spawn(producer(0));
+ ops.spawn(consumer)
+ }
+
+}
+
diff --git a/docs/examples/parsers1.scala b/docs/examples/parsers1.scala
new file mode 100644
index 0000000000..143f354049
--- /dev/null
+++ b/docs/examples/parsers1.scala
@@ -0,0 +1,118 @@
+package examples;
+
+object parsers1 {
+
+ abstract class Parsers {
+
+ type inputType;
+
+ abstract class Parser {
+
+ type Result = Option[inputType];
+
+ def apply(in: inputType): Result;
+
+ /*** p &&& q applies first p, and if that succeeds, then q
+ */
+ def &&& (q: => Parser) = new Parser {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(in1) => q(in1)
+ }
+ }
+
+ /*** p ||| q applies first p, and, if that fails, then q.
+ */
+ def ||| (q: => Parser) = new Parser {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => q(in)
+ case s => s
+ }
+ }
+ }
+
+ val empty = new Parser {
+ def apply(in: inputType): Result = Some(in)
+ }
+
+ val fail = new Parser {
+ def apply(in: inputType): Result = None
+ }
+
+ def opt(p: Parser): Parser = p ||| empty; // p? = (p | <empty>)
+ def rep(p: Parser): Parser = opt(rep1(p)); // p* = [p+]
+ def rep1(p: Parser): Parser = p &&& rep(p); // p+ = p p*
+ }
+
+ abstract class ListParsers extends Parsers {
+ def chr(p: char => boolean): Parser;
+ def chr(c: char): Parser = chr(d: char => d == c);
+
+ def letter : Parser = chr(Character.isLetter);
+ def digit : Parser = chr(Character.isDigit);
+
+ def ident : Parser = letter &&& rep(letter ||| digit);
+ def number : Parser = digit &&& rep(digit);
+ def list : Parser = chr('(') &&& listElems &&& chr(')');
+ def listElems : Parser = expr &&& (chr(',') &&& listElems ||| empty);
+ def expr : Parser = ident ||| number ||| list;
+ }
+
+ abstract class ExprParsers extends Parsers {
+ def chr(p: char => boolean): Parser;
+ def chr(c: char): Parser = chr(d: char => d == c);
+
+ def digit : Parser = chr(Character.isDigit);
+ def number : Parser = digit &&& rep(digit);
+ def summand : Parser = number ||| chr('(') &&& expr &&& chr(')');
+ def expr : Parser = summand &&& rep(chr('+') &&& summand)
+ }
+
+ class ParseString(s: String) extends Parsers {
+ type inputType = int;
+ val input = 0;
+ def chr(p: char => boolean) = new Parser {
+ def apply(in: int): Parser#Result =
+ if (in < s.length() && p(s charAt in)) Some(in + 1);
+ else None;
+ }
+ }
+
+ object TestList {
+
+ def main(args: Array[String]): unit =
+ if (args.length == 1) {
+ val ps = new ListParsers with ParseString(args(0));
+ ps.expr(ps.input) match {
+ case Some(n) =>
+ Console.println("parsed: " + args(0).substring(0, n));
+ case None =>
+ Console.println("nothing parsed");
+ }
+ }
+ else
+ Console.println("usage: java examples.TestList <expr-string>");
+ }
+
+ object TestExpr {
+
+ def main(args: Array[String]): unit =
+ if (args.length == 1) {
+ val ps = new ExprParsers with ParseString(args(0));
+ ps.expr(ps.input) match {
+ case Some(n) =>
+ Console.println("parsed: " + args(0).substring(0, n));
+ case None =>
+ Console.println("nothing parsed");
+ }
+ }
+ else
+ Console.println("usage: java examples.TestExpr <expr-string>");
+ }
+
+ def main(args: Array[String]): Unit = {
+ TestList.main(Array("(a,b,(1,2))"));
+ TestExpr.main(Array("2+3+(4+1)"))
+ }
+
+}
diff --git a/docs/examples/parsers2.scala b/docs/examples/parsers2.scala
new file mode 100644
index 0000000000..47fa8d0f2e
--- /dev/null
+++ b/docs/examples/parsers2.scala
@@ -0,0 +1,63 @@
+package examples;
+
+object parsers2 {
+
+ abstract class Tree{}
+ case class Id (s: String) extends Tree {}
+ case class Num(n: int) extends Tree {}
+ case class Lst(elems: List[Tree]) extends Tree {}
+
+ abstract class ListParsers extends CharParsers {
+
+ def ident: Parser[Tree] =
+ for (
+ val c: char <- chr(Character.isLetter);
+ val cs: List[char] <- rep(chr(Character.isLetterOrDigit))
+ ) yield Id((c :: cs).mkString("", "", ""));
+
+ def number: Parser[Tree] =
+ for (
+ val d: char <- chr(Character.isDigit);
+ val ds: List[char] <- rep(chr(Character.isDigit))
+ ) yield Num(((d - '0') /: ds) ((x, digit) => x * 10 + digit - '0'));
+
+ def list: Parser[Tree] =
+ for (
+ val _ <- chr('(');
+ val es <- listElems ||| succeed(List());
+ val _ <- chr(')')
+ ) yield Lst(es);
+
+ def listElems: Parser[List[Tree]] =
+ for (
+ val x <- expr;
+ val xs <- chr(',') &&& listElems ||| succeed(List())
+ ) yield x :: xs;
+
+ def expr: Parser[Tree] =
+ list ||| ident ||| number;
+
+ }
+
+ class ParseString(s: String) extends Parsers {
+ type inputType = int;
+ val input = 0;
+ def any = new Parser[char] {
+ def apply(in: int): Parser[char]#Result =
+ if (in < s.length()) Some(Pair(s charAt in, in + 1)) else None;
+ }
+ }
+
+ def main(args: Array[String]): unit =
+ Console.println(
+ if (args.length == 1) {
+ val ps = new ListParsers with ParseString(args(0));
+ ps.expr(ps.input) match {
+ case Some(Pair(list, _)) => Console.println("parsed: " + list);
+ case None => "nothing parsed"
+ }
+ } else "usage: scala examples.parsers2 <expr-string>"
+ );
+
+}
+
diff --git a/docs/examples/patterns.scala b/docs/examples/patterns.scala
new file mode 100644
index 0000000000..34b0db96ae
--- /dev/null
+++ b/docs/examples/patterns.scala
@@ -0,0 +1,35 @@
+package examples;
+
+object patterns {
+
+ trait Tree;
+ case class Branch(left: Tree, right: Tree) extends Tree;
+ case class Leaf(x: Int) extends Tree;
+
+ val tree1 = Branch(Branch(Leaf(1), Leaf(2)), Branch(Leaf(3), Leaf(4)));
+
+ def sumLeaves(t: Tree): Int = t match {
+ case Branch(l, r) => sumLeaves(l) + sumLeaves(r)
+ case Leaf(x) => x
+ }
+
+ def find[a,b](it: Iterator[Pair[a, b]], x: a): Option[b] = {
+ var result: Option[b] = _;
+ while (it.hasNext && result == null) {
+ val Pair(x1, y) = it.next;
+ if (x == x1) result = Some(y)
+ }
+ if (result == null) None else result
+ }
+
+ def printFinds[a](xs: List[Pair[a, String]], x: a) =
+ find(xs.elements, x) match {
+ case Some(y) => System.out.println(y)
+ case None => System.out.println("no match")
+ }
+
+ def main(args: Array[String]): Unit = {
+ Console.println("sum of leafs=" + sumLeaves(tree1));
+ printFinds(List(Pair(3, "three"), Pair(4, "four")), 4)
+ }
+} \ No newline at end of file
diff --git a/docs/examples/pilib/elasticBuffer.scala b/docs/examples/pilib/elasticBuffer.scala
new file mode 100644
index 0000000000..5e52a0fdce
--- /dev/null
+++ b/docs/examples/pilib/elasticBuffer.scala
@@ -0,0 +1,77 @@
+package examples.pilib;
+
+object elasticBuffer {
+
+ import scala.concurrent.pilib._;
+
+ /**
+ * Recursive type for channels that carry a "String" channel and
+ * an object of the type we define.
+ */
+ class MetaChan extends Chan[Pair[Chan[String], MetaChan]];
+
+ def Buffer(put: Chan[String], get: Chan[String]): unit = {
+
+ /**
+ * An empty buffer cell, ready to pass on (o,r) to the left.
+ */
+ def Bl(i:Chan[String], l: MetaChan,
+ o: Chan[String], r: MetaChan): unit =
+ choice (
+ l(Pair(o,r)) * (System.out.println("Removed one cell.")),
+ i * (inp => Cl(i, l, o, r, inp))
+ );
+
+ /**
+ * A buffer cell containing a value, ready to receive (o,r) from the right.
+ */
+ def Cl(i: Chan[String], l: MetaChan,
+ o: Chan[String], r: MetaChan, content: String): unit =
+ choice (
+ o(content) * (Bl(i,l,o,r)),
+ i * (inp => Dl(i,l,o,r,content, inp)),
+ r * ( { case Pair(newo, newr) => Cl(i,l,newo,newr,content) })
+ );
+
+ /**
+ * Two joined buffer cells, of type Cl.
+ */
+ def Dl(i: Chan[String], l: MetaChan,
+ o: Chan[String], r: MetaChan,
+ content: String, inp: String): unit = {
+ val newlr = new MetaChan;
+ val newio = new Chan[String];
+ spawn < Cl(i, l, newio, newlr, inp) | Cl(newio, newlr, o, r,content) >;
+ }
+
+ // l and r channels for the leftmost and rightmost cell, respectively.
+ val unused1 = new MetaChan;
+ val unused2 = new MetaChan;
+
+ Bl(put, unused1, get, unused2);
+ }
+
+ val random = new java.util.Random();
+
+ def Producer(n: int, put: Chan[String]): unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ val msg = "object " + n;
+ put.write(msg);
+ System.out.println("Producer gave " + msg);
+ Producer(n + 1, put)
+ }
+
+ def Consumer(get: Chan[String]): unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ val msg = get.read;
+ System.out.println("Consummer took " + msg);
+ Consumer(get)
+ }
+
+ def main(args: Array[String]): unit = {
+ val put = new Chan[String];
+ val get = new Chan[String];
+ spawn < Producer(0, put) | Consumer(get) | Buffer(put, get) >
+ }
+
+}
diff --git a/docs/examples/pilib/handover.scala b/docs/examples/pilib/handover.scala
new file mode 100644
index 0000000000..85fb899555
--- /dev/null
+++ b/docs/examples/pilib/handover.scala
@@ -0,0 +1,190 @@
+package examples.pilib;
+
+/**
+* Handover example with recursive types for channels.
+*/
+object handoverRecursive {
+
+ import concurrent.pilib._;
+
+ val random = new java.util.Random();
+
+ /**
+ * Recursive type for channels that carry a channel "unit" and
+ * an object of the type we define.
+ */
+ class Switch extends Chan[Pair[Chan[unit], Switch]];
+
+ /**
+ * Car.
+ */
+ def Car(talk: Chan[unit], switch: Switch): unit =
+ choice (
+ switch * ({ case Pair(t,s) => Car(t, s) }),
+ talk(()) * ( {
+ Thread.sleep(1 + random.nextInt(1000));
+ System.out.println("Car emitted a message.");
+ Car(talk, switch)
+ })
+ );
+
+ /**
+ * Control center.
+ */
+ def Control(talk1: Chan[unit], switch1: Switch,
+ gain1: Switch, lose1: Switch,
+ talk2: Chan[unit], switch2: Switch,
+ gain2: Switch, lose2: Switch): unit
+ = {
+ def Control1: unit= {
+ Thread.sleep(1 + random.nextInt(1000));
+ lose1.write(Pair(talk2, switch2));
+ gain2.write(Pair(talk2, switch2));
+ Control2;
+ }
+ def Control2: unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ lose2.write(Pair(talk1, switch1));
+ gain1.write(Pair(talk1, switch1));
+ Control1;
+ }
+ Control1;
+ }
+
+ /**
+ * Active transmitter.
+ */
+ def ActiveTransmitter(id: String, talk: Chan[unit], switch: Switch,
+ gain: Switch, lose: Switch): unit
+ =
+ choice (
+ talk * (x => {
+ System.out.println(id + " received a message.");
+ ActiveTransmitter(id, talk, switch, gain, lose)
+ }),
+ lose * ({ case Pair(t, s) => {
+ switch.write(Pair(t, s));
+ IdleTransmitter(id, gain, lose)
+ }})
+ );
+
+ /**
+ * Idle transmitter.
+ */
+ def IdleTransmitter(id: String, gain: Switch, lose: Switch): unit = {
+ val Pair(t, s) = gain.read;
+ ActiveTransmitter(id, t, s, gain, lose)
+ }
+
+ def main(args: Array[String]): unit = {
+ val talk1 = new Chan[unit];
+ val switch1 = new Switch;
+ val gain1 = new Switch;
+ val lose1 = new Switch;
+ val talk2 = new Chan[unit];
+ val switch2 = new Switch;
+ val gain2 = new Switch;
+ val lose2 = new Switch;
+ spawn <
+ Car(talk1, switch1) |
+ ActiveTransmitter("Transmitter 1", talk1, switch1, gain1, lose1) |
+ IdleTransmitter("Transmitter 2", gain2, lose2) |
+ Control(talk1, switch1, gain1, lose1, talk2, switch2, gain2, lose2)
+ >
+ }
+}
+
+/**
+* Handover example with type casts.
+*/
+object handoverCast {
+
+ import concurrent.pilib._;
+
+ val random = new java.util.Random();
+
+ /**
+ * Car.
+ */
+ def Car(talk: Chan[Any], switch: Chan[Any]): unit =
+ choice (
+ switch * (o => {
+ val Pair(t,s) = o.asInstanceOf[Pair[Chan[Any],Chan[Any]]];
+ Car(t, s)
+ }),
+ talk(()) * ( {
+ Thread.sleep(1 + random.nextInt(1000));
+ System.out.println("Car emitted a message.");
+ Car(talk, switch)
+ })
+ );
+
+ /**
+ * Control center.
+ */
+ def Control(talk1: Chan[Any], switch1: Chan[Any],
+ gain1: Chan[Any], lose1: Chan[Any],
+ talk2: Chan[Any], switch2: Chan[Any],
+ gain2: Chan[Any], lose2: Chan[Any]): unit
+ = {
+ def Control1: unit= {
+ Thread.sleep(1 + random.nextInt(1000));
+ lose1.write(Pair(talk2, switch2));
+ gain2.write(Pair(talk2, switch2));
+ Control2
+ }
+ def Control2: unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ lose2.write(Pair(talk1, switch1));
+ gain1.write(Pair(talk1, switch1));
+ Control1
+ }
+ Control1
+ }
+
+ /**
+ * Active transmitter.
+ */
+ def ActiveTransmitter(id: String, talk: Chan[Any], switch: Chan[Any],
+ gain: Chan[Any], lose: Chan[Any]): unit
+ =
+ choice (
+ talk * (x => {
+ System.out.println(id + " received a message.");
+ ActiveTransmitter(id, talk, switch, gain, lose)
+ }),
+ lose * (o => {
+ val Pair(t, s) = o.asInstanceOf[Pair[Chan[Any],Chan[Any]]];
+ switch.write(Pair(t, s));
+ IdleTransmitter(id, gain, lose)
+ })
+ );
+
+ /**
+ * Idle transmitter.
+ */
+ def IdleTransmitter(id: String, gain: Chan[Any], lose: Chan[Any]): unit = {
+ val Pair(t, s) = gain.read.asInstanceOf[Pair[Chan[Any],Chan[Any]]];
+ ActiveTransmitter(id, t, s, gain, lose)
+ }
+
+ def main(args: Array[String]): unit = {
+ val talk1 = new Chan[Any];
+ val switch1 = new Chan[Any];
+ val gain1 = new Chan[Any];
+ val lose1 = new Chan[Any];
+ val talk2 = new Chan[Any];
+ val switch2 = new Chan[Any];
+ val gain2 = new Chan[Any];
+ val lose2 = new Chan[Any];
+ spawn <
+ Car(talk1, switch1) |
+ ActiveTransmitter("Transmitter 1", talk1, switch1, gain1, lose1) |
+ IdleTransmitter("Transmitter 2", gain2, lose2) |
+ Control(talk1, switch1, gain1, lose1, talk2, switch2, gain2, lose2)
+ >
+ }
+
+}
+
+
diff --git a/docs/examples/pilib/mobilePhoneProtocol.scala b/docs/examples/pilib/mobilePhoneProtocol.scala
new file mode 100644
index 0000000000..0b13f78fd3
--- /dev/null
+++ b/docs/examples/pilib/mobilePhoneProtocol.scala
@@ -0,0 +1,172 @@
+package examples.pilib;
+
+/**
+* Mobile phone protocol.
+* Equivalent to a three-place buffer.
+* @see Bjoern Victor "A verification tool for the polyadic pi-calculus".
+*/
+object mobilePhoneProtocol {
+
+ import concurrent.pilib._;
+
+ val random = new java.util.Random();
+
+ // Internal messages exchanged by the protocol.
+ trait Message;
+
+ // Predefined messages used by the protocol.
+ case class Data() extends Message;
+ case class HoCmd() extends Message; // handover command
+ case class HoAcc() extends Message; // handover access
+ case class HoCom() extends Message; // handover complete
+ case class HoFail() extends Message; // handover fail
+ case class ChRel() extends Message; // release
+ case class Voice(s: String) extends Message; // voice
+ case class Channel(n: Chan[Message]) extends Message; // channel
+
+ def MobileSystem(in: Chan[String], out: Chan[String]): unit = {
+
+ def CC(fa: Chan[Message], fp: Chan[Message], l: Chan[Channel]): unit =
+ choice (
+ in * (v => { fa.write(Data()); fa.write(Voice(v)); CC(fa, fp, l) })
+ ,
+ l * (m_new => {
+ fa.write(HoCmd());
+ fa.write(m_new);
+ choice (
+ fp * ({ case HoCom() => {
+ System.out.println("Mobile has moved from one cell to another");
+ fa.write(ChRel());
+ val Channel(m_old) = fa.read;
+ l.write(Channel(m_old));
+ CC(fp, fa, l)
+ }})
+ ,
+ fa * ({ case HoFail() => {
+ System.out.println("Mobile has failed to move from one cell to another");
+ l.write(m_new);
+ CC(fa, fp, l)
+ }})
+ )
+ })
+ );
+
+ /*
+ * Continuously orders the MSC to switch the MS to the non-used BS.
+ */
+ def HC(l: Chan[Channel], m: Chan[Message]): unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ l.write(Channel(m));
+ val Channel(m_new) = l.read;
+ HC(l, m_new)
+ }
+
+ /**
+ * Mobile switching center.
+ */
+ def MSC(fa: Chan[Message], fp: Chan[Message], m: Chan[Message]): unit = {
+ val l = new Chan[Channel];
+ spawn < HC(l, m) | CC(fa, fp, l) >
+ }
+
+ /**
+ * Active base station.
+ */
+ def BSa(f: Chan[Message], m: Chan[Message]): unit =
+ (f.read) match {
+ case Data() => {
+ val v = f.read;
+ m.write(Data());
+ m.write(v);
+ BSa(f, m)
+ }
+ case HoCmd() => {
+ val v = f.read;
+ m.write(HoCmd());
+ m.write(v);
+ choice (
+ f * ({ case ChRel() => {
+ f.write(Channel(m));
+ BSp(f, m)
+ }})
+ ,
+ m * ({ case HoFail() => {
+ f.write(HoFail());
+ BSa(f, m)
+ }})
+ )
+ }
+ };
+
+ /**
+ * Passive base station.
+ */
+ def BSp(f: Chan[Message], m: Chan[Message]): unit = {
+ val HoAcc = m.read;
+ f.write(HoCom());
+ BSa(f, m)
+ };
+
+ /**
+ * Mobile station.
+ */
+ def MS(m: Chan[Message]): unit =
+ (m.read) match {
+ case Data() => {
+ val Voice(v) = m.read;
+ out.write(v);
+ MS(m)
+ }
+ case HoCmd() =>
+ (m.read) match {
+ case Channel(m_new) => {
+ if (random.nextInt(1) == 0)
+ choice ( m_new(HoAcc()) * (MS(m_new)) );
+ else
+ choice ( m(HoFail()) * (MS(m)) );
+ }
+ }
+ };
+
+ def P(fa: Chan[Message], fp: Chan[Message]): unit = {
+ val m = new Chan[Message];
+ spawn < MSC(fa, fp, m) | BSp(fp, m) >
+ }
+
+ def Q(fa: Chan[Message]): unit = {
+ val m = new Chan[Message];
+ spawn < BSa(fa, m) | MS(m) >
+ }
+
+ val fa = new Chan[Message];
+ val fp = new Chan[Message];
+ spawn < Q(fa) | P(fa, fp) >;
+ }
+
+ //***************** Entry function ******************//
+
+ def main(args: Array[String]): unit = {
+
+ def Producer(n: Int, put: Chan[String]): unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ val msg = "object " + n;
+ put.write(msg);
+ System.out.println("Producer gave " + msg);
+ Producer(n + 1, put)
+ }
+
+ def Consumer(get: Chan[String]): unit = {
+ Thread.sleep(1 + random.nextInt(1000));
+ val msg = get.read;
+ System.out.println("Consummer took " + msg);
+ Consumer(get)
+ }
+
+ val put = new Chan[String];
+ val get = new Chan[String];
+ spawn < Producer(0, put) | Consumer(get) | MobileSystem(put, get) >
+ }
+
+}
+
+
diff --git a/docs/examples/pilib/piNat.scala b/docs/examples/pilib/piNat.scala
new file mode 100644
index 0000000000..137c0e5e6a
--- /dev/null
+++ b/docs/examples/pilib/piNat.scala
@@ -0,0 +1,92 @@
+package examples.pilib;
+
+import scala.concurrent.pilib._;
+//import pilib._;
+
+/** Church encoding of naturals in the Pi-calculus */
+object piNat with Application {
+
+ /** Locations of Pi-calculus natural */
+ class NatChan extends Chan[Triple[Chan[unit], Chan[NatChan], Chan[NatChan]]];
+
+ /** Zero */
+ def Z(l: NatChan): unit = choice (
+ l * { case Triple(z, sd, d) => z.write(()) }
+ );
+
+ /** Successor of Double */
+ def SD(n: NatChan, l: NatChan): unit = choice (
+ l * { case Triple(z, sd, d) => sd.write(n) }
+ );
+
+ /** Double */
+ def D(n: NatChan, l: NatChan): unit = choice (
+ l * { case Triple(z, sd, d) => d.write(n) }
+ );
+
+ /** Make "l" a location representing the natural "n" */
+ def make(n: int, l: NatChan): unit =
+ if (n == 0) Z(l)
+ else if (n % 2 == 0) { val l1 = new NatChan; spawn < D(l1, l) >; make(n/2, l1) }
+ else { val l1 = new NatChan; spawn < SD(l1, l) >; make(n/2, l1) };
+
+ /** Consume the natural "m" and put it successor at location "n" */
+ def Succ(m: NatChan, n: NatChan): unit = {
+ val z = new Chan[unit];
+ val sd = new Chan[NatChan];
+ val d = new Chan[NatChan];
+ spawn < m.write(Triple(z, sd, d)) >;
+ choice (
+ z * { x => make(1, n) },
+ sd * { m1 => { val n1 = new NatChan; spawn < D(n1, n) >; Succ(m1, n1) } },
+ d * { m1 => SD(m1, n) }
+ )
+ }
+
+ /** Consume the natural "l" and put two copies at locations "m" and "n" */
+ def Copy(l: NatChan, m: NatChan, n: NatChan): unit = {
+ val z = new Chan[unit];
+ val sd = new Chan[NatChan];
+ val d = new Chan[NatChan];
+ spawn < l.write(Triple(z, sd, d)) >;
+ choice (
+ z * { x => spawn < Z(m) >; Z(n) },
+ sd * { l1 => { val m1 = new NatChan; val n1 = new NatChan;
+ spawn < SD(m1, m) | SD(n1, n) >;
+ Copy(l1, m1, n1) } },
+ d * { l1 => { val m1 = new NatChan; val n1 = new NatChan;
+ spawn < D(m1, m) | D(n1, n) >;
+ Copy(l1, m1, n1) } }
+ )
+ }
+
+ /** Consume the natural at location "n" and return its value */
+ def value(n: NatChan): int = {
+ val z = new Chan[unit];
+ val sd = new Chan[NatChan];
+ val d = new Chan[NatChan];
+ spawn < n.write(Triple(z, sd, d)) >;
+ choice (
+ z * { x => 0 },
+ sd * { n1 => 2 * value(n1) + 1 },
+ d * { n1 => 2 * value(n1) }
+ )
+ }
+
+ // Test
+ val i = 42;
+ val l = new NatChan;
+ val l1 = new NatChan;
+ val l2 = new NatChan;
+ val l3 = new NatChan;
+
+ spawn <
+ make(i, l) |
+ Copy(l, l1, l2) |
+ Succ(l2, l3) |
+ System.out.println("" + i + " = " + value(l1)) |
+ System.out.println("succ " + i + " = " + value(l3))
+ >;
+
+}
+
diff --git a/docs/examples/pilib/rwlock.scala b/docs/examples/pilib/rwlock.scala
new file mode 100644
index 0000000000..0ed0f71a47
--- /dev/null
+++ b/docs/examples/pilib/rwlock.scala
@@ -0,0 +1,331 @@
+package examples.pilib;
+
+/**
+* From Pi to Scala: Semaphores, monitors, read/write locks.
+* Readers/writers locks.
+*/
+object rwlock {
+
+ import scala.concurrent.pilib._;
+
+ class Signal extends Chan[unit] {
+ def send = write(());
+ def receive = read;
+ }
+
+ class CountLock {
+ private val busy = new Signal;
+ def get = busy.send;
+ def release = busy.receive;
+ spawn < release >
+ }
+
+ /** A binary semaphore
+ */
+ class Lock {
+ private val busy = new Signal;
+ private val free = new Signal;
+ def get = busy.send;
+ def release = free.send;
+ spawn < (while (true) {
+ choice (
+ busy * (x => free.receive),
+ free * (x => ())
+ )
+ })
+ >
+ }
+
+ /** A monitor a la Java
+ */
+ class JavaMonitor {
+
+ private val lock = new Lock;
+
+ private var waiting: List[Signal] = Nil;
+
+ def Wait = {
+ val s = new Signal;
+ waiting = s :: waiting;
+ lock.release;
+ s.receive;
+ lock.get;
+ }
+
+ def Notify = {
+ if (!waiting.isEmpty) {
+ waiting.head.send;
+ waiting = waiting.tail;
+ }
+ }
+
+ def NotifyAll = {
+ while (!waiting.isEmpty) {
+ waiting.head.send;
+ waiting = waiting.tail;
+ }
+ }
+
+ def await(cond: => boolean): unit = while (false == cond) (Wait)
+ }
+
+ /*
+ class Buffer[a](size: Int) extends JavaMonitor with {
+ var in = 0, out = 0, n = 0;
+ val elems = new Array[a](size);
+ def put(x: a) = synchronized {
+ await(n < size);
+ elems(out) = x;
+ out = (out + 1) % size;
+ }
+ def get: a = synchronized {
+ await(n > 0);
+ val x = elems(in);
+ in = (in + 1) % size;
+ x
+ }
+ }
+ */
+
+ /** A readers/writers lock. */
+ trait ReadWriteLock {
+ def startRead: unit;
+ def startWrite: unit;
+ def endRead: unit;
+ def endWrite: unit;
+ }
+
+ /**
+ * A readers/writers lock, using monitor abstractions.
+ */
+ class ReadWriteLock1 extends JavaMonitor with ReadWriteLock {
+
+ private var nactive: int = 0;
+ private var nwriters: int = 0;
+
+ def status =
+ System.out.println(nactive + " active, " + nwriters + " writers");
+
+ def startRead = synchronized {
+ await(nwriters == 0);
+ nactive = nactive + 1;
+ status
+ }
+
+ def startWrite = synchronized {
+ nwriters = nwriters + 1;
+ await(nactive == 0);
+ nactive = 1;
+ status
+ }
+
+ def endRead = synchronized {
+ nactive = nactive - 1;
+ if (nactive == 0) NotifyAll;
+ status
+ }
+
+ def endWrite = synchronized {
+ nwriters = nwriters - 1;
+ nactive = 0;
+ NotifyAll;
+ status
+ }
+ }
+
+ /** A readers/writers lock, using semaphores
+ */
+ class ReadWriteLock2 extends ReadWriteLock {
+
+ private var rc: int = 0; // reading readers
+ private var wc: int = 0; // writing writers
+ private var rwc: int = 0; // waiting readers
+ private var wwc: int = 0; // waiting writers
+ private val mutex = new Lock;
+ private val rsem = new Lock;
+ private val wsem = new Lock;
+
+ def startRead = {
+ mutex.get;
+ if (wwc > 0 || wc > 0) {
+ rwc = rwc + 1;
+ mutex.release;
+ rsem.get;
+ rwc = rwc - 1;
+ }
+ rc = rc + 1;
+ if (rwc > 0) rsem.release;
+ mutex.release
+ }
+
+ def startWrite = {
+ mutex.get;
+ if (rc > 0 || wc > 0) {
+ wwc = wwc + 1;
+ mutex.release;
+ wsem.get;
+ wwc = wwc - 1;
+ }
+ wc = wc + 1;
+ mutex.release;
+ }
+
+ def endRead = {
+ mutex.get;
+ rc = rc - 1;
+ if (rc == 0 && wwc > 0) wsem.release;
+ mutex.release
+ }
+
+ def endWrite = {
+ mutex.get;
+ wc = wc - 1;
+ if (rwc > 0)
+ rsem.release
+ else if (wwc > 0) wsem.release;
+ mutex.release
+ }
+ }
+
+ /** A readers/writers lock, using channels, without priortities
+ */
+ class ReadWriteLock3 extends ReadWriteLock {
+
+ private val sr = new Signal;
+ private val er = new Signal;
+ private val sw = new Signal;
+ private val ew = new Signal;
+
+ def startRead = sr.send;
+ def startWrite = sw.send;
+ def endRead = er.send;
+ def endWrite = ew.send;
+
+ private def rwlock: unit = choice (
+ sr * (x => reading(1)),
+ sw * (x => { ew.receive; rwlock })
+ );
+
+ private def reading(n: int): unit = choice (
+ sr * (x => reading(n+1)),
+ er * (x => if (n == 1) rwlock else reading(n-1))
+ );
+
+ spawn < rwlock >;
+ }
+
+ /** Same, with sequencing
+ */
+ class ReadWriteLock4 extends ReadWriteLock {
+
+ private val rwlock = new ReadWriteLock3;
+
+ private val sr = new Signal;
+ private val ww = new Signal;
+ private val sw = new Signal;
+
+ def startRead = sr.send;
+ def startWrite = { ww.send; sw.send; }
+ def endRead = rwlock.endRead;
+ def endWrite = rwlock.endWrite;
+
+ private def queue: unit = choice (
+ sr * (x => { rwlock.startRead ; queue }),
+ ww * (x => { rwlock.startWrite; sw.receive; queue })
+ );
+
+ spawn < queue >;
+ }
+
+ /** Readwritelock where writers always have priority over readers
+ */
+ class ReadWriteLock5 extends ReadWriteLock {
+
+ private val sr = new Signal;
+ private val er = new Signal;
+ private val ww = new Signal;
+ private val sw = new Signal;
+ private val ew = new Signal;
+
+ def startRead = sr.send;
+ def startWrite = { ww.send; sw.send; }
+ def endRead = er.send;
+ def endWrite = ew.send;
+
+ private def Reading(nr: int, nw: int): unit =
+ if (nr == 0 && nw == 0)
+ choice (
+ sr * (x => Reading(1, 0)),
+ ww * (x => Reading(0, 1))
+ )
+ else if (nr == 0 && nw != 0) {
+ sw.receive;
+ Writing(nw);
+ }
+ else if (nr != 0 && nw == 0)
+ choice (
+ sr * (x => Reading(nr + 1, 0)),
+ er * (x => Reading(nr - 1, 0)),
+ ww * (x => Reading(nr, 1))
+ )
+ else if (nr != 0 && nw != 0)
+ choice (
+ ww * (x => Reading(nr, nw + 1)),
+ er * (x => Reading(nr - 1, nw))
+ );
+
+ private def Writing(nw: int): unit = choice (
+ ew * (x => Reading(0, nw - 1)),
+ ww * (x => Writing(nw + 1))
+ );
+
+ spawn < Reading(0, 0) >;
+
+ }
+
+ /**
+ * Main function.
+ */
+ def main(args: Array[String]): unit = {
+ val random = new java.util.Random();
+
+ def reader(i: int, rwlock: ReadWriteLock): unit = {
+ Thread.sleep(1 + random.nextInt(100));
+ System.err.println("Reader " + i + " wants to read.");
+ rwlock.startRead;
+ System.err.println("Reader " + i + " is reading.");
+ Thread.sleep(1 + random.nextInt(100));
+ rwlock.endRead;
+ System.err.println("Reader " + i + " has read.");
+ reader(i, rwlock)
+ }
+
+ def writer(i: int, rwlock: ReadWriteLock): unit = {
+ Thread.sleep(1 + random.nextInt(100));
+ System.err.println("Writer " + i + " wants to write.");
+ rwlock.startWrite;
+ System.err.println("Writer " + i + " is writing.");
+ Thread.sleep(1 + random.nextInt(100));
+ rwlock.endWrite;
+ System.err.println("Writer " + i + " has written.");
+ writer(i, rwlock)
+ }
+
+ val n = try { Integer.parseInt(args(0)) } catch { case _ => 0 }
+ if (n < 1 || 5 < n) {
+ Console.println("Usage: scala examples.pilib.rwlock <n> (n=1..5)");
+ exit
+ }
+ val rwlock = n match {
+ case 1 => new ReadWriteLock1
+ case 2 => new ReadWriteLock2
+ case 3 => new ReadWriteLock3
+ case 4 => new ReadWriteLock4
+ case 5 => new ReadWriteLock5
+ }
+ List.range(0, 5) foreach (i => spawn < reader(i, rwlock) >);
+ List.range(0, 5) foreach (i => spawn < writer(i, rwlock) >);
+ }
+
+}
+
diff --git a/docs/examples/pilib/scheduler.scala b/docs/examples/pilib/scheduler.scala
new file mode 100644
index 0000000000..3b08a9df66
--- /dev/null
+++ b/docs/examples/pilib/scheduler.scala
@@ -0,0 +1,149 @@
+package examples.pilib;
+
+import scala.concurrent.pilib._;
+
+object scheduler {
+
+ /**
+ * Random number generator.
+ */
+ val random = new java.util.Random();
+
+ //***************** Scheduler ******************//
+
+ /**
+ * A cell of the scheduler whose attached agent is allowed to start.
+ */
+ def A(a: Chan[unit], b: Chan[unit])(d: Chan[unit], c: Chan[unit]): unit = {
+ ///- ... complete here ...
+ choice ( a * { x => C(a, b)(d, c) })
+ ///+
+ }
+
+ /**
+ * A cell of the scheduler in another intermediate state.
+ */
+ def C(a: Chan[unit], b: Chan[unit])(d: Chan[unit], c: Chan[unit]): unit = {
+ ///- ... complete here ...
+ choice (c * { x => B(a, b)(d, c) })
+ ///+
+ }
+
+ /**
+ * A cell of the scheduler whose attached agent is allowed to finish.
+ */
+ def B(a: Chan[unit], b: Chan[unit])(d: Chan[unit], c: Chan[unit]): unit = {
+ ///- ... complete here ...
+ // choice (b * { x => D(a, b)(d, c) }) // incorrect naive solution
+ choice (
+ b * { x => choice ( d(()) * A(a, b)(d, c) ) }, // b.'d.A
+ d(()) * (choice (b * { x => A(a, b)(d, c) })) // 'd.b.A
+ )
+ ///+
+ }
+
+ /**
+ * A cell of the scheduler whose attached agent is not yet allowed to start.
+ */
+ def D(a: Chan[unit], b: Chan[unit])(d: Chan[unit], c: Chan[unit]): unit = {
+ ///- ... complete here ...
+ choice (d(()) * A(a, b)(d, c))
+ ///+
+ }
+
+ //***************** Agents ******************//
+
+ def agent(i: Int)(a: Chan[unit], b: Chan[unit]): unit = {
+ // 50% chance that we sleep forever
+ if (i == 0 && random.nextInt(10) < 5) {
+ a.attach(x => System.out.println("Start and sleeps ----> " + i));
+ Thread.sleep(random.nextInt(1000));
+ a.write(());
+ }
+ else {
+ a.attach(x => System.out.println("Start ----> " + i));
+ b.attach(x => System.out.println("Stop -> " + i));
+ Thread.sleep(random.nextInt(1000));
+ a.write(());
+ Thread.sleep(random.nextInt(1000));
+ b.write(());
+ agent(i)(a, b)
+ }
+ }
+
+ //***************** Entry function ******************//
+
+ /**
+ * Creates a scheduler for five agents (programs).
+ */
+
+ def main(args: Array[String]): unit = {
+ val agentNb = 5;
+ val agents = List.range(0, agentNb) map agent;
+ scheduleAgents(agents);
+ }
+
+ //***************** Infrastructure *****************//
+
+ /**
+ * A cell is modelled as a function that takes as parameters
+ * input and output channels and which returns nothing.
+ */
+ type Cell = (Chan[unit], Chan[unit]) => unit;
+
+ /**
+ * Creates a cell composed of two cells linked together.
+ */
+ def join(cell1: Cell, cell2: Cell): Cell =
+ (l: Chan[unit], r: Chan[unit]) => {
+ val link = new Chan[unit];
+ spawn < cell1(l, link) | cell2(link, r) >
+ };
+
+ /**
+ * Links the output of a cell to its input.
+ */
+ def close(cell: Cell): unit = {
+ val a = new Chan[unit];
+ cell(a, a)
+ }
+
+ /**
+ * Creates a cell consisting of a chain of cells.
+ */
+ def chain(cells: List[Cell]): Cell =
+ cells reduceLeft join;
+
+ /**
+ * Creates a cell consisting of a chain of cells.
+ */
+ def makeRing(cells: List[Cell]): unit =
+ close(chain(cells));
+
+ /**
+ * An agent is modelled as a function that takes as parameters channels to
+ * signal that it has started or finished.
+ */
+ type Agent = (Chan[unit], Chan[unit]) => unit;
+
+ /**
+ * Takes a list of agents and schedules them.
+ */
+ def scheduleAgents(agents: List[Agent]): unit = {
+ var firstAgent = true;
+ val cells = agents map (ag => {
+ val a = new Chan[unit];
+ val b = new Chan[unit];
+ spawn < ag(a, b) >;
+ if (firstAgent) {
+ firstAgent = false;
+ A(a, b)
+ }
+ else
+ D(a, b)
+ });
+ makeRing(cells)
+ }
+}
+
+
diff --git a/docs/examples/pilib/semaphore.scala b/docs/examples/pilib/semaphore.scala
new file mode 100644
index 0000000000..cfb0c8e5a2
--- /dev/null
+++ b/docs/examples/pilib/semaphore.scala
@@ -0,0 +1,72 @@
+package examples.pilib;
+
+/** Solution of exercise session 6 (first question). */
+object semaphore {
+
+ import scala.concurrent.pilib._;
+
+ class Signal extends Chan[unit] {
+ def send = write(());
+ def receive = read;
+ }
+
+ /** Interface. */
+ trait Semaphore {
+ def get: unit;
+ def release: unit;
+ }
+
+ /** First implementation. */
+ class Sem1 extends Semaphore {
+
+ private val g = new Signal;
+ private val r = new Signal;
+
+ def get: unit = g.send;
+ def release: unit = r.send;
+
+ private def Sched: unit = choice (
+ g * (x => { r.receive; Sched }),
+ r * (x => Sched)
+ );
+ spawn< Sched >;
+ }
+
+ /** Second implementation. */
+ class Sem2 extends Semaphore {
+
+ private val a = new Signal;
+ private val na = new Signal;
+
+ def get: unit = { a.receive; spawn< na.send > }
+ def release: unit = choice (
+ a * (x => spawn< a.send >),
+ na * (x => spawn< a.send >)
+ );
+ spawn< a.send >;
+ }
+
+ /** Test program. */
+ def main(args: Array[String]): unit = {
+ val random = new java.util.Random();
+ val sem = new Sem2;
+ def mutex(p: => unit): unit = { sem.get; p; sem.release }
+
+ spawn< {
+ Thread.sleep(1 + random.nextInt(100));
+ mutex( {
+ System.out.println("a1");
+ Thread.sleep(1 + random.nextInt(100));
+ System.out.println("a2")
+ } )
+ } | {
+ Thread.sleep(1 + random.nextInt(100));
+ mutex( {
+ System.out.println("b1");
+ Thread.sleep(1 + random.nextInt(100));
+ System.out.println("b2")
+ } )
+ } >;
+ }
+}
+
diff --git a/docs/examples/pilib/twoPlaceBuffer.scala b/docs/examples/pilib/twoPlaceBuffer.scala
new file mode 100644
index 0000000000..686547b344
--- /dev/null
+++ b/docs/examples/pilib/twoPlaceBuffer.scala
@@ -0,0 +1,67 @@
+package examples.pilib;
+
+import scala.concurrent.pilib._;
+
+/** Two-place buffer specification and implementation. */
+object twoPlaceBuffer with Application {
+
+ /**
+ * Specification.
+ */
+ def Spec[a](in: Chan[a], out: Chan[a]): unit = {
+
+ def B0: unit = choice (
+ in * (x => B1(x))
+ );
+
+ def B1(x: a): unit = choice (
+ out(x) * (B0),
+ in * (y => B2(x, y))
+ );
+
+ def B2(x: a, y: a): unit = choice (
+ out(x) * (B1(y))
+ );
+
+ B0
+ }
+
+ /**
+ * Implementation using two one-place buffers.
+ */
+ def Impl[a](in: Chan[a], out: Chan[a]): unit = {
+ ///- ... complete here ...
+ // one-place buffer
+ def OnePlaceBuffer[a](in: Chan[a], out: Chan[a]): unit = {
+ def B0: unit = choice ( in * (x => B1(x)) );
+ def B1(x: a): unit = choice ( out(x) * (B0));
+ B0
+ }
+ val hidden = new Chan[a];
+ spawn < OnePlaceBuffer(in, hidden) | OnePlaceBuffer(hidden, out) >
+ ///+
+ }
+
+ val random = new java.util.Random();
+
+ def Producer(n: Int, in: Chan[String]): unit = {
+ Thread.sleep(random.nextInt(1000));
+ val msg = "" + n;
+ choice (in(msg) * {});
+ Producer(n + 1, in)
+ }
+
+ def Consumer(out: Chan[String]): unit = {
+ Thread.sleep(random.nextInt(1000));
+ choice (out * { msg => () });
+ Consumer(out)
+ }
+
+ val in = new Chan[String];
+ in.attach(s => System.out.println("put " + s));
+ val out = new Chan[String];
+ out.attach(s => System.out.println("get " + s));
+ //spawn < Producer(0, in) | Consumer(out) | Spec(in, out) >
+ spawn < Producer(0, in) | Consumer(out) | Impl(in, out) >
+
+}
diff --git a/docs/examples/sort.scala b/docs/examples/sort.scala
new file mode 100644
index 0000000000..6554a2415b
--- /dev/null
+++ b/docs/examples/sort.scala
@@ -0,0 +1,48 @@
+package examples;
+
+object sort {
+
+ def sort(a: Array[Int]): Unit = {
+
+ def swap(i: Int, j: Int): Unit = {
+ val t = a(i); a(i) = a(j); a(j) = t;
+ }
+
+ def sort1(l: Int, r: Int): Unit = {
+ val pivot = a((l + r) / 2);
+ var i = l;
+ var j = r;
+ while (i <= j) {
+ while (a(i) < pivot) { i = i + 1 }
+ while (a(j) > pivot) { j = j - 1 }
+ if (i <= j) {
+ swap(i, j);
+ i = i + 1;
+ j = j - 1;
+ }
+ }
+ if (l < j) sort1(l, j);
+ if (j < r) sort1(i, r);
+ }
+
+ if (a.length > 0)
+ sort1(0, a.length - 1);
+ }
+
+ def println(ar: Array[Int]) = {
+ def print1 = {
+ def iter(i: Int): String =
+ ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "");
+ if (ar.length == 0) "" else iter(0)
+ }
+ Console.println("[" + print1 + "]")
+ }
+
+ def main(args: Array[String]) = {
+ val ar = Array(6, 2, 8, 5, 1);
+ println(ar);
+ sort(ar);
+ println(ar)
+ }
+
+}
diff --git a/docs/examples/sort1.scala b/docs/examples/sort1.scala
new file mode 100644
index 0000000000..406bf7c911
--- /dev/null
+++ b/docs/examples/sort1.scala
@@ -0,0 +1,22 @@
+package examples;
+
+object sort1 {
+
+ def sort(a: List[Int]): List[Int] = {
+ if (a.length < 2)
+ a
+ else {
+ val pivot = a(a.length / 2);
+ sort(a.filter(x => x < pivot))
+ ::: a.filter(x => x == pivot)
+ ::: sort(a.filter(x => x > pivot))
+ }
+ }
+
+ def main(args: Array[String]) = {
+ val xs = List(6, 2, 8, 5, 1);
+ Console.println(xs);
+ Console.println(sort(xs))
+ }
+
+}
diff --git a/docs/examples/sort2.scala b/docs/examples/sort2.scala
new file mode 100644
index 0000000000..53b2f89174
--- /dev/null
+++ b/docs/examples/sort2.scala
@@ -0,0 +1,25 @@
+package examples;
+
+object sort2 {
+
+ def sort(a: List[Int]): List[Int] = {
+ if (a.length < 2)
+ a
+ else {
+ val pivot = a(a.length / 2);
+ def lePivot(x: Int) = x < pivot;
+ def gtPivot(x: Int) = x > pivot;
+ def eqPivot(x: Int) = x == pivot;
+ sort(a filter lePivot)
+ ::: sort(a filter eqPivot)
+ ::: sort(a filter gtPivot)
+ }
+ }
+
+ def main(args: Array[String]) = {
+ val xs = List(6, 2, 8, 5, 1);
+ Console.println(xs);
+ Console.println(sort(xs))
+ }
+
+}
diff --git a/docs/examples/typeinf.scala b/docs/examples/typeinf.scala
new file mode 100644
index 0000000000..a9ac59968b
--- /dev/null
+++ b/docs/examples/typeinf.scala
@@ -0,0 +1,244 @@
+package examples;
+
+object typeinf {
+
+trait Term {}
+
+case class Var(x: String) extends Term {
+ override def toString() = x
+}
+case class Lam(x: String, e: Term) extends Term {
+ override def toString() = "(\\" + x + "." + e + ")"
+}
+case class App(f: Term, e: Term) extends Term {
+ override def toString() = "(" + f + " " + e + ")"
+}
+case class Let(x: String, e: Term, f: Term) extends Term {
+ override def toString() = "let " + x + " = " + e + " in " + f;
+}
+
+sealed trait Type {}
+case class Tyvar(a: String) extends Type {
+ override def toString() = a
+}
+case class Arrow(t1: Type, t2: Type) extends Type {
+ override def toString() = "(" + t1 + "->" + t2 + ")"
+}
+case class Tycon(k: String, ts: List[Type]) extends Type {
+ override def toString() =
+ k + (if (ts.isEmpty) "" else ts.mkString("[", ",", "]"))
+}
+
+object typeInfer {
+
+ private var n: Int = 0;
+ def newTyvar(): Type = { n = n + 1 ; Tyvar("a" + n) }
+
+ trait Subst with Function1[Type,Type] {
+ def lookup(x: Tyvar): Type;
+ def apply(t: Type): Type = t match {
+ case tv @ Tyvar(a) => val u = lookup(tv); if (t == u) t else apply(u);
+ case Arrow(t1, t2) => Arrow(apply(t1), apply(t2))
+ case Tycon(k, ts) => Tycon(k, ts map apply)
+ }
+ def extend(x: Tyvar, t: Type) = new Subst {
+ def lookup(y: Tyvar): Type = if (x == y) t else Subst.this.lookup(y);
+ }
+ }
+
+ val emptySubst = new Subst { def lookup(t: Tyvar): Type = t }
+
+ case class TypeScheme(tyvars: List[Tyvar], tpe: Type) {
+ def newInstance: Type =
+ (emptySubst /: tyvars) ((s, tv) => s.extend(tv, newTyvar())) (tpe);
+ }
+
+ type Env = List[Pair[String, TypeScheme]];
+
+ def lookup(env: Env, x: String): TypeScheme = env match {
+ case List() => null
+ case Pair(y, t) :: env1 => if (x == y) t else lookup(env1, x)
+ }
+
+ def gen(env: Env, t: Type): TypeScheme =
+ TypeScheme(tyvars(t) diff tyvars(env), t);
+
+ def tyvars(t: Type): List[Tyvar] = t match {
+ case tv @ Tyvar(a) => List(tv)
+ case Arrow(t1, t2) => tyvars(t1) union tyvars(t2)
+ case Tycon(k, ts) => (List[Tyvar]() /: ts) ((tvs, t) => tvs union tyvars(t));
+ }
+
+ def tyvars(ts: TypeScheme): List[Tyvar] =
+ tyvars(ts.tpe) diff ts.tyvars;
+
+ def tyvars(env: Env): List[Tyvar] =
+ (List[Tyvar]() /: env) ((tvs, nt) => tvs union tyvars(nt._2));
+
+ def mgu(t: Type, u: Type, s: Subst): Subst = Pair(s(t), s(u)) match {
+ case Pair(Tyvar(a), Tyvar(b)) if (a == b) =>
+ s
+ case Pair(Tyvar(a), _) if !(tyvars(u) contains a) =>
+ s.extend(Tyvar(a), u)
+ case Pair(_, Tyvar(a)) =>
+ mgu(u, t, s)
+ case Pair(Arrow(t1, t2), Arrow(u1, u2)) =>
+ mgu(t1, u1, mgu(t2, u2, s))
+ case Pair(Tycon(k1, ts), Tycon(k2, us)) if (k1 == k2) =>
+ (s /: (ts zip us)) ((s, tu) => mgu(tu._1, tu._2, s))
+ case _ => throw new TypeError("cannot unify " + s(t) + " with " + s(u))
+ }
+
+ case class TypeError(s: String) extends Exception(s) {}
+
+ def tp(env: Env, e: Term, t: Type, s: Subst): Subst = {
+ current = e;
+ e match {
+ case Var(x) =>
+ val u = lookup(env, x);
+ if (u == null) throw new TypeError("undefined: " + x);
+ else mgu(u.newInstance, t, s)
+
+ case Lam(x, e1) =>
+ val a, b = newTyvar();
+ val s1 = mgu(t, Arrow(a, b), s);
+ val env1 = Pair(x, TypeScheme(List(), a)) :: env;
+ tp(env1, e1, b, s1)
+
+ case App(e1, e2) =>
+ val a = newTyvar();
+ val s1 = tp(env, e1, Arrow(a, t), s);
+ tp(env, e2, a, s1)
+
+ case Let(x, e1, e2) =>
+ val a = newTyvar();
+ val s1 = tp(env, e1, a, s);
+ tp(Pair(x, gen(env, s1(a))) :: env, e2, t, s1)
+ }
+ }
+ var current: Term = null;
+
+ def typeOf(env: Env, e: Term): Type = {
+ val a = newTyvar();
+ tp(env, e, a, emptySubst)(a)
+ }
+}
+
+ object predefined {
+ val booleanType = Tycon("Boolean", List());
+ val intType = Tycon("Int", List());
+ def listType(t: Type) = Tycon("List", List(t));
+
+ private def gen(t: Type): typeInfer.TypeScheme = typeInfer.gen(List(), t);
+ private val a = typeInfer.newTyvar();
+ val env = List(
+/*
+ Pair("true", gen(booleanType)),
+ Pair("false", gen(booleanType)),
+ Pair("if", gen(Arrow(booleanType, Arrow(a, Arrow(a, a))))),
+ Pair("zero", gen(intType)),
+ Pair("succ", gen(Arrow(intType, intType))),
+ Pair("nil", gen(listType(a))),
+ Pair("cons", gen(Arrow(a, Arrow(listType(a), listType(a))))),
+ Pair("isEmpty", gen(Arrow(listType(a), booleanType))),
+ Pair("head", gen(Arrow(listType(a), a))),
+ Pair("tail", gen(Arrow(listType(a), listType(a)))),
+*/
+ Pair("fix", gen(Arrow(Arrow(a, a), a)))
+ )
+ }
+
+ abstract class MiniMLParsers extends CharParsers {
+
+ /** whitespace */
+ def whitespace = rep{chr(' ') ||| chr('\t') ||| chr('\n')};
+
+ /** A given character, possible preceded by whitespace */
+ def wschr(ch: char) = whitespace &&& chr(ch);
+
+ /** identifiers or keywords */
+ def id: Parser[String] =
+ for (
+ val c: char <- rep(chr(' ')) &&& chr(Character.isLetter);
+ val cs: List[char] <- rep(chr(Character.isLetterOrDigit))
+ ) yield (c :: cs).mkString("", "", "");
+
+ /** Non-keyword identifiers */
+ def ident: Parser[String] =
+ for (val s <- id; s != "let" && s != "in") yield s;
+
+ /** term = '\' ident '.' term | term1 {term1} | let ident "=" term in term */
+ def term: Parser[Term] =
+ ( for (
+ val _ <- wschr('\\');
+ val x <- ident;
+ val _ <- wschr('.');
+ val t <- term)
+ yield Lam(x, t): Term )
+ |||
+ ( for (
+ val letid <- id; letid == "let";
+ val x <- ident;
+ val _ <- wschr('=');
+ val t <- term;
+ val inid <- id; inid == "in";
+ val c <- term)
+ yield Let(x, t, c) )
+ |||
+ ( for (
+ val t <- term1;
+ val ts <- rep(term1))
+ yield (t /: ts)((f, arg) => App(f, arg)) );
+
+ /** term1 = ident | '(' term ')' */
+ def term1: Parser[Term] =
+ ( for (val s <- ident)
+ yield Var(s): Term )
+ |||
+ ( for (
+ val _ <- wschr('(');
+ val t <- term;
+ val _ <- wschr(')'))
+ yield t );
+
+ /** all = term ';' */
+ def all: Parser[Term] =
+ for (
+ val t <- term;
+ val _ <- wschr(';'))
+ yield t;
+ }
+
+ class ParseString(s: String) extends Parsers {
+ type intype = int;
+ val input = 0;
+ def any = new Parser[char] {
+ def apply(in: int): Parser[char]#Result =
+ if (in < s.length()) Some(Pair(s charAt in, in + 1)) else None;
+ }
+ }
+
+ def showType(e: Term): String =
+ try {
+ typeInfer.typeOf(predefined.env, e).toString();
+ } catch {
+ case typeInfer.TypeError(msg) =>
+ "\n cannot type: " + typeInfer.current +
+ "\n reason: " + msg;
+ }
+
+ def main(args: Array[String]): unit =
+ Console.println(
+ if (args.length == 1) {
+ val ps = new MiniMLParsers with ParseString(args(0));
+ ps.all(ps.input) match {
+ case Some(Pair(term, _)) =>
+ "" + term + ": " + showType(term)
+ case None =>
+ "syntax error"
+ }
+ } else "usage: java examples.typeinf <expr-string>"
+ );
+
+}
+
diff --git a/docs/man/man1/scala.1 b/docs/man/man1/scala.1
new file mode 100644
index 0000000000..4fc89e86e4
--- /dev/null
+++ b/docs/man/man1/scala.1
@@ -0,0 +1,133 @@
+.\" ##########################################################################
+.\" # __ #
+.\" # ________ ___ / / ___ Scala On-line Manual Pages #
+.\" # / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL #
+.\" # __\ \/ /__/ __ |/ /__/ __ | #
+.\" # /____/\___/_/ |_/____/_/ | | http://scala.epfl.ch/ #
+.\" # |/ #
+.\" ##########################################################################
+.\"
+.\" Process this file with nroff -man scala.1
+.\"
+.TH scala 1 "April 29, 2005" "version 0.1" "USER COMMANDS"
+.\"
+.\" ################################# NAME ###################################
+.\"
+.SH NAME
+scala \- Launcher for the Scala language
+.\"
+.\" ############################### SYNOPSIS #################################
+.\"
+.SH SYNOPSIS
+\fBscala\fR [ <\fIoptions\fR> ] <\fIclass file\fR> [ <\fIargs\fR> ]
+.\"
+.\" ############################### PARAMETERS ###############################
+.\"
+.SH PARAMETERS
+.TP
+<\fIoptions\fR>
+Command line options. See \fBOPTIONS\fR below.
+.TP
+<\fIclass file\fR>
+Name of the class to be invoked.
+.TP
+<\fIargs\fR>
+Program arguments passed to the main function.
+.\"
+.\" ############################## DESCRIPTION ###############################
+.\"
+.SH DESCRIPTION
+The \fBscala\fR utility launches a Scala application. It does this by starting
+a Java runtime environment, loading a specified class, and invoking that
+class’s \fBmain\fR method. The method must have the following signature:
+.PP
+ \fBdef\fR main(args: Array[String]): Unit
+.PP
+The method must return a \fBUnit\fR value, and it must accept a \fBString\fR
+array as a parameter. By default, the first non-option argument is the name
+of the class to be invoked. A fully-qualified class name should be used.
+.PP
+The Scala runtime searches for the startup class, and other classes used, in
+three sets of locations: the bootstrap class path, the installed extensions,
+and the user class path.
+.\"
+.\" ############################### OPTIONS ##################################
+.\"
+.SH OPTIONS
+The launcher has a set of standard options that are supported on the current
+runtime environment and will be supported in future releases. An additional
+set of non-standard options are specific to the current virtual machine
+implementation and are subject to change in the future. Non-standard options
+begin with \fB-X\fR.
+.SS Standard Options
+.TP
+\fB\-cp -classpath\fR <\fIpath\fR>
+Specify where to find user class files (on Unix-based systems a
+colon-separated list of paths, on Windows-based systems, a semicolon-separate
+list of paths).
+.TP
+\fB\-D\fR<\fIname\fR>=<\fIvalue\fR>
+Set a system property.
+.TP
+\fB\-verbose\fR[:class|gc|jni]
+Enable verbose output.
+.TP
+\fB\-showversion\fR
+Print product version and continue.
+.TP
+\fB\-version\fR
+Print product version and exit.
+.TP
+\fB\-help\fR
+Print this help message.
+.SS Non-Standard Options
+Same options as the \fBjava\fR command.
+.\"
+.\" ############################### EXAMPLES #################################
+.\"
+.SH EXAMPLES
+.TP
+Execute a Scala program generated in the current directory
+.BR
+\fBscala\fR HelloWorld
+.PP
+.TP
+Execute a Scala program generated in a user-defined directory \fBclasses\fR
+.BR
+\fBscala\fR \-classpath classes hello.HelloWorld
+.PP
+.\"
+.\" ############################# EXIT STATUS ################################
+.\"
+.SH "EXIT STATUS"
+\fBscala\fR returns a zero exit status if it succeeds. Non zero is returned
+in case of failure.
+.\"
+.\" ############################## AUTHOR(S) #################################
+.\"
+.SH AUTHOR
+Written by Stephane Micheloud.
+.\"
+.\" ################################ BUGS ####################################
+.\"
+.SH "REPORTING BUGS"
+Report bugs to <scala@lists.epfl.ch>.
+.\"
+.\" ############################# COPYRIGHT ##################################
+.\"
+.SH COPYRIGHT
+Copyright \(co 2002-2005 LAMP/EPFL
+.PP
+This is free software; see the distribution for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" ############################### SEE ALSO #################################
+.\"
+.SH "SEE ALSO"
+.BR scalac(1),
+.BR scaladoc(1),
+.BR scalaint(1),
+.BR scalarun(1)
+.\"
+.\" ##########################################################################
+.\" $Id$
diff --git a/docs/man/man1/scalac.1 b/docs/man/man1/scalac.1
new file mode 100644
index 0000000000..068abb6ab4
--- /dev/null
+++ b/docs/man/man1/scalac.1
@@ -0,0 +1,299 @@
+.\" ##########################################################################
+.\" # __ #
+.\" # ________ ___ / / ___ Scala On-line Manual Pages #
+.\" # / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL #
+.\" # __\ \/ /__/ __ |/ /__/ __ | #
+.\" # /____/\___/_/ |_/____/_/ | | http://scala.epfl.ch/ #
+.\" # |/ #
+.\" ##########################################################################
+.\"
+.\" Process this file with nroff -man scalac.1
+.\"
+.TH scalac 1 "April 29, 2005" "version 0.1" "USER COMMANDS"
+.\"
+.\" ################################# NAME ###################################
+.\"
+.SH NAME
+scalac \- Compiler for the Scala language
+.\"
+.\" ############################### SYNOPSIS #################################
+.\"
+.SH SYNOPSIS
+\fBscalac\fR [ <\fIoptions\fR> ] <\fIsource files\fR>
+.\"
+.\" ############################### PARAMETERS ###############################
+.\"
+.SH PARAMETERS
+.TP
+<\fIoptions\fR>
+Command line options. See \fBOPTIONS\fR below.
+.TP
+<\fIsource files\fR>
+One or more source files to be compiled (such as MyClass.scala).
+.\"
+.\" ############################## DESCRIPTION ###############################
+.\"
+.SH DESCRIPTION
+The \fBscalac\fR tool reads class and object definitions, written in the
+Scala programming language, and compiles them into bytecode class files.
+.PP
+By default, the compiler puts each class file in the same directory as its
+source file. You can specify a separate destination directory with -d (see
+\fBOPTIONS\fR, below).
+.\"
+.\" ############################### OPTIONS ##################################
+.\"
+.SH OPTIONS
+The compiler has a set of standard options that are supported on the current
+development environment and will be supported in future releases. An
+additional set of non-standard options are specific to the current virtual
+machine implementation and are subject to change in the future. Non-standard
+options begin with \fB-X\fR.
+.SS Standard Options
+.TP
+\fB\-g\fR
+Generate debugging info
+.TP
+\fB\-nowarn\fR
+Generate no warnings
+.TP
+\fB\-verbose\fR
+Output messages about what the compiler is doing
+.TP
+\fB\-classpath\fR <\fIpath\fR>
+Specify where to find user class files (on Unix-based systems
+a colon-separated list of paths, on Windows-based systems, a
+semicolon-separate list of paths). This does not override the
+built-in ("boot") search path.
+.TP
+\fB\-sourcepath\fR <\fIpath\fR>
+Specify where to find input source files.
+.TP
+\fB\-bootclasspath\fR <\fIpath\fR>
+Override location of bootstrap class files (where to find the
+standard built-in classes, such as "scala.List").
+.TP
+\fB\-extdirs\fR <\fIdirs\fR>
+Override location of installed extensions.
+.TP
+\fB\-d\fR <\fIdirectory\fR>
+Specify where to place generated class files.
+.TP
+\fB\-encoding\fR <\fIencoding\fR>
+Specify character encoding used by source files.
+.TP
+\fB\-separate:\fR<\fIseparate\fR>
+Read symbol files for separate compilation: (\fIyes\fR, \fIno\fR).
+.TP
+\fB\-target:\fR<\fItarget\fR>
+Specify which backend to use (\fIjvm\fR, \fImsil\fR).
+.TP
+\fB\-r\fR <\fIassembly files\fR>
+CLR Assemblies referenced by the source program (only relevant with
+option '-target:msil').
+.TP
+\fB\-o\fR <\fIassembly name\fR>
+Name of the output assembly (only relevant with option '-target:msil').
+.TP
+\fB\-version\fR
+Print product version and exit.
+.TP
+\fB\-? -help\fR
+Print a synopsis of standard options.
+.SS Non-Standard Options
+.TP
+\fB\-Xshortname\fR
+Display short file names in error reports.
+.TP
+\fB\-Xmarkup\fR
+No effect, only for compatibility.
+.TP
+\fB\-Xnewmatch\fR
+New pattern matching.
+.TP
+\fB\-XpreserveWS\fR
+Don't trim whitespace in XML literals.
+.TP
+\fB\-XrootClass\fR <\fIclass\fR>
+Specify the root class of the global application.
+.TP
+\fB\-XappFile\fR <\fIfile\fR>
+Specify the filename where to dump the whole-application inferred from the rootclass.
+.TP
+\fB\-XdotFile\fR <\fIfile\fR>
+Specify the filename where to print the AST in graphviz dot format.
+.TP
+\fB\-Xrta\fR
+Perform Rapid Type analysis for method call resolution.
+.TP
+\fB\-Xinline\fR
+Inline method calls that can be resolved statically.
+.TP
+\fB\-Xrtt\fR
+Enable run-time types.
+.SS Debug Options
+.TP
+.B \-debug
+Output debugging messages.
+.TP
+\fB\-explaintypes\fR
+Explain type errors in more detail.
+.TP
+\fB\-uniqid\fR
+Print identifiers with unique names.
+.TP
+\fB\-types\fR
+Print tree types.
+.TP
+\fB\-prompt\fR
+Display a prompt after each error.
+.TP
+\fB\-noimports\fR
+Compile without any implicit imports.
+.TP
+\fB\-nopredefs\fR
+Compile without any implicit predefined values.
+.TP
+\fB\-skip:\fR<\fIphases\fR>
+Skip <\fIphases\fR> (see below).
+.TP
+\fB\-check:\fR<\fIphases\fR>
+Check the tree after <\fIphases\fR> (see below).
+.TP
+\fB\-print:\fR<phases>
+Print out program after <\fIphases\fR> (see below).
+.TP
+\fB\-printer:\fR<\fIprinter\fR>
+Printer to use.
+.TP
+\fB\-print-file\fR <\fIfile\fR>
+Specify file in which to print trees.
+.TP
+\fB\-graph:\fR<\fIphases\fR>
+Graph the program after <\fIphases\fR> (see below).
+.TP
+\fB\-stop:\fR<\fIphases\fR>
+Stop after first phase in <\fIphases\fR> (see below).
+.TP
+\fB\-log:\fR<\fIphases\fR>
+Log operations in <\fIphases\fR> (see below).
+.SS Compilation Phases
+.TP
+\fIinitial\fR
+initializing compiler
+.TP
+\fIparse\fR
+parse source files
+.TP
+\fInamer\fR
+create symbols
+.TP
+\fIanalyze\fR
+name and type analysis
+.TP
+\fIrefcheck\fR
+reference checking
+.TP
+\fIuncurry\fR
+uncurry function types and applications
+.TP
+\fItransmatch\fR
+translate match expressions
+.TP
+\fIlambdalift\fR
+lambda lifter
+.TP
+\fItypesasvalues\fR
+represent types as values
+.TP
+\fIaddaccessors\fR
+add accessors for constructor arguments
+.TP
+\fIexplicitouterclasses\fR
+make links from inner classes to enclosing one explicit
+.TP
+\fIaddconstructors\fR
+add explicit constructor for each class
+.TP
+\fItailcall\fR
+add tail-calls
+.TP
+\fIwholeprog\fR
+perform whole program analysis
+.TP
+\fIaddinterfaces\fR
+add one interface per class
+.TP
+\fIexpandmixins\fR
+expand mixins by code copying
+.TP
+\fIboxing\fR
+makes boxing explicit
+.TP
+\fIerasure\fR
+type eraser
+.TP
+\fIicode\fR
+generate icode
+.TP
+\fIcodegen\fR
+enable code generation
+.TP
+\fIterminal\fR
+compilation terminated
+.TP
+\fIall\fR
+matches all phases
+
+.\"
+.\" ############################### EXAMPLES #################################
+.\"
+.SH EXAMPLES
+.TP
+Compile a Scala program
+.BR
+\fBscalac\fR HelloWorld
+.TP
+Compile a Scala program to the destination directory \fBclasses\fR
+.BR
+\fBscalac\fR \-d classes HelloWorld.scala
+.TP
+Compile all Scala files found in the source directory \fBsrc\fR to the
+destination directory \fBclasses\fR
+.BR
+\fBscalac\fR \-d classes src/*.scala
+.\"
+.\" ############################# EXIT STATUS ################################
+.\"
+.SH "EXIT STATUS"
+\fBscalac\fR returns a zero exist status if it succeeds to compile the
+specified input files. Non zero is returned in case of failure.
+.\"
+.\" ############################## AUTHOR(S) #################################
+.\"
+.SH AUTHOR
+Written by Stephane Micheloud.
+.\"
+.\" ################################ BUGS ####################################
+.\"
+.SH "REPORTING BUGS"
+Report bugs to <scala@lists.epfl.ch>.
+.\"
+.\" ############################# COPYRIGHT ##################################
+.\"
+.SH COPYRIGHT
+Copyright \(co 2002-2005 LAMP/EPFL
+.PP
+This is free software; see the distribution for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" ############################## SEE ALSO ##################################
+.\"
+.SH "SEE ALSO"
+.BR scala(1),
+.BR scaladoc(1),
+.BR scalaint(1),
+.BR scalarun(1)
+.\"
+.\" ##########################################################################
+.\" $Id$
diff --git a/docs/man/man1/scaladoc.1 b/docs/man/man1/scaladoc.1
new file mode 100644
index 0000000000..5063c72918
--- /dev/null
+++ b/docs/man/man1/scaladoc.1
@@ -0,0 +1,119 @@
+.\" ##########################################################################
+.\" # __ #
+.\" # ________ ___ / / ___ Scala On-line Manual Pages #
+.\" # / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL #
+.\" # __\ \/ /__/ __ |/ /__/ __ | #
+.\" # /____/\___/_/ |_/____/_/ | | http://scala.epfl.ch/ #
+.\" # |/ #
+.\" ##########################################################################
+.\"
+.\" Process this file with nroff -man scaladoc.1
+.\"
+.TH scaladoc 1 "April 29, 2005" "version 0.1" "USER COMMANDS"
+.\"
+.\" ################################# NAME ###################################
+.\"
+.SH NAME
+scaladoc \- Scala API documentation generator
+.\"
+.\" ############################### SYNOPSIS #################################
+.\"
+.SH SYNOPSIS
+\fBscaladoc\fR [ <\fIoptions\fR> ] <\fIsource files\fR> [ -- <\fIpackages\fR> ]
+.\"
+.\" ############################### PARAMETERS ###############################
+.\"
+.SH PARAMETERS
+.TP
+<\fIoptions\fR>
+Command line options. See \fBOPTIONS\fR below.
+.TP
+<\fIsource files\fR>
+A series of source file names, separated by spaces, each of which can
+include paths and wildcards such as asterisk (*).
+.TP
+<\fIpackages\fR>
+.
+.\"
+.\" ############################## DESCRIPTION ###############################
+.\"
+.SH DESCRIPTION
+The Scaladoc tool parses the declarations and documentation comments in a
+set of Scala source files and produces a corresponding set of HTML pages
+describing (by default) the public and protected classes, nested classes,
+traits, objects, methods, and fields.
+
+During a run, the Scaladoc tool automatically adds cross-reference links to
+package, class and member names that are being documented as part of that run.
+Links appear in several places:
+
+ · Declarations (return types, argument types, field types)
+
+ · "See Also" sections generated from @see tags
+
+ · In-line text generated from {@link} tags
+
+ · Exception names generated from @throws tags
+
+.\"
+.\" ############################### OPTIONS ##################################
+.\"
+.SH OPTIONS
+The Scaladoc tool supports the following options.
+.TP
+\fB\-g\fR
+Generate debugging info.
+.TP
+\fB\-d\fR <\fIdirectory\fR>
+Specify where to place generated HTML files. The output directory
+<\fIdirectory\fR> must exist.
+.TP
+\fB\-windowtitle\fR <\fItext\fR>
+Browser window title for the documentation.
+.TP
+\fB\-doctitle\fR <\fIhtml-code\fR>
+Include title for the overview page.
+.\"
+.\" ############################### EXAMPLES #################################
+.\"
+.SH EXAMPLES
+.TP
+Generate the Scala documentation in the specified directory \fB/tmp\fR
+.BR
+\fBscaladoc\fR -d /tmp HelloWorld
+.PP
+.\"
+.\" ############################# EXIT STATUS ################################
+.\"
+.SH "EXIT STATUS"
+\fBscaladoc\fR returns a zero exist status if it succeeds. Non zero is
+returned in case of failure.
+.\"
+.\" ############################## AUTHOR(S) #################################
+.\"
+.SH AUTHOR
+Written by Stephane Micheloud.
+.\"
+.\" ################################ BUGS ####################################
+.\"
+.SH "REPORTING BUGS"
+Report bugs to <scala@lists.epfl.ch>.
+.\"
+.\" ############################# COPYRIGHT ##################################
+.\"
+.SH COPYRIGHT
+Copyright \(co 2002-2005 LAMP/EPFL
+.PP
+This is free software; see the distribution for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" ############################### SEE ALSO #################################
+.\"
+.SH "SEE ALSO"
+.BR scala(1),
+.BR scalac(1),
+.BR scalaint(1),
+.BR scalarun(1)
+.\"
+.\" ##########################################################################
+.\" $Id$
diff --git a/docs/man/man1/scalaint.1 b/docs/man/man1/scalaint.1
new file mode 100644
index 0000000000..5f67995723
--- /dev/null
+++ b/docs/man/man1/scalaint.1
@@ -0,0 +1,127 @@
+.\" ##########################################################################
+.\" # __ #
+.\" # ________ ___ / / ___ Scala On-line Manual Pages #
+.\" # / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL #
+.\" # __\ \/ /__/ __ |/ /__/ __ | #
+.\" # /____/\___/_/ |_/____/_/ | | http://scala.epfl.ch/ #
+.\" # |/ #
+.\" ##########################################################################
+.\"
+.\" Process this file with nroff -man scalaint.1
+.\"
+.TH scalaint 1 "April 29, 2005" "version 0.1" "USER COMMANDS"
+.\"
+.\" ################################# NAME ###################################
+.\"
+.SH NAME
+scalaint \- Interactive interpreter for the Scala language
+.\"
+.\" ############################### SYNOPSIS #################################
+.\"
+.SH SYNOPSIS
+\fBscalaint\fR [ <\fIoptions\fR> ] <\fIsource files\fR> [ -- <\fImodule\fR> [ <\fIargs\fR> ] ]
+.\"
+.\" ############################### PARAMETERS ###############################
+.\"
+.SH PARAMETERS
+.TP
+<\fIoptions\fR>
+Command line options. See \fBOPTIONS\fR below.
+.TP
+<\fIsource files\fR>
+One or more source files to be interpreted (such as MyClass.scala).
+.TP
+<\fImodule\fR>
+Name of the Scala object containing the main function.
+.TP
+<\fIargs\fR>
+Program arguments passed to the main function.
+.\"
+.\" ############################## DESCRIPTION ###############################
+.\"
+.SH DESCRIPTION
+The \fBscalaint\fR utility starts an interpreter shell and executes the
+specified Scala application. It does this by loading the class <\fImodule\fR>
+and invoking that class’s \fBmain\fR method. The method must have the
+following signature:
+.PP
+ \fBdef\fR main(args: Array[String]): Unit
+.PP
+The method must not return any value, and it must accept a String array as a
+parameter.
+.PP
+The Scala interpreter searches for the startup class, and other classes used,
+in three sets of locations: the bootstrap class path, the installed
+extensions, and the user class path.
+.\"
+.\" ############################### OPTIONS ##################################
+.\"
+.SH OPTIONS
+The \fBscalaint\fR command supports the following options
+.TP
+\fB\-c\fR <\fIstring\fR>
+Evaluate <\fIstring\fR> and print result.
+.TP
+\fB\-interactive\fR
+Start interpreter in interactive mode.
+.TP
+\fB\-nologo\fR
+Print no logo at interactive interpreter start.
+.TP
+\fB\-emacs\fR
+Use Emacs editing mode.
+.TP
+\fB\-g\fR
+Generate debugging info.
+.TP
+\fB\-nowarn\fR
+Generate no warnings.
+.TP
+\fB\-classpath\fR <\fIpath\fR>
+Specify where to find user class files (on Unix-based systems
+a colon-separated list of paths, on Windows-based systems, a
+semicolon-separate list of paths).
+.\"
+.\" ############################### EXAMPLES #################################
+.\"
+.SH EXAMPLES
+.TP
+Run a Scala program located in the current directory
+.BR
+\fBscalaint\fR -nologo HelloWorld.scala -- HelloWorld
+.PP
+.\"
+.\" ############################# EXIT STATUS ################################
+.\"
+.SH "EXIT STATUS"
+\fBscalaint\fR returns a zero exist status if it succeeds. Non zero is
+returned in case of failure.
+.\"
+.\" ############################## AUTHOR(S) #################################
+.\"
+.SH AUTHOR
+Written by Stephane Micheloud.
+.\"
+.\" ################################ BUGS ####################################
+.\"
+.SH "REPORTING BUGS"
+Report bugs to <scala@lists.epfl.ch>.
+.\"
+.\" ############################# COPYRIGHT ##################################
+.\"
+.SH COPYRIGHT
+Copyright \(co 2002-2005 LAMP/EPFL
+.PP
+This is free software; see the distribution for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" ############################### SEE ALSO #################################
+.\"
+.SH "SEE ALSO"
+.BR scala(1),
+.BR scalac(1),
+.BR scaladoc(1),
+.BR scalarun(1)
+.\"
+.\" ##########################################################################
+.\" $Id$
diff --git a/docs/man/man1/scalarun.1 b/docs/man/man1/scalarun.1
new file mode 100644
index 0000000000..14bc78faaf
--- /dev/null
+++ b/docs/man/man1/scalarun.1
@@ -0,0 +1,123 @@
+.\" ##########################################################################
+.\" # __ #
+.\" # ________ ___ / / ___ Scala On-line Manual Pages #
+.\" # / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL #
+.\" # __\ \/ /__/ __ |/ /__/ __ | #
+.\" # /____/\___/_/ |_/____/_/ | | http://scala.epfl.ch/ #
+.\" # |/ #
+.\" ##########################################################################
+.\"
+.\" Process this file with nroff -man scalarun.1
+.\"
+.TH scalarun 1 "April 29, 2005" "version 0.1" "USER COMMANDS"
+.\"
+.\" ################################# NAME ###################################
+.\"
+.SH NAME
+scalarun \- Non-interactive interpreter for the Scala language
+.\"
+.\" ############################### SYNOPSIS #################################
+.\"
+.SH SYNOPSIS
+\fBscalarun\fR [ <\fIoptions\fR> ] <\fIsource files\fR> [ -- <\fImodule\fR> [ <\fIargs\fR> ] ]
+.\"
+.\" ############################### PARAMETERS ###############################
+.\"
+.SH PARAMETERS
+.TP
+<\fIoptions\fR>
+Command line options. See \fBOPTIONS\fR below.
+.TP
+<\fIsource files\fR>
+One or more source files to be interpreted (such as MyClass.scala).
+.TP
+<\fImodule\fR>
+Name of the Scala object containing the main function.
+.TP
+<\fIargs\fR>
+Program arguments passed to the main function.
+.\"
+.\" ############################## DESCRIPTION ###############################
+.\"
+.SH DESCRIPTION
+The \fBscalarun\fR utility interpretes a Scala application. It does this by
+loading the class <\fImodule\fR> and invoking that class’s \fBmain\fR method.
+The method must have the following signature:
+.PP
+ \fBdef\fR main(args: Array[String]): Unit
+.PP
+The method must not return any value, and it must accept a String array as a
+parameter.
+.PP
+The Scala interpreter searches for the startup class, and other classes used,
+in three sets of locations: the bootstrap class path, the installed
+extensions, and the user class path.
+.\"
+.\" ############################### OPTIONS ##################################
+.\"
+.SH OPTIONS
+The \fBscalarun\fR command supports the following options
+.TP
+\fB\-c\fR <\fIstring\fR>
+Evaluate <\fIstring\fR> and print result.
+.TP
+\fB\-classpath\fR <\fIpath\fR>
+Specify where to find user class files (on Unix-based systems
+a colon-separated list of paths, on Windows-based systems, a
+semicolon-separate list of paths).
+.TP
+\fB\-nologo\fR
+Print no logo at interactive interpreter start.
+.TP
+\fB\-emacs\fR
+Use Emacs editing mode.
+.TP
+\fB\-g\fR
+Generate debugging info.
+.TP
+\fB\-nowarn\fR
+Generate no warnings.
+.\"
+.\" ############################### EXAMPLES #################################
+.\"
+.SH EXAMPLES
+.TP
+Run a Scala program located in the current directory
+.BR
+\fBscalarun\fR HelloWorld.scala -- HelloWord
+.PP
+.\"
+.\" ############################# EXIT STATUS ################################
+.\"
+.SH "EXIT STATUS"
+\fBscalarun\fR returns a zero exist status if it succeeds. Non zero is
+returned in case of failure.
+.\"
+.\" ############################## AUTHOR(S) #################################
+.\"
+.SH AUTHOR
+Written by Stephane Micheloud.
+.\"
+.\" ################################ BUGS ####################################
+.\"
+.SH "REPORTING BUGS"
+Report bugs to <scala@lists.epfl.ch>.
+.\"
+.\" ############################# COPYRIGHT ##################################
+.\"
+.SH COPYRIGHT
+Copyright \(co 2002-2005 LAMP/EPFL
+.PP
+This is free software; see the distribution for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" ############################### SEE ALSO #################################
+.\"
+.SH "SEE ALSO"
+.BR scala(1),
+.BR scalac(1),
+.BR scaladoc(1),
+.BR scalaint(1)
+.\"
+.\" ##########################################################################
+.\" $Id$