summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormihaylov <mihaylov@epfl.ch>2007-02-07 09:06:25 +0000
committermihaylov <mihaylov@epfl.ch>2007-02-07 09:06:25 +0000
commite3b42865333ed502b3e454c98eefbfc705e33d82 (patch)
tree68982d6051371b3731c6918e44cc0d9788b15e59 /src
parent108db60672ffa6a70617f51b166d8c751d7e65bb (diff)
downloadscala-e3b42865333ed502b3e454c98eefbfc705e33d82.tar.gz
scala-e3b42865333ed502b3e454c98eefbfc705e33d82.tar.bz2
scala-e3b42865333ed502b3e454c98eefbfc705e33d82.zip
Created src/dotnet-library from r9912 of src/li...
Created src/dotnet-library from r9912 of src/library
Diffstat (limited to 'src')
-rw-r--r--src/dotnet-library/scala/All$.scala25
-rw-r--r--src/dotnet-library/scala/AllRef$.scala25
-rw-r--r--src/dotnet-library/scala/Application.scala58
-rw-r--r--src/dotnet-library/scala/Array.scala278
-rw-r--r--src/dotnet-library/scala/Attribute.scala23
-rw-r--r--src/dotnet-library/scala/BigInt.scala363
-rw-r--r--src/dotnet-library/scala/BufferedIterator.scala29
-rwxr-xr-xsrc/dotnet-library/scala/ByNameFunction.scala27
-rw-r--r--src/dotnet-library/scala/Cell.scala22
-rw-r--r--src/dotnet-library/scala/ClassfileAttribute.scala21
-rw-r--r--src/dotnet-library/scala/Console.scala334
-rw-r--r--src/dotnet-library/scala/CountedIterator.scala26
-rw-r--r--src/dotnet-library/scala/Enumeration.scala138
-rw-r--r--src/dotnet-library/scala/Function.scala144
-rw-r--r--src/dotnet-library/scala/Function0.scala42
-rw-r--r--src/dotnet-library/scala/Function1.scala50
-rw-r--r--src/dotnet-library/scala/Function2.scala42
-rw-r--r--src/dotnet-library/scala/Function3.scala26
-rw-r--r--src/dotnet-library/scala/Function4.scala26
-rw-r--r--src/dotnet-library/scala/Function5.scala26
-rw-r--r--src/dotnet-library/scala/Function6.scala26
-rw-r--r--src/dotnet-library/scala/Function7.scala26
-rw-r--r--src/dotnet-library/scala/Function8.scala26
-rw-r--r--src/dotnet-library/scala/Function9.scala21
-rw-r--r--src/dotnet-library/scala/Iterable.scala378
-rw-r--r--src/dotnet-library/scala/IterableProxy.scala54
-rw-r--r--src/dotnet-library/scala/Iterator.scala647
-rw-r--r--src/dotnet-library/scala/List.scala1159
-rw-r--r--src/dotnet-library/scala/MatchError.scala51
-rw-r--r--src/dotnet-library/scala/Math.scala140
-rw-r--r--src/dotnet-library/scala/NotDefinedError.scala17
-rw-r--r--src/dotnet-library/scala/Option.scala132
-rw-r--r--src/dotnet-library/scala/Ordered.scala36
-rw-r--r--src/dotnet-library/scala/PartialFunction.scala45
-rw-r--r--src/dotnet-library/scala/PartiallyOrdered.scala50
-rw-r--r--src/dotnet-library/scala/Predef.scala285
-rw-r--r--src/dotnet-library/scala/Product.scala42
-rw-r--r--src/dotnet-library/scala/Product1.scala50
-rw-r--r--src/dotnet-library/scala/Product10.scala86
-rw-r--r--src/dotnet-library/scala/Product11.scala90
-rw-r--r--src/dotnet-library/scala/Product12.scala94
-rw-r--r--src/dotnet-library/scala/Product13.scala98
-rw-r--r--src/dotnet-library/scala/Product14.scala102
-rw-r--r--src/dotnet-library/scala/Product15.scala106
-rw-r--r--src/dotnet-library/scala/Product16.scala110
-rw-r--r--src/dotnet-library/scala/Product17.scala114
-rw-r--r--src/dotnet-library/scala/Product18.scala118
-rw-r--r--src/dotnet-library/scala/Product19.scala122
-rw-r--r--src/dotnet-library/scala/Product2.scala54
-rw-r--r--src/dotnet-library/scala/Product20.scala126
-rw-r--r--src/dotnet-library/scala/Product21.scala130
-rw-r--r--src/dotnet-library/scala/Product22.scala134
-rw-r--r--src/dotnet-library/scala/Product3.scala58
-rw-r--r--src/dotnet-library/scala/Product4.scala62
-rw-r--r--src/dotnet-library/scala/Product5.scala66
-rw-r--r--src/dotnet-library/scala/Product6.scala70
-rw-r--r--src/dotnet-library/scala/Product7.scala74
-rw-r--r--src/dotnet-library/scala/Product8.scala78
-rw-r--r--src/dotnet-library/scala/Product9.scala82
-rw-r--r--src/dotnet-library/scala/Proxy.scala28
-rw-r--r--src/dotnet-library/scala/Responder.scala90
-rw-r--r--src/dotnet-library/scala/ScalaObject.scala23
-rw-r--r--src/dotnet-library/scala/Seq.scala274
-rw-r--r--src/dotnet-library/scala/SeqProxy.scala44
-rw-r--r--src/dotnet-library/scala/SerialVersionUID.scala19
-rw-r--r--src/dotnet-library/scala/StaticAttribute.scala21
-rw-r--r--src/dotnet-library/scala/Stream.scala457
-rw-r--r--src/dotnet-library/scala/Symbol.scala57
-rw-r--r--src/dotnet-library/scala/Tuple1.scala25
-rw-r--r--src/dotnet-library/scala/Tuple10.scala25
-rw-r--r--src/dotnet-library/scala/Tuple11.scala25
-rw-r--r--src/dotnet-library/scala/Tuple12.scala25
-rw-r--r--src/dotnet-library/scala/Tuple13.scala25
-rw-r--r--src/dotnet-library/scala/Tuple14.scala25
-rw-r--r--src/dotnet-library/scala/Tuple15.scala25
-rw-r--r--src/dotnet-library/scala/Tuple16.scala25
-rw-r--r--src/dotnet-library/scala/Tuple17.scala25
-rw-r--r--src/dotnet-library/scala/Tuple18.scala25
-rw-r--r--src/dotnet-library/scala/Tuple19.scala25
-rw-r--r--src/dotnet-library/scala/Tuple2.scala25
-rw-r--r--src/dotnet-library/scala/Tuple20.scala25
-rw-r--r--src/dotnet-library/scala/Tuple21.scala25
-rw-r--r--src/dotnet-library/scala/Tuple22.scala25
-rw-r--r--src/dotnet-library/scala/Tuple3.scala25
-rw-r--r--src/dotnet-library/scala/Tuple4.scala25
-rw-r--r--src/dotnet-library/scala/Tuple5.scala25
-rw-r--r--src/dotnet-library/scala/Tuple6.scala25
-rw-r--r--src/dotnet-library/scala/Tuple7.scala25
-rw-r--r--src/dotnet-library/scala/Tuple8.scala25
-rw-r--r--src/dotnet-library/scala/Tuple9.scala25
-rw-r--r--src/dotnet-library/scala/cloneable.scala18
-rw-r--r--src/dotnet-library/scala/collection/BitSet.scala140
-rw-r--r--src/dotnet-library/scala/collection/Map.scala158
-rw-r--r--src/dotnet-library/scala/collection/MapProxy.scala37
-rw-r--r--src/dotnet-library/scala/collection/Set.scala103
-rw-r--r--src/dotnet-library/scala/collection/SetProxy.scala30
-rw-r--r--src/dotnet-library/scala/collection/immutable/BitSet.scala51
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/EmptyMap.scala37
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/EmptySet.scala36
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/HashMap.scala154
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/HashSet.scala118
-rw-r--r--src/dotnet-library/scala/collection/immutable/ListMap.scala160
-rw-r--r--src/dotnet-library/scala/collection/immutable/ListSet.scala138
-rw-r--r--src/dotnet-library/scala/collection/immutable/Map.scala238
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Map1.scala40
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Map2.scala46
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Map3.scala49
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Map4.scala52
-rw-r--r--src/dotnet-library/scala/collection/immutable/Queue.scala161
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/RedBlack.scala98
-rw-r--r--src/dotnet-library/scala/collection/immutable/Set.scala169
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Set1.scala42
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Set2.scala43
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Set3.scala44
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/Set4.scala45
-rw-r--r--src/dotnet-library/scala/collection/immutable/Stack.scala134
-rw-r--r--src/dotnet-library/scala/collection/immutable/Tree.scala406
-rw-r--r--src/dotnet-library/scala/collection/immutable/TreeMap.scala112
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/TreeMap.scala.disabled101
-rw-r--r--src/dotnet-library/scala/collection/immutable/TreeSet.scala84
-rwxr-xr-xsrc/dotnet-library/scala/collection/immutable/UnbalancedTreeMap.scala143
-rw-r--r--src/dotnet-library/scala/collection/jcl/ArrayList.scala20
-rw-r--r--src/dotnet-library/scala/collection/jcl/Buffer.scala159
-rw-r--r--src/dotnet-library/scala/collection/jcl/BufferIterator.scala32
-rw-r--r--src/dotnet-library/scala/collection/jcl/BufferWrapper.scala51
-rw-r--r--src/dotnet-library/scala/collection/jcl/Collection.scala84
-rw-r--r--src/dotnet-library/scala/collection/jcl/CollectionWrapper.scala41
-rw-r--r--src/dotnet-library/scala/collection/jcl/HashMap.scala19
-rw-r--r--src/dotnet-library/scala/collection/jcl/HashSet.scala20
-rw-r--r--src/dotnet-library/scala/collection/jcl/IdentityHashMap.scala22
-rw-r--r--src/dotnet-library/scala/collection/jcl/IterableWrapper.scala39
-rw-r--r--src/dotnet-library/scala/collection/jcl/LinkedHashMap.scala20
-rw-r--r--src/dotnet-library/scala/collection/jcl/LinkedHashSet.scala20
-rw-r--r--src/dotnet-library/scala/collection/jcl/LinkedList.scala29
-rw-r--r--src/dotnet-library/scala/collection/jcl/Map.scala97
-rw-r--r--src/dotnet-library/scala/collection/jcl/MapWrapper.scala66
-rw-r--r--src/dotnet-library/scala/collection/jcl/MutableIterable.scala80
-rw-r--r--src/dotnet-library/scala/collection/jcl/MutableIterator.scala100
-rw-r--r--src/dotnet-library/scala/collection/jcl/MutableSeq.scala82
-rw-r--r--src/dotnet-library/scala/collection/jcl/Ranged.scala62
-rw-r--r--src/dotnet-library/scala/collection/jcl/SeqIterator.scala58
-rw-r--r--src/dotnet-library/scala/collection/jcl/Set.scala51
-rw-r--r--src/dotnet-library/scala/collection/jcl/SetWrapper.scala21
-rw-r--r--src/dotnet-library/scala/collection/jcl/Sorted.scala46
-rw-r--r--src/dotnet-library/scala/collection/jcl/SortedMap.scala90
-rw-r--r--src/dotnet-library/scala/collection/jcl/SortedMapWrapper.scala39
-rw-r--r--src/dotnet-library/scala/collection/jcl/SortedSet.scala75
-rw-r--r--src/dotnet-library/scala/collection/jcl/SortedSetWrapper.scala38
-rw-r--r--src/dotnet-library/scala/collection/jcl/Tests.scala77
-rw-r--r--src/dotnet-library/scala/collection/jcl/TreeMap.scala19
-rw-r--r--src/dotnet-library/scala/collection/jcl/TreeSet.scala20
-rw-r--r--src/dotnet-library/scala/collection/jcl/WeakHashMap.scala29
-rw-r--r--src/dotnet-library/scala/collection/mutable/ArrayBuffer.scala178
-rw-r--r--src/dotnet-library/scala/collection/mutable/BitSet.scala100
-rw-r--r--src/dotnet-library/scala/collection/mutable/Buffer.scala245
-rw-r--r--src/dotnet-library/scala/collection/mutable/BufferProxy.scala154
-rwxr-xr-xsrc/dotnet-library/scala/collection/mutable/DefaultEntry.scala18
-rw-r--r--src/dotnet-library/scala/collection/mutable/DefaultMapModel.scala45
-rw-r--r--src/dotnet-library/scala/collection/mutable/DoubleLinkedList.scala53
-rwxr-xr-xsrc/dotnet-library/scala/collection/mutable/FlatHashTable.scala148
-rw-r--r--src/dotnet-library/scala/collection/mutable/HashMap.scala40
-rw-r--r--src/dotnet-library/scala/collection/mutable/HashSet.scala43
-rw-r--r--src/dotnet-library/scala/collection/mutable/HashTable.scala168
-rw-r--r--src/dotnet-library/scala/collection/mutable/History.scala48
-rw-r--r--src/dotnet-library/scala/collection/mutable/ImmutableMapAdaptor.scala65
-rw-r--r--src/dotnet-library/scala/collection/mutable/ImmutableSetAdaptor.scala49
-rw-r--r--src/dotnet-library/scala/collection/mutable/JavaMapAdaptor.scala68
-rw-r--r--src/dotnet-library/scala/collection/mutable/JavaSetAdaptor.scala46
-rw-r--r--src/dotnet-library/scala/collection/mutable/LinkedHashSet.scala52
-rw-r--r--src/dotnet-library/scala/collection/mutable/LinkedList.scala33
-rw-r--r--src/dotnet-library/scala/collection/mutable/ListBuffer.scala283
-rw-r--r--src/dotnet-library/scala/collection/mutable/Location.scala29
-rw-r--r--src/dotnet-library/scala/collection/mutable/Map.scala240
-rw-r--r--src/dotnet-library/scala/collection/mutable/MapProxy.scala56
-rw-r--r--src/dotnet-library/scala/collection/mutable/Message.scala82
-rw-r--r--src/dotnet-library/scala/collection/mutable/MultiMap.scala43
-rw-r--r--src/dotnet-library/scala/collection/mutable/MutableList.scala80
-rw-r--r--src/dotnet-library/scala/collection/mutable/ObservableBuffer.scala82
-rw-r--r--src/dotnet-library/scala/collection/mutable/ObservableMap.scala58
-rw-r--r--src/dotnet-library/scala/collection/mutable/ObservableSet.scala45
-rw-r--r--src/dotnet-library/scala/collection/mutable/PriorityQueue.scala193
-rw-r--r--src/dotnet-library/scala/collection/mutable/PriorityQueueProxy.scala100
-rw-r--r--src/dotnet-library/scala/collection/mutable/Publisher.scala48
-rw-r--r--src/dotnet-library/scala/collection/mutable/Queue.scala196
-rw-r--r--src/dotnet-library/scala/collection/mutable/QueueProxy.scala101
-rw-r--r--src/dotnet-library/scala/collection/mutable/ResizableArray.scala85
-rw-r--r--src/dotnet-library/scala/collection/mutable/RevertableHistory.scala33
-rw-r--r--src/dotnet-library/scala/collection/mutable/Scriptable.scala26
-rw-r--r--src/dotnet-library/scala/collection/mutable/Set.scala211
-rw-r--r--src/dotnet-library/scala/collection/mutable/SetProxy.scala58
-rw-r--r--src/dotnet-library/scala/collection/mutable/SingleLinkedList.scala63
-rw-r--r--src/dotnet-library/scala/collection/mutable/Stack.scala133
-rw-r--r--src/dotnet-library/scala/collection/mutable/StackProxy.scala111
-rw-r--r--src/dotnet-library/scala/collection/mutable/Subscriber.scala25
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedBuffer.scala191
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedMap.scala157
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedPriorityQueue.scala99
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedQueue.scala95
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedSet.scala110
-rw-r--r--src/dotnet-library/scala/collection/mutable/SynchronizedStack.scala111
-rw-r--r--src/dotnet-library/scala/collection/mutable/Undoable.scala26
-rw-r--r--src/dotnet-library/scala/compat/Math.scala51
-rw-r--r--src/dotnet-library/scala/compat/Platform.scala37
-rw-r--r--src/dotnet-library/scala/compat/StringBuilder.scala59
-rw-r--r--src/dotnet-library/scala/concurrent/Actor.scala48
-rw-r--r--src/dotnet-library/scala/concurrent/Channel.scala46
-rw-r--r--src/dotnet-library/scala/concurrent/Lock.scala31
-rw-r--r--src/dotnet-library/scala/concurrent/MailBox.scala176
-rw-r--r--src/dotnet-library/scala/concurrent/NameServer.scala46
-rw-r--r--src/dotnet-library/scala/concurrent/Pid.scala48
-rw-r--r--src/dotnet-library/scala/concurrent/Process.scala93
-rw-r--r--src/dotnet-library/scala/concurrent/SyncChannel.scala44
-rw-r--r--src/dotnet-library/scala/concurrent/SyncVar.scala43
-rw-r--r--src/dotnet-library/scala/concurrent/TIMEOUT.scala21
-rw-r--r--src/dotnet-library/scala/concurrent/jolib.scala80
-rw-r--r--src/dotnet-library/scala/concurrent/ops.scala78
-rw-r--r--src/dotnet-library/scala/concurrent/pilib.scala205
-rwxr-xr-xsrc/dotnet-library/scala/deprecated.scala18
-rw-r--r--src/dotnet-library/scala/io/BytePickle.scala318
-rw-r--r--src/dotnet-library/scala/io/Position.scala108
-rw-r--r--src/dotnet-library/scala/io/Source.scala371
-rw-r--r--src/dotnet-library/scala/io/UTF8Codec.scala83
-rw-r--r--src/dotnet-library/scala/mobile/Code.scala234
-rw-r--r--src/dotnet-library/scala/mobile/Location.scala100
-rw-r--r--src/dotnet-library/scala/reflect/BeanProperty.scala34
-rw-r--r--src/dotnet-library/scala/reflect/Code.scala22
-rw-r--r--src/dotnet-library/scala/reflect/Print.scala98
-rw-r--r--src/dotnet-library/scala/reflect/Symbol.scala62
-rw-r--r--src/dotnet-library/scala/reflect/Tree.scala35
-rw-r--r--src/dotnet-library/scala/reflect/Type.scala48
-rw-r--r--src/dotnet-library/scala/reflect/TypedCode.scala15
-rw-r--r--src/dotnet-library/scala/remote.scala20
-rw-r--r--src/dotnet-library/scala/runtime/BooleanRef.java18
-rw-r--r--src/dotnet-library/scala/runtime/BoxedAnyArray.scala255
-rw-r--r--src/dotnet-library/scala/runtime/BoxedArray.scala125
-rw-r--r--src/dotnet-library/scala/runtime/BoxedBoolean.java44
-rw-r--r--src/dotnet-library/scala/runtime/BoxedBooleanArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedByte.java57
-rw-r--r--src/dotnet-library/scala/runtime/BoxedByteArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedChar.java58
-rw-r--r--src/dotnet-library/scala/runtime/BoxedCharArray.scala61
-rw-r--r--src/dotnet-library/scala/runtime/BoxedDouble.java49
-rw-r--r--src/dotnet-library/scala/runtime/BoxedDoubleArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedFloat.java48
-rw-r--r--src/dotnet-library/scala/runtime/BoxedFloatArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedInt.java57
-rw-r--r--src/dotnet-library/scala/runtime/BoxedIntArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedLong.java49
-rw-r--r--src/dotnet-library/scala/runtime/BoxedLongArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedNumber.java23
-rw-r--r--src/dotnet-library/scala/runtime/BoxedObjectArray.scala65
-rw-r--r--src/dotnet-library/scala/runtime/BoxedShort.java58
-rw-r--r--src/dotnet-library/scala/runtime/BoxedShortArray.scala60
-rw-r--r--src/dotnet-library/scala/runtime/BoxedUnit.java34
-rw-r--r--src/dotnet-library/scala/runtime/ByteRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/CharRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/DoubleRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/ExceptionHandling.java26
-rw-r--r--src/dotnet-library/scala/runtime/FloatRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/IntRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/LongRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/NonLocalReturnException.scala15
-rw-r--r--src/dotnet-library/scala/runtime/Nothing$.scala21
-rw-r--r--src/dotnet-library/scala/runtime/Null$.scala21
-rw-r--r--src/dotnet-library/scala/runtime/ObjectRef.java19
-rw-r--r--src/dotnet-library/scala/runtime/RichBoolean.scala23
-rw-r--r--src/dotnet-library/scala/runtime/RichByte.scala23
-rw-r--r--src/dotnet-library/scala/runtime/RichChar.scala50
-rw-r--r--src/dotnet-library/scala/runtime/RichDouble.scala33
-rw-r--r--src/dotnet-library/scala/runtime/RichException.scala28
-rw-r--r--src/dotnet-library/scala/runtime/RichFloat.scala33
-rw-r--r--src/dotnet-library/scala/runtime/RichInt.scala28
-rw-r--r--src/dotnet-library/scala/runtime/RichLong.scala27
-rw-r--r--src/dotnet-library/scala/runtime/RichShort.scala23
-rw-r--r--src/dotnet-library/scala/runtime/RichString.scala145
-rw-r--r--src/dotnet-library/scala/runtime/ScalaRunTime.scala148
-rw-r--r--src/dotnet-library/scala/runtime/ShortRef.java18
-rw-r--r--src/dotnet-library/scala/runtime/StringAdd.scala14
-rw-r--r--src/dotnet-library/scala/serializable.scala18
-rw-r--r--src/dotnet-library/scala/testing/Benchmark.scala87
-rw-r--r--src/dotnet-library/scala/testing/SUnit.scala195
-rw-r--r--src/dotnet-library/scala/testing/UnitTest.scala85
-rw-r--r--src/dotnet-library/scala/text/Document.scala123
-rw-r--r--src/dotnet-library/scala/throws.scala30
-rw-r--r--src/dotnet-library/scala/transient.scala15
-rw-r--r--src/dotnet-library/scala/util/Fluid.scala78
-rw-r--r--src/dotnet-library/scala/util/Sorting.scala519
-rw-r--r--src/dotnet-library/scala/util/automata/BaseBerrySethi.scala198
-rw-r--r--src/dotnet-library/scala/util/automata/DetWordAutom.scala84
-rw-r--r--src/dotnet-library/scala/util/automata/Inclusion.scala72
-rw-r--r--src/dotnet-library/scala/util/automata/NondetWordAutom.scala113
-rw-r--r--src/dotnet-library/scala/util/automata/SubsetConstruction.scala178
-rw-r--r--src/dotnet-library/scala/util/automata/WordBerrySethi.scala297
-rw-r--r--src/dotnet-library/scala/util/grammar/HedgeRHS.scala23
-rw-r--r--src/dotnet-library/scala/util/grammar/TreeRHS.scala20
-rw-r--r--src/dotnet-library/scala/util/logging/ConsoleLogger.scala28
-rw-r--r--src/dotnet-library/scala/util/logging/Logged.scala40
-rw-r--r--src/dotnet-library/scala/util/parsing/CharInputStreamIterator.scala46
-rw-r--r--src/dotnet-library/scala/util/parsing/Parsers.scala85
-rw-r--r--src/dotnet-library/scala/util/parsing/SimpleTokenizer.scala65
-rw-r--r--src/dotnet-library/scala/util/regexp/Base.scala76
-rw-r--r--src/dotnet-library/scala/util/regexp/PointedHedgeExp.scala37
-rw-r--r--src/dotnet-library/scala/util/regexp/SyntaxError.scala20
-rw-r--r--src/dotnet-library/scala/util/regexp/WordExp.scala56
-rw-r--r--src/dotnet-library/scala/volatile.scala15
-rw-r--r--src/dotnet-library/scala/xml/Atom.scala55
-rw-r--r--src/dotnet-library/scala/xml/Comment.scala47
-rw-r--r--src/dotnet-library/scala/xml/Document.scala89
-rw-r--r--src/dotnet-library/scala/xml/Elem.scala70
-rw-r--r--src/dotnet-library/scala/xml/EntityRef.scala58
-rw-r--r--src/dotnet-library/scala/xml/Group.scala74
-rw-r--r--src/dotnet-library/scala/xml/MalformedAttributeException.scala15
-rw-r--r--src/dotnet-library/scala/xml/MetaData.scala215
-rw-r--r--src/dotnet-library/scala/xml/NamespaceBinding.scala73
-rw-r--r--src/dotnet-library/scala/xml/Node.scala193
-rw-r--r--src/dotnet-library/scala/xml/NodeBuffer.scala64
-rw-r--r--src/dotnet-library/scala/xml/NodeSeq.scala178
-rw-r--r--src/dotnet-library/scala/xml/NodeTraverser.scala34
-rw-r--r--src/dotnet-library/scala/xml/Null.scala84
-rw-r--r--src/dotnet-library/scala/xml/Parsing.scala105
-rw-r--r--src/dotnet-library/scala/xml/PrefixedAttribute.scala101
-rw-r--r--src/dotnet-library/scala/xml/PrettyPrinter.scala306
-rw-r--r--src/dotnet-library/scala/xml/ProcInstr.scala68
-rw-r--r--src/dotnet-library/scala/xml/SpecialNode.scala35
-rw-r--r--src/dotnet-library/scala/xml/Text.scala43
-rw-r--r--src/dotnet-library/scala/xml/TextBuffer.scala65
-rw-r--r--src/dotnet-library/scala/xml/TopScope.scala38
-rw-r--r--src/dotnet-library/scala/xml/TypeSymbol.scala15
-rw-r--r--src/dotnet-library/scala/xml/Unparsed.scala36
-rw-r--r--src/dotnet-library/scala/xml/UnprefixedAttribute.scala87
-rw-r--r--src/dotnet-library/scala/xml/Utility.scala444
-rw-r--r--src/dotnet-library/scala/xml/XML.scala157
-rw-r--r--src/dotnet-library/scala/xml/dtd/ContentModel.scala212
-rw-r--r--src/dotnet-library/scala/xml/dtd/ContentModelParser.scala156
-rw-r--r--src/dotnet-library/scala/xml/dtd/DTD.scala58
-rw-r--r--src/dotnet-library/scala/xml/dtd/Decl.scala176
-rw-r--r--src/dotnet-library/scala/xml/dtd/DocType.scala47
-rw-r--r--src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala15
-rw-r--r--src/dotnet-library/scala/xml/dtd/ElementValidator.scala179
-rw-r--r--src/dotnet-library/scala/xml/dtd/ExternalID.scala91
-rw-r--r--src/dotnet-library/scala/xml/dtd/Scanner.scala99
-rw-r--r--src/dotnet-library/scala/xml/dtd/Tokens.scala44
-rw-r--r--src/dotnet-library/scala/xml/dtd/ValidationException.scala45
-rw-r--r--src/dotnet-library/scala/xml/factory/Binder.scala55
-rw-r--r--src/dotnet-library/scala/xml/factory/LoggedNodeFactory.scala95
-rw-r--r--src/dotnet-library/scala/xml/factory/NodeFactory.scala77
-rw-r--r--src/dotnet-library/scala/xml/parsing/ConstructingHandler.scala38
-rw-r--r--src/dotnet-library/scala/xml/parsing/ConstructingParser.scala67
-rw-r--r--src/dotnet-library/scala/xml/parsing/DefaultMarkupHandler.scala28
-rw-r--r--src/dotnet-library/scala/xml/parsing/ExternalSources.scala78
-rw-r--r--src/dotnet-library/scala/xml/parsing/FactoryAdapter.scala336
-rw-r--r--src/dotnet-library/scala/xml/parsing/FatalError.scala15
-rw-r--r--src/dotnet-library/scala/xml/parsing/MarkupHandler.scala161
-rw-r--r--src/dotnet-library/scala/xml/parsing/MarkupParser.scala1213
-rw-r--r--src/dotnet-library/scala/xml/parsing/NoBindingFactoryAdapter.scala57
-rw-r--r--src/dotnet-library/scala/xml/parsing/TokenTests.scala146
-rw-r--r--src/dotnet-library/scala/xml/parsing/ValidatingMarkupHandler.scala116
-rw-r--r--src/dotnet-library/scala/xml/path/Expression.scala66
-rw-r--r--src/dotnet-library/scala/xml/pull/XMLEvent.scala21
-rw-r--r--src/dotnet-library/scala/xml/pull/XMLEventReader.scala131
-rw-r--r--src/dotnet-library/scala/xml/transform/BasicTransformer.scala146
-rw-r--r--src/dotnet-library/scala/xml/transform/RewriteRule.scala26
-rw-r--r--src/dotnet-library/scala/xml/transform/RuleTransformer.scala26
363 files changed, 32237 insertions, 0 deletions
diff --git a/src/dotnet-library/scala/All$.scala b/src/dotnet-library/scala/All$.scala
new file mode 100644
index 0000000000..879e18a259
--- /dev/null
+++ b/src/dotnet-library/scala/All$.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: All$.scala 9262 2006-11-14 17:29:59Z mihaylov $
+
+
+package scala
+
+
+/**
+ * Dummy class which exist only to satisfy the JVM. It corresponds
+ * to <code>scala.All</code>. If such type appears in method
+ * signatures, it is erased to this one.
+ *
+ * @deprecated <i>To be removed at some time in the future. Kept only for
+ * backward compatibility. Newly compiled code will refer to
+ * <code>scala.runtime.Nothing$</code></i>
+ */
+
+sealed abstract class All$
diff --git a/src/dotnet-library/scala/AllRef$.scala b/src/dotnet-library/scala/AllRef$.scala
new file mode 100644
index 0000000000..b0dc552b05
--- /dev/null
+++ b/src/dotnet-library/scala/AllRef$.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/**
+ * Dummy class which exist only to satisfy the JVM. It corresponds
+ * to <code>scala.AllRef</code>. If such type appears in method
+ * signatures, it is erased to this one.
+ *
+ * @deprecated <i>To be removed at some time in the future. Kept only for
+ * backward compatibility. Newly compiled code will refer to
+ * <code>scala.runtime.Null$</code></i>
+ */
+
+sealed abstract class AllRef$
diff --git a/src/dotnet-library/scala/Application.scala b/src/dotnet-library/scala/Application.scala
new file mode 100644
index 0000000000..672969e91c
--- /dev/null
+++ b/src/dotnet-library/scala/Application.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import compat.Platform.currentTime
+import java.lang.System.getProperty
+
+/** The <code>Application</code> class can be used to quickly turn objects
+ * into executable programs. Here is an example:
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ * Console.println("Hello World!")
+ * }
+ * </pre>
+ * Here, object <code>Main</code> inherits the <code>main</code> method
+ * of <code>Application</code>. The body of the <code>Main</code> object
+ * defines the main program. This technique does not work if the main
+ * program depends on command-line arguments (which are not accessible
+ * with the technique presented here).
+ *
+ * It is possible to time the execution of objects that inherit from
+ * class <code>Application</code> by setting the global scala.time property.
+ * Here is an example for benchmarking object <code>Main</code>:
+ * <pre>
+ * java -Dscala.time Main
+ * </pre>
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/09/2003
+ */
+
+trait Application {
+
+ /** The time when execution of this program started.
+ */
+ val executionStart: Long = currentTime
+
+ /** The default main method.
+ *
+ * @param args the arguments passed to the main method
+ */
+ def main(args: Array[String]) = {
+ if (getProperty("scala.time") ne null) {
+ val total = currentTime - executionStart
+ Console.println("[total " + total + "ms]")
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/Array.scala b/src/dotnet-library/scala/Array.scala
new file mode 100644
index 0000000000..8a29abb0b5
--- /dev/null
+++ b/src/dotnet-library/scala/Array.scala
@@ -0,0 +1,278 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import compat.Platform.arraycopy
+
+/** This object ...
+ *
+ * @author Martin Odersky
+ * @version 1.0
+ */
+object Array {
+
+ /** Copy one array to another.
+ * Equivalent to
+ * <code>System.arraycopy(src, srcPos, dest, destPos, length)</code>,
+ * except that this works also for polymorphic and boxed arrays.
+ *
+ * @param src ...
+ * @param srcPos ...
+ * @param dest ...
+ * @param destPos ...
+ * @param length ...
+ */
+ def copy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit = src match {
+ case xs: runtime.BoxedArray =>
+ xs.copyTo(srcPos, dest, destPos, length)
+ case _ =>
+ dest match {
+ case xs: runtime.BoxedArray =>
+ xs.copyFrom(src, srcPos, destPos, length)
+ case _ =>
+ arraycopy(src, srcPos, dest, destPos, length)
+ }
+ }
+
+ /** Concatenate all argument arrays into a single array.
+ *
+ * @param xs ...
+ */
+ def concat[T](xs: Array[T]*) = {
+ var len = 0
+ for (val x <- xs) {
+ len = len + x.length
+ }
+ val result = new Array[T](len)
+ var start = 0
+ for (val x <- xs) {
+ copy(x, 0, result, start, x.length)
+ start = start + x.length
+ }
+ result
+ }
+
+ /** Create a an array containing of successive integers.
+ *
+ * @param from the value of the first element of the array
+ * @param end the value of the last element fo the array plus 1
+ * @return the sorted array of all integers in range [from;end).
+ */
+ def range(start: Int, end: Int): Array[Int] = {
+ val result = new Array[Int](end - start)
+ for (val i <- Iterator.range(start, end)) result(i - start) = i
+ result
+ }
+
+ /** Create an array with given elements.
+ *
+ * @param xs the elements to put in the array
+ * @return the array containing elements xs.
+ */
+ def apply[A <: AnyRef](xs: A*): Array[A] = {
+ val array = new Array[A](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+
+
+/* The following metod clashes with the previous one, and has therefore been
+ * removed. Note that this is a choice between efficiency and generality.
+ * The previous factory method is more efficient than the one that has been
+ * commented out. Since it is anyway possible to create a polymorphic array
+ * using
+ * new Array[T]
+ * it was preferred to restrict the definition of the factory method.
+
+ def Array[A](xs: A*): Array[A] = {
+ val array = new Array[A](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+*/
+
+ def apply(xs: Boolean*): Array[Boolean] = {
+ val array = new Array[Boolean](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Byte*): Array[Byte] = {
+ val array = new Array[Byte](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Short*): Array[Short] = {
+ val array = new Array[Short](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Char*): Array[Char] = {
+ val array = new Array[Char](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Int*): Array[Int] = {
+ val array = new Array[Int](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Long*): Array[Long] = {
+ val array = new Array[Long](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Float*): Array[Float] = {
+ val array = new Array[Float](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Double*): Array[Double] = {
+ val array = new Array[Double](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+ def apply(xs: Unit*): Array[Unit] = {
+ val array = new Array[Unit](xs.length)
+ var i = 0
+ for (val x <- xs.elements) { array(i) = x; i = i + 1; }
+ array
+ }
+
+ /** Create an array containing several copies of an element.
+ *
+ * @param n the length of the resulting array
+ * @param elem the element composing the resulting array
+ * @return an array composed of n elements all equal to elem
+ */
+ def make[a](n: Int, elem: a): Array[a] = {
+ val a = new Array[a](n)
+ var i = 0
+ while (i < n) {
+ a(i) = elem
+ i = i + 1
+ }
+ a
+ }
+
+ /** This method is called in a pattern match { case Array(...) => }.
+ *
+ * @param x the selector value
+ * @return array wrapped in an option, if this is a Seq, otherwise none
+ */
+ def unapplySeq[A](x: Any): Option[Seq[A]] =
+ if (x.isInstanceOf[Array[A]]) Some(x.asInstanceOf[Array[A]]) else None
+}
+
+/** This class represents polymorphic arrays. It is never instantiated.
+ *
+ * @author Martin Odersky
+ * @version 1.0
+ */
+final class Array[A](_length: Int) extends Seq[A] {
+ import Predef.Error
+
+ /** The length of the array */
+ def length: Int = throw new Error()
+
+ /** The element at given index.
+ * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first
+ * element of array <code>xs</code>.
+ * Note the indexing syntax <code>xs(i)</code> is a shorthand for <code>xs.apply(i)</code>.
+ * @param i the index
+ * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or
+ * <code>length <= i</code>
+ */
+ def apply(i: Int): A = throw new Error()
+
+ /** Update the element at given index.
+ * Indices start a <code>0</code>; <code>xs.apply(0)</code> is the first
+ * element of array <code>xs</code>.
+ * Note the indexing syntax <code>xs(i) = x</code> is a shorthand
+ * for <code>xs.update(i, x)</code>.
+ * @param i the index
+ * @param x the value to be written at index <code>i</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>i < 0</code> or
+ * <code>length <= i</code>
+ */
+ def update(i: Int, x: A): Unit = throw new Error()
+
+ /** An iterator returning the elements of this array, starting from 0.
+ */
+ def elements: Iterator[A] = throw new Error()
+
+ /** @deprecated use slice instead */
+ def subArray(from: Int, end: Int): Array[A] = throw new Error()
+
+ /** A sub-array of <code>len</code> elements
+ * starting at index <code>from</code>
+ * @param from The index of the first element of the slice
+ * @param end The index of the element following the slice
+ * @throws IndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>length < from + len<code>
+ */
+ override def slice(from: Int, end: Int): Array[A] = throw new Error()
+
+ /** Returns an array consisting of all elements of this array that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the array.
+ * @return the elements of this array satisfying <code>p</code>.
+ */
+ override def filter(p: A => Boolean): Array[A] = throw new Error()
+
+ /** Returns the array resulting from applying the given function <code>f</code> to each
+ * element of this array.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this array is <code>[a0, ..., an]</code>.
+ */
+ override def map[B](f: A => B): Array[B] = throw new Error()
+
+ /** Applies the given function <code>f</code> to each element of
+ * this array, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this array is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def flatMap[B](f: A => Iterable[B]): Array[B] = throw new Error()
+
+ /** Returns an array formed from this array and the specified array
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two arrays is longer than the other, its remaining elements are ignored.
+ *
+ * @return <code>Array({a<sub>0</sub>,b<sub>0</sub>}, ...,
+ * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>})</code> when
+ * <code>Array(a<sub>0</sub>, ..., a<sub>m</sub>)
+ * zip Array(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.
+ */
+ def zip[B](that: Array[B]): Array[Tuple2[A,B]] = throw new Error()
+
+ /** Returns an array that pairs each element of this array
+ * with its index, counting from 0.
+ *
+ * @return the array <code>Array({a<sub>0</sub>,0}, {a<sub>1</sub>,1},...)</code>
+ * where <code>a<sub>i</sub></code> are the elements of this stream.
+ */
+ def zipWithIndex: Array[Tuple2[A,Int]] = throw new Error()
+}
diff --git a/src/dotnet-library/scala/Attribute.scala b/src/dotnet-library/scala/Attribute.scala
new file mode 100644
index 0000000000..869800458d
--- /dev/null
+++ b/src/dotnet-library/scala/Attribute.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** <p>A base class for attributes. Atributes extending this class directly
+ * are not preserved for the Scala type checker and are also not stored as
+ * Java annotations in classfiles. To enable either or both of these, one needs to
+ * inherit from <code>StaticAttribute</code> or/and <code>ClassfileAttribute</code>.
+ * </p>
+ *
+ * @author Martin Odersky
+ * @version 1.1, 2/02/2007
+ */
+abstract class Attribute {}
diff --git a/src/dotnet-library/scala/BigInt.scala b/src/dotnet-library/scala/BigInt.scala
new file mode 100644
index 0000000000..4fcbfd82ce
--- /dev/null
+++ b/src/dotnet-library/scala/BigInt.scala
@@ -0,0 +1,363 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala
+
+import java.math.BigInteger
+import java.util.Random
+
+/**
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+object BigInt {
+
+ private val minCached = -1024
+ private val maxCached = 1024
+ private val cache = new Array[BigInt](maxCached - minCached + 1)
+
+ /** Constructs a <code>BigInt</code> whose value is equal to that of the
+ * specified integer value.
+ *
+ * @param i the specified integer value
+ * @return the constructed <code>BigInt</code>
+ */
+ def apply(i: Int): BigInt =
+ if (minCached <= i && i <= maxCached) {
+ var n = cache(i)
+ if (n eq null) { n = new BigInt(BigInteger.valueOf(i)); cache(i) = n }
+ n
+ } else new BigInt(BigInteger.valueOf(i))
+
+ /** Constructs a <code>BigInt</code> whose value is equal to that of the
+ * specified long value.
+ *
+ * @param l the specified long value
+ * @return the constructed <code>BigInt</code>
+ */
+ def apply(l: Long): BigInt =
+ if (minCached <= l && l <= maxCached) apply(l.toInt)
+ else new BigInt(BigInteger.valueOf(l))
+
+ /** Translates a byte array containing the two's-complement binary
+ * representation of a BigInt into a BigInt.
+ */
+ def apply(x: Array[byte]): BigInt =
+ new BigInt(new BigInteger(x))
+
+ /** Translates the sign-magnitude representation of a BigInt into a BigInt.
+ */
+ def apply(signum: Int, magnitude: Array[byte]): BigInt =
+ new BigInt(new BigInteger(signum, magnitude))
+
+ /** Constructs a randomly generated positive BigInt that is probably prime,
+ * with the specified bitLength.
+ */
+ def apply(bitlength: Int, certaInty: Int, rnd: Random): BigInt =
+ new BigInt(new BigInteger(bitlength, certaInty, rnd))
+
+ /** Constructs a randomly generated BigInt, uniformly distributed over the
+ * range 0 to (2 ^ numBits - 1), inclusive.
+ *
+ * @param numbits ...
+ * @param rnd ...
+ * @return ...
+ */
+ def apply(numbits: Int, rnd: Random): BigInt =
+ new BigInt(new BigInteger(numbits, rnd))
+
+ /** Translates the decimal String representation of a BigInt into a BigInt.
+ */
+ def apply(x: String): BigInt =
+ new BigInt(new BigInteger(x))
+
+ /** Translates the string representation of a BigInt in the
+ * specified <code>radix</code> into a BigInt.
+ *
+ * @param x ...
+ * @param radix ...
+ * @return ...
+ */
+ def apply(x: String, radix: Int): BigInt =
+ new BigInt(new BigInteger(x, radix))
+
+ /** Returns a positive BigInt that is probably prime, with the specified bitLength.
+ */
+ def probablePrime(bitLength: Int, rnd: Random): BigInt =
+ new BigInt(BigInteger.probablePrime(bitLength, rnd))
+
+ /** Implicit conversion from <code>int</code> to <code>BigInt</code>.
+ */
+ implicit def int2bigInt(i: Int): BigInt = apply(i)
+
+ /** Implicit copnversion from long to BigInt
+ */
+ implicit def long2bigInt(l: Long): BigInt = apply(l)
+
+ /** Implicit conversion from BigInt to <code>Ordered</code>.
+ */
+ implicit def bigInt2ordered(x: BigInt): Ordered[BigInt] = new Ordered[BigInt] with Proxy {
+ def self: Any = x;
+ def compare (y: BigInt): int = x.bigInteger.compareTo(y.bigInteger)
+ }
+}
+
+/**
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+[serializable]
+class BigInt(val bigInteger: BigInteger) extends runtime.BoxedNumber {
+
+ /** Returns the hash code for this BigInt. */
+ override def hashCode(): Int = this.bigInteger.hashCode()
+
+ /** Compares this BigInt with the specified value for equality.
+ */
+ override def equals (that: Any): boolean = that match {
+ case that: runtime.BoxedDouble => this.bigInteger.doubleValue == that
+ case that: runtime.BoxedFloat => this.bigInteger.floatValue == that
+ case that: runtime.BoxedNumber => this equals BigInt(that.longValue)
+ case _ => false
+ }
+
+ /** Compares this BigInt with the specified BigInt for equality.
+ */
+ def equals (that: BigInt): boolean =
+ this.bigInteger.compareTo(that.bigInteger) == 0
+
+ /** Compares this BigInt with the specified BigInt
+ */
+ def compare (that: BigInt): int = this.bigInteger.compareTo(that.bigInteger)
+
+ /** Less-than-or-equals comparison of BigInts
+ */
+ def <= (that: BigInt): boolean = this.bigInteger.compareTo(that.bigInteger) <= 0
+
+ /** Greater-than-or-equals comparison of BigInts
+ */
+ def >= (that: BigInt): boolean = this.bigInteger.compareTo(that.bigInteger) >= 0
+
+ /** Less-than of BigInts
+ */
+ def < (that: BigInt): boolean = this.bigInteger.compareTo(that.bigInteger) < 0
+
+ /** Greater-than comparison of BigInts
+ */
+ def > (that: BigInt): boolean = this.bigInteger.compareTo(that.bigInteger) >= 0
+
+ /** Addition of BigInts
+ */
+ def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger))
+
+ /** Subtraction of BigInts
+ */
+ def - (that: BigInt): BigInt = new BigInt(this.bigInteger.subtract(that.bigInteger))
+
+ /** Multiplication of BigInts
+ */
+ def * (that: BigInt): BigInt = new BigInt(this.bigInteger.multiply(that.bigInteger))
+
+ /** Division of BigInts
+ */
+ def / (that: BigInt): BigInt = new BigInt(this.bigInteger.divide(that.bigInteger))
+
+ /** Remainder of BigInts
+ */
+ def % (that: BigInt): BigInt = new BigInt(this.bigInteger.remainder(that.bigInteger))
+
+ /** Returns a pair of two BigInts containing (this / that) and (this % that).
+ */
+ def /% (that: BigInt): {BigInt, BigInt} = {
+ val dr = this.bigInteger.divideAndRemainder(that.bigInteger)
+ {new BigInt(dr(0)), new BigInt(dr(1))}
+ }
+
+ /** Leftshift of BigInt
+ */
+ def << (n: Int): BigInt = new BigInt(this.bigInteger.shiftLeft(n))
+
+ /** (Signed) rightshift of BigInt
+ */
+ def >> (n: Int): BigInt = new BigInt(this.bigInteger.shiftRight(n))
+
+ /** Bitwise and of BigInts
+ */
+ def & (that: BigInt): BigInt = new BigInt(this.bigInteger.and(that.bigInteger))
+
+ /** Bitwise or of BigInts
+ */
+ def | (that: BigInt): BigInt = new BigInt(this.bigInteger.or (that.bigInteger))
+
+ /** Bitwise exclusive-or of BigInts
+ */
+ def ^ (that: BigInt): BigInt = new BigInt(this.bigInteger.xor(that.bigInteger))
+
+ /** Bitwise and-not of BigInts. Returns a BigInt whose value is (this & ~that).
+ */
+ def &~ (that: BigInt): BigInt = new BigInt(this.bigInteger.andNot(that.bigInteger))
+
+ /** Returns the greatest common divisor of abs(this) and abs(that)
+ */
+ def gcd (that: BigInt): BigInt = new BigInt(this.bigInteger.gcd(that.bigInteger))
+
+ /** Returns a BigInt whose value is (this mod m).
+ * This method differs from `%' in that it always returns a non-negative BigInt.
+ */
+ def mod (that: BigInt): BigInt = new BigInt(this.bigInteger.mod(that.bigInteger))
+
+ /** Returns the minimum of this and that
+ */
+ def min (that: BigInt): BigInt = new BigInt(this.bigInteger.min(that.bigInteger))
+
+ /** Returns the maximum of this and that
+ */
+ def max (that: BigInt): BigInt = new BigInt(this.bigInteger.max(that.bigInteger))
+
+ /** Returns a BigInt whose value is (<tt>this</tt> raised to the power of <tt>exp</tt>).
+ */
+ def pow (exp: Int): BigInt = new BigInt(this.bigInteger.pow(exp))
+
+ /** Returns a BigInt whose value is
+ * (<tt>this</tt> raised to the power of <tt>exp</tt> modulo <tt>m</tt>).
+ */
+ def modPow (exp: BigInt, m: BigInt): BigInt =
+ new BigInt(this.bigInteger.modPow(exp.bigInteger, m.bigInteger))
+
+ /** Returns a BigInt whose value is (the inverse of <tt>this</tt> modulo <tt>m</tt>).
+ */
+ def modInverse (m: BigInt): BigInt = new BigInt(this.bigInteger.modInverse(m.bigInteger))
+
+ /** Returns a BigInt whose value is the negation of this BigInt
+ */
+ def - : BigInt = new BigInt(this.bigInteger.negate())
+
+ /** Returns the absolute value of this BigInt
+ */
+ def abs: BigInt = new BigInt(this.bigInteger.abs())
+
+ /** Returns the sign of this BigInt, i.e.
+ * -1 if it is less than 0,
+ * +1 if it is greater than 0
+ * 0 if it is equal to 0
+ */
+ def signum: Int = this.bigInteger.signum()
+
+ /** Returns the bitwise complement of this BigNum
+ */
+ def ~ : BigInt = new BigInt(this.bigInteger.not())
+
+ /** Returns true if and only if the designated bit is set.
+ */
+ def testBit (n: Int): Boolean = this.bigInteger.testBit(n)
+
+ /** Returns a BigInt whose value is equivalent to this BigInt with the designated bit set.
+ */
+ def setBit (n: Int): BigInt = new BigInt(this.bigInteger.setBit(n))
+
+ /** Returns a BigInt whose value is equivalent to this BigInt with the designated bit cleared.
+ */
+ def clearBit(n: Int): BigInt = new BigInt(this.bigInteger.clearBit(n))
+
+ /** Returns a BigInt whose value is equivalent to this BigInt with the designated bit flipped.
+ */
+ def flipBit (n: Int): BigInt = new BigInt(this.bigInteger.flipBit(n))
+
+ /** Returns the index of the rightmost (lowest-order) one bit in this BigInt
+ * (the number of zero bits to the right of the rightmost one bit).
+ */
+ def lowestSetBit: int = this.bigInteger.getLowestSetBit()
+
+ /** Returns the number of bits in the minimal two's-complement representation of this BigInt,
+ * excluding a sign bit.
+ */
+ def bitLength: int = this.bigInteger.bitLength()
+
+ /** Returns the number of bits in the two's complement representation of this BigInt
+ * that differ from its sign bit.
+ */
+ def bitCount: int = this.bigInteger.bitCount()
+
+ /** Returns true if this BigInt is probably prime, false if it's definitely composite.
+ * @param certainty a measure of the uncertainty that the caller is willing to tolerate:
+ * if the call returns true the probability that this BigInt is prime
+ * exceeds (1 - 1/2 ^ certainty).
+ * The execution time of this method is proportional to the value of
+ * this parameter.
+ */
+ def isProbablePrime(certainty: Int) = this.bigInteger.isProbablePrime(certainty)
+
+ /** Converts this BigInt to a <tt>byte</tt>.
+ * If the BigInt is too big to fit in a byte, only the low-order 8 bits are returned.
+ * Note that this conversion can lose information about the overall magnitude of the
+ * BigInt value as well as return a result with the opposite sign.
+ */
+ def byteValue = intValue.toByte
+
+ /** Converts this BigInt to a <tt>short</tt>.
+ * If the BigInt is too big to fit in a byte, only the low-order 16 bits are returned.
+ * Note that this conversion can lose information about the overall magnitude of the
+ * BigInt value as well as return a result with the opposite sign.
+ */
+ def shortValue = intValue.toShort
+
+ /** Converts this BigInt to a <tt>char</tt>.
+ * If the BigInt is too big to fit in a char, only the low-order 16 bits are returned.
+ * Note that this conversion can lose information about the overall magnitude of the
+ * BigInt value and that it always returns a positive result.
+ */
+ def charValue = intValue.toChar
+
+ /** Converts this BigInt to an <tt>int</tt>.
+ * If the BigInt is too big to fit in a char, only the low-order 32 bits
+ * are returned. Note that this conversion can lose information about the
+ * overall magnitude of the BigInt value as well as return a result with
+ * the opposite sign.
+ */
+ def intValue = this.bigInteger.intValue
+
+ /** Converts this BigInt to a <tt>long</tt>.
+ * If the BigInt is too big to fit in a char, only the low-order 64 bits
+ * are returned. Note that this conversion can lose information about the
+ * overall magnitude of the BigInt value as well as return a result with
+ * the opposite sign.
+ */
+ def longValue = this.bigInteger.longValue
+
+ /** Converts this BigInt to a <tt>float</tt>.
+ * if this BigInt has too great a magnitude to represent as a float,
+ * it will be converted to <code>Float.NEGATIVE_INFINITY</code> or
+ * <code>Float.POSITIVE_INFINITY</code> as appropriate.
+ */
+ def floatValue = this.bigInteger.floatValue
+
+ /** Converts this BigInt to a <tt>double</tt>.
+ * if this BigInt has too great a magnitude to represent as a float,
+ * it will be converted to <code>Float.NEGATIVE_INFINITY</code> or
+ * <code>Float.POSITIVE_INFINITY</code> as appropriate.
+ */
+ def doubleValue = this.bigInteger.doubleValue
+
+ /** Returns the decimal String representation of this BigInt.
+ */
+ override def toString(): String = this.bigInteger.toString()
+
+ /** Returns the String representation in the specified radix of this BigInt.
+ */
+ def toString(radix: Int): String = this.bigInteger.toString(radix)
+
+ /** Returns a byte array containing the two's-complement representation of
+ * this BigInt. The byte array will be in big-endian byte-order: the most
+ * significant byte is in the zeroth element. The array will contain the
+ * minimum number of bytes required to represent this BigInt, including at
+ * least one sign bit.
+ */
+ def toByteArray: Array[Byte] = this.bigInteger.toByteArray()
+}
diff --git a/src/dotnet-library/scala/BufferedIterator.scala b/src/dotnet-library/scala/BufferedIterator.scala
new file mode 100644
index 0000000000..67d5016193
--- /dev/null
+++ b/src/dotnet-library/scala/BufferedIterator.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** Buffered iterators are iterators which allow to inspect the next
+ * element without discarding it.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+trait BufferedIterator[+A] extends Iterator[A] {
+
+ /** Checks what the next available element is.
+ *
+ * @return the current element
+ */
+ def head: A
+
+ override def buffered: BufferedIterator[A] = this
+}
diff --git a/src/dotnet-library/scala/ByNameFunction.scala b/src/dotnet-library/scala/ByNameFunction.scala
new file mode 100755
index 0000000000..bb423d5412
--- /dev/null
+++ b/src/dotnet-library/scala/ByNameFunction.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: PartialFunction.scala 7931 2006-06-20 16:34:51 +0000 (Tue, 20 Jun 2006) odersky $
+
+
+package scala;
+
+
+/** A partial function of type <code>PartialFunction[A, B]</code> is a
+ * unary function where the domain does not include all values of type
+ * <code>A</code>. The function <code>isDefinedAt</code> allows to
+ * test dynamically, if a value is in the domain of the function.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+trait ByNameFunction[-A, +B] extends AnyRef {
+ def apply(x: => A): B
+ override def toString() = "<function>"
+}
+
diff --git a/src/dotnet-library/scala/Cell.scala b/src/dotnet-library/scala/Cell.scala
new file mode 100644
index 0000000000..b9e3ed7a7e
--- /dev/null
+++ b/src/dotnet-library/scala/Cell.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** A <code>Cell</code> is a generic wrapper which completely
+ * hides the functionality of the wrapped object. The wrapped
+ * object is accessible via the <code>elem</code> accessor method.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 08/08/2003
+ */
+case class Cell[+T](elem: T)
diff --git a/src/dotnet-library/scala/ClassfileAttribute.scala b/src/dotnet-library/scala/ClassfileAttribute.scala
new file mode 100644
index 0000000000..f505906d80
--- /dev/null
+++ b/src/dotnet-library/scala/ClassfileAttribute.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Attribute.scala 8926 2006-10-11 09:58:51 +0000 (Wed, 11 Oct 2006) dragos $
+
+
+package scala
+
+/** <p>A base class for classfile attributes. These are stored as
+ * Java annotations in classfiles.
+ * </p>
+ *
+ * @author Martin Odersky
+ * @version 1.1, 2/02/2007
+ */
+trait ClassfileAttribute extends Attribute {}
diff --git a/src/dotnet-library/scala/Console.scala b/src/dotnet-library/scala/Console.scala
new file mode 100644
index 0000000000..488e091390
--- /dev/null
+++ b/src/dotnet-library/scala/Console.scala
@@ -0,0 +1,334 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import java.io.{InputStream, Reader, InputStreamReader, BufferedReader}
+import java.io.{OutputStream, PrintStream}
+import java.text.MessageFormat
+
+import scala.util.Fluid
+
+
+/** The <code>Console</code> object implements functionality for
+ * printing Scala values on the terminal. There are also functions
+ * for reading specific values. <code>Console</code> also defines
+ * constants for marking up text on ANSI terminals.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/09/2003
+ */
+object Console {
+
+ // ANSI colors foreground
+ final val BLACK = "\033[30m"
+ final val RED = "\033[31m"
+ final val GREEN = "\033[32m"
+ final val YELLOW = "\033[33m"
+ final val BLUE = "\033[34m"
+ final val MAGENTA = "\033[35m"
+ final val CYAN = "\033[36m"
+ final val WHITE = "\033[37m"
+
+ // ANSI colors background
+ final val BLACK_B = "\033[40m"
+ final val RED_B = "\033[41m"
+ final val GREEN_B = "\033[42m"
+ final val YELLOW_B = "\033[43m"
+ final val BLUE_B = "\033[44m"
+ final val MAGENTA_B = "\033[45m"
+ final val CYAN_B = "\033[46m"
+ final val WHITE_B = "\033[47m"
+
+ // ANSI styles
+ final val RESET = "\033[0m"
+ final val BOLD = "\033[1m"
+ final val UNDERLINED = "\033[4m"
+ final val BLINK = "\033[5m"
+ final val REVERSED = "\033[7m"
+ final val INVISIBLE = "\033[8m"
+
+ private val outFluid = new Fluid[PrintStream](java.lang.System.out)
+ private val inFluid = new Fluid[BufferedReader](
+ new BufferedReader(new InputStreamReader(java.lang.System.in)))
+
+ def out = outFluid.value
+ def in = inFluid.value
+
+ val err = java.lang.System.err
+
+ /** Set the default output stream.
+ *
+ * @param out the new output stream.
+ */
+ def setOut(out: PrintStream): Unit = outFluid.value = out
+
+ /** Set the default output stream for the duration
+ * of execution of one thunk.
+ *
+ * @param out the new output stream.
+ * @param thunk the code to execute with
+ * the new output stream active
+ * @return ...
+ */
+ def withOut[T](out: PrintStream)(thunk: =>T): T =
+ outFluid.withValue(out)(thunk)
+
+ /** Set the default output stream.
+ *
+ * @param@ out the new output stream.
+ */
+ def setOut(out: OutputStream): Unit =
+ setOut(new PrintStream(out))
+
+ /** Set the default output stream for the duration
+ * of execution of one thunk.
+ *
+ * @param out the new output stream.
+ * @param thunk the code to execute with
+ * the new output stream active
+ * @return ...
+ */
+ def withOut[T](out: OutputStream)(thunk: =>T): T =
+ withOut(new PrintStream(out))(thunk)
+
+
+ /** Set the default input stream.
+ *
+ * @param reader specifies the new input stream.
+ */
+ def setIn(reader: Reader): Unit = {
+ inFluid.value = new BufferedReader(reader)
+ }
+
+ /** Set the default input stream for the duration
+ * of execution of one thunk.
+ *
+ * @param in the new input stream.
+ * @param thunk the code to execute with
+ * the new input stream active
+ */
+ def withIn[T](reader: Reader)(thunk: =>T): T =
+ inFluid.withValue(new BufferedReader(reader))(thunk)
+
+
+ /** Set the default input stream.
+ *
+ * @param in the new input stream.
+ */
+ def setIn(in: InputStream): Unit =
+ setIn(new InputStreamReader(in))
+
+ /** Set the default input stream for the duration
+ * of execution of one thunk.
+ *
+ * @param in the new input stream.
+ * @param thunk the code to execute with
+ * the new input stream active
+ */
+ def withIn[T](in: InputStream)(thunk: =>T): T =
+ withIn(new InputStreamReader(in))(thunk)
+
+ /** Print an object on the terminal.
+ *
+ * @param obj the object to print.
+ */
+ def print(obj: Any): Unit =
+ out.print(if (null == obj) "null" else obj.toString())
+
+ /** Flush the output stream. This function is required when partial
+ * output (i.e. output not terminated by a new line character) has
+ * to be made visible on the terminal.
+ */
+ def flush: Unit = out.flush()
+
+ /** Print a new line character on the terminal.
+ */
+ def println: Unit = out.println()
+
+ /** Print out an object followed by a new line character.
+ *
+ * @param x the object to print.
+ */
+ def println(x: Any): Unit = out.println(x)
+
+ /** <p>
+ * Format and print out some text (in a fashion similar to printf in C or
+ * <code>printf</code> in Java 6).
+ * </p>
+ * <p>
+ * The format of the text to print is specified by the parameter
+ * <code>text</code>. The arguments that are inserted into specific
+ * locations in <code>text</code> are provided with parameter
+ * <code>args</code>. See class <a href="" target="contentFrame"
+ * class="java_text_MessageFormat"><code>java.text.MessageFormat</code></a>
+ * for a full specification of the <a href="#syntax" target="contentFrame"
+ * class="java_util_Formatter">format syntax</a>.
+ * </p>
+ *
+ * @param text the format of the text to print out.
+ * @param args the parameters used to instantiate the format.
+ * @throws java.lang.IllegalArgumentException
+ */
+ def printf(text: String, args: Any*): Unit = format(text, args: _*)
+
+ /**
+ * @see <a href="#printf(java.lang.String,scala.Any*)"
+ * target="contentFrame">Console.printf</a>.
+ */
+ def format(text: String, args: Any*): Unit =
+ out.print(
+ if (text eq null) "null"
+ else MessageFormat.format(text, textParams(args))
+ )
+
+ /** Read a full line from the terminal.
+ *
+ * @return the string read from the terminal.
+ */
+ def readLine: String = in.readLine()
+
+ /** Print a formatted text and read a full line from the terminal
+ *
+ * @param text the format of the text to print out.
+ * @param args the parameters used to instantiate the format.
+ * @return the string read from the terminal.
+ */
+ def readLine(text: String, args: Any*): String = {
+ format(text, args: _*)
+ readLine
+ }
+
+
+ /** Read a boolean value from the terminal.
+ *
+ * @return the boolean value read from the terminal.
+ */
+ def readBoolean: Boolean = readLine.toLowerCase() match {
+ case "true" => true
+ case "t" => true
+ case "yes" => true
+ case "y" => true
+ case _ => false
+ }
+
+ /** Read a byte value from the terminal.
+ */
+ def readByte: Byte = readLine.toByte
+
+ /** Read a short value from the terminal.
+ */
+ def readShort: Short = readLine.toByte
+
+ /** Read a char value from the terminal.
+ */
+ def readChar: Char = readLine charAt 0
+
+ /** Read an int value from the terminal.
+ */
+ def readInt: Int = readLine.toInt
+
+ /** Read a float value from the terminal.
+ */
+ def readFloat: Float = readLine.toFloat
+
+ /** Read a double value from the terminal.
+ */
+ def readDouble: Double = readLine.toDouble
+
+ /** Read in some structured input, specified by a format specifier.
+ * See class <code>java.text.MessageFormat</code> for details of
+ * the format specification.
+ *
+ * @param format the format of the input.
+ * @return a list of all extracted values.
+ */
+ def readf(format: String): List[Any] =
+ textComponents(new MessageFormat(format).parse(readLine))
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first value extracted from the input according to the format
+ * specification.
+ *
+ * @param format ...
+ * @return ...
+ */
+ def readf1(format: String): Any = readf(format).head
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first two values extracted from the input according to the format
+ * specification.
+ *
+ * @param format ...
+ * @return ...
+ */
+ def readf2(format: String): {Any, Any} = {
+ val res = readf(format)
+ {res.head, res.tail.head}
+ }
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first three values extracted from the input according to the format
+ * specification.
+ *
+ * @param format ...
+ * @return ...
+ */
+ def readf3(format: String): Triple[Any, Any, Any] = {
+ val res = readf(format)
+ {res.head, res.tail.head, res.tail.tail.head}
+ }
+
+ private def textComponents(a: Array[AnyRef]): List[Any] = {
+ var i: Int = a.length - 1
+ var res: List[Any] = Nil
+ while (i >= 0) {
+ res = (a(i) match {
+ case x: java.lang.Boolean => x.booleanValue()
+ case x: java.lang.Byte => x.byteValue()
+ case x: java.lang.Short => x.shortValue()
+ case x: java.lang.Character => x.charValue()
+ case x: java.lang.Integer => x.intValue()
+ case x: java.lang.Long => x.longValue()
+ case x: java.lang.Float => x.floatValue()
+ case x: java.lang.Double => x.doubleValue()
+ case x => x
+ }) :: res;
+ i = i - 1
+ }
+ res
+ }
+
+ private def textParams(s: Seq[Any]): Array[AnyRef] = {
+ val res = new Array[AnyRef](s.length);
+ var i: Int = 0;
+ val iter = s.elements;
+ while (iter.hasNext) {
+ res(i) = iter.next match {
+ case x: Boolean => new java.lang.Boolean(x)
+ case x: Byte => new java.lang.Byte(x)
+ case x: Short => new java.lang.Short(x)
+ case x: Char => new java.lang.Character(x)
+ case x: Int => new java.lang.Integer(x)
+ case x: Long => new java.lang.Long(x)
+ case x: Float => new java.lang.Float(x)
+ case x: Double => new java.lang.Double(x)
+ case x: Unit => "()"
+ case x: AnyRef => x
+ }
+ i = i + 1
+ }
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/CountedIterator.scala b/src/dotnet-library/scala/CountedIterator.scala
new file mode 100644
index 0000000000..ab95b97d52
--- /dev/null
+++ b/src/dotnet-library/scala/CountedIterator.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala;
+
+
+/** Counted iterators keep track of the number of elements seen so far
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+trait CountedIterator[+A] extends Iterator[A] {
+
+ /** counts the elements in this iterator; counts start at 0
+ */
+ def count: Int
+
+}
diff --git a/src/dotnet-library/scala/Enumeration.scala b/src/dotnet-library/scala/Enumeration.scala
new file mode 100644
index 0000000000..bdd2846272
--- /dev/null
+++ b/src/dotnet-library/scala/Enumeration.scala
@@ -0,0 +1,138 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import scala.collection.mutable.{Map, HashMap}
+
+/**
+ * <p>The class <code>Enumeration</code> provides the same functionality as the
+ * <code>enum</code> construct found in C-like languages like C++ or Java.
+ * Here is an example:</p>
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ *
+ * <b>object</b> WeekDays <b>extends</b> Enumeration {
+ * <b>val</b> Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ * }
+ *
+ * <b>def</b> isWorkingDay(d: WeekDays.Value) =
+ * ! (d == WeekDays.Sat || d == WeekDays.Sun)
+ *
+ * WeekDays filter (isWorkingDay) foreach { d =&gt; Console.println(d) }
+ * }
+ * </pre>
+ *
+ * @param initial the initial integer value associated with the first element
+ * @param names the sequence of element names of the enumeration
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/02/04
+ */
+abstract class Enumeration(initial: Int, names: String*) {
+
+ def this() = this(0, null)
+
+ def this(names: String*) = this(0, names: _*)
+
+ def name = {
+ val cname = this.getClass().getName()
+ if (cname.endsWith("$"))
+ cname.substring(0, cname.length() - 1)
+ else if (cname.endsWith("$class"))
+ cname.substring(0, cname.length() - 6)
+ else
+ cname
+ }
+
+ /**
+ * A mapping between the enumeration value id and the enumeration
+ * object.
+ */
+ private var values: Map[Int, Value] = new HashMap
+
+ /**
+ * A cache listing all values of this enumeration.
+ */
+ private var vcache: List[Value] = null
+
+ private def updateCache: List[Value] =
+ if (vcache eq null) {
+ vcache = values.values.toList.sort((p1, p2) => p1.id < p2.id);
+ vcache
+ } else
+ vcache;
+
+ protected var nextId = initial
+
+ protected var nextName = names.elements
+
+ private var topId = initial
+
+ final def maxId = topId
+
+ /**
+ * Returns the enumeration value for the given id.
+ */
+ final def apply(x: Int): Value = values(x)
+
+ /**
+ * Returns all values of this enumeration.
+ */
+ final def elements: Iterator[Value] = updateCache.elements
+
+ def foreach(f: Value => Unit): Unit = elements foreach f
+
+ def forall(p: Value => Boolean): Boolean = elements forall p
+
+ def exists(p: Value => Boolean): Boolean = elements exists p
+
+ def map[b](f: Value => b): Iterator[b] = elements map f
+
+ def flatMap[b](f: Value => Iterator[b]): Iterator[b] = elements flatMap f
+
+ def filter(p: Value => Boolean): Iterator[Value] = elements filter p
+
+ override def toString(): String = updateCache.mkString("{", ", ", "}")
+
+ protected final def Value: Value =
+ new Val(nextId, if (nextName.hasNext) nextName.next else null)
+
+ protected final def Value(i: Int): Value =
+ new Val(i, if (nextName.hasNext) nextName.next else null)
+
+ protected final def Value(name: String): Value = new Val(nextId, name)
+
+ protected final def Value(i: Int, name: String): Value = new Val(i, name)
+
+ abstract class Value extends Ordered[Value] {
+ def id: Int
+ override def compare(that: Value): Int = this.id - that.id
+ }
+
+ protected class Val(i: Int, name: String) extends Value {
+ def this(i: Int) =
+ this(i, if (nextName.hasNext) nextName.next else i.toString())
+ def this(name: String) = this(nextId, name)
+ def this() =
+ this(nextId, if (nextName.hasNext) nextName.next else nextId.toString())
+ assert(!values.isDefinedAt(i))
+ values(i) = this
+ nextId = i + 1
+ if (nextId > topId)
+ topId = nextId
+ def id = i
+ override def toString() =
+ if (name eq null) Enumeration.this.name + "(" + i + ")"
+ else name
+ }
+}
diff --git a/src/dotnet-library/scala/Function.scala b/src/dotnet-library/scala/Function.scala
new file mode 100644
index 0000000000..12e124779b
--- /dev/null
+++ b/src/dotnet-library/scala/Function.scala
@@ -0,0 +1,144 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** A module defining utility methods for higher-order functional programming.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 29/11/2006
+ */
+object Function {
+
+ /** Given a sequence of functions <code>f<sub>1</sub></code>, ...,
+ * <code>f<sub>n</sub></code>, return the function <code>f<sub>1</sub>
+ * andThen ... andThen f<sub>n</sub></code>.
+ *
+ * @param fs The given sequence of functions
+ * @return ...
+ */
+ def chain[a](fs: Seq[a => a]): a => a = { x => (x /: fs) ((x, f) => f(x)) }
+
+ /** Currying for functions of arity 2. This transforms a function
+ * of arity 2 into a a unary function returning another unary function.
+ *
+ * @param f ...
+ * @return ...
+ */
+ def curried[a1, a2, b](f: (a1, a2) => b): a1 => a2 => b = {
+ x1 => x2 => f(x1, x2)
+ }
+
+ /** Currying for functions of arity 3.
+ *
+ * @param f ...
+ * @return ...
+ */
+ def curried[a1, a2, a3, b](f: (a1, a2, a3) => b): a1 => a2 => a3 => b = {
+ x1 => x2 => x3 => f(x1, x2, x3)
+ }
+
+ /** Currying for functions of arity 4.
+ */
+ def curried[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) => b): a1 => a2 => a3 => a4 => b = {
+ x1 => x2 => x3 => x4 => f(x1, x2, x3, x4)
+ }
+
+ /** Currying for functions of arity 5.
+ */
+ def curried[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) => b): a1 => a2 => a3 => a4 => a5 => b = {
+ x1 => x2 => x3 => x4 => x5 => f(x1, x2, x3, x4, x5)
+ }
+
+ /** Uncurrying for functions of arity 2. This transforms a unary function
+ * returning another unary function into a function of arity 2.
+ */
+ def uncurried[a1, a2, b](f: a1 => a2 => b): (a1, a2) => b = {
+ (x1, x2) => f(x1)(x2)
+ }
+
+ /** Uncurrying for functions of arity 3.
+ */
+ def uncurried[a1, a2, a3, b](f: a1 => a2 => a3 => b): (a1, a2, a3) => b = {
+ (x1, x2, x3) => f(x1)(x2)(x3)
+ }
+
+ /** Uncurrying for functions of arity 4.
+ */
+ def uncurried[a1, a2, a3, a4, b](f: a1 => a2 => a3 => a4 => b): (a1, a2, a3, a4) => b = {
+ (x1, x2, x3, x4) => f(x1)(x2)(x3)(x4)
+ }
+
+ /** Uncurrying for functions of arity 5.
+ */
+ def uncurried[a1, a2, a3, a4, a5, b](f: a1 => a2 => a3 => a4 => a5 => b): (a1, a2, a3, a4, a5) => b = {
+ (x1, x2, x3, x4, x5) => f(x1)(x2)(x3)(x4)(x5)
+ }
+
+ /** Tupling for functions of arity 2. This transforms a function
+ * of arity 2 into a unary function that takes a pair of arguments.
+ *
+ * @param f ...
+ * @return ...
+ */
+ def tupled[a1, a2, b](f: (a1, a2) => b): Tuple2[a1, a2] => b = {
+ case Tuple2(x1, x2) => f(x1, x2)
+ }
+
+ /** Tupling for functions of arity 3. This transforms a function
+ * of arity 3 into a unary function that takes a triple of arguments.
+ */
+ def tupled[a1, a2, a3, b](f: (a1, a2, a3) => b): Tuple3[a1, a2, a3] => b = {
+ case Tuple3(x1, x2, x3) => f(x1, x2, x3)
+ }
+
+ /** Tupling for functions of arity 4. This transforms a function
+ * of arity 4 into a unary function that takes a 4-tuple of arguments.
+ */
+ def tupled[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) => b): Tuple4[a1, a2, a3, a4] => b = {
+ case Tuple4(x1, x2, x3, x4) => f(x1, x2, x3, x4)
+ }
+
+ /** Tupling for functions of arity 5. This transforms a function
+ * of arity 5 into a unary function that takes a 5-tuple of arguments.
+ */
+ def tupled[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) => b): Tuple5[a1, a2, a3, a4, a5] => b = {
+ case Tuple5(x1, x2, x3, x4, x5) => f(x1, x2, x3, x4, x5)
+ }
+
+ /** Un-tupling for functions of arity 2. This transforms a function taking
+ * a pair of arguments into a binary function which takes each argument separately.
+ */
+ def untupled[a1, a2, b](f: Tuple2[a1, a2] => b): (a1, a2) => b = {
+ (x1, x2) => f(Tuple2(x1, x2))
+ }
+
+ /** Un-tupling for functions of arity 3. This transforms a function taking
+ * a triple of arguments into a ternary function which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, b](f: Tuple3[a1, a2, a3] => b): (a1, a2, a3) => b = {
+ (x1, x2, x3) => f(Tuple3(x1, x2, x3))
+ }
+
+ /** Un-tupling for functions of arity 4. This transforms a function taking
+ * a 4-tuple of arguments into a function of arity 4 which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, a4, b](f: Tuple4[a1, a2, a3, a4] => b): (a1, a2, a3, a4) => b = {
+ (x1, x2, x3, x4) => f(Tuple4(x1, x2, x3, x4))
+ }
+
+ /** Un-tupling for functions of arity 5. This transforms a function taking
+ * a 5-tuple of arguments into a function of arity 5 which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, a4, a5, b](f: Tuple5[a1, a2, a3, a4, a5] => b): (a1, a2, a3, a4, a5) => b = {
+ (x1, x2, x3, x4, x5) => f(Tuple5(x1, x2, x3, x4, x5))
+ }
+}
diff --git a/src/dotnet-library/scala/Function0.scala b/src/dotnet-library/scala/Function0.scala
new file mode 100644
index 0000000000..0e2c20b93e
--- /dev/null
+++ b/src/dotnet-library/scala/Function0.scala
@@ -0,0 +1,42 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007 (with fancy comment)
+
+package scala
+
+
+/** <p>
+ * Function with 0 parameters.
+ * </p>
+ * <p>
+ In the following example the definition of
+ * <code>currentSeconds</code> is a shorthand for the anonymous class
+ * definition <code>anonfun0</code>:
+ * </p>
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ *
+ * <b>val</b> currentSeconds = () => System.currentTimeMillis() / 1000L
+ *
+ * <b>val</b> anonfun0 = <b>new</b> Function0[Long] {
+ * <b>def</b> apply(): Long = System.currentTimeMillis() / 1000L
+ * }
+ *
+ * Console.println(currentSeconds())
+ * Console.println(anonfun0())
+ * }</pre>
+ */
+trait Function0[+R] extends AnyRef {
+ def apply(): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function1.scala b/src/dotnet-library/scala/Function1.scala
new file mode 100644
index 0000000000..dc3e6529e5
--- /dev/null
+++ b/src/dotnet-library/scala/Function1.scala
@@ -0,0 +1,50 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007 (with fancy comment) (with extra methods)
+
+package scala
+
+
+/** <p>
+ * Function with 1 parameters.
+ * </p>
+ * <p>
+ In the following example the definition of
+ * <code>succ</code> is a shorthand for the anonymous class definition
+ * <code>anonfun1</code>:
+ * </p>
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ *
+ * <b>val</b> succ = (x: Int) => x + 1
+ *
+ * <b>val</b> anonfun1 = <b>new</b> Function1[Int, Int] {
+ * <b>def</b> apply(x: Int): Int = x + 1
+ * }
+ *
+ * Console.println(succ(0))
+ * Console.println(anonfun1(0))
+ * }</pre>
+ */
+trait Function1[-T1, +R] extends AnyRef {
+ def apply(v1:T1): R
+ override def toString() = "<function>"
+
+ /** (f compose g)(x) = f(g(x))
+ */
+ def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
+
+ /** (f andThen g)(x) = g(f(x))
+ */
+ def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
+
+}
diff --git a/src/dotnet-library/scala/Function2.scala b/src/dotnet-library/scala/Function2.scala
new file mode 100644
index 0000000000..12abf932f3
--- /dev/null
+++ b/src/dotnet-library/scala/Function2.scala
@@ -0,0 +1,42 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007 (with fancy comment)
+
+package scala
+
+
+/** <p>
+ * Function with 2 parameters.
+ * </p>
+ * <p>
+ In the following example the definition of
+ * <code>max</code> is a shorthand for the anonymous class definition
+ * <code>anonfun2</code>:
+ * </p>
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ *
+ * <b>val</b> max = (x: Int, y: Int) => <b>if</b> (x < y) y <b>else</b> x
+ *
+ * <b>val</b> anonfun2 = <b>new</b> Function2[Int, Int, Int] {
+ * <b>def</b> apply(x: Int, y: Int): Int = <b>if</b> (x < y) y <b>else</b> x
+ * }
+ *
+ * Console.println(max(0, 1))
+ * Console.println(anonfun2(0, 1))
+ * }</pre>
+ */
+trait Function2[-T1, -T2, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function3.scala b/src/dotnet-library/scala/Function3.scala
new file mode 100644
index 0000000000..419b9667ba
--- /dev/null
+++ b/src/dotnet-library/scala/Function3.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 3 parameters.
+ * </p>
+ *
+ */
+trait Function3[-T1, -T2, -T3, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function4.scala b/src/dotnet-library/scala/Function4.scala
new file mode 100644
index 0000000000..1d05de1902
--- /dev/null
+++ b/src/dotnet-library/scala/Function4.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 4 parameters.
+ * </p>
+ *
+ */
+trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3, v4:T4): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function5.scala b/src/dotnet-library/scala/Function5.scala
new file mode 100644
index 0000000000..beb41bb3c5
--- /dev/null
+++ b/src/dotnet-library/scala/Function5.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 5 parameters.
+ * </p>
+ *
+ */
+trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3, v4:T4, v5:T5): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function6.scala b/src/dotnet-library/scala/Function6.scala
new file mode 100644
index 0000000000..f678a64ae3
--- /dev/null
+++ b/src/dotnet-library/scala/Function6.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 6 parameters.
+ * </p>
+ *
+ */
+trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3, v4:T4, v5:T5, v6:T6): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function7.scala b/src/dotnet-library/scala/Function7.scala
new file mode 100644
index 0000000000..a8f64b42bd
--- /dev/null
+++ b/src/dotnet-library/scala/Function7.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 7 parameters.
+ * </p>
+ *
+ */
+trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3, v4:T4, v5:T5, v6:T6, v7:T7): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function8.scala b/src/dotnet-library/scala/Function8.scala
new file mode 100644
index 0000000000..757955ae7a
--- /dev/null
+++ b/src/dotnet-library/scala/Function8.scala
@@ -0,0 +1,26 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+
+/** <p>
+ * Function with 8 parameters.
+ * </p>
+ *
+ */
+trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef {
+ def apply(v1:T1, v2:T2, v3:T3, v4:T4, v5:T5, v6:T6, v7:T7, v8:T8): R
+ override def toString() = "<function>"
+
+}
diff --git a/src/dotnet-library/scala/Function9.scala b/src/dotnet-library/scala/Function9.scala
new file mode 100644
index 0000000000..bbac15ce5e
--- /dev/null
+++ b/src/dotnet-library/scala/Function9.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/**
+ * Function with 9 parameters
+ */
+trait Function9[-T0, -T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8): R
+ override def toString() = "<function>"
+}
diff --git a/src/dotnet-library/scala/Iterable.scala b/src/dotnet-library/scala/Iterable.scala
new file mode 100644
index 0000000000..916b0ecdf4
--- /dev/null
+++ b/src/dotnet-library/scala/Iterable.scala
@@ -0,0 +1,378 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import Predef.IllegalArgumentException
+import collection.mutable.{Buffer,ArrayBuffer}
+import compat.StringBuilder
+
+/** This object ...
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+object Iterable {
+/*
+ implicit def view[A <% Ordered[A]](x: Iterable[A]): Ordered[Iterable[A]] =
+ new Ordered[Iterable[A]] {
+ def compare[B >: Iterable[A] <% Ordered[B]](that: B): Int = that match {
+ case y: Iterable[A] =>
+ val xs = x.elements
+ val ys = y.elements
+ var res = 0
+ while (xs.hasNext && ys.hasNext && (res == 0)) {
+ res = xs.next compare ys.next
+ }
+ if (xs.hasNext) 1
+ else if (ys.hasNext) -1
+ else res
+ case _ =>
+ -(that compare x)
+ }
+ }
+*/
+ /** The minimum element of a non-empty sequence of ordered elements */
+ def min[A <% Ordered[A]](seq: Iterable[A]): A = {
+ val xs = seq.elements
+ if (!xs.hasNext) throw new IllegalArgumentException("min(<empty>)")
+ var min = xs.next
+ while (xs.hasNext) {
+ val x = xs.next
+ if (x < min) min = x
+ }
+ min
+ }
+
+ /** The maximum element of a non-empty sequence of ordered elements */
+ def max[A <% Ordered[A]](seq: Iterable[A]): A = {
+ val xs = seq.elements
+ if (!xs.hasNext) throw new IllegalArgumentException("max(<empty>)")
+ var max = xs.next
+ while (xs.hasNext) {
+ val x = xs.next
+ if (max < x) max = x
+ }
+ max
+ }
+
+ /** The empty iterable object */
+ val empty = new Iterable[Nothing] {
+ def elements = Iterator.empty
+ }
+}
+
+
+/** Collection classes mixing in this class provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+trait Iterable[+A] {
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A]
+
+ /** Appends two iterable objects.
+ *
+ * @return the new iterable object
+ * @deprecated use <code>++</code> instead
+ */
+ [deprecated] def concat[B >: A](that: Iterable[B]): Iterable[B] =
+ this ++ that
+
+ /** Appends two iterable objects.
+ *
+ * @return the new iterable object
+ */
+ def ++ [B >: A](that: Iterable[B]): Iterable[B] = {
+ val buf = new ArrayBuffer[B]
+ this copyToBuffer buf
+ that copyToBuffer buf
+ buf
+ }
+
+ /** Returns the iterable resulting from applying the given function
+ * <code>f</code> to each element of this iterable.
+ *
+ * @param f function to apply to each element.
+ * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code>
+ * if this iterable is <code>a<sub>0</sub>, ..., an</code>.
+ */
+ def map[B](f: A => B): Iterable[B] = {
+ val buf = new ArrayBuffer[B]
+ val elems = elements
+ while (elems.hasNext) buf += f(elems.next)
+ buf
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this iterable, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this iterable is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def flatMap[B](f: A => Iterable[B]): Iterable[B] = {
+ val buf = new ArrayBuffer[B]
+ val elems = elements
+ while (elems.hasNext) f(elems.next) copyToBuffer buf
+ buf
+ }
+
+ /** Returns all the elements of this iterable that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): Iterable[A] = {
+ val buf = new ArrayBuffer[A]
+ val elems = elements
+ while (elems.hasNext) { val x = elems.next; if (p(x)) buf += x }
+ buf
+ }
+
+ /** Returns the longest prefix of this iterable whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this iterable whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ def takeWhile(p: A => Boolean): Iterable[A] =
+ new ArrayBuffer[A] ++ elements.takeWhile(p)
+
+ /** Returns the longest suffix of this iterable whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the iterable whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ def dropWhile(p: A => Boolean): Iterable[A] =
+ new ArrayBuffer[A] ++ elements.dropWhile(p)
+
+ /** Returns an iterable consisting only over the first <code>n</code>
+ * elements of this iterable, or else the whole iterable, if it has less
+ * than <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the new iterable
+ */
+ def take(n: Int): Iterable[A] =
+ new ArrayBuffer[A] ++ elements.take(n)
+
+ /** Returns this iterable without its <code>n</code> first elements
+ * If this iterable has less than <code>n</code> elements, the empty
+ * iterable is returned.
+ *
+ * @param n the number of elements to drop
+ * @return the new iterable
+ */
+ def drop(n: Int): Iterable[A] =
+ new ArrayBuffer[A] ++ elements.take(n)
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ def foreach(f: A => Unit): Unit = elements.foreach(f)
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff the predicate yields
+ * true for all elements.
+ *
+ * @param p the predicate
+ * @return true, iff the predicate yields true for all elements.
+ */
+ def forall(p: A => Boolean): Boolean = elements.forall(p)
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields true.
+ *
+ * @param p the predicate
+ * @return true, iff the predicate yields true for at least one element.
+ */
+ def exists(p: A => Boolean): Boolean = elements.exists(p)
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = elements.find(p)
+
+ /** Returns index of the first element satisying a predicate, or -1.
+ *
+ * @param p the predicate
+ * @return the index of the first element satisfying <code>p</code>,
+ * or -1 if such an element does not exist
+ */
+ def findIndexOf(p: A => Boolean): Int = {
+ val it = elements
+ var i = 0
+ while (it.hasNext)
+ if (p(it.next))
+ return i
+ else
+ i = i + 1
+ return -1
+ }
+
+ /** Returns the index of the first occurence of the specified
+ * object in this iterable object.
+ *
+ * @param elem element to search for.
+ * @return the index in this sequence of the first occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def indexOf[B >: A](elem: B): Int = {
+ val it = elements
+ var i = 0
+ var found = false
+ while (!found && it.hasNext) {
+ if (it.next == elem) {
+ found = true
+ } else {
+ i = i + 1
+ }
+ }
+ if (found) i else -1
+ }
+
+ /** Combines the elements of this iterable object together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = elements.foldLeft(z)(op)
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op)
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ */
+ def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ */
+ def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ /** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the iterable object has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the iterable object is empty.
+ */
+ def reduceLeft[B >: A](op: (B, B) => B): B = elements.reduceLeft(op)
+
+/** Combines the elements of this iterable object together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the iterable object has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceRight[B >: A](op: (B, B) => B): B = elements.reduceRight(op)
+
+ /** Copy all elements to a given buffer
+ * @param dest The buffer to which elements are copied
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]): Unit = elements copyToBuffer dest
+
+ /** Checks if the other iterable object contains the same elements.
+ *
+ * @param that the other iterable object
+ * @return true, iff both iterable objects contain the same elements.
+ */
+ def sameElements[B >: A](that: Iterable[B]): Boolean = {
+ val ita = this.elements
+ val itb = that.elements
+ var res = true
+ while (res && ita.hasNext && itb.hasNext) {
+ res = (ita.next == itb.next)
+ }
+ !ita.hasNext && !itb.hasNext && res
+ }
+
+ /**
+ * @return a list with all the elements of this iterable object
+ */
+ def toList: List[A] = elements.toList
+
+ /** Returns a string representation of this iterable object. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * <p/>
+ * Ex: <br/>
+ * <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ *
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(start: String, sep: String, end: String): String = {
+ val buf = new StringBuilder()
+ addString(buf, start, sep, end).toString
+ }
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ *
+ * @param sep separator string.
+ * @return a string representation of this iterable object. */
+ def mkString(sep: String): String = this.mkString("", sep, "")
+
+ /** Write all elements of this string into given string builder */
+ def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ buf.append(start)
+ val elems = elements
+ if (elems.hasNext) buf.append(elems.next)
+ while (elems.hasNext) {
+ buf.append(sep); buf.append(elems.next)
+ }
+ buf.append(end)
+ }
+}
diff --git a/src/dotnet-library/scala/IterableProxy.scala b/src/dotnet-library/scala/IterableProxy.scala
new file mode 100644
index 0000000000..a69fc91dd4
--- /dev/null
+++ b/src/dotnet-library/scala/IterableProxy.scala
@@ -0,0 +1,54 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import scala.collection.mutable.Buffer
+import scala.compat.StringBuilder
+
+
+/** This class implements a proxy for iterable objects. It forwards
+ * all calls to a different iterable object.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+trait IterableProxy[+A] extends Iterable[A] with Proxy {
+
+ def self: Iterable[A]
+ override def elements: Iterator[A] = self.elements
+ [deprecated] override def concat [B >: A](that: Iterable[B]): Iterable[B] = self concat that
+ override def map[B](f: A => B): Iterable[B] = self map f
+ override def flatMap[B](f: A => Iterable[B]): Iterable[B] = self flatMap f
+ override def filter(p: A => Boolean): Iterable[A] = self filter p
+ override def takeWhile(p: A => Boolean): Iterable[A] = self takeWhile p
+ override def dropWhile(p: A => Boolean): Iterable[A] = self dropWhile p
+ override def take(n: Int): Iterable[A] = self take n
+ override def drop(n: Int): Iterable[A] = self drop n
+ override def foreach(f: A => Unit): Unit = self foreach f
+ override def forall(p: A => Boolean): Boolean = self forall p
+ override def exists(p: A => Boolean): Boolean = self exists p
+ override def find(p: A => Boolean): Option[A] = self find p
+ override def findIndexOf(p: A => Boolean): Int = self findIndexOf p
+ override def indexOf[B >: A](elem: B): Int = self indexOf elem
+ override def foldLeft[B](z: B)(op: (B, A) => B): B = (self foldLeft z)(op)
+ override def foldRight[B](z: B)(op: (A, B) => B): B = (self foldRight z)(op)
+ override def /:[B](z: B)(op: (B, A) => B): B = (z /: self)(op)
+ override def :\[B](z: B)(op: (A, B) => B): B = (self :\ z)(op)
+ override def reduceLeft[B >: A](op: (B, B) => B): B = self reduceLeft op
+ override def reduceRight[B >: A](op: (B, B) => B): B = self reduceRight op
+ override def sameElements[B >: A](that: Iterable[B]): Boolean = self sameElements that
+ override def copyToBuffer[B >: A](dest: Buffer[B]): Unit = self copyToBuffer dest
+ override def toList: List[A] = self.toList
+ override def mkString(start: String, sep: String, end: String): String = self.mkString(start, sep, end)
+ override def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = self.addString(buf, start, sep, end)
+}
diff --git a/src/dotnet-library/scala/Iterator.scala b/src/dotnet-library/scala/Iterator.scala
new file mode 100644
index 0000000000..a4f2c27c25
--- /dev/null
+++ b/src/dotnet-library/scala/Iterator.scala
@@ -0,0 +1,647 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import Predef._
+import collection.mutable.{Buffer, ArrayBuffer}
+import compat.StringBuilder
+
+/** The <code>Iterator</code> object provides various functions for
+ * creating specialized iterators.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+object Iterator {
+
+ val empty = new Iterator[Nothing] {
+ def hasNext: Boolean = false
+ def next: Nothing = throw new NoSuchElementException("next on empty iterator")
+ }
+
+ /**
+ * @param x the element
+ * @return the iterator with one single element
+ */
+ def single[a](x: a) = new Iterator[a] {
+ private var hasnext = true
+ def hasNext: Boolean = hasnext
+ def next: a =
+ if (hasnext) { hasnext = false; x }
+ else throw new NoSuchElementException("next on empty iterator")
+ }
+
+ def fromValues[a](xs: a*) = xs.elements
+
+ /**
+ * @param xs the array of elements
+ * @return the iterator on <code>xs</code>.
+ */
+ def fromArray[a](xs: Array[a]): Iterator[a] =
+ fromArray(xs, 0, xs.length)
+
+ /**
+ * @param xs the array of elements
+ * @param start ...
+ * @param length ...
+ * @return ...
+ */
+ def fromArray[a](xs: Array[a], start: Int, length: Int): Iterator[a] =
+ new BufferedIterator[a] {
+ private var i = start
+ val end = if ((start + length) < xs.length) start else xs.length
+ def hasNext: Boolean = i < end
+ def next: a = if (hasNext) { val x = xs(i) ; i = i + 1 ; x }
+ else throw new NoSuchElementException("next on empty iterator")
+ def head: a = if (hasNext) xs(i);
+ else throw new NoSuchElementException("head on empty iterator")
+ }
+
+ /**
+ * @param str the given string
+ * @return the iterator on <code>str</code>
+ */
+ def fromString(str: String): Iterator[Char] =
+ new BufferedIterator[Char] {
+ private var i = 0
+ private val len = str.length()
+ def hasNext = i < len
+ def next = { val c = str charAt i; i = i + 1; c }
+ def head = str charAt i
+ }
+
+ /**
+ * @param n the product arity
+ * @return the iterator on <code>Product&lt;n&gt;</code>.
+ */
+ def fromProduct(n: Product): Iterator[Any] = new Iterator[Any] {
+ private var c: Int = 0
+ private val cmax = n.arity
+ def hasNext = c < cmax
+ def next = { val a = n element c; c = c + 1; a }
+ }
+
+ /**
+ * @deprecated use <code>fromProduct</code> instead.
+ */
+ [deprecated] def fromCaseClass(n: Product) = fromProduct(n)
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @return the iterator with values in range <code>[lo;end)</code>.
+ */
+ def range(lo: Int, end: Int): Iterator[Int] =
+ range(lo, end, 1)
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment value of the iterator (must be positive or negative)
+ * @return the iterator with values in range <code>[lo;end)</code>.
+ */
+ def range(lo: Int, end: Int, step: Int): Iterator[Int] = {
+ assert(step != 0)
+ new BufferedIterator[Int] {
+ private var i = lo
+ def hasNext: Boolean = if (step > 0) i < end else i > end
+ def next: Int =
+ if (hasNext) { val j = i; i = i + step; j }
+ else throw new NoSuchElementException("next on empty iterator")
+ def head: Int =
+ if (hasNext) i
+ else throw new NoSuchElementException("head on empty iterator")
+ }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment function of the iterator
+ * @return the iterator with values in range <code>[lo;end)</code>.
+ */
+ def range(lo: Int, end: Int, step: Int => Int): Iterator[Int] =
+ new BufferedIterator[Int] {
+ private var i = lo
+ def hasNext: Boolean = i < end
+ def next: Int =
+ if (i < end) { val j = i; i = step(i); j }
+ else throw new NoSuchElementException("next on empty iterator")
+ def head: Int =
+ if (i < end) i
+ else throw new NoSuchElementException("head on empty iterator")
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int): Iterator[Int] =
+ from(lo, 1)
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param step the increment value of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int, step: Int): Iterator[Int] =
+ new BufferedIterator[Int] {
+ private var i = lo
+ def hasNext: Boolean = true
+ def next: Int = { val j = i; i = i + step; j }
+ def head: Int = i
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param step the increment function of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int, step: Int => Int): Iterator[Int] =
+ new BufferedIterator[Int] {
+ private var i = lo
+ def hasNext: Boolean = true
+ def next: Int = { val j = i; i = step(i); j }
+ def head: Int = i
+ }
+
+}
+
+/** Iterators are data structures that allow to iterate over a sequence
+ * of elements. They have a <code>hasNext</code> method for checking
+ * if there is a next element available, and a <code>next</code> method
+ * which returns the next element and discards it from the iterator.
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 1.2, 15/03/2004
+ */
+trait Iterator[+A] {
+
+ /** Does this iterator provide another element?
+ */
+ def hasNext: Boolean
+
+ /** Returns the next element.
+ */
+ def next: A
+
+ /** Returns a new iterator that iterates only over the first <code>n</code>
+ * elements.
+ *
+ * @param n the number of elements to take
+ * @return the new iterator
+ */
+ def take(n: Int) = new Iterator[A] {
+ var remaining = n
+ def hasNext = remaining > 0 && Iterator.this.hasNext
+ def next: A =
+ if (hasNext) { remaining = remaining - 1; Iterator.this.next }
+ else throw new NoSuchElementException("next on empty iterator")
+ }
+
+ /** Removes the first <code>n</code> elements from this iterator.
+ *
+ * @param n the number of elements to drop
+ * @return the new iterator
+ */
+ def drop(n: Int): Iterator[A] =
+ if (n > 0) { next; drop(n - 1) } else this
+
+ /** Returns a new iterator that maps all elements of this iterator
+ * to new elements using function <code>f</code>.
+ */
+ def map[B](f: A => B): Iterator[B] = new Iterator[B] {
+ def hasNext = Iterator.this.hasNext
+ def next = f(Iterator.this.next)
+ }
+
+ /** Returns a new iterator that first yields the elements of this
+ * iterator followed by the elements provided by iterator <code>that</code>.
+ * @deprecated use <code>++</code>
+ */
+ def append[B >: A](that: Iterator[B]) = new Iterator[B] {
+ def hasNext = Iterator.this.hasNext || that.hasNext
+ def next = if (Iterator.this.hasNext) Iterator.this.next else that.next
+ }
+
+ /** Returns a new iterator that first yields the elements of this
+ * iterator followed by the elements provided by iterator <code>that</code>.
+ */
+ def ++[B >: A](that: Iterator[B]) = new Iterator[B] {
+ def hasNext = Iterator.this.hasNext || that.hasNext
+ def next = if (Iterator.this.hasNext) Iterator.this.next else that.next
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this iterator, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return an iterator over <code>f(a<sub>0</sub>), ... ,
+ * f(a<sub>n</sub>)</code> if this iterator yields the
+ * elements <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ def flatMap[B](f: A => Iterator[B]): Iterator[B] = new Iterator[B] {
+ private var cur: Iterator[B] = Iterator.empty
+ def hasNext: Boolean =
+ if (cur.hasNext) true
+ else if (Iterator.this.hasNext) {
+ cur = f(Iterator.this.next)
+ hasNext
+ } else false
+ def next: B =
+ if (cur.hasNext) cur.next
+ else if (Iterator.this.hasNext) {
+ cur = f(Iterator.this.next)
+ next
+ } else throw new NoSuchElementException("next on empty iterator")
+ }
+
+ private def predicatedIterator(p: A => boolean, isFilter: boolean) = new BufferedIterator[A] {
+ private var hd: A = _
+ private var ahead: Boolean = false
+ private var hasMore = Iterator.this.hasNext
+ private def skip: Unit =
+ while (!ahead && hasMore) {
+ hd = Iterator.this.next
+ hasMore = Iterator.this.hasNext
+ ahead = p(hd)
+ }
+ def hasNext: Boolean = { skip; ahead || isFilter && hasMore }
+ def next: A =
+ if (hasNext) { ahead = false; hd }
+ else throw new NoSuchElementException("next on empty iterator")
+ def head: A = { skip; hd }
+ }
+
+ /** Returns an iterator over all the elements of this iterator that
+ * satisfy the predicate <code>p</code>. The order of the elements
+ * is preserved.
+ *
+ * @param p the predicate used to filter the iterator.
+ * @return the elements of this iterator satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): Iterator[A] = predicatedIterator(p, true)
+
+ /** Returns an iterator over the longest prefix of this iterator such that
+ * all elements of the result satisfy the predicate <code>p</code>.
+ * The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the iterator.
+ * @return the longest prefix of this iterator satisfying <code>p</code>.
+ */
+ def takeWhile(p: A => Boolean): Iterator[A] = predicatedIterator(p, false)
+
+ /** Skips longest sequence of elements of this iterator which satisfy given
+ * predicate <code>p</code>, and returns an iterator of the remaining elements.
+ *
+ * @param p the predicate used to skip elements.
+ * @return an iterator consisting of the remaining elements
+ */
+ def dropWhile(p: A => Boolean): Iterator[A] =
+ if (hasNext) {
+ val x = next
+ if (p(x)) dropWhile(p)
+ else Iterator.single(x) append this
+ } else this
+
+ /** Return an iterator formed from this iterator and the specified iterator
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two iterators is longer than the other, its remaining elements are ignored.
+ *
+ * @return an iterator yielding <code>{a<sub>0</sub>,b<sub>0</sub>},
+ * {a<sub>1</sub>,b<sub>1</sub>}, ...</code> where
+ * <code>a<sub>i</sub></code> are the elements from this iterator
+ * and <code>b<sub>i</sub></code> are the elements from iterator
+ * <code>that</code>.
+ */
+ def zip[B](that: Iterator[B]) = new Iterator[{A, B}] {
+ def hasNext = Iterator.this.hasNext && that.hasNext
+ def next = {Iterator.this.next, that.next}
+ }
+
+ /** Return an iterator that pairs each element of this iterator
+ * with its index, counting from 0.
+ *
+ * @param start the index of the first element.
+ * @return an iterator yielding <code>{a<sub>0</sub>,0},
+ * {a<sub>1</sub>,1}...</code> where <code>a<sub>i</sub></code>
+ * are the elements from this iterator.
+ */
+ def zipWithIndex = new Iterator[{A, int}] {
+ var idx = 0
+ def hasNext = Iterator.this.hasNext
+ def next = {
+ val ret = {Iterator.this.next, idx}
+ idx = idx + 1
+ ret
+ }
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ def foreach(f: A => Unit): Unit = while (hasNext) f(next)
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return <code>true</code> iff the predicate yields
+ * <code>true</code> for all elements.
+ *
+ * @param p the predicate
+ * @return <code>true</code> iff the predicate yields <code>true</code>
+ * for all elements.
+ */
+ def forall(p: A => Boolean): Boolean = {
+ var res = true
+ while (res && hasNext) { res = p(next) }
+ res
+ }
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields <code>true</code>.
+ *
+ * @param p the predicate
+ * @return <code>true</code> iff the predicate yields <code>true</code>
+ * for at least one element.
+ */
+ def exists(p: A => Boolean): Boolean = {
+ var res = false
+ while (!res && hasNext) { res = p(next) }
+ res
+ }
+
+ /** Tests if the given value <code>elem</code> is a member of this iterator.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return <code>true</code> iff there is an element of this iterator which
+ * is equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists { x => x == elem }
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying
+ * <code>p</code>, or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = {
+ var res: Option[A] = None
+ while (res.isEmpty && hasNext) {
+ val e = next
+ if (p(e)) res = Some(e)
+ }
+ res
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>op(... (op(op(z,a<sub>0</sub>),a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the iterator yields elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var acc = z
+ while (hasNext) { acc = op(acc, next) }
+ acc
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n</sub> op z)...)</code>
+ * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = {
+ def fold(z: B): B = if (hasNext) op(next, fold(z)) else z
+ fold(z)
+ }
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of iterator and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>.
+ *
+ * @param z the left argument of the first application of <code>op</code>
+ * (evaluation occurs from left to right).
+ * @param op the applied operator.
+ * @return the result value
+ * @see <code><a href="#foldLeft">foldLeft</a></code>.
+ */
+ def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>.
+ *
+ * @param z the right argument of the first application of <code>op</code>
+ * (evaluation occurs from right to left).
+ * @param op the applied operator.
+ * @return the result value.
+ * @see <code><a href="#foldRight">foldRight</a></code>.
+ */
+ def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the iterator yields elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceLeft[B >: A](op: (B, B) => B): B = {
+ if (hasNext) foldLeft[B](next)(op)
+ else throw new UnsupportedOperationException("empty.reduceLeft")
+ }
+
+ /** Combines the elements of this iterator together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the iterator yields elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+
+ * @throws Predef.UnsupportedOperationException if the iterator is empty.
+ */
+ def reduceRight[B >: A](op: (B, B) => B): B = {
+ if (!hasNext) throw new UnsupportedOperationException("empty.reduceRight")
+ val x = next
+ if (hasNext) op(x, reduceRight(op))
+ else x
+ }
+
+ /** Returns a buffered iterator from this iterator.
+ */
+ def buffered: BufferedIterator[A] = new BufferedIterator[A] {
+ private var hd: A = _
+ private var ahead: Boolean = false
+ def head: A = {
+ if (!ahead) {
+ hd = Iterator.this.next
+ ahead = true
+ }
+ hd
+ }
+ def next: A =
+ if (ahead) { ahead = false; hd } else head;
+ def hasNext: Boolean = ahead || Iterator.this.hasNext
+ }
+
+ /** Returns a counted iterator from this iterator.
+ */
+ def counted = new CountedIterator[A] {
+ private var cnt = -1
+ def count = cnt
+ def hasNext: Boolean = Iterator.this.hasNext
+ def next: A = { cnt = cnt + 1; Iterator.this.next }
+ }
+
+ /** Creates two new iterators that both iterate over the same elements
+ * than this iterator (in the same order).
+ *
+ * @return a pair of iterators
+ */
+ def duplicate: {Iterator[A], Iterator[A]} = {
+ var xs: List[A] = Nil
+ var ahead: Iterator[A] = null
+ class Partner extends Iterator[A] {
+ var ys: List[A] = Nil
+ def hasNext: Boolean = Iterator.this.synchronized (
+ ((this == ahead) && Iterator.this.hasNext) ||
+ ((this != ahead) && (!xs.isEmpty || !ys.isEmpty || Iterator.this.hasNext))
+ )
+ def next: A = Iterator.this.synchronized {
+ if (this == ahead) {
+ val e = Iterator.this.next
+ xs = e :: xs; e
+ } else {
+ if (ys.isEmpty) {
+ ys = xs.reverse
+ xs = Nil
+ }
+ ys match {
+ case Nil =>
+ val e = Iterator.this.next
+ ahead = this
+ xs = e :: xs; e
+ case z :: zs =>
+ ys = zs; z
+ }
+ }
+ }
+ }
+ ahead = new Partner
+ {ahead, new Partner}
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start the starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int): Unit = {
+ var i = start
+ while (hasNext) {
+ xs(i) = next
+ i = i + 1
+ }
+ }
+
+ /** Copy all elements to a buffer
+ * @param The buffer to which elements are copied
+ * @return The buffer to which elements are copied
+ */
+ def copyToBuffer[B >: A](dest: Buffer[B]): Unit =
+ while (hasNext) dest += next
+
+ /** Transform this iterator into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this iterator.
+ */
+ def toList: List[A] = {
+ val res = new collection.mutable.ListBuffer[A]
+ while (hasNext) {
+ res += next
+ }
+ res.toList
+ }
+
+ /** Returns a string representation of the elements in this iterator. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * <p/>
+ * Ex: <br/>
+ * <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ *
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this iterable object.
+ */
+ def mkString(start: String, sep: String, end: String): String = {
+ val buf = new StringBuilder()
+ addString(buf, start, sep, end).toString
+ }
+
+ /** Returns a string representation of this iterable object. The string
+ * representations of elements (w.r.t. the method <code>toString()</code>)
+ * are separated by the string <code>sep</code>.
+ *
+ * @param sep separator string.
+ * @return a string representation of this iterable object. */
+ def mkString(sep: String): String = this.mkString("", sep, "")
+
+ /** Write all elements of this string into given string builder */
+ def addString(buf: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ buf.append(start)
+ val elems = this
+ if (elems.hasNext) buf.append(elems.next)
+ while (elems.hasNext) {
+ buf.append(sep); buf.append(elems.next)
+ }
+ buf.append(end)
+ }
+}
diff --git a/src/dotnet-library/scala/List.scala b/src/dotnet-library/scala/List.scala
new file mode 100644
index 0000000000..25b7032ca9
--- /dev/null
+++ b/src/dotnet-library/scala/List.scala
@@ -0,0 +1,1159 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import scala.collection.mutable.ListBuffer
+import Predef._
+
+/** This object provides methods for creating specialized lists, and for
+ * transforming special kinds of lists (e.g. lists of lists).
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 15/07/2003
+ */
+object List {
+
+ /** Create a list with given elements.
+ *
+ * @param xs the elements to put in the list
+ * @return the list containing elements xs.
+ */
+ def apply[A](xs: A*): List[A] = xs.toList
+
+ /** for unapply matching
+ */
+ def unapplySeq[A](x: List[A]): Option[List[A]] = Some(x)
+
+ /** Create a sorted list of all integers in a range.
+ *
+ * @param from the start value of the list
+ * @param end the end value of the list
+ * @return the sorted list of all integers in range [from;end).
+ */
+ def range(from: Int, end: Int): List[Int] =
+ range(from, end, 1)
+
+ /** Create a sorted list of all integers in a range.
+ *
+ * @param from the start value of the list
+ * @param end the end value of the list
+ * @param step the increment value of the list
+ * @return the sorted list of all integers in range [from;end).
+ */
+ def range(from: Int, end: Int, step: Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = from
+ while (i < end) {
+ b += i
+ i = i + step
+ }
+ b.toList
+ }
+
+ /** Create a sorted list of all integers in a range.
+ *
+ * @param from the start value of the list
+ * @param end the end value of the list
+ * @param step the increment function of the list
+ * @return the sorted list of all integers in range [from;end).
+ */
+ def range(from: Int, end: Int, step: Int => Int): List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = from
+ while (i < end) {
+ b += i
+ i = i + step(i)
+ }
+ b.toList
+ }
+
+ /** Create a list containing several copies of an element.
+ *
+ * @param n the length of the resulting list
+ * @param elem the element composing the resulting list
+ * @return a list composed of n elements all equal to elem
+ */
+ def make[a](n: Int, elem: a): List[a] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ while (i < n) {
+ b += elem
+ i = i + 1
+ }
+ b.toList
+ }
+
+ /** Create a list by applying a function to successive integers.
+ *
+ * @param n the length of the resulting list
+ * @param maker the procedure which, given an integer <code>n</code>,
+ * returns the nth element of the resulting list, where
+ * <code>n</code> is in interval <code>[0;n)</code>.
+ * @return the list obtained by applying the maker function to
+ * successive integers from 0 to n (exclusive).
+ */
+ def tabulate[a](n: Int, maker: Int => a): List[a] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ while (i < n) {
+ b += maker(i)
+ i = i + 1
+ }
+ b.toList
+ }
+
+ /** Concatenate all the elements of a given list of lists.
+ *
+ * @param xss the list of lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def flatten[a](xss: List[List[a]]): List[a] = concat(xss: _*)
+
+ /** Concatenate all the argument lists into a single list.
+ *
+ * @param xss the lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def concat[a](xss: List[a]*): List[a] = {
+ val b = new ListBuffer[a]
+ for (val xs <- xss) {
+ var xc = xs
+ while (!xc.isEmpty) {
+ b += xc.head
+ xc = xc.tail
+ }
+ }
+ b.toList
+ }
+
+ /** Transforms a list of pair into a pair of lists.
+ *
+ * @param xs the list of pairs to unzip
+ * @return a pair of lists: the first list in the pair contains the list
+ */
+ def unzip[a,b](xs: List[{a,b}]): {List[a], List[b]} = {
+ val b1 = new ListBuffer[a]
+ val b2 = new ListBuffer[b]
+ var xc = xs
+ while (!xc.isEmpty) {
+ b1 += xc.head._1
+ b2 += xc.head._2
+ xc = xc.tail
+ }
+ {b1.toList, b2.toList}
+ }
+
+ /** Converts an iterator to a list
+ *
+ * @param it the iterator to convert
+ * @return a list that contains the elements returned by successive
+ * calls to <code>it.next</code>
+ */
+ def fromIterator[a](it: Iterator[a]): List[a] = it.toList;
+
+ /** Converts an array into a list.
+ *
+ * @param arr the array to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[a](arr: Array[a]): List[a] = fromArray(arr, 0, arr.length);
+
+ /** Converts a range of an array into a list.
+ *
+ * @param arr the array to convert
+ * @param start the first index to consider
+ * @param len the lenght of the range to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[a](arr: Array[a], start: Int, len: Int): List[a] = {
+ var res: List[a] = Nil
+ var i = start + len
+ while (i > start) {
+ i = i - 1
+ res = arr(i) :: res
+ }
+ res
+ }
+
+ /** Parses a string which contains substrings separated by a
+ * separator character and returns a list of all substrings.
+ *
+ * @param str the string to parse
+ * @param separator the separator character
+ * @return the list of substrings
+ */
+ def fromString(str: String, separator: Char): List[String] = {
+ var words: List[String] = List()
+ var pos = str.length()
+ while (pos > 0) {
+ val pos1 = str.lastIndexOf(separator, pos - 1)
+ if (pos1 + 1 < pos)
+ words = str.substring(pos1 + 1, pos) :: words
+ pos = pos1
+ }
+ words
+ }
+
+ /** Returns the given string as a list of characters.
+ *
+ * @param str the string to convert.
+ * @return the string as a list of characters.
+ */
+ def fromString(str: String): List[Char] =
+ Iterator.fromString(str).toList
+
+ /** Returns the given list of characters as a string.
+ *
+ * @param xs the list to convert.
+ * @return the list in form of a string.
+ */
+ def toString(xs: List[Char]): String = {
+ val sb = new compat.StringBuilder()
+ var xc = xs
+ while (!xc.isEmpty) {
+ sb.append(xc.head)
+ xc = xc.tail
+ }
+ sb.toString()
+ }
+
+ /** Like xs map f, but returns <code>xs</code> unchanged if function
+ * <code>f</code> maps all elements to themselves.
+ *
+ * @param xs ...
+ * @param f ...
+ * @return ...
+ */
+ def mapConserve[a <: AnyRef](xs: List[a])(f: a => a): List[a] = {
+ def loop(ys: List[a]): List[a] =
+ if (ys.isEmpty) xs
+ else {
+ val head0 = ys.head
+ val head1 = f(head0)
+ if (head1 eq head0) {
+ loop(ys.tail)
+ } else {
+ val ys1 = head1 :: mapConserve(ys.tail)(f)
+ if (xs eq ys) ys1
+ else {
+ val b = new ListBuffer[a]
+ var xc = xs
+ while (xc ne ys) {
+ b += xc.head
+ xc = xc.tail
+ }
+ b.prependToList(ys1)
+ }
+ }
+ }
+ loop(xs)
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code>
+ * to corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def map2[a,b,c](xs: List[a], ys: List[b])(f: (a, b) => c): List[c] = {
+ val b = new ListBuffer[c]
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ b += f(xc.head, yc.head)
+ xc = xc.tail
+ yc = yc.tail
+ }
+ b.toList
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code> to
+ * corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0,c0), ..., f(an,bn,cn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code>, <code>[c0, ..., cm]</code> and
+ * <code>n = min(k,l,m)</code>
+ */
+ def map3[a,b,c, d](xs: List[a], ys: List[b], zs: List[c])(f: (a, b, c) => d): List[d] = {
+ val b = new ListBuffer[d]
+ var xc = xs
+ var yc = ys
+ var zc = zs
+ while (!xc.isEmpty && !yc.isEmpty && !zc.isEmpty) {
+ b += f(xc.head, yc.head, zc.head)
+ xc = xc.tail
+ yc = yc.tail
+ zc = zc.tail
+ }
+ b.toList
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for all corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n == 0 || (p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
+ * ... &amp;&amp; p(a<sub>n</sub>,b<sub>n</sub>))]</code>
+ * if the lists are <code>[a<sub>0</sub>, ..., a<sub>k</sub>]</code>;
+ * <code>[b<sub>0</sub>, ..., b<sub>l</sub>]</code>
+ * and <code>m = min(k,l)</code>
+ */
+ def forall2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (!f(xc.head, yc.head)) return false
+ xc = xc.tail
+ yc = yc.tail
+ }
+ true
+ }
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for some corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n != 0 &amp;&amp; (p(a0,b0) || ... || p(an,bn))]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = min(k,l)</code>
+ */
+ def exists2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean = {
+ var xc = xs
+ var yc = ys
+ while (!xc.isEmpty && !yc.isEmpty) {
+ if (f(xc.head, yc.head)) return true
+ xc = xc.tail
+ yc = yc.tail
+ }
+ false
+ }
+
+ /** Transposes a list of lists.
+ * pre: All element lists have the same length.
+ */
+ def transpose[a](xss: List[List[a]]): List[List[a]] =
+ if (xss.head.isEmpty) List()
+ else (xss map (xs => xs.head)) :: transpose(xss map (xs => xs.tail))
+
+ /** Lists with ordered elements are ordered
+ implicit def list2ordered[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] {
+ def compare [b >: List[a] <% Ordered[b]](y: b): Int = y match {
+ case y1: List[a] => compareLists(x, y1);
+ case _ => -(y compare x)
+ }
+ private def compareLists(xs: List[a], ys: List[a]): Int = {
+ if (xs.isEmpty && ys.isEmpty) 0
+ else if (xs.isEmpty) -1
+ else if (ys.isEmpty) 1
+ else {
+ val s = xs.head compare ys.head;
+ if (s != 0) s
+ else compareLists(xs.tail, ys.tail)
+ }
+ }
+ }
+ */
+}
+
+/** A class representing an ordered collection of elements of type
+ * <code>a</code>. This class comes with two implementing case
+ * classes <code>scala.Nil</code> and <code>scala.::</code> that
+ * implement the abstract members <code>isEmpty</code>,
+ * <code>head</code> and <code>tail</code>.
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 16/07/2003
+ */
+sealed abstract class List[+a] extends Seq[a] {
+
+ /** Returns true if the list does not contain any elements.
+ * @return <code>true</code>, iff the list is empty.
+ */
+ override def isEmpty: Boolean
+
+ /** Returns this first element of the list.
+ *
+ * @return the first element of this list.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def head: a
+
+ /** Returns this list without its first element.
+ *
+ * @return this list without its first element.
+ * @throws Predef.NoSuchElementException if the list is empty.
+ */
+ def tail: List[a]
+
+ /** <p>
+ * Add an element <code>x</code> at the beginning of this list.
+ * Example:
+ * </p>
+ * <pre>
+ * 1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)</pre>
+ *
+ * @param x the element to append.
+ * @return the list with <code>x</code> appended at the beginning.
+ */
+ def ::[b >: a] (x: b): List[b] =
+ new scala.::(x, this)
+
+ /** <p>
+ * Returns a list resulting from the concatenation of the given
+ * list <code>prefix</code> and this list. Example:
+ * </p>
+ * <pre>
+ * List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)</pre>
+ *
+ * @param prefix the list to concatenate at the beginning of this list.
+ * @return the concatenation of the two lists.
+ */
+ def :::[b >: a](prefix: List[b]): List[b] =
+ if (isEmpty) prefix
+ else {
+ val b = new ListBuffer[b]
+ var those = prefix
+ while (!those.isEmpty) {
+ b += those.head
+ those = those.tail
+ }
+ b.prependToList(this)
+ }
+
+ /** Reverse the given prefix and append the current list to that.
+ * This function is equivalent to an application of <code>reverse</code>
+ * on the prefix followed by a call to <code>:::</code>, but more
+ * efficient (and tail recursive).
+ *
+ * @param prefix the prefix to reverse and then prepend
+ * @return the concatenation of the reversed prefix and the current list.
+ */
+ def reverse_:::[b >: a](prefix: List[b]): List[b] = prefix match {
+ case Nil => this
+ case head :: tail => tail.reverse_:::(head :: this)
+ }
+
+ /** Returns the number of elements in the list.
+ *
+ * @return the number of elements in the list.
+ */
+ def length: Int = {
+ var these = this
+ var len = 0
+ while (!these.isEmpty) {
+ len = len + 1
+ these = these.tail
+ }
+ len
+ }
+
+ /** Creates a list with all indices in the list. This is
+ * equivalent to a call to <code>List.range(0, xs.length)</code>.
+ *
+ * @return a list of all indices in the list.
+ */
+ def indices: List[Int] = {
+ val b = new ListBuffer[Int]
+ var i = 0
+ var these = this
+ while (!these.isEmpty) {
+ b += i
+ i = i + 1
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the elements in the list as an iterator
+ *
+ * @return an iterator on the list elements.
+ */
+ def elements: Iterator[a] = new Iterator[a] {
+ var these = List.this
+ def hasNext: Boolean = !these.isEmpty
+ def next: a =
+ if (!hasNext)
+ throw new NoSuchElementException("next on empty Iterator")
+ else {
+ val result = these.head; these = these.tail; result
+ }
+ override def toList: List[a] = these
+ }
+
+ /** Overrides the method in Iterable for efficiency.
+ *
+ * @return the list itself
+ */
+ override def toList: List[a] = this
+
+ /** Returns the list without its last element.
+ *
+ * @return the list without its last element.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ def init: List[a] =
+ if (isEmpty) throw new UnsupportedOperationException("Nil.init")
+ else {
+ val b = new ListBuffer[a]
+ var elem = head
+ var next = tail
+ while (!next.isEmpty) {
+ b += elem
+ elem = next.head
+ next = next.tail
+ }
+ b.toList
+ }
+
+ /** Returns the last element of this list.
+ *
+ * @return the last element of the list.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ def last: a =
+ if (isEmpty) throw new Predef.NoSuchElementException("Nil.last")
+ else if (tail.isEmpty) head
+ else tail.last
+
+ /** Returns the <code>n</code> first elements of this list, or else the whole
+ * list, if it has less than <code>n</code> elements.
+ *
+ * @param n the number of elements to take.
+ * @return the <code>n</code> first elements of this list.
+ */
+ override def take(n: Int): List[a] = {
+ val b = new ListBuffer[a]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i = i + 1
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the list without its <code>n</code> first elements.
+ * If this list has less than <code>n</code> elements, the empty list is returned.
+ *
+ * @param n the number of elements to drop.
+ * @return the list without its <code>n</code> first elements.
+ */
+ override def drop(n: Int): List[a] =
+ if (n == 0 || isEmpty) this
+ else (tail drop (n-1))
+
+ /** Returns the rightmost <code>n</code> elements from this list.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ */
+ def takeRight(n: Int): List[a] = {
+ def loop(lead: List[a], lag: List[a]): List[a] = lead match {
+ case Nil => lag
+ case _ :: tail => loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Returns the list wihout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ */
+ def dropRight(n: Int): List[a] = {
+ def loop(lead: List[a], lag: List[a]): List[a] = lead match {
+ case Nil => Nil
+ case _ :: tail => lag.head :: loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Split the list at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of lists composed of the first <code>n</code>
+ * elements, and the other elements.
+ */
+ def splitAt(n: Int): {List[a], List[a]} = {
+ val b = new ListBuffer[a]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i = i + 1
+ b += these.head
+ these = these.tail
+ }
+ {b.toList, these}
+ }
+
+ /** Returns the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ override def takeWhile(p: a => Boolean): List[a] = {
+ val b = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Returns the longest suffix of this list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ override def dropWhile(p: a => Boolean): List[a] =
+ if (isEmpty || !p(head)) this
+ else tail dropWhile p;
+
+ /** Returns the longest prefix of the list whose elements all satisfy
+ * the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ */
+ def span(p: a => Boolean): {List[a], List[a]} = {
+ val b = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ {b.toList, these}
+ }
+
+ /** Like <code>span</code> but with the predicate inverted.
+ */
+ def break(p: a => Boolean): {List[a], List[a]} = span { x => !p(x) }
+
+ /** Returns the <code>n</code>-th element of this list. The first element
+ * (head of the list) is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this list.
+ * @throws Predef.NoSuchElementException if the list is too short.
+ */
+ def apply(n: Int): a = drop(n).head
+
+ /** Returns the list resulting from applying the given function <code>f</code> to each
+ * element of this list.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>.
+ */
+ override def map[b](f: a => b): List[b] = {
+ val b = new ListBuffer[b]
+ var these = this
+ while (!these.isEmpty) {
+ b += f(these.head)
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Apply a function to all the elements of the list, and return the
+ * reversed list of results. This is equivalent to a call to <code>map</code>
+ * followed by a call to <code>reverse</code>, but more efficient.
+ *
+ * @param f the function to apply to each elements.
+ * @return the reversed list of results.
+ */
+ def reverseMap[b](f: a => b): List[b] = {
+ def loop(l: List[a], res: List[b]): List[b] = l match {
+ case Nil => res
+ case head :: tail => loop(tail, f(head) :: res)
+ }
+ loop(this, Nil)
+ }
+
+ /** Apply the given function <code>f</code> to each element of this list
+ * (while respecting the order of the elements).
+ *
+ * @param f the treatment to apply to each element.
+ */
+ override def foreach(f: a => Unit): Unit = {
+ var these = this
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
+ }
+ }
+
+ /** Returns all the elements of this list that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ override def filter(p: a => Boolean): List[a] = {
+ // return same list if all elements satisfy p
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ these = these.tail
+ }
+ if (these.isEmpty) this
+ else {
+ val b = new ListBuffer[a]
+ var these1 = this;
+ while (these1 ne these) {
+ b += these1.head
+ these1 = these1.tail
+ }
+
+ these = these.tail // prevent the second evaluation of the predicate
+ // on the element on which it first failed
+ while (!these.isEmpty) {
+ if (p(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+ }
+
+ /** Removes all elements of the list which satisfy the predicate
+ * <code>p</code>. This is like <code>filter</code> with the
+ * predicate inversed.
+ *
+ * @param p the predicate to use to test elements
+ * @return the list without all elements which satisfy <code>p</code>
+ */
+ def remove(p: a => Boolean): List[a] = filter (x => !p(x))
+
+ /** Partition the list in two sub-lists according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of lists: the list of all elements which satisfy
+ * <code>p</code> and the list of all elements which do not.
+ * The relative order of the elements in the sub-lists is the
+ * same as in the original list.
+ */
+ def partition(p: a => Boolean): {List[a], List[a]} = {
+ val btrue = new ListBuffer[a]
+ val bfalse = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty) {
+ (if (p(these.head)) btrue else bfalse) += these.head
+ these = these.tail
+ }
+ {btrue.toList, bfalse.toList}
+ }
+
+ /** <p>
+ * Sort the list according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff <code>e1</code> is smaller than
+ * <code>e2</code>. Example:
+ * </p>
+ * <pre>
+ * List("Steve", "Tom", "John", "Bob")
+ * .sort((e1, e2) => (e1 compareTo e2) &lt; 0) =
+ * List("Bob", "John", "Steve", "Tom")</pre>
+ * <p>
+ * Note: The current implementation is inefficent for
+ * already sorted lists.
+ * </p>
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ */
+ def sort(lt : (a,a) => Boolean): List[a] = {
+ def sort_1(smaller: List[a], acc: List[a]): List[a] =
+ smaller match {
+ case Nil =>
+ acc
+ //case List(x) =>
+ case x :: Nil =>
+ x::acc
+ //case List(x, y) =>
+ case x :: y :: Nil =>
+ if (lt(x, y)) x::(y::acc) else y::x::acc
+ //case List(x, y, z) =>
+ case x :: y :: z :: Nil =>
+ if (lt(x, y)) {
+ if (lt(y, z)) x::y::z::acc
+ else if (lt(x, z)) x::z::y::acc
+ else z::x::y::acc
+ } else if (lt(x, z)) y::x::z::acc
+ else if (lt(z, y)) z::y::x::acc
+ else y::z::x::acc
+ case hd1::hd2::hd3::tail => {
+ val List(x, y, z) = sort_1(hd1::hd2::hd3::Nil, Nil)
+ val {small, large} = tail.partition((e2) => lt(e2, y))
+ sort_1(x::small, y::sort_1(z::large, acc))
+ }
+ }
+ this match {
+ case Nil =>
+ this
+// case List(x) =>
+ case x :: Nil =>
+ this
+// case List(x, y) =>
+ case x::y::Nil =>
+ if (lt(x, y)) this else y::x::Nil
+// case List(x, y, z) =>
+ case x::y::z::Nil =>
+ if (lt(x, y)) {
+ if (lt(y, z)) this
+ else if (lt(x, z)) x::z::y::Nil
+ else z::x::y::Nil
+ } else if (lt(x, z)) y::x::z::Nil
+ else if (lt(z, y)) z::y::x::Nil
+ else y::z::x::Nil
+ case hd1::hd2::hd3::tail => {
+ val List(x, y, z) = sort_1(hd1::hd2::hd3::Nil, Nil)
+ val {small,large} = tail.partition((e2) => lt(e2, y))
+ sort_1(x::small, y::sort_1(z::large, Nil));
+ }
+ }
+ }
+
+
+ /** Count the number of elements in the list which satisfy a predicate.
+ *
+ * @param p the predicate for which to count
+ * @return the number of elements satisfying the predicate <code>p</code>.
+ */
+ def count(p: a => Boolean): Int = {
+ var cnt = 0
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) cnt = cnt + 1
+ these = these.tail
+ }
+ cnt
+ }
+
+ /** Tests if the predicate <code>p</code> is satisfied by all elements
+ * in this list.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff all elements of this list satisfy the
+ * predicate <code>p</code>.
+ */
+ override def forall(p: a => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (!p(these.head)) return false
+ these = these.tail
+ }
+ true
+ }
+
+ /** Tests the existence in this list of an element that satisfies the
+ * predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff there exists an element in this list that
+ * satisfies the predicate <code>p</code>.
+ */
+ override def exists(p: a => Boolean): Boolean = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return true
+ these = these.tail
+ }
+ false
+ }
+
+ /** Find and return the first element of the list satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the list satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ override def find(p: a => Boolean): Option[a] = {
+ var these = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return Some(these.head)
+ these = these.tail
+ }
+ None
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the list is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldLeft[b](z: b)(f: (b, a) => b): b = {
+ var acc = z
+ var these = this
+ while (!these.isEmpty) {
+ acc = f(acc, these.head)
+ these = these.tail
+ }
+ acc
+ }
+
+ /** Combines the elements of this list together using the binary
+ * function <code>f</code>, from right to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the list is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldRight[b](z: b)(f: (a, b) => b): b = this match {
+ case Nil => z
+ case x :: xs => f(x, xs.foldRight(z)(f))
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right
+ * @param op The operator to apply
+ * @return <code>op(... op(a<sub>0</sub>,a<sub>1</sub>), ..., a<sub>n</sub>)</code>
+ if the list has elements
+ * <code>a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub></code>.
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceLeft[b >: a](f: (b, b) => b): b = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceLeft")
+ case x :: xs => ((xs: List[b]) foldLeft (x: b))(f)
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from right to left
+ * @param op The operator to apply
+ *
+ * @return <code>a<sub>0</sub> op (... op (a<sub>n-1</sub> op a<sub>n</sub>)...)</code>
+ * if the list has elements <code>a<sub>0</sub>, a<sub>1</sub>, ...,
+ * a<sub>n</sub></code>.
+ *
+ * @throws Predef.UnsupportedOperationException if the list is empty.
+ */
+ override def reduceRight[b >: a](f: (b, b) => b): b = this match {
+ case Nil => throw new UnsupportedOperationException("Nil.reduceRight")
+ case x :: Nil => x: b
+ case x :: xs => f(x, xs reduceRight f)
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this list, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this list is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def flatMap[b](f: a => Iterable[b]): List[b] = {
+ val b = new ListBuffer[b]
+ var these = this
+ while (!these.isEmpty) {
+ var those = f(these.head).elements
+ while (those.hasNext) {
+ b += those.next
+ }
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** A list consisting of all elements of this list in reverse order.
+ */
+ override def reverse: List[a] = {
+ var result: List[a] = Nil
+ var these = this
+ while (!these.isEmpty) {
+ result = these.head :: result
+ these = these.tail
+ }
+ result
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two lists is longer than the other, its remaining elements are ignored.
+ *
+ * @return <code>List({a<sub>0</sub>,b<sub>0</sub>}, ...,
+ * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>})</code> when
+ * <code>List(a<sub>0</sub>, ..., a<sub>m</sub>)
+ * zip List(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.
+ */
+ def zip[b](that: List[b]): List[{a,b}] = {
+ val b = new ListBuffer[{a, b}]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += {these.head, those.head}
+ these = these.tail
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Returns a list that pairs each element of this list
+ * with its index, counting from 0.
+ *
+ * @return the list <code>List({a<sub>0</sub>,0}, {a<sub>1</sub>,1}...)</code>
+ * where <code>a<sub>i</sub></code> are the elements of this list.
+ */
+ def zipWithIndex = {
+ val b = new ListBuffer[{a,int}]
+ var these = this
+ var idx = 0
+
+ while(!these.isEmpty) {
+ b += {these.head, idx}
+ these = these.tail
+ idx = idx + 1
+ }
+
+ b.toList
+ }
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param that list <code>that</code> may have a different length
+ * as the self list.
+ * @param thisElem element <code>thisElem</code> is used to fill up the
+ * resulting list if the self list is shorter than
+ * <code>that</code>
+ * @param thatElem element <code>thatElem</code> is used to fill up the
+ * resulting list if <code>that</code> is shorter than
+ * the self list
+ * @return <code>List({a<sub>0</sub>,b<sub>0</sub>}, ...,
+ * {a<sub>n</sub>,b<sub>n</sub>}, {elem,b<sub>n+1</sub>},
+ * ..., {elem,b<sub>m</sub>})</code>
+ * when <code>[a<sub>0</sub>, ..., a<sub>n</sub>] zip
+ * [b<sub>0</sub>, ..., b<sub>m</sub>]</code> is
+ * invoked where <code>m &gt; n</code>.
+ */
+ def zipAll[b, c >: a, d >: b](that: List[b], thisElem: c, thatElem: d): List[{c,d}] = {
+ val b = new ListBuffer[{c, d}]
+ var these = this
+ var those = that
+ while (!these.isEmpty && !those.isEmpty) {
+ b += {these.head, those.head}
+ these = these.tail
+ those = those.tail
+ }
+ while (!these.isEmpty) {
+ b += {these.head, thatElem}
+ these = these.tail
+ }
+ while (!those.isEmpty) {
+ b += {thisElem, those.head}
+ those = those.tail
+ }
+ b.toList
+ }
+
+ /** Computes the union of this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to add to the list.
+ * @return a list without doubles containing the elements of this
+ * list and those of the given list <code>that</code>.
+ */
+ def union[b >: a](that: List[b]): List[b] = {
+ val b = new ListBuffer[b]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.prependToList(that)
+ }
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list
+ * <code>that</code>.
+ */
+ def diff[b >: a](that: List[b]): List[b] = {
+ val b = new ListBuffer[b]
+ var these = this
+ while (!these.isEmpty) {
+ if (!that.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ /** Computes the intersection between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list to intersect.
+ * @return the list of elements contained both in this list and
+ * in the given list <code>that</code>.
+ */
+ def intersect[b >: a](that: List[b]): List[b] = filter(x => that contains x)
+
+ /** Removes redundant elements from the list. Uses the method <code>==</code>
+ * to decide if two elements are identical.
+ *
+ * @return the list without doubles.
+ */
+ def removeDuplicates: List[a] = {
+ val b = new ListBuffer[a]
+ var these = this
+ while (!these.isEmpty) {
+ if (!these.tail.contains(these.head)) b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ protected override def stringPrefix: String = "List"
+
+}
+
+/** The empty list.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+[SerialVersionUID(0 - 8256821097970055419L)]
+case object Nil extends List[Nothing] {
+ override def isEmpty = true
+ def head: Nothing =
+ throw new NoSuchElementException("head of empty list")
+ def tail: List[Nothing] =
+ throw new NoSuchElementException("tail of empty list")
+}
+
+/** A non empty list characterized by a head and a tail.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+[SerialVersionUID(0L - 8476791151983527571L)]
+final case class ::[b](hd: b, private[scala] var tl: List[b]) extends List[b] {
+ def head = hd
+ def tail = tl
+ override def isEmpty: boolean = false
+}
diff --git a/src/dotnet-library/scala/MatchError.scala b/src/dotnet-library/scala/MatchError.scala
new file mode 100644
index 0000000000..57ada9efbd
--- /dev/null
+++ b/src/dotnet-library/scala/MatchError.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import Predef._
+
+/** This class implements errors which are thrown whenever an
+ * object doesn't match any pattern of a pattern matching
+ * expression.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 1.1, 05/03/2004
+ */
+object MatchError {
+
+ def string(obj: Any) =
+ if (null != obj) obj.toString() else "null"
+
+ // todo: change pattern matcher so that dummy type parameter T can be removed.
+ def fail[T](source: String, line: Int): Nothing =
+ throw new MatchError(source, line)
+
+ def report(source: String, line: Int, obj: Any) =
+ try {
+ throw new MatchError(source, line, string(obj))
+ } catch {
+ case e: MatchError => throw e
+ case e: Throwable => throw new MatchError(source, line)
+ }
+}
+
+final class MatchError(msg: String) extends Error(msg) {
+ def this(source: String, line: Int) =
+ this(" in '" + source + "' at line " + line)
+
+ def this(source: String, line: Int, obj: String) =
+ this("for object " + obj + " in '" + source + "' at line " + line)
+
+ def this(obj: Any) =
+ this(MatchError.string(obj))
+}
diff --git a/src/dotnet-library/scala/Math.scala b/src/dotnet-library/scala/Math.scala
new file mode 100644
index 0000000000..23bb4e73ce
--- /dev/null
+++ b/src/dotnet-library/scala/Math.scala
@@ -0,0 +1,140 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** The object <code>Math</code> contains methods for performing basic numeric
+ * operations such as the elementary exponential, logarithm, square root, and
+ * trigonometric functions.
+ */
+object Math {
+
+ /** The <code>double</code> value that is closer than any other to
+ * <code>e</code>, the base of the natural logarithms.
+ */
+ val E = java.lang.Math.E
+
+ /** The <code>double</code> value that is closer than any other to
+ * <code>pi</code>, the ratio of the circumference of a circle to its
+ * diameter.
+ */
+ val Pi = java.lang.Math.PI
+
+ /** Returns a <code>double</code> value with a positive sign, greater than
+ * or equal to <code>0.0</code> and less than <code>1.0</code>.
+ */
+ def random: Double = java.lang.Math.random()
+
+ def sin(x: Double): Double = java.lang.Math.sin(x)
+ def cos(x: Double): Double = java.lang.Math.cos(x)
+ def tan(x: Double): Double = java.lang.Math.tan(x)
+ def asin(x: Double): Double = java.lang.Math.asin(x)
+ def acos(x: Double): Double = java.lang.Math.acos(x)
+ def atan(x: Double): Double = java.lang.Math.atan(x)
+
+ /** Converts an angle measured in degrees to an approximately equivalent
+ * angle measured in radians.
+ *
+ * @param x an angle, in degrees
+ * @return the measurement of the angle <code>x</code> in radians.
+ */
+ def toRadians(x: Double): Double = java.lang.Math.toRadians(x)
+
+ /** Converts an angle measured in radians to an approximately equivalent
+ * angle measured in degrees.
+ *
+ * @param x angle, in radians
+ * @return the measurement of the angle <code>x</code> in degrees.
+ */
+ def toDegrees(x: Double): Double = java.lang.Math.toDegrees(x)
+
+ /** Returns Euler's number <code>e</code> raised to the power of a
+ * <code>double</code> value.
+ *
+ * @param x the exponent to raise <code>e</code> to.
+ * @return the value <code>e<sup>a</sup></code>, where <code>e</code>
+ * is the base of the natural logarithms.
+ */
+ def exp(x: Double): Double = java.lang.Math.exp(x)
+ def log(x: Double): Double = java.lang.Math.log(x)
+ def sqrt(x: Double): Double = java.lang.Math.sqrt(x)
+ def IEEEremainder(x: Double, y: Double): Double = java.lang.Math.IEEEremainder(x, y)
+ def ceil(x: Double): Double = java.lang.Math.ceil(x)
+ def floor(x: Double): Double = java.lang.Math.floor(x)
+
+ /** Returns the <code>double</code> value that is closest in value to the
+ * argument and is equal to a mathematical integer.
+ *
+ * @param x a <code>double</code> value
+ * @return the closest floating-point value to a that is equal to a
+ * mathematical integer.
+ */
+ def rint(x: Double): Double = java.lang.Math.rint(x)
+
+ /** Converts rectangular coordinates <code>(x, y)</code> to polar
+ * <code>(r, theta)</code>.
+ *
+ * @param x the ordinate coordinate
+ * @param y the abscissa coordinate
+ * @return the <em>theta</em> component of the point <code>(r, theta)</code>
+ * in polar coordinates that corresponds to the point
+ * <code>(x, y)</code> in Cartesian coordinates.
+ */
+ def atan2(x: Double, y: Double): Double = java.lang.Math.atan2(x, y)
+
+ /** Returns the value of the first argument raised to the power of the
+ * second argument.
+ *
+ * @param x the base.
+ * @param y the exponent.
+ * @return the value <code>x<sup>y</sup></code>.
+ */
+ def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y)
+
+ /** Returns the closest <code>long</code> to the argument.
+ *
+ * @param x a floating-point value to be rounded to a <code>long</code>.
+ * @return the value of the argument rounded to the nearest
+ * <code>long</code> value.
+ */
+ def round(x: Float): Int = java.lang.Math.round(x)
+ def round(x: Double): Long = java.lang.Math.round(x)
+ def abs(x: Int): Int = java.lang.Math.abs(x)
+ def abs(x: Long): Long = java.lang.Math.abs(x)
+ def abs(x: Float): Float = java.lang.Math.abs(x)
+ def abs(x: Double): Double = java.lang.Math.abs(x)
+
+ def max(x: Int, y: Int): Int = java.lang.Math.max(x, y)
+ def max(x: Long, y: Long): Long = java.lang.Math.max(x, y)
+ def max(x: Float, y: Float): Float = java.lang.Math.max(x, y)
+ def max(x: Double, y: Double): Double = java.lang.Math.max(x, y)
+
+ def min(x: Int, y: Int): Int = java.lang.Math.min(x, y)
+ def min(x: Long, y: Long): Long = java.lang.Math.min(x, y)
+ def min(x: Float, y: Float): Float = java.lang.Math.min(x, y)
+ def min(x: Double, y: Double): Double = java.lang.Math.min(x, y)
+
+ // from Java 1.5
+// def log10(x: Double): Double = java.lang.Math.log10(x)
+// def cbrt(x: Double): Double = java.lang.Math.cbrt(x)
+
+// def ulp(x: Double): Double = java.lang.Math.ulp(x)
+// def ulp(x: Float): Float = java.lang.Math.ulp(x)
+// def signum(x: Double): Double = java.lang.Math.signum(x)
+// def signum(x: Float): Float = java.lang.Math.signum(x)
+// def sinh(x: Double): Double = java.lang.Math.sinh(x)
+// def cosh(x: Double): Double = java.lang.Math.cosh(x)
+// def tanh(x: Double):Double = java.lang.Math.tanh(x)
+// def hypot(x: Double, y: Double): Double = java.lang.Math.hypot(x, y)
+// def expm1(x: Double): Double = java.lang.Math.expm1(x)
+// def log1p(x: Double): Double = java.lang.Math.log1p(x)
+
+}
diff --git a/src/dotnet-library/scala/NotDefinedError.scala b/src/dotnet-library/scala/NotDefinedError.scala
new file mode 100644
index 0000000000..60e61d9e89
--- /dev/null
+++ b/src/dotnet-library/scala/NotDefinedError.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import Predef.Error
+
+final class NotDefinedError(msg: String) extends Error("not defined: " + msg)
diff --git a/src/dotnet-library/scala/Option.scala b/src/dotnet-library/scala/Option.scala
new file mode 100644
index 0000000000..46b659caac
--- /dev/null
+++ b/src/dotnet-library/scala/Option.scala
@@ -0,0 +1,132 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala;
+
+
+import Predef._
+
+object Option {
+ /** An implicit conversion that converts an option to an iterable value
+ */
+ implicit def option2Iterable[a](xo: Option[a]): Iterable[a] = xo.toList
+}
+
+
+/** This class represents optional values. Instances of <code>Option</code>
+ * are either instances of case class <code>Some</code> or it is case
+ * object <code>None</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.1, 16/01/2007
+ */
+sealed abstract class Option[+A] extends Product {
+
+ /** True if the option is the <code>None</code> value, false otherwise.
+ */
+ def isEmpty: Boolean
+
+ /** True if the option is a <code>Some</code>(...) false otherwise.
+ */
+ def isDefined: Boolean = !isEmpty
+
+ /** get the value of this option.
+ * @requires that the option is nonEmpty.
+ * @throws Predef.NoSuchElementException if the option is empty.
+ */
+ def get: A
+
+ /** @deprecated; use getOrElse instead */
+ [deprecated] def get[B >: A](default: B): B = this match {
+ case None => default
+ case Some(x) => x
+ }
+
+ /** If the option is nonempty return its value,
+ * otherwise return the result of evaluating a default expression.
+ * @param default the default expression.
+ */
+ def getOrElse[B >: A](default: => B): B =
+ if (isEmpty) default else this.get
+
+ /** If the option is nonempty, return a function applied to its value,
+ * wrapped in a Some i.e. <code>Some(f(this.get))</code>.
+ * Otherwise return None.
+ * @param f the function to apply
+ */
+ def map[B](f: A => B): Option[B] =
+ if (isEmpty) None else Some(f(this.get))
+
+ /** If the option is nonempty, return a function applied to its value.
+ * Otherwise return None.
+ * @param f the function to apply
+ */
+ def flatMap[B](f: A => Option[B]): Option[B] =
+ if (isEmpty) None else f(this.get)
+
+ /** If the option is nonempty and the given predicate <code>p</code>
+ * yields <code>false</code> on its value, return <code>None</code>.
+ * Otherwise return the option value itself.
+ * @param p the predicate used for testing.
+ */
+ def filter(p: A => Boolean): Option[A] =
+ if (isEmpty || p(this.get)) this else None
+
+ /** Apply the given procedure <code>f</code> to the option's value,
+ * if it is nonempty. Do nothing if it is empty.
+ * @param f the procedure to apply.
+ */
+ def foreach(f: A => Unit) {
+ if (!isEmpty) f(this.get)
+ }
+
+ /** If the option is nonempty return it,
+ * otherwise return the result of evaluating an alternative expression.
+ * @param alternative the alternative expression.
+ */
+ def orElse[B >: A](alternative: => Option[B]): Option[B] =
+ if (isEmpty) alternative else this
+
+ /** An singleton iterator returning the option's value if it is nonempty
+ * or the empty iterator if the option is empty.
+ */
+ def elements: Iterator[A] =
+ if (isEmpty) Iterator.empty else Iterator.fromValues(this.get)
+
+ /** A singleton list containing the option's value if it is nonempty
+ * or the empty list if the option is empty.
+ */
+ def toList: List[A] =
+ if (isEmpty) List() else List(this.get)
+}
+
+/** Class <code>Some[A]</code> represents existing values of type
+ * <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+final case class Some[+A](x: A) extends Option[A] {
+ def isEmpty = false
+ def get = x
+}
+
+
+/** This case object represents non-existent values.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+case object None extends Option[Nothing] {
+ def isEmpty = true
+ def get = throw new NoSuchElementException("None.get")
+}
diff --git a/src/dotnet-library/scala/Ordered.scala b/src/dotnet-library/scala/Ordered.scala
new file mode 100644
index 0000000000..4eeab101f0
--- /dev/null
+++ b/src/dotnet-library/scala/Ordered.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** A class for totally ordered data.
+ *
+ * Note that since version 2006-07-24 this class is no longer covariant in a.
+ *
+ * @author Martin Odersky
+ * @version 1.1, 2006-07-24
+ */
+trait Ordered[a] {
+
+ /** Result of comparing <code>this</code> with operand <code>that</code>.
+ * returns <code>x</code> where
+ * <code>x &lt; 0</code> iff <code>this &lt; that</code>
+ * <code>x == 0</code> iff <code>this == that</code>
+ * <code>x &gt; 0</code> iff <code>this &gt; that</code>
+ */
+ def compare(that: a): Int
+
+ def < (that: a): Boolean = (this compare that) < 0
+ def > (that: a): Boolean = (this compare that) > 0
+ def <= (that: a): Boolean = (this compare that) <= 0
+ def >= (that: a): Boolean = (this compare that) >= 0
+ def compareTo(that: a): Int = compare(that)
+}
diff --git a/src/dotnet-library/scala/PartialFunction.scala b/src/dotnet-library/scala/PartialFunction.scala
new file mode 100644
index 0000000000..06b9f70681
--- /dev/null
+++ b/src/dotnet-library/scala/PartialFunction.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala;
+
+
+/** A partial function of type <code>PartialFunction[A, B]</code> is a
+ * unary function where the domain does not include all values of type
+ * <code>A</code>. The function <code>isDefinedAt</code> allows to
+ * test dynamically, if a value is in the domain of the function.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+trait PartialFunction[-A, +B] extends AnyRef with (A => B) {
+
+ /** Checks if a value is contained in the functions domain.
+ *
+ * @param x the value to test
+ * @return true, iff <code>x</code> is in the domain of this function.
+ */
+ def isDefinedAt(x: A): Boolean;
+
+ def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) = new PartialFunction[A1, B1] {
+ def isDefinedAt(x: A1): Boolean =
+ PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x)
+ def apply(x: A1): B1 =
+ if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x)
+ else that.apply(x)
+ }
+
+ override def andThen[C](k: B => C) = new PartialFunction[A, C] {
+ def isDefinedAt(x: A): Boolean = PartialFunction.this.isDefinedAt(x)
+ def apply(x: A): C = k(PartialFunction.this.apply(x))
+ }
+}
+
diff --git a/src/dotnet-library/scala/PartiallyOrdered.scala b/src/dotnet-library/scala/PartiallyOrdered.scala
new file mode 100644
index 0000000000..b4c86fedd8
--- /dev/null
+++ b/src/dotnet-library/scala/PartiallyOrdered.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** A class for partially ordered data.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 23/04/2004
+ */
+trait PartiallyOrdered[+a] {
+
+ /** Result of comparing <code>this</code> with operand <code>that</code>.
+ * Returns <code>None</code> if operands are not comparable.
+ * If operands are comparable, returns <code>Some(x)</code> where
+ * <code>x &lt; 0</code> iff <code>this &lt; that</code>
+ * <code>x == 0</code> iff <code>this == that</code>
+ * <code>x &gt; 0</code> iff <code>this &gt; that</code>
+ */
+ def tryCompareTo [b >: a <% PartiallyOrdered[b]](that: b): Option[int]
+
+ def < [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x < 0 => true
+ case _ => false
+ }
+ def > [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x > 0 => true
+ case _ => false
+ }
+ def <= [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x <= 0 => true
+ case _ => false
+ }
+ def >= [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x >= 0 => true
+ case _ => false
+ }
+}
diff --git a/src/dotnet-library/scala/Predef.scala b/src/dotnet-library/scala/Predef.scala
new file mode 100644
index 0000000000..b4724266cd
--- /dev/null
+++ b/src/dotnet-library/scala/Predef.scala
@@ -0,0 +1,285 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** The <code>Predef</code> object provides definitions that are
+ * accessible in all Scala compilation units without explicit
+ * qualification.
+ */
+object Predef {
+
+ // classOf dummy -------------------------------------------------
+
+ /** Return the runtime representation of a class type. */
+ def classOf[T]: Class = null
+
+ // aliases -------------------------------------------------------
+
+ type byte = scala.Byte
+ type short = scala.Short
+ type char = scala.Char
+ type int = scala.Int
+ type long = scala.Long
+ type float = scala.Float
+ type double = scala.Double
+ type boolean = scala.Boolean
+ type unit = scala.Unit
+
+ type All = Nothing
+ type AllRef = Null
+
+ type String = java.lang.String
+ type StringBuilder = compat.StringBuilder
+ type Class = java.lang.Class
+
+ type Throwable = java.lang.Throwable
+ type Exception = java.lang.Exception
+ type Error = java.lang.Error
+ type RuntimeException = java.lang.RuntimeException
+ type NullPointerException = java.lang.NullPointerException
+ type ClassCastException = java.lang.ClassCastException
+ type IndexOutOfBoundsException = java.lang.IndexOutOfBoundsException
+ type ArrayIndexOutOfBoundsException = java.lang.ArrayIndexOutOfBoundsException
+ type UnsupportedOperationException = java.lang.UnsupportedOperationException
+ type IllegalArgumentException = java.lang.IllegalArgumentException
+ type NoSuchElementException = java.util.NoSuchElementException
+ type NumberFormatException = java.lang.NumberFormatException
+
+ // --- Miscelleaneous -----------------------------------------------
+
+ val $scope = scala.xml.TopScope
+
+ type Function[-a,+b] = Function1[a,b]
+
+ type Map[a, b] = collection.immutable.Map[a, b]
+ type Set[a] = collection.immutable.Set[a]
+
+ val Map = collection.immutable.Map
+ val Set = collection.immutable.Set
+
+
+ // errors and asserts -------------------------------------------------
+
+ def error(message: String): Nothing = throw new Error(message)
+
+ def exit: Nothing = exit(0)
+
+ def exit(status: Int): Nothing = {
+ java.lang.System.exit(status)
+ throw new Throwable()
+ }
+
+ def assert(assertion: Boolean): Unit = {
+ if (!assertion)
+ throw new java.lang.AssertionError("assertion failed")
+ }
+
+ def assert(assertion: Boolean, message: Any): Unit = {
+ if (!assertion)
+ throw new java.lang.AssertionError("assertion failed: " + message)
+ }
+
+ def assume(assumption: Boolean): Unit = {
+ if (!assumption)
+ throw new Error("assumption failed")
+ }
+
+ def assume(assumption: Boolean, message: Any): Unit = {
+ if (!assumption)
+ throw new Error("assumption failed: " + message)
+ }
+
+ // --- Tupling ----------------------------------------------
+
+ type Pair[+a, +b] = Tuple2[a, b]
+ object Pair {
+ def apply[a, b](x: a, y: b) = Tuple2(x, y)
+ def unapply[a, b](x: Tuple2[a, b]): Option[Tuple2[a, b]] = Some(x)
+ }
+
+ type Triple[+a, +b, +c] = Tuple3[a, b, c]
+ object Triple {
+ def apply[a, b, c](x: a, y: b, z: c) = Tuple3(x, y, z)
+ def unapply[a, b, c](x: Tuple3[a, b, c]): Option[Tuple3[a, b, c]] = Some(x)
+ }
+
+ class ArrowAssoc[a](x: a) {
+ def -> [b](y: b): Tuple2[a, b] = Tuple2(x, y)
+ }
+ implicit def any2ArrowAssoc[a](x: a): ArrowAssoc[a] = new ArrowAssoc(x)
+
+ def Tuple[a1](x1: a1) = Tuple1(x1)
+ def Tuple[a1, a2](x1: a1, x2: a2) = Tuple2(x1, x2)
+ def Tuple[a1, a2, a3](x1: a1, x2: a2, x3: a3) = Tuple3(x1, x2, x3)
+ def Tuple[a1, a2, a3, a4](x1: a1, x2: a2, x3: a3, x4: a4) = Tuple4(x1, x2, x3, x4)
+ def Tuple[a1, a2, a3, a4, a5](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5) = Tuple5(x1, x2, x3, x4, x5)
+ def Tuple[a1, a2, a3, a4, a5, a6](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6) = Tuple6(x1, x2, x3, x4, x5, x6)
+ def Tuple[a1, a2, a3, a4, a5, a6, a7](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7) = Tuple7(x1, x2, x3, x4, x5, x6, x7)
+ def Tuple[a1, a2, a3, a4, a5, a6, a7, a8](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8) = Tuple8(x1, x2, x3, x4, x5, x6, x7, x8)
+ def Tuple[a1, a2, a3, a4, a5, a6, a7, a8, a9](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8, x9: a9) = Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9)
+
+ // views -------------------------------------------------------------
+
+ implicit def identity[a](x: a): a = x
+
+ implicit def byteWrapper(x: byte) = new runtime.RichByte(x)
+ implicit def shortWrapper(x: short) = new runtime.RichShort(x)
+ implicit def intWrapper(x: int) = new runtime.RichInt(x)
+ implicit def charWrapper(c: char) = new runtime.RichChar(c)
+ implicit def longWrapper(x: long) = new runtime.RichLong(x)
+ implicit def floatWrapper(x: float) = new runtime.RichFloat(x)
+ implicit def doubleWrapper(x: double) = new runtime.RichDouble(x)
+
+ implicit def booleanWrapper(x: boolean) = new runtime.RichBoolean(x)
+
+ implicit def stringWrapper(x: String) = new runtime.RichString(x)
+
+ implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
+
+ implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
+
+ implicit def unit2ordered(x: unit): Ordered[unit] = new Ordered[unit] with Proxy {
+ def self: Any = x
+ def compare (y: unit): int = 0
+ }
+
+ implicit def iterable2ordered[a <% Ordered[a]](xs: Iterable[a]): Ordered[Iterable[a]] =
+ new Ordered[Iterable[a]] with Proxy {
+ val self = xs
+ def compare (that: Iterable[a]) = {
+ var res = 0
+ val these = xs.elements
+ val those = that.elements
+ while (res == 0 && these.hasNext)
+ res = if (those.hasNext) these.next compare those.next else 1
+ res
+ }
+ }
+
+ implicit def tuple22ordered[a1 <% Ordered[a1], a2 <% Ordered[a2]](x: Tuple2[a1, a2]): Ordered[Tuple2[a1, a2]] =
+ new Ordered[Tuple2[a1, a2]] with Proxy {
+ val self = x
+ def compare (y: Tuple2[a1, a2]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) x._2 compare y._2
+ else res
+ }
+ }
+
+ implicit def tuple32ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3]](x: Tuple3[a1, a2, a3]): Ordered[Tuple3[a1, a2, a3]] =
+ new Ordered[Tuple3[a1, a2, a3]] with Proxy {
+ val self = x
+ def compare (y: Tuple3[a1, a2, a3]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple2(x._2, x._3) compare Tuple2(y._2, y._3)
+ else res
+ }
+ }
+
+ implicit def tuple42ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4]](x: Tuple4[a1, a2, a3, a4]): Ordered[Tuple4[a1, a2, a3, a4]] =
+ new Ordered[Tuple4[a1, a2, a3, a4]] with Proxy {
+ val self = x
+ def compare (y: Tuple4[a1, a2, a3, a4]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple3(x._2, x._3, x._4) compare Tuple3(y._2, y._3, y._4)
+ else res
+ }
+ }
+
+ implicit def tuple52ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4], a5 <% Ordered[a5]](x: Tuple5[a1, a2, a3, a4, a5]): Ordered[Tuple5[a1, a2, a3, a4, a5]] =
+ new Ordered[Tuple5[a1, a2, a3, a4, a5]] with Proxy {
+ val self = x
+ def compare (y: Tuple5[a1, a2, a3, a4, a5]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple4(x._2, x._3, x._4, x._5) compare Tuple4(y._2, y._3, y._4, y._5)
+ else res
+ }
+ }
+
+ implicit def tuple62ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4], a5 <% Ordered[a5], a6 <% Ordered[a6]](x: Tuple6[a1, a2, a3, a4, a5, a6]): Ordered[Tuple6[a1, a2, a3, a4, a5, a6]] =
+ new Ordered[Tuple6[a1, a2, a3, a4, a5, a6]] with Proxy {
+ val self = x
+ def compare (y: Tuple6[a1, a2, a3, a4, a5, a6]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple5(x._2, x._3, x._4, x._5, x._6) compare Tuple5(y._2, y._3, y._4, y._5, y._6)
+ else res
+ }
+ }
+
+ implicit def tuple72ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4], a5 <% Ordered[a5], a6 <% Ordered[a6], a7 <% Ordered[a7]](x: Tuple7[a1, a2, a3, a4, a5, a6, a7]): Ordered[Tuple7[a1, a2, a3, a4, a5, a6, a7]] =
+ new Ordered[Tuple7[a1, a2, a3, a4, a5, a6, a7]] with Proxy {
+ val self = x
+ def compare (y: Tuple7[a1, a2, a3, a4, a5, a6, a7]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple6(x._2, x._3, x._4, x._5, x._6, x._7) compare Tuple6(y._2, y._3, y._4, y._5, y._6, y._7)
+ else res
+ }
+ }
+
+ implicit def tuple82ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4], a5 <% Ordered[a5], a6 <% Ordered[a6], a7 <% Ordered[a7], a8 <% Ordered[a8]](x: Tuple8[a1, a2, a3, a4, a5, a6, a7, a8]): Ordered[Tuple8[a1, a2, a3, a4, a5, a6, a7, a8]] =
+ new Ordered[Tuple8[a1, a2, a3, a4, a5, a6, a7, a8]] with Proxy {
+ val self = x
+ def compare (y: Tuple8[a1, a2, a3, a4, a5, a6, a7, a8]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple7(x._2, x._3, x._4, x._5, x._6, x._7, x._8) compare Tuple7(y._2, y._3, y._4, y._5, y._6, y._7, y._8)
+ else res
+ }
+ }
+
+ implicit def tuple92ordered[a1 <% Ordered[a1], a2 <% Ordered[a2], a3 <% Ordered[a3], a4 <% Ordered[a4], a5 <% Ordered[a5], a6 <% Ordered[a6], a7 <% Ordered[a7], a8 <% Ordered[a8], a9 <% Ordered[a9]](x: Tuple9[a1, a2, a3, a4, a5, a6, a7, a8, a9]): Ordered[Tuple9[a1, a2, a3, a4, a5, a6, a7, a8, a9]] =
+ new Ordered[Tuple9[a1, a2, a3, a4, a5, a6, a7, a8, a9]] with Proxy {
+ val self = x
+ def compare (y: Tuple9[a1, a2, a3, a4, a5, a6, a7, a8, a9]): Int = {
+ val res = x._1 compare y._1
+ if (res == 0) Tuple8(x._2, x._3, x._4, x._5, x._6, x._7, x._8, x._9) compare Tuple8(y._2, y._3, y._4, y._5, y._6, y._7, y._8, y._9)
+ else res
+ }
+ }
+
+ implicit def byte2short(x: byte): short = x.toShort
+ implicit def byte2int(x: byte): int = x.toInt
+ implicit def byte2long(x: byte): long = x.toLong
+ implicit def byte2float(x: byte): float = x.toFloat
+ implicit def byte2double(x: byte): double = x.toDouble
+
+ implicit def short2int(x: short): int = x.toInt
+ implicit def short2long(x: short): long = x.toLong
+ implicit def short2float(x: short): float = x.toFloat
+ implicit def short2double(x: short): double = x.toDouble
+
+ implicit def char2int(x: char): int = x.toInt
+ implicit def char2long(x: char): long = x.toLong
+ implicit def char2float(x: char): float = x.toFloat
+ implicit def char2double(x: char): double = x.toDouble
+
+ implicit def int2long(x: int): long = x.toLong
+ implicit def int2float(x: int): float = x.toFloat
+ implicit def int2double(x: int): double = x.toDouble
+
+ implicit def long2float(x: long): float = x.toFloat
+ implicit def long2double(x: long): double = x.toDouble
+
+ implicit def float2double(x: float): double = x.toDouble
+
+ implicit def byte2Byte(x: byte) = new java.lang.Byte(x)
+ implicit def short2Short(x: short) = new java.lang.Short(x)
+ implicit def char2Character(x: char) = new java.lang.Character(x)
+ implicit def int2Integer(x: int) = new java.lang.Integer(x)
+ implicit def long2Long(x: long) = new java.lang.Long(x)
+ implicit def float2Float(x: float) = new java.lang.Float(x)
+ implicit def double2Double(x: double) = new java.lang.Double(x)
+ implicit def boolean2Boolean(x: boolean) = new java.lang.Boolean(x)
+
+ def currentThread = java.lang.Thread.currentThread()
+
+}
diff --git a/src/dotnet-library/scala/Product.scala b/src/dotnet-library/scala/Product.scala
new file mode 100644
index 0000000000..75ffa84378
--- /dev/null
+++ b/src/dotnet-library/scala/Product.scala
@@ -0,0 +1,42 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** The trait <code>Product</code> defines access functions for instances
+ * of products, in particular case classes.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+trait Product extends AnyRef {
+
+ /** for a case class <code>A(x_1,...,x_k))</code>, returns <code>x_(i+1)</code>
+ * for <code>0 &lt;= i &lt; k</code>
+ *
+ * @param n the position of the n-th element
+ * @throws IndexOutOfBoundsException
+ * @return ...
+ */
+ def element(n: Int): Any
+
+ /** return k for a product <code>A(x_1,...,x_k))</code>
+ */
+ def arity: Int
+
+ /**
+ * By default the empty string. Implementations may override this
+ * method in order to prepend a string prefix to the result of the
+ * toString methods.
+ */
+ def productPrefix = ""
+
+}
diff --git a/src/dotnet-library/scala/Product1.scala b/src/dotnet-library/scala/Product1.scala
new file mode 100644
index 0000000000..33b61f3b33
--- /dev/null
+++ b/src/dotnet-library/scala/Product1.scala
@@ -0,0 +1,50 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product1 {
+ def unapply[T1](x: Product1[T1]): Option[Product1[T1]] =
+ Some(x)
+}
+
+/** Product1 is a cartesian product of 1 components
+ */
+trait Product1[+T1] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 1
+ */
+ override def arity = 1
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+
+}
diff --git a/src/dotnet-library/scala/Product10.scala b/src/dotnet-library/scala/Product10.scala
new file mode 100644
index 0000000000..7fb54b5494
--- /dev/null
+++ b/src/dotnet-library/scala/Product10.scala
@@ -0,0 +1,86 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product10 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](x: Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]): Option[Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] =
+ Some(x)
+}
+
+/** Product10 is a cartesian product of 10 components
+ */
+trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 10
+ */
+ override def arity = 10
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+
+}
diff --git a/src/dotnet-library/scala/Product11.scala b/src/dotnet-library/scala/Product11.scala
new file mode 100644
index 0000000000..40a94f0c57
--- /dev/null
+++ b/src/dotnet-library/scala/Product11.scala
@@ -0,0 +1,90 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product11 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](x: Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]): Option[Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] =
+ Some(x)
+}
+
+/** Product11 is a cartesian product of 11 components
+ */
+trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 11
+ */
+ override def arity = 11
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+
+}
diff --git a/src/dotnet-library/scala/Product12.scala b/src/dotnet-library/scala/Product12.scala
new file mode 100644
index 0000000000..a1ff52f39e
--- /dev/null
+++ b/src/dotnet-library/scala/Product12.scala
@@ -0,0 +1,94 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product12 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](x: Product12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]): Option[Product12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] =
+ Some(x)
+}
+
+/** Product12 is a cartesian product of 12 components
+ */
+trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 12
+ */
+ override def arity = 12
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+
+}
diff --git a/src/dotnet-library/scala/Product13.scala b/src/dotnet-library/scala/Product13.scala
new file mode 100644
index 0000000000..284b46bee9
--- /dev/null
+++ b/src/dotnet-library/scala/Product13.scala
@@ -0,0 +1,98 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product13 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](x: Product13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]): Option[Product13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] =
+ Some(x)
+}
+
+/** Product13 is a cartesian product of 13 components
+ */
+trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 13
+ */
+ override def arity = 13
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+
+}
diff --git a/src/dotnet-library/scala/Product14.scala b/src/dotnet-library/scala/Product14.scala
new file mode 100644
index 0000000000..b3b38b244c
--- /dev/null
+++ b/src/dotnet-library/scala/Product14.scala
@@ -0,0 +1,102 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product14 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](x: Product14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]): Option[Product14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] =
+ Some(x)
+}
+
+/** Product14 is a cartesian product of 14 components
+ */
+trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 14
+ */
+ override def arity = 14
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+
+}
diff --git a/src/dotnet-library/scala/Product15.scala b/src/dotnet-library/scala/Product15.scala
new file mode 100644
index 0000000000..4bfe909ec5
--- /dev/null
+++ b/src/dotnet-library/scala/Product15.scala
@@ -0,0 +1,106 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product15 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](x: Product15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]): Option[Product15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] =
+ Some(x)
+}
+
+/** Product15 is a cartesian product of 15 components
+ */
+trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 15
+ */
+ override def arity = 15
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+
+}
diff --git a/src/dotnet-library/scala/Product16.scala b/src/dotnet-library/scala/Product16.scala
new file mode 100644
index 0000000000..b12aed6c27
--- /dev/null
+++ b/src/dotnet-library/scala/Product16.scala
@@ -0,0 +1,110 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product16 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](x: Product16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]): Option[Product16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]] =
+ Some(x)
+}
+
+/** Product16 is a cartesian product of 16 components
+ */
+trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 16
+ */
+ override def arity = 16
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+
+}
diff --git a/src/dotnet-library/scala/Product17.scala b/src/dotnet-library/scala/Product17.scala
new file mode 100644
index 0000000000..b39c3df051
--- /dev/null
+++ b/src/dotnet-library/scala/Product17.scala
@@ -0,0 +1,114 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product17 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](x: Product17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]): Option[Product17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]] =
+ Some(x)
+}
+
+/** Product17 is a cartesian product of 17 components
+ */
+trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 17
+ */
+ override def arity = 17
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+
+}
diff --git a/src/dotnet-library/scala/Product18.scala b/src/dotnet-library/scala/Product18.scala
new file mode 100644
index 0000000000..beba913a0d
--- /dev/null
+++ b/src/dotnet-library/scala/Product18.scala
@@ -0,0 +1,118 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product18 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](x: Product18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]): Option[Product18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]] =
+ Some(x)
+}
+
+/** Product18 is a cartesian product of 18 components
+ */
+trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 18
+ */
+ override def arity = 18
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case 17 => _18
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+/** projection of this product */
+ def _18: T18
+
+
+}
diff --git a/src/dotnet-library/scala/Product19.scala b/src/dotnet-library/scala/Product19.scala
new file mode 100644
index 0000000000..b5f300d9e4
--- /dev/null
+++ b/src/dotnet-library/scala/Product19.scala
@@ -0,0 +1,122 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product19 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](x: Product19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]): Option[Product19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]] =
+ Some(x)
+}
+
+/** Product19 is a cartesian product of 19 components
+ */
+trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 19
+ */
+ override def arity = 19
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case 17 => _18
+ case 18 => _19
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+/** projection of this product */
+ def _18: T18
+
+/** projection of this product */
+ def _19: T19
+
+
+}
diff --git a/src/dotnet-library/scala/Product2.scala b/src/dotnet-library/scala/Product2.scala
new file mode 100644
index 0000000000..0866c141c7
--- /dev/null
+++ b/src/dotnet-library/scala/Product2.scala
@@ -0,0 +1,54 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product2 {
+ def unapply[T1, T2](x: Product2[T1, T2]): Option[Product2[T1, T2]] =
+ Some(x)
+}
+
+/** Product2 is a cartesian product of 2 components
+ */
+trait Product2[+T1, +T2] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 2
+ */
+ override def arity = 2
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+
+}
diff --git a/src/dotnet-library/scala/Product20.scala b/src/dotnet-library/scala/Product20.scala
new file mode 100644
index 0000000000..fe7e0b1f4e
--- /dev/null
+++ b/src/dotnet-library/scala/Product20.scala
@@ -0,0 +1,126 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product20 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](x: Product20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]): Option[Product20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]] =
+ Some(x)
+}
+
+/** Product20 is a cartesian product of 20 components
+ */
+trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 20
+ */
+ override def arity = 20
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case 17 => _18
+ case 18 => _19
+ case 19 => _20
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+/** projection of this product */
+ def _18: T18
+
+/** projection of this product */
+ def _19: T19
+
+/** projection of this product */
+ def _20: T20
+
+
+}
diff --git a/src/dotnet-library/scala/Product21.scala b/src/dotnet-library/scala/Product21.scala
new file mode 100644
index 0000000000..e09700eb77
--- /dev/null
+++ b/src/dotnet-library/scala/Product21.scala
@@ -0,0 +1,130 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product21 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](x: Product21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]): Option[Product21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]] =
+ Some(x)
+}
+
+/** Product21 is a cartesian product of 21 components
+ */
+trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 21
+ */
+ override def arity = 21
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case 17 => _18
+ case 18 => _19
+ case 19 => _20
+ case 20 => _21
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+/** projection of this product */
+ def _18: T18
+
+/** projection of this product */
+ def _19: T19
+
+/** projection of this product */
+ def _20: T20
+
+/** projection of this product */
+ def _21: T21
+
+
+}
diff --git a/src/dotnet-library/scala/Product22.scala b/src/dotnet-library/scala/Product22.scala
new file mode 100644
index 0000000000..a9682cedbd
--- /dev/null
+++ b/src/dotnet-library/scala/Product22.scala
@@ -0,0 +1,134 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product22 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](x: Product22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]): Option[Product22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]] =
+ Some(x)
+}
+
+/** Product22 is a cartesian product of 22 components
+ */
+trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 22
+ */
+ override def arity = 22
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case 9 => _10
+ case 10 => _11
+ case 11 => _12
+ case 12 => _13
+ case 13 => _14
+ case 14 => _15
+ case 15 => _16
+ case 16 => _17
+ case 17 => _18
+ case 18 => _19
+ case 19 => _20
+ case 20 => _21
+ case 21 => _22
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+/** projection of this product */
+ def _10: T10
+
+/** projection of this product */
+ def _11: T11
+
+/** projection of this product */
+ def _12: T12
+
+/** projection of this product */
+ def _13: T13
+
+/** projection of this product */
+ def _14: T14
+
+/** projection of this product */
+ def _15: T15
+
+/** projection of this product */
+ def _16: T16
+
+/** projection of this product */
+ def _17: T17
+
+/** projection of this product */
+ def _18: T18
+
+/** projection of this product */
+ def _19: T19
+
+/** projection of this product */
+ def _20: T20
+
+/** projection of this product */
+ def _21: T21
+
+/** projection of this product */
+ def _22: T22
+
+
+}
diff --git a/src/dotnet-library/scala/Product3.scala b/src/dotnet-library/scala/Product3.scala
new file mode 100644
index 0000000000..58ed57f556
--- /dev/null
+++ b/src/dotnet-library/scala/Product3.scala
@@ -0,0 +1,58 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product3 {
+ def unapply[T1, T2, T3](x: Product3[T1, T2, T3]): Option[Product3[T1, T2, T3]] =
+ Some(x)
+}
+
+/** Product3 is a cartesian product of 3 components
+ */
+trait Product3[+T1, +T2, +T3] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 3
+ */
+ override def arity = 3
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+
+}
diff --git a/src/dotnet-library/scala/Product4.scala b/src/dotnet-library/scala/Product4.scala
new file mode 100644
index 0000000000..0f7ad52392
--- /dev/null
+++ b/src/dotnet-library/scala/Product4.scala
@@ -0,0 +1,62 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product4 {
+ def unapply[T1, T2, T3, T4](x: Product4[T1, T2, T3, T4]): Option[Product4[T1, T2, T3, T4]] =
+ Some(x)
+}
+
+/** Product4 is a cartesian product of 4 components
+ */
+trait Product4[+T1, +T2, +T3, +T4] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 4
+ */
+ override def arity = 4
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+
+}
diff --git a/src/dotnet-library/scala/Product5.scala b/src/dotnet-library/scala/Product5.scala
new file mode 100644
index 0000000000..c03007bbb5
--- /dev/null
+++ b/src/dotnet-library/scala/Product5.scala
@@ -0,0 +1,66 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product5 {
+ def unapply[T1, T2, T3, T4, T5](x: Product5[T1, T2, T3, T4, T5]): Option[Product5[T1, T2, T3, T4, T5]] =
+ Some(x)
+}
+
+/** Product5 is a cartesian product of 5 components
+ */
+trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 5
+ */
+ override def arity = 5
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+
+}
diff --git a/src/dotnet-library/scala/Product6.scala b/src/dotnet-library/scala/Product6.scala
new file mode 100644
index 0000000000..2dd6dca489
--- /dev/null
+++ b/src/dotnet-library/scala/Product6.scala
@@ -0,0 +1,70 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product6 {
+ def unapply[T1, T2, T3, T4, T5, T6](x: Product6[T1, T2, T3, T4, T5, T6]): Option[Product6[T1, T2, T3, T4, T5, T6]] =
+ Some(x)
+}
+
+/** Product6 is a cartesian product of 6 components
+ */
+trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 6
+ */
+ override def arity = 6
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+
+}
diff --git a/src/dotnet-library/scala/Product7.scala b/src/dotnet-library/scala/Product7.scala
new file mode 100644
index 0000000000..32eec71c36
--- /dev/null
+++ b/src/dotnet-library/scala/Product7.scala
@@ -0,0 +1,74 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product7 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7](x: Product7[T1, T2, T3, T4, T5, T6, T7]): Option[Product7[T1, T2, T3, T4, T5, T6, T7]] =
+ Some(x)
+}
+
+/** Product7 is a cartesian product of 7 components
+ */
+trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 7
+ */
+ override def arity = 7
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+
+}
diff --git a/src/dotnet-library/scala/Product8.scala b/src/dotnet-library/scala/Product8.scala
new file mode 100644
index 0000000000..b60a6aa75f
--- /dev/null
+++ b/src/dotnet-library/scala/Product8.scala
@@ -0,0 +1,78 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product8 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8](x: Product8[T1, T2, T3, T4, T5, T6, T7, T8]): Option[Product8[T1, T2, T3, T4, T5, T6, T7, T8]] =
+ Some(x)
+}
+
+/** Product8 is a cartesian product of 8 components
+ */
+trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 8
+ */
+ override def arity = 8
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+
+}
diff --git a/src/dotnet-library/scala/Product9.scala b/src/dotnet-library/scala/Product9.scala
new file mode 100644
index 0000000000..7673dc85ca
--- /dev/null
+++ b/src/dotnet-library/scala/Product9.scala
@@ -0,0 +1,82 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+import Predef._
+
+object Product9 {
+ def unapply[T1, T2, T3, T4, T5, T6, T7, T8, T9](x: Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9]): Option[Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] =
+ Some(x)
+}
+
+/** Product9 is a cartesian product of 9 components
+ */
+trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product {
+
+ /**
+ * The arity of this product.
+ * @return 9
+ */
+ override def arity = 9
+
+ /**
+ * Returns the n-th projection of this product if 0&lt;=n&lt;arity,
+ * otherwise null.
+ *
+ * @param n number of the projection to be returned
+ * @return same as _(n+1)
+ * @throws IndexOutOfBoundsException
+ */
+ override def element(n: Int) = n match {
+ case 0 => _1
+ case 1 => _2
+ case 2 => _3
+ case 3 => _4
+ case 4 => _5
+ case 5 => _6
+ case 6 => _7
+ case 7 => _8
+ case 8 => _9
+ case _ => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** projection of this product */
+ def _1: T1
+
+/** projection of this product */
+ def _2: T2
+
+/** projection of this product */
+ def _3: T3
+
+/** projection of this product */
+ def _4: T4
+
+/** projection of this product */
+ def _5: T5
+
+/** projection of this product */
+ def _6: T6
+
+/** projection of this product */
+ def _7: T7
+
+/** projection of this product */
+ def _8: T8
+
+/** projection of this product */
+ def _9: T9
+
+
+}
diff --git a/src/dotnet-library/scala/Proxy.scala b/src/dotnet-library/scala/Proxy.scala
new file mode 100644
index 0000000000..b32c53b12d
--- /dev/null
+++ b/src/dotnet-library/scala/Proxy.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** This class implements a simple proxy that forwards all calls to
+ * methods of class <code>Any</code> to another object <code>self</code>.
+ * Please note that only those methods can be forwarded that are
+ * overridable and public.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 26/04/2004
+ */
+trait Proxy {
+ def self: Any
+ override def hashCode(): Int = self.hashCode()
+ override def equals(y: Any): Boolean = self.equals(y)
+ override def toString(): String = self.toString()
+}
diff --git a/src/dotnet-library/scala/Responder.scala b/src/dotnet-library/scala/Responder.scala
new file mode 100644
index 0000000000..050caa342e
--- /dev/null
+++ b/src/dotnet-library/scala/Responder.scala
@@ -0,0 +1,90 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2005-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala
+
+/** This object contains utility methods to build responders.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ *
+ * @see class Responder
+ * @since revision 6897 (will be 2.1.1)
+ */
+object Responder {
+
+ /** Creates a responder that answer continuations with the constant
+ * <code>a</code>.
+ *
+ * @param x ...
+ * @return ...
+ */
+ def constant[a](x: a) = new Responder[a] {
+ def respond(k: a => unit) = k(x)
+ }
+
+ /** Executes <code>x</code> and returns <code>true</code>, useful
+ * as syntactic convenience in for comprehensions.
+ *
+ * @param x ...
+ * @return ...
+ */
+ def exec[a](x: => unit): boolean = { x; true }
+
+ /** runs a responder, returning an optional result
+ */
+ def run[a](r: Responder[a]): Option[a] = {
+ var result: Option[a] = None
+ r.foreach(x => result = Some(x))
+ result
+ }
+
+ def loop[a](r: Responder[unit]): Responder[Nothing] =
+ for (val _ <- r; val y <- loop(r)) yield y
+
+ def loopWhile[a](cond: => boolean)(r: Responder[unit]): Responder[unit] =
+ if (cond) for (val _ <- r; val y <- loopWhile(cond)(r)) yield y
+ else constant(())
+
+}
+
+/** Instances of responder are the building blocks of small programs
+ * written in continuation passing style. By using responder classes
+ * in for comprehensions, one can embed domain-specific languages in
+ * Scala while giving the impression that programs in these DSLs are
+ * written in direct style.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ *
+ * @since revision 6897 (will be 2.1.1)
+ */
+abstract class Responder[+a] {
+
+ def respond(k: a => unit): unit
+
+ def foreach(k: a => unit): unit = respond(k)
+
+ def map[b](f: a => b) = new Responder[b] {
+ def respond(k: b => unit): unit =
+ Responder.this.respond(x => k(f(x)))
+ }
+
+ def flatMap[b](f: a => Responder[b]) = new Responder[b] {
+ def respond(k: b => unit): unit =
+ Responder.this.respond(x => f(x).respond(k))
+ }
+
+ def filter(p: a => boolean) = new Responder[a] {
+ def respond(k: a => unit): unit =
+ Responder.this.respond(x => if (p(x)) k(x) else ())
+ }
+}
+
diff --git a/src/dotnet-library/scala/ScalaObject.scala b/src/dotnet-library/scala/ScalaObject.scala
new file mode 100644
index 0000000000..7d213e33b3
--- /dev/null
+++ b/src/dotnet-library/scala/ScalaObject.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+trait ScalaObject extends AnyRef {
+
+ /** This method is needed for optimizing pattern matching expressions
+ * which match on constructors of case classes.
+ */
+ [remote]
+ def $tag(): Int = 0
+
+}
diff --git a/src/dotnet-library/scala/Seq.scala b/src/dotnet-library/scala/Seq.scala
new file mode 100644
index 0000000000..1a488b82b2
--- /dev/null
+++ b/src/dotnet-library/scala/Seq.scala
@@ -0,0 +1,274 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import Predef.{IllegalArgumentException, NoSuchElementException}
+import collection.mutable.ArrayBuffer
+
+object Seq {
+
+ /** The empty sequence */
+ val empty = new Seq[Nothing] {
+ def length = 0
+ def apply(i: Int): Nothing = throw new NoSuchElementException("empty sequence")
+ def elements = Iterator.empty
+ }
+
+ /** This method is called in a pattern match { case Seq(...) => }.
+ *
+ * @param x the selector value
+ * @return sequence wrapped in an option, if this is a Seq, otherwise none
+ */
+ def unapplySeq[A](x: Any): Option[Seq[A]] = x match {
+ case z: Seq[_] => Some(z.asInstanceOf[Seq[A]])
+ case z: AnyRef if runtime.ScalaRunTime.isArray(z) => Some(runtime.ScalaRunTime.boxArray(z).asInstanceOf[Seq[A]])
+ case _ => None
+ }
+
+ /** Builds a singleton sequence.
+ *
+ * @param x ...
+ * @return ...
+ */
+ def single[A](x: A) = new Seq[A] {
+ def length = 1
+ def elements = Iterator.single(x)
+ override def isDefinedAt(x: Int): Boolean = (x == 0)
+ def apply(i: Int) = x // caller's responsibility to check isDefinedAt
+ }
+/*
+ implicit def view[A <% Ordered[A]](xs: Seq[A]): Ordered[Seq[A]] =
+ new Ordered[Seq[A]] with Proxy {
+ def self: Any = xs;
+ def compare[B >: Seq[A] <% Ordered[B]](that: B): Int = that match {
+ case ys: Seq[A] =>
+ var res = 0;
+ val xsit = xs.elements;
+ val ysit = ys.elements;
+ while (xsit.hasNext && ysit.hasNext && (res == 0)) {
+ res = xsit.next compare ysit.next;
+ }
+ if (res != 0) res else if (xsit.hasNext) 1 else -1
+ case _ =>
+ -(that compare xs)
+ }
+ }
+*/
+}
+
+
+/** Class <code>Seq[A]</code> represents finite sequences of elements
+ * of type <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.0, 16/07/2003
+ */
+trait Seq[+A] extends AnyRef with PartialFunction[Int, A] with Iterable[A] {
+
+ /** Returns the length of the sequence.
+ *
+ * @return the sequence length.
+ */
+ def length: Int
+
+ /** Returns true if length == 0
+ */
+ def isEmpty: Boolean = { length == 0 }
+
+ /** Appends two iterable objects.
+ *
+ * @return the new iterable object
+ * @deprecated use <code>++</code> instead
+ */
+ [deprecated] override def concat [B >: A](that: Iterable[B]): Seq[B] = {
+ val buf = new ArrayBuffer[B]
+ this copyToBuffer buf
+ that copyToBuffer buf
+ buf
+ }
+
+ /** Appends two iterable objects.
+ *
+ * @param that ..
+ * @return the new iterable object
+ */
+ override def ++ [B >: A](that: Iterable[B]): Seq[B] = {
+ val buf = new ArrayBuffer[B]
+ this copyToBuffer buf
+ that copyToBuffer buf
+ buf
+ }
+
+ /** Is this partial function defined for the index <code>x</code>?
+ *
+ * @param x ..
+ * @return <code>true</code>, iff <code>x</code> is a legal sequence index.
+ */
+ def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length)
+
+ /** Returns the index of the last occurence of the specified element
+ * in this sequence, or -1 if the sequence does not contain this element.
+ *
+ * @param elem element to search for.
+ * @return the index in this sequence of the last occurence of the
+ * specified element, or -1 if the sequence does not contain
+ * this element.
+ */
+ def lastIndexOf[B >: A](elem: B): Int = {
+ var i = length;
+ var found = false;
+ while (!found && (i > 0)) {
+ i = i - 1;
+ if (this(i) == elem) {
+ found = true;
+ }
+ }
+ if (found) i else -1;
+ }
+
+ /** Returns the sequence resulting from applying the given function
+ * <code>f</code> to each element of this sequence.
+ *
+ * @param f function to apply to each element.
+ * @return <code>f(a<sub>0</sub>), ..., f(a<sub>n</sub>)</code> if this
+ * sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ override def map[B](f: A => B): Seq[B] = {
+ // todo: malformed scala signature suing build when replaced by
+ // super.map(f).asInstanceOf[Seq[B2]]
+ val buf = new ArrayBuffer[B]
+ val elems = elements
+ while (elems.hasNext) buf += f(elems.next)
+ buf
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this sequence, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this sequence is <code>a<sub>0</sub>, ..., a<sub>n</sub></code>.
+ */
+ override def flatMap[B](f: A => Iterable[B]): Seq[B] = {
+ val buf = new ArrayBuffer[B]
+ val elems = elements
+ while (elems.hasNext) f(elems.next) copyToBuffer buf
+ buf
+ }
+
+ /** Returns all the elements of this sequence that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ override def filter(p: A => Boolean): Seq[A] = super.filter(p).asInstanceOf[Seq[A]]
+
+ /** Returns a sequence consisting only over the first <code>n</code>
+ * elements of this sequence, or else the whole sequence, if it has less
+ * than <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the new sequence
+ */
+ override def take(n: Int): Seq[A] = super.take(n).asInstanceOf[Seq[A]]
+
+ /** Returns this sequence without its <code>n</code> first elements
+ * If this sequence has less than <code>n</code> elements, the empty
+ * sequence is returned.
+ *
+ * @param n the number of elements to drop
+ * @return the new sequence
+ */
+ override def drop(n: Int): Seq[A] = super.drop(n).asInstanceOf[Seq[A]]
+
+ /** Returns the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this sequence whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ override def takeWhile(p: A => Boolean): Seq[A] = super.takeWhile(p).asInstanceOf[Seq[A]]
+
+ /** Returns the longest suffix of this sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the sequence whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ override def dropWhile(p: A => Boolean): Seq[A] = super.dropWhile(p).asInstanceOf[Seq[A]]
+
+ /** A sequence consisting of all elements of this sequence in reverse order.
+ */
+ def reverse: Seq[A] = {
+ var result: List[A] = Nil
+ val elems = elements
+ while (elems.hasNext) result = elems.next :: result
+ result
+ }
+
+ /** Tests if the given value <code>elem</code> is a member of this
+ * sequence.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return <code>true</code> iff there is an element of this sequence
+ * which is equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists (.==(elem))
+
+ /** Returns a subsequence starting from index <code>from</code>
+ * consisting of <code>len</code> elements.
+ *
+ * @param from ..
+ * @param len ..
+ * @return ..
+ */
+ def slice(from: Int, len: Int): Seq[A] = this.drop(from).take(len)
+
+ /** Returns a subsequence starting from index <code>from</code>
+ * consisting of <code>len</code> elements.
+ *
+ * @deprecated use <code>slice</code> instead
+ */
+ [deprecated] def subseq(from: Int, end: Int): Seq[A] = slice(from, end - from)
+
+ /** Converts this sequence to a fresh Array with <code>length</code> elements.
+ */
+ def toArray[B >: A]: Array[B] = {
+ val result = new Array[B](length)
+ copyToArray(result, 0)
+ result
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int): Unit = elements.copyToArray(xs, start)
+
+ /** Customizes the <code>toString</code> method.
+ *
+ * @return a string representation of this sequence.
+ */
+ override def toString() = mkString(stringPrefix+"(", ",", ")")
+
+ /** Defines the prefix of the string representation.
+ */
+ protected def stringPrefix: String = "Seq"
+}
+
diff --git a/src/dotnet-library/scala/SeqProxy.scala b/src/dotnet-library/scala/SeqProxy.scala
new file mode 100644
index 0000000000..5af95e0953
--- /dev/null
+++ b/src/dotnet-library/scala/SeqProxy.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/** This class implements a proxy for sequences. It forwards
+ * all calls to a different sequence object.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 2.0, 31/12/2006
+ */
+trait SeqProxy[+A] extends Seq[A] with IterableProxy[A] {
+
+ def self: Seq[A]
+
+ override def apply(i: Int): A = self(i)
+ override def length: Int = self.length
+ override def isEmpty: Boolean = self.isEmpty
+ [deprecated] override def concat [B >: A](that: Iterable[B]): Seq[B] = self concat that
+ override def isDefinedAt(x: Int): Boolean = self isDefinedAt x
+ override def lastIndexOf[B >: A](elem: B): Int = self lastIndexOf elem
+ override def map[B](f: A => B): Seq[B] = self map f
+ override def flatMap[B](f: A => Iterable[B]): Seq[B] = self flatMap f
+ override def filter(p: A => Boolean): Seq[A] = self filter p
+ override def take(n: Int): Seq[A] = self take n
+ override def drop(n: Int): Seq[A] = self drop n
+ override def takeWhile(p: A => Boolean): Seq[A] = self takeWhile p
+ override def dropWhile(p: A => Boolean): Seq[A] = self dropWhile p
+ override def reverse: Seq[A] = self.reverse
+ override def contains(elem: Any): Boolean = self contains elem
+ override def slice(from: Int, len: Int): Seq[A] = self.slice(from, len)
+ override def toArray[B >: A]: Array[B] = self.toArray
+ override def copyToArray[B >: A](xs: Array[B], start: Int): Unit = self.copyToArray(xs, start)
+}
diff --git a/src/dotnet-library/scala/SerialVersionUID.scala b/src/dotnet-library/scala/SerialVersionUID.scala
new file mode 100644
index 0000000000..4467303067
--- /dev/null
+++ b/src/dotnet-library/scala/SerialVersionUID.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+*/
+
+// $Id$
+
+
+package scala
+
+
+/**
+ * Attribute for specifying the static SerialVersionUID field
+ * of a serializable class
+ */
+class SerialVersionUID(uid: Long) extends Attribute
diff --git a/src/dotnet-library/scala/StaticAttribute.scala b/src/dotnet-library/scala/StaticAttribute.scala
new file mode 100644
index 0000000000..8b4815472b
--- /dev/null
+++ b/src/dotnet-library/scala/StaticAttribute.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Attribute.scala 8926 2006-10-11 09:58:51 +0000 (Wed, 11 Oct 2006) dragos $
+
+
+package scala
+
+/** <p>A base class for static attributes. These are available
+ * to the Scala typechecker, even across different compilation units.
+ * </p>
+ *
+ * @author Martin Odersky
+ * @version 1.1, 2/02/2007
+ */
+trait StaticAttribute extends Attribute {}
diff --git a/src/dotnet-library/scala/Stream.scala b/src/dotnet-library/scala/Stream.scala
new file mode 100644
index 0000000000..db02cd89d8
--- /dev/null
+++ b/src/dotnet-library/scala/Stream.scala
@@ -0,0 +1,457 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+import compat.StringBuilder
+import Predef.{NoSuchElementException, UnsupportedOperationException}
+
+/**
+ * The object <code>Stream</code> provides helper functions
+ * to manipulate streams.
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 1.1 08/08/03
+ */
+object Stream {
+
+ /** The empty stream */
+ val empty: Stream[Nothing] = new Stream[Nothing] {
+ override def isEmpty = true
+ def head: Nothing = throw new NoSuchElementException("head of empty stream")
+ def tail: Stream[Nothing] = throw new UnsupportedOperationException("tail of empty stream")
+ protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = buf
+ }
+
+
+ object cons {
+ /** A stream consisting of a given first element and remaining elements
+ * @param hd The first element of the result stream
+ * @param tl The remaining elements of the result stream
+ */
+ def apply[a](hd: a, tl: => Stream[a]) = new Stream[a] {
+ override def isEmpty = false
+ def head = hd
+ private var tlVal: Stream[a] = _
+ private var tlDefined = false
+ def tail: Stream[a] = {
+ if (!tlDefined) { tlVal = tl; tlDefined = true }
+ tlVal
+ }
+ protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder = {
+ val buf1 = buf.append(prefix).append(hd)
+ if (tlDefined) tlVal.addDefinedElems(buf1, ", ") else buf1 append ", ?"
+ }
+ }
+
+ def unapply[a](str: Stream[a]): Option[{a,Stream[a]}] =
+ if(str.isEmpty)
+ None
+ else
+ Some{str.head, str.tail}
+ }
+
+ /** A stream containing all elements of a given iterator, in the order they are produced.
+ * @param it The iterator producing the stream's elements
+ */
+ def fromIterator[a](it: Iterator[a]): Stream[a] =
+ if (it.hasNext) cons(it.next, fromIterator(it)) else empty
+
+ /** The concatenation of a sequence of streams
+ */
+ def concat[a](xs: Iterable[Stream[a]]): Stream[a] = concat(xs.elements)
+
+ /** The concatenation of all given streams
+ */
+ def concat[a](s1: Stream[a], s2: Stream[a], ss: Stream[a]*): Stream[a] =
+ s1 append s2 append concat(ss.elements)
+
+ /** The concatenation of all streams returned by an iterator
+ */
+ def concat[a](xs: Iterator[Stream[a]]): Stream[a] =
+ if (xs.hasNext) xs.next append concat(xs)
+ else empty
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + 1</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int): Stream[Int] =
+ range(start, end, 1)
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @param step the increment value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int, step: Int): Stream[Int] = {
+ def loop(lo: Int): Stream[Int] =
+ if (lo >= end) empty
+ else cons(lo, loop(lo + step));
+ loop(start)
+ }
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @param step the increment function of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int, step: Int => Int): Stream[Int] = {
+ def loop(lo: Int): Stream[Int] =
+ if (lo >= end) empty
+ else cons(lo, loop(step(lo)));
+ loop(start)
+ }
+
+ /**
+ * Create an infinite stream starting at <code>start</code>
+ * and incrementing by step <code>step</code>
+ *
+ * @param start the start value of the stream
+ * @param step the increment value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def from(start: Int, step: Int): Stream[Int] =
+ cons(start, from(start+step, step))
+
+ /**
+ * Create an infinite stream starting at <code>start</code>
+ * and incrementing by 1.
+ *
+ * @param start the start value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def from(start: Int): Stream[Int] = from(start, 1)
+}
+
+/**
+ * <p>The class <code>Stream</code> implements lazy lists where elements
+ * are only evaluated when they are needed. Here is an example:</p>
+ * <pre>
+ * <b>object</b> Main <b>extends</b> Application {
+ *
+ * <b>def</b> from(n: Int): Stream[Int] =
+ * Stream.cons(n, from(n + 1))
+ *
+ * <b>def</b> sieve(s: Stream[Int]): Stream[Int] =
+ * Stream.cons(s.head, sieve(s.tail filter { x => x % s.head != 0 }))
+ *
+ * <b>def</b> primes = sieve(from(2))
+ *
+ * primes take 10 print
+ * }
+ * </pre>
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 1.1 08/08/03
+ */
+trait Stream[+a] extends Seq[a] {
+
+ /** is this stream empty? */
+ override def isEmpty: Boolean
+
+ /** The first element of this stream
+ * @throws Predef.NoSuchElementException if the stream is empty.
+ */
+ def head: a
+
+ /** A stream consisting of the remaining elements of this stream after the first one.
+ * @throws Predef.UnsupportedOperationException if the stream is empty.
+ */
+ def tail: Stream[a]
+
+ /** The length of this stream */
+ def length: Int = if (isEmpty) 0 else tail.length + 1
+
+ /** The stream resulting from the concatenation of thsi stream with the argument stream.
+ * @param rest The stream that gets appended to this stream
+ */
+ def append[b >: a](rest: => Stream[b]): Stream[b] =
+ if (isEmpty) rest
+ else Stream.cons(head, tail.append(rest))
+
+ /** An iterator returning the elements of this stream one by one.
+ */
+ def elements: Iterator[a] = new Iterator[a] {
+ var current = Stream.this
+ def hasNext: Boolean = !current.isEmpty
+ def next: a = { val result = current.head; current = current.tail; result }
+ }
+
+ /** The stream without its last element.
+ * @throws Predef.UnsupportedOperationException if the stream is empty.
+ */
+ def init: Stream[a] =
+ if (isEmpty) throw new UnsupportedOperationException("Stream.empty.init")
+ else if (tail.isEmpty) Stream.empty
+ else Stream.cons(head, tail.init)
+
+ /** Returns the last element of this stream.
+ *
+ * @return the last element of the stream.
+ * @throws Predef.NoSuchElementException if the stream is empty.
+ */
+ def last: a =
+ if (isEmpty) throw new NoSuchElementException("Stream.empty.last")
+ else {
+ def loop(s: Stream[a]): a = {
+ if (s.tail.isEmpty) s.head
+ else loop(s.tail)
+ }
+ loop(this)
+ }
+
+ /** Returns the <code>n</code>-th element of this stream. The first element
+ * (head of the stream) is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this stream.
+ * @throws Predef.NoSuchElementException if the stream is too short.
+ */
+ def apply(n: Int) = drop(n).head
+
+ /** Returns the <code>n</code> first elements of this stream, or else the whole
+ * stream, if it has less than <code>n</code> elements.
+ *
+ * @param n the number of elements to take.
+ * @return the <code>n</code> first elements of this stream.
+ */
+ override def take(n: Int): Stream[a] =
+ if (n == 0) Stream.empty
+ else Stream.cons(head, tail.take(n-1))
+
+ /** Returns the stream without its <code>n</code> first elements.
+ * If the stream has less than <code>n</code> elements, the empty stream is returned.
+ *
+ * @param n the number of elements to drop.
+ * @return the stream without its <code>n</code> first elements.
+ */
+ override def drop(n: Int): Stream[a] = {
+ def loop(s: Stream[a], n: Int): Stream[a] =
+ if (n == 0) s
+ else loop(s.tail, n-1)
+ loop(this, n)
+ }
+
+ /** Returns the longest prefix of this stream whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this stream whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ override def takeWhile(p: a => Boolean): Stream[a] =
+ if (isEmpty || !p(head)) Stream.empty
+ else Stream.cons(head, tail.takeWhile(p))
+
+ /** Returns the longest suffix of this stream whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the stream whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ override def dropWhile(p: a => Boolean): Stream[a] = {
+ def loop(s: Stream[a]): Stream[a] =
+ if (s.isEmpty || !p(s.head)) this
+ else loop(s.tail)
+ loop(this)
+ }
+
+ /** Returns the stream resulting from applying the given function <code>f</code> to each
+ * element of this stream.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this stream is <code>[a0, ..., an]</code>.
+ */
+ override def map[b](f: a => b): Stream[b] =
+ if (isEmpty) Stream.empty
+ else Stream.cons(f(head), tail.map(f))
+
+ /** Apply the given function <code>f</code> to each element of this stream
+ * (while respecting the order of the elements).
+ *
+ * @param f the treatment to apply to each element.
+ */
+ override def foreach(f: a => Unit) {
+ def loop(s: Stream[a]) {
+ if (s.isEmpty) {}
+ else { f(s.head); loop(s.tail) }
+ }
+ loop(this)
+ }
+
+ /** Returns all the elements of this stream that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the predicate used to filter the stream.
+ * @return the elements of this stream satisfying <code>p</code>.
+ */
+ override def filter(p: a => Boolean): Stream[a] = {
+ def loop(s: Stream[a]): Stream[a] =
+ if (s.isEmpty) s
+ else if (p(s.head)) Stream.cons(s.head, loop(s.tail))
+ else loop(s.tail)
+ loop(this)
+ }
+
+ /** Tests if the predicate <code>p</code> is satisfied by all elements
+ * in this stream.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff all elements of this stream satisfy the
+ * predicate <code>p</code>.
+ */
+ override def forall(p: a => Boolean): Boolean = {
+ def loop(s: Stream[a]): Boolean = {
+ if (s.isEmpty) true
+ else if (p(s.head)) loop(s.tail)
+ else false
+ }
+ loop(this)
+ }
+
+ /** Tests the existence in this stream of an element that satisfies the
+ * predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return <code>true</code> iff there exists an element in this stream that
+ * satisfies the predicate <code>p</code>.
+ */
+ override def exists(p: a => Boolean): Boolean = {
+ def loop(s: Stream[a]): Boolean = {
+ if (s.isEmpty) false
+ else if (p(s.head)) true
+ else loop(s.tail)
+ }
+ loop(this)
+ }
+
+ /** Combines the elements of this stream together using the binary
+ * function <code>f</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),
+ * a<sub>n</sub>)</code> if the stream is
+ * <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldLeft[b](z: b)(f: (b, a) => b): b = {
+ def loop(s: Stream[a], z: b): b =
+ if (s.isEmpty) z
+ else loop(s.tail, f(z, s.head))
+ loop(this, z)
+ }
+
+ /** Combines the elements of this stream together using the binary
+ * function <code>f</code>, from rigth to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>
+ * if the stream is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.
+ */
+ override def foldRight[b](z: b)(f: (a, b) => b): b =
+ if (isEmpty) z
+ else f(head, tail.foldRight(z)(f))
+
+ /** Applies the given function <code>f</code> to each element of
+ * this stream, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if
+ * this stream is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.
+ */
+ override def flatMap[b](f: a => Iterable[b]): Stream[b] =
+ if (isEmpty) Stream.empty
+ else Stream.fromIterator(f(head).elements).append(tail.flatMap(f))
+
+ /** A stream consisting of all elements of this stream in reverse order.
+ */
+ override def reverse: Stream[a] =
+ foldLeft(Stream.empty: Stream[a])((xs, x) => Stream.cons(x, xs))
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this stream starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ override def copyToArray[b >: a](xs: Array[b], start: Int) {
+ def loop(s: Stream[a], start: Int) {
+ if (!xs.isEmpty) { xs(start) = s.head; loop(s.tail, start + 1) }
+ }
+ loop(this, start)
+ }
+
+ /** Returns a stream formed from this stream and the specified stream
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ * If one of the two streams is longer than the other, its remaining elements are ignored.
+ *
+ * @return <code>Stream({a<sub>0</sub>,b<sub>0</sub>}, ...,
+ * {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>)}</code> when
+ * <code>Stream(a<sub>0</sub>, ..., a<sub>m</sub>)
+ * zip Stream(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.
+ */
+ def zip[b](that: Stream[b]): Stream[Tuple2[a, b]] =
+ if (this.isEmpty || that.isEmpty) Stream.empty
+ else Stream.cons(Tuple2(this.head, that.head), this.tail.zip(that.tail))
+
+
+ /** Returns a stream that pairs each element of this stream
+ * with its index, counting from 0.
+ *
+ * @return the stream <code>Stream({a<sub>0</sub>,0}, {a<sub>0</sub>,1},...)</code>
+ * where <code>a<sub>i</sub></code> are the elements of this stream.
+ */
+ def zipWithIndex: Stream[Tuple2[a, Int]] =
+ zip(Stream.from(0))
+
+ /** Prints elements of this stream one by one, separated by commas */
+ def print { print(", ") }
+
+ /** Prints elements of this stream one by one, separated by <code>sep</code>
+ * @param sep The separator string printed between consecutive elements.
+ */
+ def print(sep: String) {
+ def loop(s: Stream[a]) {
+ if (s.isEmpty) Console.println("Stream.empty")
+ else { Console.print(s.head); Console.print(sep); loop(s.tail) }
+ }
+ loop(this)
+ }
+
+ /** Converts stream to string */
+ override def toString() =
+ "Stream(" + addDefinedElems(new StringBuilder(), "") + ")"
+
+ /** Write all elements of this string into given string builder */
+ protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder
+}
diff --git a/src/dotnet-library/scala/Symbol.scala b/src/dotnet-library/scala/Symbol.scala
new file mode 100644
index 0000000000..9bc195dce6
--- /dev/null
+++ b/src/dotnet-library/scala/Symbol.scala
@@ -0,0 +1,57 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+import collection.jcl.WeakHashMap
+
+private[scala] object internedSymbols extends WeakHashMap[String, Symbol]
+
+/** <p>
+ * Instances of <code>Symbol</code> can be created easily with
+ * Scala's built-in quote mechanism.
+ * </p>
+ * <p>
+ * For instance, the <a href="http://scala-lang.org/" target="_top">Scala</a>
+ * term <code>'mysym</code> will invoke the constructor of the
+ * <code>Symbol</code> class in the following way:
+ * <code>new Symbol("mysym")</code>.
+ * </p>
+ *
+ * @author Martin Odersky
+ * @version 1.7, 08/12/2003
+ */
+final case class Symbol(name: String) {
+
+ /** Converts this symbol to a string.
+ */
+ override def toString(): String = {
+ "'" + name
+ }
+
+ /** <p>
+ * Makes this symbol into a unique reference.
+ * </p>
+ * <p>
+ * If two interened symbols are equal (i.e. they have the same name)
+ * then they must be identical (wrt reference equality).
+ * </p>
+ *
+ * @return the unique reference to this symbol.
+ */
+ def intern: Symbol = internedSymbols get name match {
+ case Some(sym) =>
+ sym
+ case None =>
+ internedSymbols(name) = this
+ this
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple1.scala b/src/dotnet-library/scala/Tuple1.scala
new file mode 100644
index 0000000000..f38c9011a3
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple1.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple1 is the canonical representation of a @see Product1 */
+case class Tuple1[+T1](_1:T1)
+ extends Product1[T1] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(",}")
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple10.scala b/src/dotnet-library/scala/Tuple10.scala
new file mode 100644
index 0000000000..ce061776a0
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple10.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple10 is the canonical representation of a @see Product10 */
+case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10)
+ extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple11.scala b/src/dotnet-library/scala/Tuple11.scala
new file mode 100644
index 0000000000..7598fc7289
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple11.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple11 is the canonical representation of a @see Product11 */
+case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11)
+ extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple12.scala b/src/dotnet-library/scala/Tuple12.scala
new file mode 100644
index 0000000000..e7e2c4effd
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple12.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple12 is the canonical representation of a @see Product12 */
+case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12)
+ extends Product12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple13.scala b/src/dotnet-library/scala/Tuple13.scala
new file mode 100644
index 0000000000..63a3b1d2b9
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple13.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple13 is the canonical representation of a @see Product13 */
+case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13)
+ extends Product13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple14.scala b/src/dotnet-library/scala/Tuple14.scala
new file mode 100644
index 0000000000..5c508e6b38
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple14.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple14 is the canonical representation of a @see Product14 */
+case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14)
+ extends Product14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple15.scala b/src/dotnet-library/scala/Tuple15.scala
new file mode 100644
index 0000000000..93cfb32591
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple15.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple15 is the canonical representation of a @see Product15 */
+case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15)
+ extends Product15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple16.scala b/src/dotnet-library/scala/Tuple16.scala
new file mode 100644
index 0000000000..c4888f9e98
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple16.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple16 is the canonical representation of a @see Product16 */
+case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16)
+ extends Product16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple17.scala b/src/dotnet-library/scala/Tuple17.scala
new file mode 100644
index 0000000000..23f0a66d5e
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple17.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple17 is the canonical representation of a @see Product17 */
+case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17)
+ extends Product17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple18.scala b/src/dotnet-library/scala/Tuple18.scala
new file mode 100644
index 0000000000..ad3ed96cf6
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple18.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple18 is the canonical representation of a @see Product18 */
+case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17, _18:T18)
+ extends Product18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append(',').append(_18).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple19.scala b/src/dotnet-library/scala/Tuple19.scala
new file mode 100644
index 0000000000..ff30bfa386
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple19.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple19 is the canonical representation of a @see Product19 */
+case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17, _18:T18, _19:T19)
+ extends Product19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append(',').append(_18).append(',').append(_19).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple2.scala b/src/dotnet-library/scala/Tuple2.scala
new file mode 100644
index 0000000000..77a9271277
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple2.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple2 is the canonical representation of a @see Product2 */
+case class Tuple2[+T1, +T2](_1:T1, _2:T2)
+ extends Product2[T1, T2] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple20.scala b/src/dotnet-library/scala/Tuple20.scala
new file mode 100644
index 0000000000..1878a8892b
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple20.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple20 is the canonical representation of a @see Product20 */
+case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17, _18:T18, _19:T19, _20:T20)
+ extends Product20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append(',').append(_18).append(',').append(_19).append(',').append(_20).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple21.scala b/src/dotnet-library/scala/Tuple21.scala
new file mode 100644
index 0000000000..c2a3a952cf
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple21.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple21 is the canonical representation of a @see Product21 */
+case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17, _18:T18, _19:T19, _20:T20, _21:T21)
+ extends Product21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append(',').append(_18).append(',').append(_19).append(',').append(_20).append(',').append(_21).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple22.scala b/src/dotnet-library/scala/Tuple22.scala
new file mode 100644
index 0000000000..64d135f3b4
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple22.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: genprod.scala 9547 2007-01-03 16:34:59Z emir $
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple22 is the canonical representation of a @see Product22 */
+case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9, _10:T10, _11:T11, _12:T12, _13:T13, _14:T14, _15:T15, _16:T16, _17:T17, _18:T18, _19:T19, _20:T20, _21:T21, _22:T22)
+ extends Product22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append(',').append(_10).append(',').append(_11).append(',').append(_12).append(',').append(_13).append(',').append(_14).append(',').append(_15).append(',').append(_16).append(',').append(_17).append(',').append(_18).append(',').append(_19).append(',').append(_20).append(',').append(_21).append(',').append(_22).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple3.scala b/src/dotnet-library/scala/Tuple3.scala
new file mode 100644
index 0000000000..0e28ce0ced
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple3.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple3 is the canonical representation of a @see Product3 */
+case class Tuple3[+T1, +T2, +T3](_1:T1, _2:T2, _3:T3)
+ extends Product3[T1, T2, T3] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple4.scala b/src/dotnet-library/scala/Tuple4.scala
new file mode 100644
index 0000000000..f6d4c12709
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple4.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple4 is the canonical representation of a @see Product4 */
+case class Tuple4[+T1, +T2, +T3, +T4](_1:T1, _2:T2, _3:T3, _4:T4)
+ extends Product4[T1, T2, T3, T4] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple5.scala b/src/dotnet-library/scala/Tuple5.scala
new file mode 100644
index 0000000000..4f21a6f3e6
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple5.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple5 is the canonical representation of a @see Product5 */
+case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5)
+ extends Product5[T1, T2, T3, T4, T5] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple6.scala b/src/dotnet-library/scala/Tuple6.scala
new file mode 100644
index 0000000000..bf196246a2
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple6.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple6 is the canonical representation of a @see Product6 */
+case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6)
+ extends Product6[T1, T2, T3, T4, T5, T6] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple7.scala b/src/dotnet-library/scala/Tuple7.scala
new file mode 100644
index 0000000000..9d3bd0ae22
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple7.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple7 is the canonical representation of a @see Product7 */
+case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7)
+ extends Product7[T1, T2, T3, T4, T5, T6, T7] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple8.scala b/src/dotnet-library/scala/Tuple8.scala
new file mode 100644
index 0000000000..1e18daf6c2
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple8.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple8 is the canonical representation of a @see Product8 */
+case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8)
+ extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/Tuple9.scala b/src/dotnet-library/scala/Tuple9.scala
new file mode 100644
index 0000000000..b6632a8980
--- /dev/null
+++ b/src/dotnet-library/scala/Tuple9.scala
@@ -0,0 +1,25 @@
+
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// generated by genprod on Wed Jan 03 17:36:14 CET 2007
+
+package scala
+
+/** Tuple9 is the canonical representation of a @see Product9 */
+case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1:T1, _2:T2, _3:T3, _4:T4, _5:T5, _6:T6, _7:T7, _8:T8, _9:T9)
+ extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] {
+
+ override def toString() = {
+ val sb = new compat.StringBuilder
+ sb.append('{').append(_1).append(',').append(_2).append(',').append(_3).append(',').append(_4).append(',').append(_5).append(',').append(_6).append(',').append(_7).append(',').append(_8).append(',').append(_9).append('}')
+ sb.toString
+ }
+}
diff --git a/src/dotnet-library/scala/cloneable.scala b/src/dotnet-library/scala/cloneable.scala
new file mode 100644
index 0000000000..5db2713132
--- /dev/null
+++ b/src/dotnet-library/scala/cloneable.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala;
+
+
+/**
+ * An attribute that designates the class to which it is applied as cloneable
+ */
+class cloneable extends Attribute {}
diff --git a/src/dotnet-library/scala/collection/BitSet.scala b/src/dotnet-library/scala/collection/BitSet.scala
new file mode 100644
index 0000000000..374ad1fb71
--- /dev/null
+++ b/src/dotnet-library/scala/collection/BitSet.scala
@@ -0,0 +1,140 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+
+
+/** <p>
+ * The class <code>BitSet</code> provides the interface for a space-efficient
+ * implementation of dense integer sets represented as bits in array of
+ * integers. Bit indices are between <code>0..(capacity-1)</code> inclusive.
+ * </p>
+ *
+ * @author Burak Emir, Stephane Micheloud, Nikolay Mihaylov
+ * @author Martin Odersky
+ * @version 2.0 01/01/2007
+ */
+
+abstract class BitSet extends Set[Int] {
+
+ import compat.Platform.arraycopy
+ import compat.Math.min
+
+ /** number of bits in this bitset */
+ def size: Int
+
+ /**
+ * @param i ...
+ * @return <code>true</code> if bit <code>i</code> is set.
+ */
+ def contains(i: Int): Boolean =
+ (i < capacity) && ((arr(offset(i)) & mask(i)) != 0)
+
+ def capacity: Int
+
+ protected def arr: Array[Int]
+
+ /** returns an iterator over the truth values of all bits */
+ final def elements: Iterator[Int] = new Iterator[Int] {
+ var i = 0
+ def findNext: Unit = {
+ while (!BitSet.this.contains(i) && (i < capacity))
+ i = i + 1
+ }
+ findNext
+ def hasNext: Boolean = i < capacity
+ def next: Int = { val j = i; i = i + 1; findNext; j }
+ }
+
+
+ /**
+ * @return a copy of the array underlying this bitset
+ */
+ def toArray: Array[Int] = {
+ val length = memsize(capacity)
+ val newarr = new Array[Int](length)
+ arraycopy(newarr, 0, this.arr, 0, length)
+ newarr
+ }
+
+ /** Checks if two bitsets are structurally identical.
+ * Uses accelerated (32 x faster) check if the other set is a BitSet
+ *
+ * @param other ...
+ * @return <code>true</code>, iff both bitsets contain the same
+ * elements.
+ */
+ override def equals(other: Any): Boolean = other match {
+ case that: BitSet =>
+ (size == that.size) && {
+ var len = memsize(min(this.capacity, that.capacity))
+ var i = 0
+ while (i < len && arr(i) == that.arr(i)) i = i + 1
+ i == len
+ }
+ case _ =>
+ super.equals(other)
+ }
+
+ override def hashCode(): Int = {
+ val len = memsize(this.capacity)
+ var h = 0
+ var i = 0
+ while (i < len) { h = h * 41 + arr(i); i = i + 1 }
+ h
+ }
+
+ /** Checks if this set is a subset of set <code>that</code>.
+ * Uses accelerated (32 x faster) check if the other set is a BitSet
+ *
+ * @param other another set.
+ * @return <code>true</code>, iff the other set is a superset of
+ * this set.
+ */
+ override def subsetOf(other: Set[Int]): Boolean = other match {
+ case that: BitSet =>
+ val thisLen = memsize(this.capacity)
+ val thatLen = memsize(that.capacity)
+ val minLen = min(thisLen, thatLen)
+ var i = 0
+ while (i < minLen && that.arr(i) == (that.arr(i) | arr(i))) i = i + 1
+ while (i < thisLen && arr(i) == 0) i = i + 1
+ i == thisLen
+ case _ =>
+ super.subsetOf(other)
+ }
+
+ /**
+ * @param n the number of bits to be stored.
+ * @return the number of <code>Int</code> cells needed to store
+ * <code>n</code> bits.
+ */
+ protected final def memsize(n: Int): Int = offset(n + 31)
+
+ /**
+ * @param n ...
+ * @return the number of bits represented by <code>n</code> words.
+ */
+ protected final def nbits(n: Int): Int = n << 5
+
+ /**
+ * @param n ...
+ * @return the position in the array where the bit resides.
+ */
+ protected final def offset(n: Int): Int = n >>> 5
+
+ /**
+ * @param n ...
+ * @return a mask with 1 at the position of the bit.
+ */
+ protected final def mask(n: Int): Int = 1 << (n & 0x1F)
+
+}
diff --git a/src/dotnet-library/scala/collection/Map.scala b/src/dotnet-library/scala/collection/Map.scala
new file mode 100644
index 0000000000..45f45a110b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/Map.scala
@@ -0,0 +1,158 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+
+import Predef._
+
+
+/** <p>
+ * This class defines the interface of collections that unambiguously map
+ * keys to values (i.e. a key is mapped to at least one value).
+ * </p>
+ * <p>
+ * Class <code>Map</code> may only be used for accessing elements from map
+ * implementations. Two different extensions of class <code>Map</code> in
+ * the package <code><a href="mutable$content.html" target="contentFrame">
+ * scala.collection.mutable</a></code>
+ * and <code><a href="immutable$content.html" target="contentFrame">
+ * scala.collection.immutable</a></code> provide functionality for
+ * adding new key/value mappings to a map. The class in the first package is
+ * implemented by maps that are modified destructively, whereas the class in
+ * the second package is used by functional map implementations that rely on
+ * immutable data structures.
+ * </p>
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 1.2, 31/12/2006
+ */
+trait Map[A, +B] extends PartialFunction[A, B] with Iterable[{A, B}] {
+
+ /** Compute the number of key-to-value mappings.
+ *
+ * @return the number of mappings
+ */
+ def size: Int
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ def get(key: A): Option[B]
+
+ /** Is this an empty map?
+ *
+ * @return <code>true</code> iff the map is empty.
+ */
+ def isEmpty: Boolean = size == 0
+
+ /** Retrieve the value which is associated with the given key. This
+ * method throws an exception if there is no mapping from the given
+ * key to a value.
+ *
+ * @param key the key
+ * @return the value associated with the given key.
+ */
+ def apply(key: A): B = get(key) match {
+ case None => default(key)
+ case Some(value) => value
+ }
+
+ /** Is the given key mapped to a value by this map?
+ *
+ * @param key the key
+ * @return <code>true</code> iff there is a mapping for key in this map
+ */
+ def contains(key: A): Boolean = get(key) match {
+ case None => false
+ case Some(_) => true
+ }
+
+ /** Does this map contain a mapping from the given key to a value?
+ *
+ * @param key the key
+ * @return <code>true</code> iff there is a mapping for key in this map
+ */
+ def isDefinedAt(key: A) = contains(key)
+
+ /** Creates an iterator for all keys.
+ *
+ * @return an iterator over all keys.
+ */
+ def keys: Iterator[A] = new Iterator[A] {
+ val iter = Map.this.elements
+ def hasNext = iter.hasNext
+ def next = iter.next._1
+ }
+
+ /** @return the keys of this map as a set.
+ */
+ def keySet = new Set[A] {
+ def size = Map.this.size
+ def contains(key : A) = Map.this.contains(key)
+ def elements = Map.this.elements.map(._1)
+ }
+
+ /** Creates an iterator for a contained values.
+ *
+ * @return an iterator over all values.
+ */
+ def values: Iterator[B] = new Iterator[B] {
+ val iter = Map.this.elements
+ def hasNext = iter.hasNext
+ def next = iter.next._2
+ }
+
+ /** Compares two maps structurally; i.e. checks if all mappings
+ * contained in this map are also contained in the other map,
+ * and vice versa.
+ *
+ * @param that the other map
+ * @return <code>true</code> iff both maps contain exactly the
+ * same mappings.
+ */
+ override def equals(that: Any): Boolean = that match {
+ case other: Map[a, b] =>
+ this.size == other.size && this.elements.forall {
+ case {key, value} => other.get(key.asInstanceOf[a]) match {
+ case None => false
+ case Some(otherval) => value == otherval
+ }
+ }
+ case _ => false
+ }
+
+ /** A hash method compatible with <code>equals</code>
+ */
+ override def hashCode() =
+ (0 /: elements) ((hash, kv) => hash + kv.hashCode)
+
+ /** Creates a string representation for this map.
+ *
+ * @return a string showing all mappings
+ */
+ override def toString() =
+ elements.toList.map(kv => kv._1 + " -> " + kv._2).mkString("Map(", ", ", ")")
+
+ /** The default value for the map, returned when a key is not found
+ * The method implemented here yields an error,
+ * but it might be overridden in subclasses.
+ *
+ * @param key the given key value
+ * @throws Predef.NoSuchElementException
+ */
+ def default(key: A): B =
+ throw new NoSuchElementException("key not found: " + key)
+
+}
diff --git a/src/dotnet-library/scala/collection/MapProxy.scala b/src/dotnet-library/scala/collection/MapProxy.scala
new file mode 100644
index 0000000000..142d2c5ba0
--- /dev/null
+++ b/src/dotnet-library/scala/collection/MapProxy.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+
+
+/** This is a simple wrapper class for <a href="Map.html"
+ * target="contentFrame"><code>scala.collection.Map</code></a>.
+ * It is most useful for assembling customized map abstractions
+ * dynamically using object composition and forwarding.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+trait MapProxy[A, +B] extends Map[A, B] with IterableProxy[{A, B}] {
+
+ def self: Map[A, B]
+
+ override def size: Int = self.size
+ override def get(key: A): Option[B] = self.get(key)
+ override def isEmpty: Boolean = self.isEmpty
+ override def apply(key: A): B = self.apply(key)
+ override def contains(key: A): Boolean = self.contains(key)
+ override def isDefinedAt(key: A) = self.isDefinedAt(key)
+ override def keys: Iterator[A] = self.keys
+ override def keySet: Set[A] = self.keySet
+ override def values: Iterator[B] = self.values
+ override def default(key: A): B = self.default(key)
+}
diff --git a/src/dotnet-library/scala/collection/Set.scala b/src/dotnet-library/scala/collection/Set.scala
new file mode 100644
index 0000000000..2de995df25
--- /dev/null
+++ b/src/dotnet-library/scala/collection/Set.scala
@@ -0,0 +1,103 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+
+
+/** <p>
+ * This class defines the interface of collections that do not contain
+ * duplicate elements.
+ * </p>
+ * <p>
+ * Class <code>Set</code> may only be used for accessing elements
+ * from set implementations. Two different extensions
+ * of class <code>Set</code> in the package
+ * <code><a href="mutable$content.html" target="contentFrame">
+ * scala.collection.mutable</a></code> and
+ * <code><a href="immutable$content.html" target="contentFrame">
+ * scala.collection.immutable</a></code> provide functionality for adding
+ * new elements to a set. The class in the first package is implemented
+ * by sets the are modified destructively, whereas the class in the second
+ * package is used by functional set implementations that rely on immutable
+ * data structures.
+ * </p>
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 01/01/2007
+ */
+trait Set[A] extends (A => Boolean) with Iterable[A] {
+
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ def size: Int
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return <code>true</code> iff <code>elem</code> is contained in
+ * this set.
+ */
+ def contains(elem: A): Boolean
+
+ /** This method allows sets to be interpreted as predicates.
+ * It returns <code>true</code>, iff this set contains element
+ * <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return <code>true</code> iff <code>elem</code> is contained in
+ * this set.
+ */
+ def apply(elem: A): Boolean = contains(elem)
+
+ /** Checks if this set is empty.
+ *
+ * @return <code>true</code> iff there is no element in the set.
+ */
+ def isEmpty: Boolean = size == 0
+
+ /** Checks if this set is a subset of set <code>that</code>.
+ *
+ * @param that another set.
+ * @return <code>true</code> iff the other set is a superset of
+ * this set.
+ * todo: rename to isSubsetOf
+ */
+ def subsetOf(that: Set[A]): Boolean = forall(that.contains)
+
+ /** Compares this set with another object and returns true, iff the
+ * other object is also a set which contains the same elements as
+ * this set.
+ *
+ * @param that the other object
+ * @return <code>true</code> iff this set and the other set
+ * contain the same elements.
+ */
+ override def equals(that: Any): Boolean = that match {
+ case other: Set[a] =>
+ this.size == other.size && subsetOf(other.asInstanceOf[Set[A]])
+ case _ =>
+ false
+ }
+
+ /** hashcode for this set */
+ override def hashCode() =
+ (0 /: this)((hash, e) => hash * 41 + e.hashCode())
+
+ /** Returns a string representation of this set.
+ *
+ * @return a string showing all elements of this set.
+ */
+ override def toString(): String = mkString("Set(", ", ", ")")
+
+}
diff --git a/src/dotnet-library/scala/collection/SetProxy.scala b/src/dotnet-library/scala/collection/SetProxy.scala
new file mode 100644
index 0000000000..d710ce48ba
--- /dev/null
+++ b/src/dotnet-library/scala/collection/SetProxy.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection
+
+
+/** This is a simple wrapper class for <a href="Set.html"
+ * target="contentFrame"><code>scala.collection.Set</code></a>.
+ * It is most useful for assembling customized set abstractions
+ * dynamically using object composition and forwarding.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 01/01/2007
+ */
+trait SetProxy[A] extends Set[A] with IterableProxy[A] {
+ def self: Set[A]
+ def size: Int = self.size
+ override def isEmpty: Boolean = self.isEmpty
+ def contains(elem: A): Boolean = self.contains(elem)
+ override def subsetOf(that: Set[A]): Boolean = self.subsetOf(that)
+}
diff --git a/src/dotnet-library/scala/collection/immutable/BitSet.scala b/src/dotnet-library/scala/collection/immutable/BitSet.scala
new file mode 100644
index 0000000000..b2d50c329f
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/BitSet.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+
+/** The class <code>BitSet</code> provides an immutable bitset view on an
+ * int array. Instances can conveniently be created from instances of
+ * Bit indices are between <code>0..(capacity-1)</code> inclusive.
+ *
+ * @param size <code>size</code> represents the number of relevant bits
+ * @param capacity ...
+ * @param ba <code>ba</code> array of ints of length
+ * <code>n&gt;&gt;&gt;5</code>
+ * @param copy <code>copy</code> if yes, then <code>ba</code> is copied
+ * and updates will not affect this bitset
+ *
+ * @author Burak Emir, Nikolay Mihaylov
+ * @version 1.0
+ */
+
+[serializable]
+/*
+ * This is a strange class! It claims to be immutable but is not.
+ * It claims to be a BitSet but it is not a Set.
+ * Remove it or integrate it into the Set hierarchy.
+ * [Comments by Martin]
+ */
+class BitSet(val size: Int, val capacity: Int, ba: Array[Int], copy: Boolean)
+ extends collection.BitSet
+{
+ import compat.Platform.arraycopy
+
+ protected val arr: Array[Int] =
+ if (copy) {
+ val arr = new Array[Int](ba.length)
+ arraycopy(ba, 0, arr, 0, ba.length)
+ arr
+ }
+ else
+ ba
+
+}
diff --git a/src/dotnet-library/scala/collection/immutable/EmptyMap.scala b/src/dotnet-library/scala/collection/immutable/EmptyMap.scala
new file mode 100755
index 0000000000..fbf8c10c1a
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/EmptyMap.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class EmptyMap[A, +B] extends Map[A, B] {
+
+ def size: Int = 0
+
+ def get(key: A): Option[B] = None
+
+ def elements: Iterator[{A, B}] = Iterator.empty
+
+ def empty[C]: Map[A, C] = new EmptyMap[A, C]
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] =
+ new Map1(key, value)
+
+ def - (key: A): Map[A, B] = this
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/EmptySet.scala b/src/dotnet-library/scala/collection/immutable/EmptySet.scala
new file mode 100755
index 0000000000..83a4f77813
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/EmptySet.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class EmptySet[A] extends Set[A] {
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def size: Int = 0
+
+ def contains(elem: A): Boolean = false
+
+ def + (elem: A): Set[A] = new Set1(elem)
+
+ def - (elem: A): Set[A] = this
+
+ def elements: Iterator[A] = Iterator.empty
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/HashMap.scala b/src/dotnet-library/scala/collection/immutable/HashMap.scala
new file mode 100755
index 0000000000..3cda6cf08b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/HashMap.scala
@@ -0,0 +1,154 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: HashMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+package scala.collection.immutable
+
+import Predef._
+
+/** This class implements immutable maps using a hashtable.
+ *
+ * @author Martin Odersky
+ * @version 2.0, 19/01/2007
+ */
+object HashMap {
+
+ /** The empty map of this type */
+ def empty[A, B] = new HashMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+[serializable]
+class HashMap[A, B] extends Map[A,B] with mutable.HashTable[A] {
+ type Entry = mutable.DefaultEntry[A, Any]
+
+ protected var later: HashMap[A, B] = null
+ protected var oldKey: A = _
+ protected var oldValue: Option[B] = _
+ protected var deltaSize: int = _
+
+ def empty[C]: Map[A, C] = new EmptyMap[A, C]
+
+ def get(key: A): Option[B] = {
+ var m = this
+ var cnt = 0
+ while (m.later != null) {
+ if (key == m.oldKey) return m.oldValue
+ cnt = cnt + 1
+ m = m.later
+ }
+ if (cnt > logLimit) makeCopy(m)
+ val e = m.findEntry(key)
+ if (e == null) None
+ else Some(getValue(e))
+ }
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] = {
+ makeCopyIfUpdated()
+ val e = findEntry(key)
+ if (e == null) {
+ markUpdated(key, None, 1)
+ later.addEntry(new Entry(key, value))
+ } else {
+ markUpdated(key, Some(getValue(e)), 0)
+ e.value = value
+ }
+ later
+ }
+
+ def - (key: A): Map[A, B] = {
+ makeCopyIfUpdated()
+ val e = findEntry(key)
+ if (e == null) this
+ else {
+ markUpdated(key, Some(getValue(e)), -1)
+ later removeEntry key
+ later
+ }
+ }
+
+ override def size: int = {
+ var m = this
+ var cnt = 0
+ var s = tableSize
+ while (m.later != null) {
+ s = s - m.deltaSize
+ cnt = cnt + 1
+ m = m.later
+ }
+ if (cnt > logLimit) makeCopy(m)
+ s
+ }
+
+ def elements = {
+ makeCopyIfUpdated()
+ entries map {e => {e.key, getValue(e)}}
+ }
+
+ private def getValue(e: Entry) =
+ e.value.asInstanceOf[B]
+
+ private def logLimit: int = Math.sqrt(table.length.toDouble).toInt
+
+ private def markUpdated(key: A, ov: Option[B], delta: int) {
+ val lv = loadFactor
+ later = new HashMap[A, B] {
+ override def initialSize = 0
+ override def loadFactor = lv
+ table = HashMap.this.table
+ tableSize = HashMap.this.tableSize
+ threshold = HashMap.this.threshold
+ }
+ oldKey = key
+ oldValue = ov
+ deltaSize = delta
+ }
+
+ private def makeCopy(last: HashMap[A, B]) {
+ def undo(m: HashMap[A, B]) {
+ if (m ne last) {
+ undo(m.later)
+ if (m.deltaSize == 1) removeEntry(m.oldKey)
+ else if (m.deltaSize == 0) findEntry(m.oldKey).value = m.oldValue.get
+ else if (m.deltaSize == -1) addEntry(new Entry(m.oldKey, m.oldValue.get))
+ }
+ }
+ def copy(e: Entry): Entry =
+ if (e == null) null
+ else {
+ val rest = copy(e.next)
+ val result = new Entry(e.key, e.value)
+ result.next = rest
+ result
+ }
+ val ltable = last.table
+ val s = ltable.length
+ table = new Array[Entry](s)
+ var i = 0
+ while (i < s) {
+ table(i) = copy(ltable(i))
+ i = i + 1
+ }
+ tableSize = last.tableSize
+ threshold = last.threshold
+ undo(this)
+ later = null
+ }
+
+ private def makeCopyIfUpdated() {
+ var m = this
+ while (m.later != null) m = m.later
+ if (m ne this) makeCopy(m)
+ }
+}
+
diff --git a/src/dotnet-library/scala/collection/immutable/HashSet.scala b/src/dotnet-library/scala/collection/immutable/HashSet.scala
new file mode 100755
index 0000000000..aa4d832537
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/HashSet.scala
@@ -0,0 +1,118 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: HashSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+package scala.collection.immutable
+
+object HashSet {
+
+ /** The empty set of this type.
+ */
+ def empty[A] = new HashSet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: A*) = empty[A] ++ elems
+}
+
+[serializable]
+class HashSet[A] extends Set[A] with mutable.FlatHashTable[A] {
+ protected var later: HashSet[A] = null
+ protected var changedElem: A = _
+ protected var deleted: Boolean = _
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def contains(elem: A): Boolean = {
+ var m = this
+ var cnt = 0
+ while (m.later != null) {
+ if (elem == m.changedElem) return m.deleted
+ cnt = cnt + 1
+ m = m.later
+ }
+ if (cnt > logLimit) makeCopy(m)
+ m.containsEntry(elem)
+ }
+
+ def + (elem: A): Set[A] = {
+ makeCopyIfUpdated()
+ if (containsEntry(elem)) this
+ else {
+ markUpdated(elem, false)
+ later addEntry elem
+ later
+ }
+ }
+
+ def - (elem: A): Set[A] = {
+ makeCopyIfUpdated()
+ if (!containsEntry(elem)) this
+ else {
+ markUpdated(elem, true)
+ later removeEntry elem
+ later
+ }
+ }
+
+ override def size: Int = {
+ var m = this
+ var cnt = 0
+ var s = tableSize
+ while (m.later != null) {
+ if (m.deleted) s = s + 1 else s = s - 1
+ cnt = cnt + 1
+ m = m.later
+ }
+ if (cnt > logLimit) makeCopy(m)
+ s
+ }
+
+ override def elements = {
+ makeCopyIfUpdated()
+ super.elements
+ }
+
+ private def logLimit: Int = Math.sqrt(table.length.toDouble).toInt
+
+ private def markUpdated(elem: A, del: Boolean) {
+ val lv = loadFactor
+ later = new HashSet[A] {
+ override def initialSize = 0
+ override def loadFactor = lv
+ table = HashSet.this.table
+ tableSize = HashSet.this.tableSize
+ threshold = HashSet.this.threshold
+ }
+ changedElem = elem
+ deleted = del
+ }
+
+ private def makeCopy(last: HashSet[A]) {
+ def undo(m: HashSet[A]) {
+ if (m ne last) {
+ undo(m.later)
+ if (m.deleted) addEntry(changedElem)
+ else removeEntry(changedElem)
+ }
+ }
+ table = new Array[AnyRef](last.table.length)
+ Array.copy(last.table, 0, table, 0, table.length)
+ tableSize = last.tableSize
+ threshold = last.threshold
+ undo(this)
+ later = null
+ }
+
+ private def makeCopyIfUpdated() {
+ var m = this
+ while (m.later != null) m = m.later
+ if (m ne this) makeCopy(m)
+ }
+}
+
diff --git a/src/dotnet-library/scala/collection/immutable/ListMap.scala b/src/dotnet-library/scala/collection/immutable/ListMap.scala
new file mode 100644
index 0000000000..4ce9c4cc39
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/ListMap.scala
@@ -0,0 +1,160 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+
+package scala.collection.immutable
+
+object ListMap {
+
+ /** The empty map of this type
+ * @deprecated use <code>empty</code> instead
+ */
+ [deprecated] def Empty[A, B] = new ListMap[A, B]
+
+ /** The empty map of this type */
+ def empty[A, B] = new ListMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+/** This class implements immutable maps using a list-based data
+ * structure. Instances of <code>ListMap</code> represent
+ * empty maps; they can be either created by calling the constructor
+ * directly, or by applying the function <code>ListMap.empty</code>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Oderskty
+ * @version 2.0, 01/01/2007
+ */
+[serializable]
+class ListMap[A, +B] extends Map[A, B] {
+
+ /** Returns a <code>new ListMap</code> instance mapping keys of the
+ * same type to values of type <code>C</code>.
+ */
+ def empty[C] = ListMap.empty[A, C]
+
+ /** Returns the number of mappings in this map.
+ *
+ * @return number of mappings in this map.
+ */
+ def size: Int = 0
+
+ /** Checks if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ def get(key: A): Option[B] = None
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ *
+ * @param key the key element of the updated entry.
+ * @param value the value element of the updated entry.
+ */
+ def update [B1 >: B](key: A, value: B1): ListMap[A, B1] = new Node(key, value)
+
+ /** This creates a new mapping without the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method returns the same map.
+ *
+ * @param key a map without a mapping for the given key.
+ */
+ def - (key: A): ListMap[A, B] = this
+
+ /** Returns an iterator over key-value pairs.
+ */
+ def elements: Iterator[{A,B}] =
+ new Iterator[{A,B}] {
+ var self: ListMap[A,B] = ListMap.this
+ def hasNext = !self.isEmpty
+ def next: {A,B} =
+ if (!hasNext) throw new NoSuchElementException("next on empty iterator")
+ else { val res = {self.key, self.value}; self = self.next; res }
+ }.toList.reverse.elements
+
+ protected def key: A = throw new NoSuchElementException("empty map")
+ protected def value: B = throw new NoSuchElementException("empty map")
+ protected def next: ListMap[A, B] = throw new NoSuchElementException("empty map")
+
+ [serializable]
+ protected class Node[B1 >: B](override protected val key: A,
+ override protected val value: B1) extends ListMap[A, B1] {
+ /** Returns the number of mappings in this map.
+ *
+ * @return number of mappings.
+ */
+ override def size: Int = next.size + 1
+
+ /** Is this an empty map?
+ *
+ * @return true, iff the map is empty.
+ */
+ override def isEmpty: Boolean = false
+
+ /** Retrieves the value which is associated with the given key. This
+ * method throws an exception if there is no mapping from the given
+ * key to a value.
+ *
+ * @param key the key
+ * @return the value associated with the given key.
+ */
+ override def apply(k: A): B1 = if (k == key) value else next(k)
+
+ /** Checks if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(k: A): Option[B1] =
+ if (k == key) Some(value) else next.get(k)
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ *
+ * @param k ...
+ * @param v ...
+ */
+ override def update [B2 >: B1](k: A, v: B2): ListMap[A, B2] = {
+ val m = if (contains(k)) this - k else this
+ new m.Node(k, v)
+ }
+
+ /** Creates a new mapping without the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method returns the same map.
+ *
+ * @param k ...
+ * @return ...
+ */
+ override def - (k: A): ListMap[A, B1] =
+ if (k == key)
+ next
+ else {
+ val tail = next - k
+ if (tail eq next) this
+ else new tail.Node(key, value)
+ }
+
+ override protected def next: ListMap[A,B1] = ListMap.this
+ }
+}
diff --git a/src/dotnet-library/scala/collection/immutable/ListSet.scala b/src/dotnet-library/scala/collection/immutable/ListSet.scala
new file mode 100644
index 0000000000..e869e6258d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/ListSet.scala
@@ -0,0 +1,138 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+
+//import Predef.NoSuchElementException
+
+object ListSet {
+
+ /** constructs an empty ListSet
+ * @deprecated use <code>empty</code> instead
+ */
+ [deprecated] def Empty[A] = new ListSet[A]
+
+ /** The empty set of this type.
+ */
+ def empty[A] = new ListSet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: A*) = empty[A] ++ elems
+}
+
+
+/** This class implements immutable sets using a list-based data
+ * structure. Instances of <code>ListSet</code> represent
+ * empty sets; they can be either created by calling the constructor
+ * directly, or by applying the function <code>ListSet.empty</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 09/07/2003
+ */
+[serializable]
+class ListSet[A] extends AnyRef with Set[A] {
+
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ def size: Int = 0
+
+ override def isEmpty: Boolean = true;
+
+ def empty[B] = ListSet.empty[B]
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def contains(elem: A): Boolean = false
+
+ /** This method creates a new set with an additional element.
+ */
+ def +(elem: A): ListSet[A] = new Node(elem)
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ def -(elem: A): ListSet[A] = this
+
+ /** Creates a new iterator over all elements contained in this set.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the new iterator
+ */
+ def elements: Iterator[A] = new Iterator[A] {
+ var that: ListSet[A] = ListSet.this;
+ def hasNext = !that.isEmpty;
+ def next: A =
+ if (!hasNext) throw new NoSuchElementException("next on empty iterator")
+ else { val res = that.elem; that = that.next; res }
+ }
+
+ /** Compares two sets for equality.
+ * Two set are equal iff they contain the same elements.
+ */
+ override def equals(obj: Any): Boolean =
+ if (obj.isInstanceOf[scala.collection.Set[A]]) {
+ val that = obj.asInstanceOf[scala.collection.Set[A]]
+ if (size != that.size) false else toList.forall(that.contains)
+ } else
+ false
+
+ /**
+ * @throws Predef.NoSuchElementException
+ */
+ protected def elem: A = throw new NoSuchElementException("Set has no elements");
+
+ /**
+ * @throws Predef.NoSuchElementException
+ */
+ protected def next: ListSet[A] = throw new NoSuchElementException("Next of an empty set");
+
+ [serializable]
+ protected class Node(override protected val elem: A) extends ListSet[A] {
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ override def size = ListSet.this.size + 1
+
+ /** Checks if this set is empty.
+ *
+ * @return true, iff there is no element in the set.
+ */
+ override def isEmpty: Boolean = false
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ override def contains(e: A) = (e == elem) || ListSet.this.contains(e)
+
+ /** This method creates a new set with an additional element.
+ */
+ override def +(e: A): ListSet[A] = if (contains(e)) this else new Node(e)
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ override def -(e: A): ListSet[A] = if (e == elem) ListSet.this else {
+ val tail = ListSet.this - e; new tail.Node(elem)
+ }
+
+ override protected def next: ListSet[A] = ListSet.this;
+ }
+}
diff --git a/src/dotnet-library/scala/collection/immutable/Map.scala b/src/dotnet-library/scala/collection/immutable/Map.scala
new file mode 100644
index 0000000000..65fd32379f
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Map.scala
@@ -0,0 +1,238 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+import Predef._
+
+/** <p>
+ * This class extends the <code>Map</code> interface of collections
+ * that unambiguously map keys to values (i.e. a key is mapped to at
+ * least one value).
+ * </p>
+ * <p>
+ * This class defines the interface for functional map implementations
+ * relying on immutable data structures.
+ * </p>
+ * <p>
+ * Concrete map implementations have to provide functionality for
+ * the abstract methods in <a href="../Map.html" target="contentFrame">
+ * <code>scala.collection.Map</code></a> as well as for
+ * <code>factory</code>, <code>update</code>, and <code>-</code>.
+ * </p>
+ *
+ * @author Matthias Zenger
+ * @author Erik Stenman
+ * @author Martin Odersky
+ * @version 1.2, 31/06/2006
+ */
+object Map {
+
+ /** The empty map of this type; this is implemented as a treemap */
+ def empty[A, B]: Map[A, B] = new EmptyMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+trait Map[A, +B] extends collection.Map[A, B] {
+
+ /** This method returns a new map instance of the same class
+ * mapping keys of the same type to values of type <code>C</code>.
+ */
+ def empty[C]: Map[A, C]
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ *
+ * @param key ...
+ * @param value ...
+ * @return the created map
+ * @deprecated use <code>+({A, B})</code> instead
+ */
+ def update [B1 >: B] (key: A, value: B1): Map[A, B1]
+
+ /** Add a key/value pair to this map.
+ * @param kv the key/value pair.
+ * @return A new map with the new binding added to this map
+ */
+ def + [B1 >: B] (kv: {A, B1}): Map[A, B1] = update(kv._1, kv._2)
+
+ /** Add two or more key/value pairs to this map.
+ * @param kv1 the first key/value pair.
+ * @param kv2 the second key/value pair.
+ * @param kvs the remaining key/value pairs.
+ * @return A new map with the new bindings added
+ */
+ def + [B1 >: B] (kv1: {A, B1}, kv2: {A, B1}, kvs: {A, B1}*): Map[A, B1] =
+ this + kv1 + kv2 ++ kvs
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterable object containing all key/value pairs.
+ * @return A new map with the new bindings added
+ */
+ def ++ [B1 >: B] (kvs: Iterable[{A, B1}]): Map[A, B1] =
+ ((this: Map[A, B1]) /: kvs) ((m, kv) => m + kv)
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterator containing all key/value pairs.
+ * @return A new map with the new bindings added
+ */
+ def ++ [B1 >: B] (kvs: Iterator[{A, B1}]): Map[A, B1] =
+ ((this: Map[A, B1]) /: kvs) ((m, kv) => m + kv)
+
+ /** Remove a key from this map
+ * @param key the key to be removed
+ * @return If the map does not contain a binding for <code>key</code>
+ * it is returned unchanged. Otherwise, return a new map
+ * without a binding for <code>key</code>
+ */
+ def - (key: A): Map[A, B]
+
+ /** Remove two or more keys from this map
+ * @param key1 the first key to be removed
+ * @param key2 the second key to be removed
+ * @param keys the remaining keys to be removed
+ * @return A map without bindings for <code>keys</code>
+ * If the map is mutable, the bindings are removed in place
+ * and the map itself is returned.
+ * If the map is immutable, a new map with the bindings removed is returned.
+ */
+ def - (key1: A, key2: A, keys: A*): Map[A, B] =
+ this - key1 - key2 -- keys
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ * @return A map without bindings for the given keys.
+ * If the map is mutable, the bindings are removed in place
+ * and the map itself is returned.
+ * If the map is immutable, a new map with the bindings removed is returned.
+ */
+ def -- (keys: Iterable[A]): Map[A, B] = this -- keys.elements
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ * @return A map without bindings for the given keys.
+ * If the map is mutable, the bindings are removed in place
+ * and the map itself is returned.
+ * If the map is immutable, a new map with the bindings removed is returned.
+ */
+ def -- (keys: Iterator[A]): Map[A, B] =
+ (this /: keys) ((m, key) => m - key)
+
+ /** This function transforms all the values of mappings contained
+ * in this map with function <code>f</code>.
+ *
+ * @param f A function over keys and values
+ * @return the updated map
+ */
+ def transform[C](f: (A, B) => C): Map[A, C] = {
+ var res = empty[C]
+ foreach { case {key, value} => res = res.update(key, f(key, value)) }
+ res
+ }
+
+ /** This method removes all the mappings for which the predicate
+ * <code>p</code> returns <code>false</code>.
+ *
+ * @param p A prediacte over key-value pairs
+ * @return the updated map
+ */
+ override def filter(p: {A, B} => Boolean): Map[A, B] = {
+ var res = this
+ foreach {
+ case kv @ {key, _} => if (!p(kv)) { res = res - key }
+ }
+ res
+ }
+
+ /** <p>
+ * This method defines syntactic sugar for adding a
+ * mapping. It is typically used in the following way:
+ * </p>
+ * <pre>
+ * map + key -> value
+ * </pre>
+ * @deprecated use <code>+({A, B})</code> instead
+ */
+ [deprecated] def +(key: A): MapTo = new MapTo(key)
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that a mapping is represented
+ * by a <code>Pair</code> object who's first component denotes the
+ * key, and who's second component refers to the value.
+ *
+ * @param mappings ...
+ * @return ...
+ * @deprecated use <code>+</code> instead
+ */
+ [deprecated] def incl[B1 >: B](mappings: {A, B1}*): Map[A, B1] = incl(mappings)
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that each mapping is represented
+ * by an Iterator over <code>Pair</code> objects who's first component
+ * denotes the key, and who's second component refers to the value.
+ *
+ * @deprecated use <code>++</code> instead
+ */
+ [deprecated] def incl[B1 >: B](map: Iterable[{A, B1}]): Map[A, B1] = {
+ val iter = map.elements
+ var res: Map[A, B1] = this
+ while (iter.hasNext) {
+ val {key, value} = iter.next
+ res = res.update(key, value);
+ }
+ res
+ }
+
+ /** This method will return a map where all the mappings
+ * for the given sequence of keys are removed from the map.
+ *
+ * @param keys ...
+ * @return the updated map
+ * @deprecated use <code>-</code> instead */
+ [deprecated] def excl(keys: A*): Map[A, B] = excl(keys)
+
+ /** This method removes all the mappings for keys provided by an
+ * iterator over the elements of the <code>keys</code> object.
+ *
+ * @param keys ...
+ * @return the updated map
+ * @deprecated use <code>--</code> instead
+ */
+ [deprecated] def excl(keys: Iterable[A]): Map[A, B] = {
+ val iter = keys.elements
+ var res = this
+ while (iter.hasNext) {
+ res = res - iter.next
+ }
+ res
+ }
+
+ /** This method controls how a mapping is represented in the string
+ * representation provided by method <code>toString</code>.
+ *
+ * @param p ...
+ * @return the string representation of a map entry
+ */
+ [deprecated] def mappingToString[B1 >: B](p: {A, B1}) = p._1.toString() + " -> " + p._2
+
+ /** @deprecated use <code>+({A, B})</code> instead
+ */
+ [deprecated] class MapTo(key: A) {
+ def -> [B1 >: B](value: B1) = update(key, value)
+ }
+}
+
diff --git a/src/dotnet-library/scala/collection/immutable/Map1.scala b/src/dotnet-library/scala/collection/immutable/Map1.scala
new file mode 100755
index 0000000000..22a2e05b09
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Map1.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Map1[A, +B](key1: A, value1: B) extends Map[A, B] {
+
+ def size = 1
+
+ def get(key: A): Option[B] =
+ if (key == key1) Some(value1) else None
+
+ def elements = Iterator.single({key1, value1})
+
+ def empty[B]: Map[A, B] = new EmptyMap[A, B]
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] =
+ if (key == key1) new Map1(key1, value)
+ else new Map2(key1, value1, key, value)
+
+ def - (key: A): Map[A, B] =
+ if (key == key1) empty else this
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Map2.scala b/src/dotnet-library/scala/collection/immutable/Map2.scala
new file mode 100755
index 0000000000..fbadfaa68d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Map2.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Map2[A, +B](key1: A, value1: B, key2: A, value2: B) extends Map[A, B] {
+
+ def size = 2
+
+ def get(key: A): Option[B] =
+ if (key == key1) Some(value1)
+ else if (key == key2) Some(value2)
+ else None
+
+ def elements = Iterator.fromValues(
+ {key1, value1}, {key2, value2})
+
+ def empty[C]: Map[A, C] = new EmptyMap[A, C]
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] =
+ if (key == key1) new Map2(key1, value, key2, value2)
+ else if (key == key2) new Map2(key1, value1, key2, value)
+ else new Map3(key1, value1, key2, value2, key, value)
+
+ def - (key: A): Map[A, B] =
+ if (key == key1) new Map1(key2, value2)
+ else if (key == key2) new Map1(key1, value1)
+ else this
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Map3.scala b/src/dotnet-library/scala/collection/immutable/Map3.scala
new file mode 100755
index 0000000000..38198bbc71
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Map3.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Map3[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends Map[A, B] {
+
+ def size = 3
+
+ def get(key: A): Option[B] =
+ if (key == key1) Some(value1)
+ else if (key == key2) Some(value2)
+ else if (key == key3) Some(value3)
+ else None
+
+ def elements = Iterator.fromValues(
+ {key1, value1}, {key2, value2}, {key3, value3})
+
+ def empty[C]: Map[A, C] = new EmptyMap[A, C]
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] =
+ if (key == key1) new Map3(key1, value, key2, value2, key3, value3)
+ else if (key == key2) new Map3(key1, value1, key2, value, key3, value3)
+ else if (key == key3) new Map3(key1, value1, key2, value2, key3, value)
+ else new Map4(key1, value1, key2, value2, key3, value3, key, value)
+
+ def - (key: A): Map[A, B] =
+ if (key == key1) new Map2(key2, value2, key3, value3)
+ else if (key == key2) new Map2(key1, value1, key3, value3)
+ else if (key == key3) new Map2(key1, value1, key2, value2)
+ else this
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Map4.scala b/src/dotnet-library/scala/collection/immutable/Map4.scala
new file mode 100755
index 0000000000..3596008109
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Map4.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListMap.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+package scala.collection.immutable
+
+import Predef._
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Map4[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends Map[A, B] {
+
+ def size = 4
+
+ def get(key: A): Option[B] =
+ if (key == key1) Some(value1)
+ else if (key == key2) Some(value2)
+ else if (key == key3) Some(value3)
+ else if (key == key4) Some(value4)
+ else None
+
+ def elements = Iterator.fromValues(
+ {key1, value1}, {key2, value2}, {key3, value3}, {key4, value4})
+
+ def empty[C]: Map[A, C] = new EmptyMap[A, C]
+
+ def update [B1 >: B](key: A, value: B1): Map[A, B1] =
+ if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4)
+ else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4)
+ else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4)
+ else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value)
+ else HashMap(key1 -> value1, key2 -> value2, key3 -> value3, key4 -> value4, key -> value)
+
+ def - (key: A): Map[A, B] =
+ if (key == key1) new Map3(key2, value2, key3, value3, key4, value4)
+ else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4)
+ else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4)
+ else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3)
+ else this
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Queue.scala b/src/dotnet-library/scala/collection/immutable/Queue.scala
new file mode 100644
index 0000000000..c88bbbdb27
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Queue.scala
@@ -0,0 +1,161 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+
+//import Predef.NoSuchElementException
+
+object Queue {
+ val Empty: Queue[Nothing] = new Queue()
+}
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Erik Stenman
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class Queue[+A](elem: A*) extends Seq[A] {
+
+ protected val in: List[A] = Nil
+ protected val out: List[A] = elem.elements.toList
+
+ protected def mkQueue[A](i: List[A], o: List[A]): Queue[A] =
+ new Queue[A]() {
+ override protected val in = i
+ override protected val out = o
+ }
+
+ /** Returns the <code>n</code>-th element of this queue.
+ * The first element is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this queue.
+ * @throws Predef.NoSuchElementException if the queue is too short.
+ */
+ def apply(n: Int): A = {
+ val len = out.length
+ if (n < len) out.apply(n)
+ else {
+ val m = n - len
+ if (m < in.length) in.reverse.apply(m)
+ else throw new NoSuchElementException("index out of range")
+ }
+ }
+
+ /** Returns the elements in the list as an iterator
+ */
+ def elements: Iterator[A] = (out ::: in.reverse).elements
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = in.isEmpty && out.isEmpty
+
+ /** Returns the length of the queue.
+ */
+ def length = in.length + out.length
+
+ /** Creates a new queue with element added at the end
+ * of the old queue.
+ *
+ * @param elem the element to insert
+ */
+ def +[B >: A](elem: B) = mkQueue(elem :: in, out)
+
+ /** Returns a new queue with all all elements provided by
+ * an <code>Iterable</code> object added at the end of
+ * the queue.
+ * The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def +[B >: A](iter: Iterable[B]) = {
+ var q: List[B] = in
+ iter.elements.foreach(e => q = e :: q)
+ mkQueue(q, out)
+ }
+
+ /** Returns a new queue with all elements added.
+ *
+ * @param elems the elements to add.
+ */
+ def enqueue [B >: A](elems: B*) = this + elems
+
+ /** Returns a tuple with the first element in the queue,
+ * and a new queue with this element removed.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the first element of the queue.
+ */
+ def dequeue: {A, Queue[A]} = {
+ val {newOut, newIn} =
+ if (out.isEmpty) {in.reverse, Nil}
+ else {out, in};
+ if (newOut.isEmpty) throw new NoSuchElementException("queue empty")
+ else {newOut.head, mkQueue(newIn, newOut.tail)}
+ }
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the first element.
+ */
+ def front: A =
+ if (out.isEmpty) {
+ if (in.isEmpty) throw new NoSuchElementException("queue empty") else in.last
+ } else
+ out.head
+
+ /** Returns a string representation of this queue.
+ */
+ override def toString() = mkString("Queue(", ",", ")")
+
+ /** Compares two queues for equality by comparing
+ * each element in the queues.
+ *
+ * @return true, iff the two queues are structurally equal.
+ */
+ override def equals(o: Any): Boolean = o match {
+ case q: Queue[_] =>
+ /* A function that compares the element at
+ position index in q with the element at
+ the same position in this (queue).
+ If they are equal the next element is
+ compared. */
+ def eqe(index: Int): Boolean = (
+ /* If all elements are compared
+ the queues are equal. */
+ index >= this.length ||
+ /* Otherwise: compare the elements */
+ (q.apply(index) == this.apply(index) &&
+ /* if they are equal compare the rest. */
+ eqe(index + 1))
+ );
+ /* If the length of the ques are the same,
+ compare each element, starting at index 0. */
+ (q.length == this.length) && eqe(0);
+
+ case _ => false /* o is not a queue: not equal to this. */
+ }
+
+ override def hashCode(): Int =
+ if (isEmpty) 0
+ else {
+ val q: {A,Queue[A]} = dequeue;
+ q._1.hashCode() + q._2.hashCode()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/immutable/RedBlack.scala b/src/dotnet-library/scala/collection/immutable/RedBlack.scala
new file mode 100755
index 0000000000..cd0fd432f9
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/RedBlack.scala
@@ -0,0 +1,98 @@
+package scala.collection.immutable
+
+[serializable]
+abstract class RedBlack[A] {
+
+ def isSmaller(x: A, y: A): boolean
+
+ private def blacken[B](t: Tree[B]): Tree[B] = t match {
+ case RedTree(k, v, l, r) => BlackTree(k, v, l, r)
+ case t => t
+ }
+ private def mkTree[B](isBlack: boolean, k: A, v: B, l: Tree[B], r: Tree[B]) =
+ if (isBlack) BlackTree(k, v, l, r) else RedTree(k, v, l, r)
+
+ [serializable]
+ abstract class Tree[+B] {
+ def isEmpty: boolean
+ def isBlack: boolean
+ def lookup(x: A): Tree[B]
+ def update[B1 >: B](k: A, v: B1): Tree[B1] = blacken(upd(k, v))
+ def delete(k: A): Tree[B] = del(k)
+ def elements: Iterator[{A, B}]
+ def upd[B1 >: B](k: A, v: B1): Tree[B1]
+ def del(k: A): Tree[B]
+ def smallest: NonEmpty[B]
+ }
+ [serializable]
+ abstract class NonEmpty[+B] extends Tree[B] {
+ def isEmpty = false
+ def key: A
+ def value: B
+ def left: Tree[B]
+ def right: Tree[B]
+ def lookup(k: A): Tree[B] =
+ if (isSmaller(k, key)) left.lookup(k)
+ else if (isSmaller(key, k)) right.lookup(k)
+ else this
+ def upd[B1 >: B](k: A, v: B1): Tree[B1] = {
+ def balanceLeft(isBlack: boolean, z: A, zv: B, l: Tree[B1], d: Tree[B1]) = l match {
+ case RedTree(y, yv, RedTree(x, xv, a, b), c) =>
+ RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d))
+ case RedTree(x, xv, a, RedTree(y, yv, b, c)) =>
+ RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d))
+ case _ =>
+ mkTree(isBlack, z, zv, l, d)
+ }
+ def balanceRight(isBlack: boolean, x: A, xv: B, a: Tree[B1], r: Tree[B1]) = r match {
+ case RedTree(z, zv, RedTree(y, yv, b, c), d) =>
+ RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d))
+ case RedTree(y, yv, b, RedTree(z, zv, c, d)) =>
+ RedTree(y, yv, BlackTree(x, xv, a, b), BlackTree(z, zv, c, d))
+ case _ =>
+ mkTree(isBlack, x, xv, a, r)
+ }
+ if (isSmaller(k, key)) balanceLeft(isBlack, key, value, left.upd(k, v), right)
+ else if (isSmaller(key, k)) balanceRight(isBlack, key, value, left, right.upd(k, v))
+ else mkTree(isBlack, k, v, left, right)
+ }
+ def del(k: A): Tree[B] = {
+ if (isSmaller(k, key)) mkTree(isBlack, key, value, left.del(k), right)
+ else if (isSmaller(key, k)) mkTree(isBlack, key, value, left, right.del(k))
+ else if (left.isEmpty) right
+ else if (right.isEmpty) left
+ else {
+ val s = right.smallest
+ mkTree(isBlack, s.key, s.value, left, right.del(s.key))
+ }
+ }
+ def smallest: NonEmpty[B] = if (left.isEmpty) this else left.smallest
+ def elements: Iterator[{A, B}] =
+ left.elements append Iterator.single({key, value}) append right.elements
+ }
+ [serializable]
+ case object Empty extends Tree[Nothing] {
+ def isEmpty = true
+ def isBlack = true
+ def lookup(k: A): Tree[Nothing] = this
+ def upd[B](k: A, v: B): Tree[B] = RedTree(k, v, Empty, Empty)
+ def del(k: A): Tree[Nothing] = this
+ def smallest: NonEmpty[Nothing] = throw new NoSuchElementException("empty map")
+ def elements: Iterator[{A, Nothing}] = Iterator.empty
+ }
+ [serializable]
+ case class RedTree[+B](override val key: A,
+ override val value: B,
+ override val left: Tree[B],
+ override val right: Tree[B]) extends NonEmpty[B] {
+ def isBlack = false
+ }
+ [serializable]
+ case class BlackTree[+B](override val key: A,
+ override val value: B,
+ override val left: Tree[B],
+ override val right: Tree[B]) extends NonEmpty[B] {
+ def isBlack = true
+ }
+}
+
diff --git a/src/dotnet-library/scala/collection/immutable/Set.scala b/src/dotnet-library/scala/collection/immutable/Set.scala
new file mode 100644
index 0000000000..4aa51755c4
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Set.scala
@@ -0,0 +1,169 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+
+/** This class represents immutable sets. Concrete set implementations
+ * just have to provide functionality for the abstract methods in
+ * <code>scala.collection.Set</code> as well as for <code>+</code> and
+ * <code>-</code>.
+ *
+ * Note that abstract immutable.Set's are not covariant in their type
+ * parameter. This is because some subclasses cannot support the
+ * <code>+</code> method for arbitrary types.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 1.1, 03/05/2004
+ */
+object Set {
+ /** The empty set of this type
+ */
+ def empty[A]: Set[A] = new EmptySet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A](elems: A*) = empty[A] ++ elems
+}
+
+trait Set[A] extends AnyRef with collection.Set[A] {
+
+ /** @return an empty set of arbitrary element type
+ */
+ def empty[B]: Set[B]
+
+ /** Create a new set with an additional element.
+ */
+ def +(elem: A): Set[A]
+
+ /** Add two or more elements to this set.
+ * @param elem1 the first element.
+ * @param elem2 the second element.
+ * @param elems the remaining elements.
+ * @return a new set with the elements added.
+ */
+ def + (elem1: A, elem2: A, elems: A*): Set[A] =
+ this + elem1 + elem2 ++ elems
+
+ /** Add all the elements provided by an iterator
+ * of the iterable object <code>elems</code> to the set.
+ *
+ * @param elems the iterable object containing the elements to be added
+ * @return a new set with the elements added.
+ */
+ def ++ (elems: Iterable[A]): Set[A] =
+ (this /: elems) ((s, elem) => s + elem)
+
+ /** Add all the elements provided by an iterator to the set.
+ * @param elems the iterator containing the elements to be added
+ * @return a new set with the elements added.
+ */
+ def ++ (elems: Iterator[A]): Set[A] =
+ (this /: elems) ((s, elem) => s + elem)
+
+ /** <code>incl</code> can be used to add many elements to the set
+ * at the same time.
+ */
+ [deprecated] def incl(elems: A*): Set[A] = incl(elems)
+
+ /** This method will add all the elements provided by an iterator
+ * of the iterable object <code>that</code> to the set.
+ *
+ * @param that ...
+ */
+ [deprecated] def incl(that: Iterable[A]): Set[A] =
+ that.foldLeft(this)((set, elem) => set + elem)
+
+ /** Remove a single element from a set.
+ * @param elem the element to be removed
+ * @return a new set with the element removed.
+ */
+ def -(elem: A): Set[A]
+
+ /** Remove two or more elements from this set.
+ * @param elem1 the first element.
+ * @param elem2 the second element.
+ * @param elems the remaining elements.
+ * @return a new set with the elements removed.
+ */
+ def - (elem1: A, elem2: A, elems: A*): Set[A] =
+ this - elem1 - elem2 -- elems
+
+ /** Remove all the elements provided by an iterator
+ * of the iterable object <code>elems</code> from the set.
+ *
+ * @param elems An iterable object containing the elements to remove from the set.
+ * @return a new set with the elements removed.
+ */
+ def -- (elems: Iterable[A]): Set[A] = this -- elems.elements
+
+ /** Remove all the elements provided by an iterator
+ * <code>elems</code> from the set.
+ * @param elems An iterator containing the elements to remove from the set.
+ * @return a new set with the elements removed.
+ */
+ def -- (elems: Iterator[A]): Set[A] =
+ (this /: elems) ((s, elem) => s - elem)
+
+ /** <code>excl</code> removes many elements from the set.
+ */
+ [deprecated] def excl(elems: A*): Set[A] = excl(elems)
+
+ /** This method removes all the elements provided by an iterator
+ * of the iterable object <code>that</code> from the set.
+ */
+ [deprecated] def excl(that: Iterable[A]): Set[A] =
+ that.foldLeft(this)((set, elem) => set - elem)
+
+ /** This method computes an intersection with set <code>that</code>.
+ * It removes all the elements that are not present in <code>that</code>.
+ *
+ * @param that the set to intersect with
+ */
+ def intersect(that: collection.Set[A]): Set[A] = filter(that.contains)
+
+ /** This method is an alias for <code>intersect</code>.
+ * It computes an intersection with set <code>that</code>.
+ * It removes all the elements that are not present in <code>that</code>.
+ *
+ * @param that the set to intersect with
+ */
+ def ** (that: collection.Set[A]): Set[A] = intersect(that)
+
+ /** Returns the set resulting from applying the given function <code>f</code> to each
+ * element of this set.
+ *
+ * @param f function to apply to each element.
+ * @return a set containing <code>f(a0), ..., f(an)</code>
+ * if this set contains <code>a0, ..., an</code>.
+ */
+ override def map[B](f: A => B): Set[B] =
+ foldLeft(empty[B])((set: Set[B], elem: A) => set + f(elem))
+
+ /** Applies the given function <code>f</code> to each element of
+ * this set, then forms the union of all results.
+ * @param f function to apply to each element.
+ * @return a set containing all elements in each <code>f(a0), ..., f(an)</code>
+ * if this set contains <code>a0, ..., an</code>.
+ */
+ override def flatMap[B](f: A => Iterable[B]): Set[B] =
+ foldLeft(empty[B])((set: Set[B], elem: A) => set incl f(elem))
+
+ /** Method <code>filter</code> removes all elements from the set for
+ * which the predicate <code>p</code> yields the value <code>false</code>.
+ *
+ * @param p The predicate used to filter the set
+ */
+ override def filter(p: A => Boolean): Set[A] =
+ foldLeft(this)((set, elem) => if (p(elem)) set else set - elem)
+
+}
diff --git a/src/dotnet-library/scala/collection/immutable/Set1.scala b/src/dotnet-library/scala/collection/immutable/Set1.scala
new file mode 100755
index 0000000000..86d5c1d275
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Set1.scala
@@ -0,0 +1,42 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Set1[A](elem1: A) extends Set[A] {
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def size: Int = 1
+
+ def contains(elem: A): Boolean =
+ elem == elem1
+
+ def + (elem: A): Set[A] =
+ if (contains(elem)) this
+ else new Set2(elem1, elem)
+
+ def - (elem: A): Set[A] =
+ if (elem == elem1) empty
+ else this
+
+ def elements: Iterator[A] =
+ Iterator.fromValues(elem1)
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Set2.scala b/src/dotnet-library/scala/collection/immutable/Set2.scala
new file mode 100755
index 0000000000..20ddd6a43d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Set2.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Set2[A](elem1: A, elem2: A) extends Set[A] {
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def size: Int = 2
+
+ def contains(elem: A): Boolean =
+ elem == elem1 || elem == elem2
+
+ def + (elem: A): Set[A] =
+ if (contains(elem)) this
+ else new Set3(elem1, elem2, elem)
+
+ def - (elem: A): Set[A] =
+ if (elem == elem1) new Set1(elem2)
+ else if (elem == elem2) new Set1(elem1)
+ else this
+
+ def elements: Iterator[A] =
+ Iterator.fromValues(elem1, elem2)
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Set3.scala b/src/dotnet-library/scala/collection/immutable/Set3.scala
new file mode 100755
index 0000000000..1ffcc833df
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Set3.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Set3[A](elem1: A, elem2: A, elem3: A) extends Set[A] {
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def size: Int = 3
+
+ def contains(elem: A): Boolean =
+ elem == elem1 || elem == elem2 || elem == elem3
+
+ def + (elem: A): Set[A] =
+ if (contains(elem)) this
+ else new Set4(elem1, elem2, elem3, elem)
+
+ def - (elem: A): Set[A] =
+ if (elem == elem1) new Set2(elem2, elem3)
+ else if (elem == elem2) new Set2(elem1, elem3)
+ else if (elem == elem3) new Set2(elem1, elem2)
+ else this
+
+ def elements: Iterator[A] =
+ Iterator.fromValues(elem1, elem2, elem3)
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Set4.scala b/src/dotnet-library/scala/collection/immutable/Set4.scala
new file mode 100755
index 0000000000..a51ad8d546
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Set4.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: ListSet.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+
+package scala.collection.immutable
+
+/** This class implements empty immutable maps
+ * @author Martin Oderskty
+ * @version 1.0, 019/01/2007
+ */
+[serializable]
+class Set4[A](elem1: A, elem2: A, elem3: A, elem4: A) extends Set[A] {
+
+ def empty[C]: Set[C] = new EmptySet[C]
+
+ def size: Int = 4
+
+ def contains(elem: A): Boolean =
+ elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4
+
+ def + (elem: A): Set[A] =
+ if (contains(elem)) this
+ else HashSet(elem1, elem2, elem3, elem4, elem)
+
+ def - (elem: A): Set[A] =
+ if (elem == elem1) new Set3(elem2, elem3, elem4)
+ else if (elem == elem2) new Set3(elem1, elem3, elem4)
+ else if (elem == elem3) new Set3(elem1, elem2, elem4)
+ else if (elem == elem4) new Set3(elem1, elem2, elem3)
+ else this
+
+ def elements: Iterator[A] =
+ Iterator.fromValues(elem1, elem2, elem3, elem4)
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/Stack.scala b/src/dotnet-library/scala/collection/immutable/Stack.scala
new file mode 100644
index 0000000000..fccf9197ef
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Stack.scala
@@ -0,0 +1,134 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+
+//import Predef.NoSuchElementException
+
+object Stack {
+ val Empty = new Stack[Nothing]
+}
+
+/** This class implements immutable stacks using a list-based data
+ * structure. Instances of <code>Stack</code> represent
+ * empty stacks; they can be either created by calling the constructor
+ * directly, or by applying the function <code>Stack.Empty</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/07/2003
+ */
+[serializable]
+class Stack[+A] extends Seq[A] {
+
+ /** Checks if this stack is empty.
+ *
+ * @return true, iff there is no element on the stack.
+ */
+ override def isEmpty: Boolean = true
+
+ /** Returns the size of this stack.
+ *
+ * @return the stack size.
+ */
+ def length: Int = 0
+
+ /** Push an element on the stack.
+ *
+ * @param elem the element to push on the stack.
+ * @return the stack with the new element on top.
+ */
+ def +[B >: A](elem: B): Stack[B] = new Node(elem)
+
+ /** Push all elements provided by the given iterable object onto
+ * the stack. The last element returned by the iterable object
+ * will be on top of the new stack.
+ *
+ * @param elems the iterable object.
+ * @return the stack with the new elements on top.
+ */
+ def +[B >: A](elems: Iterable[B]): Stack[B] =
+ elems.foldLeft(this: Stack[B]){ (stack, elem) => stack + elem }
+
+ /** Push a sequence of elements onto the stack. The last element
+ * of the sequence will be on top of the new stack.
+ *
+ * @param elems the element sequence.
+ * @return the stack with the new elements on top.
+ */
+ def push[B >: A](elems: B*): Stack[B] = this + elems
+
+ /** Returns the top element of the stack. An error is signaled if
+ * there is no element on the stack.
+ *
+ * @return the top element.
+ */
+ def top: A = throw new NoSuchElementException("no element on stack")
+
+ /** Removes the top element from the stack.
+ *
+ * @return the new stack without the former top element.
+ */
+ def pop: Stack[A] = throw new NoSuchElementException("no element on stack")
+
+ /** Returns the n-th element of this stack. The top element has index
+ * 0, elements below are indexed with increasing numbers.
+ *
+ * @param n the index number.
+ * @return the n-th element on the stack.
+ */
+ def apply(n: Int): A = throw new NoSuchElementException("no element on stack")
+
+ /** Returns an iterator over all elements on the stack. The iterator
+ * issues elements in the reversed order they were inserted into the
+ * stack (LIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ def elements: Iterator[A] = new Iterator[A] {
+ var that: Stack[A] = Stack.this;
+ def hasNext = !that.isEmpty;
+ def next =
+ if (!hasNext) throw new NoSuchElementException("next on empty iterator")
+ else { val res = that.top; that = that.pop; res }
+ }
+
+ /** Compares this stack with the given object.
+ *
+ * @return true, iff the two stacks are equal; i.e. they contain the
+ * same elements in the same order.
+ */
+ override def equals(obj: Any): Boolean =
+ obj.isInstanceOf[Stack[A]] && sameElements(obj.asInstanceOf[Stack[A]])
+
+ /** Returns the hash code for this stack.
+ *
+ * @return the hash code of the stack.
+ */
+ override def hashCode(): Int = 0
+
+ /**
+ * Redefines the prefix of the string representation.
+ */
+ override def stringPrefix: String = "Stack"
+
+ // Here comes true magic: covariant lists with implicit tail references
+ [serializable]
+ protected class Node[+B >: A](elem: B) extends Stack[B] {
+ override def isEmpty: Boolean = false
+ override def length: Int = Stack.this.length + 1
+ override def top: B = elem
+ override def pop: Stack[B] = Stack.this
+ override def apply(n: Int): B = if (n > 0) Stack.this(n - 1) else elem
+ override def hashCode(): Int = elem.hashCode() + Stack.this.hashCode()
+ }
+
+}
diff --git a/src/dotnet-library/scala/collection/immutable/Tree.scala b/src/dotnet-library/scala/collection/immutable/Tree.scala
new file mode 100644
index 0000000000..bc69b7c4db
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/Tree.scala
@@ -0,0 +1,406 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+/* General Balanced Trees - highly efficient functional dictionaries.
+**
+** This is a scala version of gb_trees.erl which is
+** copyrighted (C) 1999-2001 by Sven-Olof Nystrom, and Richard Carlsson
+**
+** An efficient implementation of Prof. Arne Andersson's General
+** Balanced Trees. These have no storage overhead compared to plain
+** unbalanced binary trees, and their performance is in general better
+** than AVL trees.
+** ---------------------------------------------------------------------
+** This library is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as
+** published by the Free Software Foundation; either version 2 of the
+** License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+** USA
+**
+** Author contact: erik.stenman@epfl.ch
+** ---------------------------------------------------------------------
+*/
+
+package scala.collection.immutable
+
+
+//import Predef.NoSuchElementException
+
+/** <p>
+ * General Balanced Trees - highly efficient functional dictionaries.
+ * </p>
+ * <p>
+ * An efficient implementation of Prof. Arne Andersson's
+ * <a href="http://citeseer.ist.psu.edu/andersson99general.html"
+ * target="_top">General Balanced Trees</a>. These have no storage overhead
+ * compared to plain unbalanced binary trees, and their performance is in
+ * general better than AVL trees.
+ * </p>
+ * <p>
+ * This implementation does not balance the trees after deletions.
+ * Since deletions don't increase the height of a tree, this should
+ * be OK in most applications. A balance method is provided for those
+ * cases where rebalancing is needed.
+ * </p>
+ * <p>
+ * The tree consists of entries conatining a key with an order.
+ * </p>
+ * <p>
+ * When instanciating the tree an order for the keys has to be
+ * supplied.
+ * </p>
+ *
+ * @author Erik Stenman, Michel Schinz
+ * @version 1.1, 2005-01-20
+ */
+
+[serializable]
+abstract class Tree[A <% Ordered[A], B]() extends AnyRef {
+ /* Data structure:
+ ** - size:Int - the number of elements in the tree.
+ ** - tree:T, which is composed of nodes of the form:
+ ** - GBNode(key: A, entry:B, smaller:T, bigger:T),
+ ** - and the "empty tree" node GBLeaf.
+ **
+ ** Original balance condition h(T) <= ceil(c * log(|T|)) has been
+ ** changed to the similar (but not quite equivalent) condition
+ ** 2 ^ h(T) <= |T| ^ c.
+ **
+ */
+
+ /** The type returned when creating a new tree.
+ * This type should be defined by concrete implementations
+ * e.g. <pre>
+ * class C[T](...) extends Tree[A,B](...) {
+ * type This = C[T];
+ * </pre>
+ */
+ protected type This <: Tree[A,B]
+ protected def getThis: This
+
+ /**
+ * The type of nodes that the tree is build from.
+ */
+ protected type aNode = GBTree[A,B]
+
+ /** The nodes in the tree.
+ */
+ protected def tree: aNode = GBLeaf[A,B]()
+
+ /** <p>
+ * This abstract method should be defined by a concrete implementation
+ * <code>C[T]</code> as something like:
+ * </p>
+ * <pre>
+ * <b>override def</b> New(sz: Int, t: aNode): This {
+ * <b>new</b> C[T](order) {
+ * <b>override def</b> size = sz
+ * <b>override protected def</b> tree: aNode = t
+ * }
+ * </pre>
+ * <p>
+ * The concrete implementation should also override the def of This
+ * <code>override type This = C[T];</code>
+ * </p>
+ */
+ protected def New(sz: Int, t: aNode): This
+
+ /** The size of the tree, returns 0 (zero) if the tree is empty.
+ *
+ * @return The number of nodes in the tree as an integer.
+ */
+ def size: Int = 0
+
+ /** A new tree with the entry added is returned,
+ * assuming that key is <em>not</em> in the tree.
+ *
+ * @param key ...
+ * @param entry ...
+ * @return ...
+ */
+ protected def add(key: A, entry: B): This = {
+ val newSize = size + 1
+ New(newSize, tree.insert(key, entry, newSize * newSize).node)
+ }
+
+ /** A new tree with the entry added is returned,
+ * if key is <em>not</em> in the tree, otherwise
+ * the key is updated with the new entry.
+ */
+ protected def updateOrAdd(key: A, entry: B): This =
+ if (tree.isDefinedAt(key))
+ New(size,tree.update(key,entry))
+ else
+ add(key,entry)
+
+ /** Removes the key from the tree.
+ *
+ * @param key ...
+ * @return ...
+ */
+ protected def deleteAny(key: A): This =
+ if (tree.isDefinedAt(key))
+ delete(key)
+ else
+ getThis
+
+ /** Removes the key from the tree, assumimg that key is present.
+ *
+ * @param key ...
+ * @return ...
+ */
+ private def delete(key: A): This =
+ New(size - 1, tree.delete(key))
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ protected def findValue(key: A): Option[B] =
+ tree.get(key)
+
+ /** Gives you an iterator over all elements in the tree.
+ * The iterator structure corresponds to
+ * the call stack of an in-order traversal.
+ *
+ * Note: The iterator itself has a state, i.e., it is not functional.
+ */
+ protected def entries: Iterator[B] =
+ new Iterator[B] {
+ var iter = tree.mk_iter(scala.Nil)
+ def hasNext = !iter.isEmpty
+ def next = iter match {
+ case GBNode(_,v,_,t)::iter_tail =>
+ iter = t.mk_iter(iter_tail)
+ v
+ case scala.Nil =>
+ throw new NoSuchElementException("next on empty iterator")
+ }
+ }
+
+ /** Create a new balanced tree from the tree. Might be useful to call
+ * after many deletions, since deletion does not rebalance the tree.
+ */
+ def balance: This =
+ New(size, tree.balance(size))
+}
+
+protected abstract class InsertTree[A <% Ordered[A],B]() extends AnyRef {
+ def insertLeft(k: A, v: B, t: GBTree[A,B]): InsertTree[A,B]
+ def insertRight(k: A, v: B, t: GBTree[A,B]): InsertTree[A,B]
+ def node: GBTree[A,B]
+}
+
+/**
+ * <code>ITree</code> is an internal class used by
+ * <a href="Tree.html" target="contentFrame"><code>Tree</code></a>.
+ */
+private case class ITree[A <% Ordered[A],B](t: GBTree[A,B])
+ extends InsertTree[A,B] {
+ def insertLeft(key: A, value: B, bigger: GBTree[A,B]) =
+ ITree(GBNode(key, value, t, bigger))
+ def insertRight(key: A, value: B, smaller: GBTree[A,B]) =
+ ITree(GBNode(key, value, smaller, t))
+ def node = t
+}
+
+/**
+ * <code>INode</code> is an internal class used by
+ * <a href="Tree.html" target="contentFrame"><code>Tree</code></a>.
+ */
+private case class INode[A <% Ordered[A],B](t1: GBTree[A,B],
+ height: int,
+ size: int)
+ extends InsertTree[A,B] {
+ def insertLeft(key: A, value: B, bigger: GBTree[A,B]) =
+ balance_p(GBNode(key, value, t1, bigger), bigger);
+ def insertRight(key: A, value: B, smaller: GBTree[A,B]) =
+ balance_p(GBNode(key, value, smaller, t1),smaller);
+ protected def balance_p(t:GBTree[A,B],subtree:GBTree[A,B]):InsertTree[A,B] = {
+ val {subHeight, subSize} = subtree.count
+ val totalHeight = 2 * compat.Math.max(height, subHeight)
+ val totalSize = size + subSize + 1
+ val BalanceHeight = totalSize * totalSize
+ if (totalHeight > BalanceHeight) ITree(t.balance(totalSize))
+ else INode(t, totalHeight, totalSize)
+ }
+ def node = t1
+}
+
+/**
+ * <code>GBTree</code> is an internal class used by
+ * <a href="Tree.html" target="contentFrame"><code>Tree</code></a>.
+ *
+ * @author Erik Stenman
+ * @version 1.0, 2005-01-20
+ */
+[serializable]
+protected abstract class GBTree[A <% Ordered[A],B] extends AnyRef {
+ type aNode = GBTree[A,B]
+ type anInsertTree = InsertTree[A,B]
+
+ /** Calculates 2^h, and size, where h is the height of the tree
+ * and size is the number of nodes in the tree.
+ */
+ def count: {Int,Int}
+ def isDefinedAt(Key: A): Boolean
+ def get(key: A): Option[B]
+ def apply(key: A): B
+ def update(key: A, value: B): aNode
+ def insert(key: A, value: B, size: Int): anInsertTree
+ def toList(acc: List[{A,B}]): List[{A,B}]
+ def mk_iter(iter_tail: List[aNode]): List[aNode]
+ def delete(key: A): aNode
+ def merge(t: aNode): aNode
+ def takeSmallest: Triple[A,B,aNode]
+ def balance(s: int): GBTree[A,B]
+}
+
+private case class GBLeaf[A <% Ordered[A],B]() extends GBTree[A,B] {
+ def count = {1, 0}
+ def isDefinedAt(key: A) = false
+ def get(_key: A) = None
+ def apply(key: A) = throw new NoSuchElementException("key " + key + " not found")
+ def update(key: A, value: B) = throw new NoSuchElementException("key " + key + " not found")
+ def insert(key: A, value: B, s: Int): anInsertTree = {
+ if (s == 0)
+ INode(GBNode(key, value, this, this), 1, 1)
+ else
+ ITree(GBNode(key, value, this, this))
+ }
+ def toList(acc: List[{A,B}]): List[{A,B}] = acc
+ def mk_iter(iter_tail: List[GBTree[A,B]]) = iter_tail
+ def merge(larger: GBTree[A,B]) = larger
+ def takeSmallest: Triple[A,B, GBTree[A,B]] =
+ throw new NoSuchElementException("takeSmallest on empty tree")
+ def delete(_key: A) = throw new NoSuchElementException("Delete on empty tree.")
+ def balance(s: int) = this
+ override def hashCode() = 0
+}
+
+private case class GBNode[A <% Ordered[A],B](key: A,
+ value: B,
+ smaller: GBTree[A,B],
+ bigger: GBTree[A,B])
+ extends GBTree[A,B] {
+ def count: {Int,Int} = {
+ val {sHeight, sSize} = smaller.count
+ val {bHeight, bSize} = bigger.count
+ val mySize = sSize + bSize + 1
+ if (mySize == 1)
+ {1, mySize}
+ else
+ {2 * compat.Math.max(sHeight, bHeight), mySize}
+ }
+
+ def isDefinedAt(sKey: A): Boolean =
+ if (sKey < key) smaller.isDefinedAt(sKey)
+ else if (sKey > key) bigger.isDefinedAt(sKey)
+ else true
+
+ def get(sKey: A): Option[B] =
+ if (sKey < key) smaller.get(sKey)
+ else if (sKey > key) bigger.get(sKey)
+ else Some(value)
+
+ def apply(sKey: A): B =
+ if (sKey < key) smaller.apply(sKey)
+ else if (sKey > key) bigger.apply(sKey)
+ else value
+
+ def update(newKey: A, newValue: B): aNode =
+ if (newKey < key)
+ GBNode(key, value, smaller.update(newKey,newValue), bigger)
+ else if (newKey > key)
+ GBNode(key, value, smaller, bigger.update(newKey,newValue))
+ else
+ GBNode(newKey, newValue, smaller, bigger)
+
+ def insert(newKey: A, newValue: B, s: int): anInsertTree = {
+ if (newKey < key)
+ smaller.insert(newKey, newValue, s / 2).insertLeft(key, value, bigger)
+ else if (newKey > key)
+ bigger.insert(newKey, newValue, s / 2).insertRight(key, value, smaller)
+ else
+ throw new NoSuchElementException("Key exists: " + newKey)
+ }
+
+ def toList(acc: List[{A,B}]): List[{A,B}] =
+ smaller.toList({key, value} :: bigger.toList(acc))
+
+ def mk_iter(iter_tail:List[aNode]):List[aNode] =
+ smaller.mk_iter(this :: iter_tail)
+
+ def delete(sKey:A):aNode = {
+ if (sKey < key)
+ GBNode(key, value, smaller.delete(sKey), bigger)
+ else if (sKey > key)
+ GBNode(key, value, smaller, bigger.delete(sKey))
+ else
+ smaller.merge(bigger)
+ }
+
+ def merge(larger: aNode): GBTree[A,B] = larger match {
+ case GBLeaf() =>
+ this
+ case _ =>
+ val {key1, value1, larger1} = larger.takeSmallest
+ GBNode(key1, value1, this, larger1)
+ }
+
+ def takeSmallest: Triple[A, B, aNode] = smaller match {
+ case GBLeaf() =>
+ {key, value, bigger}
+ case _ =>
+ val {key1, value1, smaller1} = smaller.takeSmallest
+ {key1, value1, GBNode(key, value, smaller1, bigger)}
+ }
+
+ /**
+ * @param s ...
+ * @return ...
+ */
+ def balance(s: int): GBTree[A,B] =
+ balance_list(toList(scala.Nil), s)
+
+ protected def balance_list(list: List[{A,B}], s: int): GBTree[A,B] = {
+ val empty = GBLeaf[A,B]();
+ def bal(list: List[{A,B}], s: Int): {aNode, List[{A,B}]} = {
+ if (s > 1) {
+ val sm = s - 1
+ val s2 = sm / 2
+ val s1 = sm - s2
+ val {t1, {k, v} :: l1} = bal(list, s1)
+ val {t2, l2} = bal(l1, s2)
+ val t = GBNode(k, v, t1, t2)
+ {t, l2}
+ } else if (s == 1) {
+ val {k,v} :: rest = list
+ {GBNode(k, v, empty, empty), rest}
+ } else
+ {empty, list}
+ }
+ bal(list, s)._1
+ }
+
+ override def hashCode() =
+ value.hashCode() + smaller.hashCode() + bigger.hashCode()
+}
diff --git a/src/dotnet-library/scala/collection/immutable/TreeMap.scala b/src/dotnet-library/scala/collection/immutable/TreeMap.scala
new file mode 100644
index 0000000000..22664f1e20
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/TreeMap.scala
@@ -0,0 +1,112 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+// todo: make balanced once Tree.scala is updated to be covariant.
+
+package scala.collection.immutable
+
+
+object TreeMap {
+
+ /** The empty map of this type
+ * @deprecated use <code>empty</code> instead
+ */
+ [deprecated] def Empty[A <% Ordered[A], B] = empty[A, B]
+
+ /** The empty map of this type */
+ def empty[A <% Ordered[A], B] = new TreeMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A <% Ordered[A], B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+/** This class implements immutable maps using a tree.
+ *
+ * @author Erik Stenman
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+[serializable]
+class TreeMap[A <% Ordered[A], +B](val size: int, t: RedBlack[A]#Tree[B])
+extends RedBlack[A] with Map[A, B] {
+
+ def isSmaller(x: A, y: A) = x < y
+
+ def this() = this(0, null)
+
+ protected val tree: RedBlack[A]#Tree[B] = if (size == 0) Empty else t
+
+ private def newMap[B](s: int, t: RedBlack[A]#Tree[B]) = new TreeMap[A, B](s, t)
+
+ /** A factory to create empty maps of the same type of keys.
+ */
+ def empty[C] = ListMap.empty[A, C]
+
+ /** A new TreeMap with the entry added is returned,
+ * if key is <em>not</em> in the TreeMap, otherwise
+ * the key is updated with the new entry.
+ *
+ * @param key ...
+ * @param value ...
+ * @return ...
+ */
+ def update [B1 >: B](key: A, value: B1): TreeMap[A, B1] = {
+ val newsize = if (tree.lookup(key).isEmpty) size + 1 else size
+ newMap(newsize, tree.update(key, value))
+ }
+
+ /** A new TreeMap with the entry added is returned,
+ * assuming that key is <em>not</em> in the TreeMap.
+ */
+ def insert [B1 >: B](key: A, value: B1): TreeMap[A, B1] = {
+ assert(tree.lookup(key).isEmpty)
+ newMap(size + 1, tree.update(key, value))
+ }
+
+ def - (key:A): TreeMap[A, B] =
+ if (tree.lookup(key).isEmpty) this
+ else newMap(size - 1, tree.delete(key))
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(key: A): Option[B] = tree.lookup(key) match {
+ case n: NonEmpty[b] => Some(n.value)
+ case _ => None
+ }
+
+ /** Retrieve the value which is associated with the given key. This
+ * method throws an exception if there is no mapping from the given
+ * key to a value.
+ *
+ * @param key the key
+ * @return the value associated with the given key.
+ * @throws Error("key not found").
+ */
+ override def apply(key: A): B = tree.lookup(key) match {
+ case n: NonEmpty[b] => n.value
+ case _ => super.apply(key)
+ }
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[{A, B}] = tree.elements
+}
+
+
+
+
diff --git a/src/dotnet-library/scala/collection/immutable/TreeMap.scala.disabled b/src/dotnet-library/scala/collection/immutable/TreeMap.scala.disabled
new file mode 100755
index 0000000000..3e470e9442
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/TreeMap.scala.disabled
@@ -0,0 +1,101 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: TreeMap.scala 8997 2006-10-19 20:52:30Z odersky $
+
+package scala.collection.immutable
+
+
+object TreeMap {
+ def Empty[A <% Ordered[A], B] = new TreeMap[A, B]
+}
+
+/** This class implements immutable maps using a tree.
+ *
+ * @author Erik Stenman
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+
+[serializable]
+class TreeMap[A <% Ordered[A], B] extends Tree[A, Pair[A, B]] with Map[A, B] {
+
+ override protected type This = TreeMap[A, B]
+ override protected def getThis: This = this
+
+ /** A factory to create empty maps of the same type of keys.
+ */
+ def empty[C] = new TreeMap[A, C]
+
+ /** Creates a new TreeMap from a GBTree and its size.
+ *
+ * @param sz ...
+ * @param t ...
+ * @return ...
+ */
+ protected def New(sz: Int, t: aNode): This = new TreeMap[A, B] {
+ override def size = sz
+ override protected def tree: aNode = t
+ }
+
+ /** A new TreeMap with the entry added is returned,
+ * if key is <em>not</em> in the TreeMap, otherwise
+ * the key is updated with the new entry.
+ *
+ * @param key ...
+ * @param value ...
+ * @return ...
+ */
+ def update [B1 >: B](key: A, value: B1) = updateOrAdd(key, {key, value})
+
+ /** A new TreeMap with the entry added is returned,
+ * assuming that key is <em>not</em> in the TreeMap.
+ */
+ def insert [B1 >: B](key:A, value:B) = add(key, {key, value})
+
+ /** Removes the key from the TreeMap.
+ */
+ def remove(key:A) = deleteAny(key)
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(key: A): Option[B] =
+ findValue(key) match {
+ case Some(Pair(_, value)) => Some(value)
+ case _ => None
+ }
+
+ /** Retrieve the value which is associated with the given key. This
+ * method throws an exception if there is no mapping from the given
+ * key to a value.
+ *
+ * @param key the key
+ * @return the value associated with the given key.
+ * @throws Error("key not found").
+ */
+ override def apply(key: A): B = tree.apply(key)._2
+
+ /** Creates a list of all (key, value) mappings.
+ *
+ * @return the list of all mappings
+ */
+ override def toList: List[Pair[A, B]] =
+ tree.toList(scala.Nil) map (._2)
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[Pair[A, B]] = entries
+}
+
diff --git a/src/dotnet-library/scala/collection/immutable/TreeSet.scala b/src/dotnet-library/scala/collection/immutable/TreeSet.scala
new file mode 100644
index 0000000000..1226923d66
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/TreeSet.scala
@@ -0,0 +1,84 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.immutable
+
+object TreeSet {
+
+ /** The empty set of this type
+ * @deprecated use <code>empty</code> instead
+ */
+ [deprecated] def Empty[A <% Ordered[A]] = empty[A]
+
+ /** The empty set of this type
+ */
+ def empty[A <% Ordered[A]] = new TreeSet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A <% Ordered[A]](elems: A*) = empty[A] ++ elems
+}
+
+/** This class implements immutable sets using a tree.
+ *
+ * @author Martin Odersky
+ * @version 2.0, 02/01/2007
+ */
+
+[serializable]
+class TreeSet[A <% Ordered[A]](val size: int, t: RedBlack[A]#Tree[Unit])
+extends RedBlack[A] with Set[A] {
+
+ def isSmaller(x: A, y: A) = x < y
+
+ def this() = this(0, null)
+
+ protected val tree: RedBlack[A]#Tree[Unit] = if (size == 0) Empty else t
+
+ private def newSet(s: int, t: RedBlack[A]#Tree[Unit]) = new TreeSet[A](s, t)
+
+ /** A factory to create empty maps of the same type of keys.
+ */
+ def empty[B]: Set[B] = ListSet.empty[B]
+
+ /** A new TreeSet with the entry added is returned,
+ */
+ def + (elem: A): TreeSet[A] = {
+ val newsize = if (tree.lookup(elem).isEmpty) size + 1 else size
+ newSet(newsize, tree.update(elem, ()))
+ }
+
+ /** A new TreeSet with the entry added is returned,
+ * assuming that elem is <em>not</em> in the TreeSet.
+ */
+ def insert (elem: A): TreeSet[A] = {
+ assert(tree.lookup(elem).isEmpty)
+ newSet(size + 1, tree.update(elem, ()))
+ }
+
+ def - (elem:A): TreeSet[A] =
+ if (tree.lookup(elem).isEmpty) this
+ else newSet(size - 1, tree.delete(elem))
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def contains(elem: A): Boolean = !tree.lookup(elem).isEmpty
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A] = tree.elements map (._1)
+}
diff --git a/src/dotnet-library/scala/collection/immutable/UnbalancedTreeMap.scala b/src/dotnet-library/scala/collection/immutable/UnbalancedTreeMap.scala
new file mode 100755
index 0000000000..dabc3a11cf
--- /dev/null
+++ b/src/dotnet-library/scala/collection/immutable/UnbalancedTreeMap.scala
@@ -0,0 +1,143 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: TreeMap.scala 8997 2006-10-19 20:52:30Z odersky $
+
+// todo: make balanced once Tree.scala is updated to be covariant.
+
+package scala.collection.immutable
+
+
+object UnbalancedTreeMap {
+
+ /** The empty map of this type */
+ def empty[A <% Ordered[A], B] = new UnbalancedTreeMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A<% Ordered[A], B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+/** This class implements immutable maps using a tree.
+ *
+ * @author Martin Odersky
+ * @version 1.1, 02/01/2007
+ */
+
+[serializable]
+class UnbalancedTreeMap[A <% Ordered[A], +B] extends Map[A, B] {
+
+ /** A factory to create empty maps of the same type of keys.
+ */
+ def empty[C] = UnbalancedTreeMap.empty[A, C]
+
+ def size: Int = 0
+
+ override def isEmpty: boolean = true
+
+ protected def add [B1 >: B](key: A, value: B1) = new Node(key, value, this, this)
+ protected def findValue (key: A): UnbalancedTreeMap[A, B] = this
+
+ protected def key: A = throw new NoSuchElementException("empty map")
+ protected def value: B = throw new NoSuchElementException("empty map")
+ protected def smallest: UnbalancedTreeMap[A, B] = throw new NoSuchElementException("empty map")
+
+ /** A new TreeMap with the entry added is returned,
+ * if key is <em>not</em> in the TreeMap, otherwise
+ * the key is updated with the new entry.
+ *
+ * @param key ...
+ * @param value ...
+ * @return ...
+ */
+ def update [B1 >: B](key: A, value: B1) = add(key, value)
+
+ /** A new TreeMap with the entry added is returned,
+ * assuming that key is <em>not</em> in the TreeMap.
+ */
+ def insert [B1 >: B](key: A, value: B1) = add(key, value)
+
+ def - (key:A): UnbalancedTreeMap[A, B] = this
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(key: A): Option[B] = {
+ val t = findValue(key)
+ if (t.isEmpty) None
+ else Some(t.value)
+ }
+
+ /** Retrieve the value which is associated with the given key. This
+ * method throws an exception if there is no mapping from the given
+ * key to a value.
+ *
+ * @param key the key
+ * @return the value associated with the given key.
+ * @throws Error("key not found").
+ */
+ override def apply(key: A): B = {
+ val t = findValue(key)
+ if (!t.isEmpty) t.value
+ else super.apply(key)
+ }
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[{A, B}] = Iterator.empty
+
+ protected class Node[+B](override protected val key: A,
+ override protected val value: B,
+ left: UnbalancedTreeMap[A, B],
+ right: UnbalancedTreeMap[A, B]) extends UnbalancedTreeMap[A, B]
+ {
+ override def size = left.size + right.size + 1
+
+ override def isEmpty = false
+
+ override protected def add [B1 >: B](k: A, v: B1) =
+ if (k < key) new Node[B1](key, value, left.add(k, v), right)
+ else if (k > key) new Node[B1](key, value, left, right.add(k, v))
+ else new Node[B1](k, v, left, right)
+
+ override protected def findValue (k: A): UnbalancedTreeMap[A, B] =
+ if (k < key) left.findValue(k)
+ else if (k > key) right.findValue(k)
+ else this
+
+ override protected def smallest: UnbalancedTreeMap[A, B] =
+ if (left.isEmpty) this else left.smallest
+
+ override def - (k: A): UnbalancedTreeMap[A, B] =
+ if (k < key) new Node(key, value, left - k, right)
+ else if (k > key) new Node(key, value, left, right - k)
+ else combine(left, right)
+
+ private def combine[B](l: UnbalancedTreeMap[A, B], r: UnbalancedTreeMap[A, B]) = {
+ if (l.isEmpty) r
+ else if (r.isEmpty) l
+ else {
+ val s = r.smallest
+ new Node(s.key, s.value, l, r - s.key)
+ }
+ }
+
+ override def elements: Iterator[{A, B}] =
+ left.elements append Iterator.single({key, value}) append right.elements
+ }
+}
+
+
+
+
diff --git a/src/dotnet-library/scala/collection/jcl/ArrayList.scala b/src/dotnet-library/scala/collection/jcl/ArrayList.scala
new file mode 100644
index 0000000000..d6ca5ee42c
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/ArrayList.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Creates a buffer backed by a Java array list.
+ *
+ * @author Sean McDirmid
+ */
+class ArrayList[A](override val underlying : java.util.ArrayList) extends CollectionWrapper[A] with BufferWrapper[A] {
+ def this() = this(new java.util.ArrayList);
+ override def elements = super[BufferWrapper].elements;
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Buffer.scala b/src/dotnet-library/scala/collection/jcl/Buffer.scala
new file mode 100644
index 0000000000..db22270f97
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Buffer.scala
@@ -0,0 +1,159 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A mutable sequence that supports element insertion and update.
+ *
+ * @author Sean McDirmid
+ */
+trait Buffer[A] extends MutableSeq[A] with Collection[A] with Ranged[Int,A] {
+ final protected type SortedSelf = Buffer[A];
+
+ override def elements : BufferIterator[Int,A];
+ /** The first index of a buffer is 0. */
+ override def first = 0;
+ /** The last index of a buffer is its size - 1. */
+ override def last = size - 1;
+ /** Indices are compared through subtraction. */
+ final def compare(k0 : Int, k1 : Int) = k0 - k1;
+ /** Removes the element at index "idx" */
+ def remove(idx : Int) = {
+ val i = elements;
+ val ret = i.seek(idx); i.remove; ret;
+ }
+
+ /** Replaces the element at index "idx" with "a."
+ * @returns the element replaced.
+ */
+ def set(idx : Int, a : A) : A = {
+ val i = elements;
+ val ret = i.seek(idx); i.set(a); ret;
+ }
+
+ /** Equivalent to set except the replaced element is not returned. */
+ def update(idx : Int, a : A) : Unit = set(idx, a);
+
+ /** @returns always true. */
+ def add(a : A) : Boolean = {
+ val i = elements;
+ while (i.hasNext) i.next;
+ i.add(a);
+ true;
+ }
+
+ /** Inserts "a" into this buffer just before the element at index "idx." */
+ def add(idx: Int, a: A): Unit = {
+ val i = elements; i.seek(idx);
+ i.add(a);
+ }
+
+ /** Inserts all elements of <code>that</code> into this buffer just before
+ * the element at index <code>idx</code>.
+ *
+ * @param idx ..
+ * @param that ..
+ */
+ def addAll(idx: Int, that: Iterable[A]): Unit = {
+ val i = elements; i.seek(idx);
+ for (val that <- that) {
+ i.add(that); i.next;
+ }
+ }
+
+ override def transform(f: A => A): Boolean = {
+ var changed = false;
+ val i = elements;
+ while (i.hasNext) {
+ val a0 = i.next;
+ val a1 = f(a0);
+ if (a0 != a1) {
+ i.set(a1); changed = true;
+ }
+ }
+ changed;
+ }
+ override def +(a : A) : this.type = super[Collection].+(a);
+ override def -=(a : A) = super[Collection].-=(a);
+ override def isEmpty = super[MutableSeq].isEmpty;
+ override def pfilter(p : A => Boolean) : MutableSeq[A] = super[MutableSeq].pfilter(p);
+ override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until);
+
+ protected class Range(var from : Option[Int], var until : Option[Int]) extends Buffer[A] {
+ if (from == None && until == None) throw new IllegalArgumentException;
+ if (from != None && until != None && !(from.get < until.get)) throw new IllegalArgumentException;
+ override def add(a : A) =
+ if (until == None) Buffer.this.add(a);
+ else {
+ Buffer.this.add(until.get, a);
+ true;
+ }
+ private def translate(idx : Int) = {
+ if (until != None && idx > until.get) throw new IllegalArgumentException;
+ else if (from != None) from.get + idx;
+ else idx;
+ }
+ override def apply(idx : Int) : A = Buffer.this.apply(translate(idx));
+ override def set(idx : Int, a : A) = Buffer.this.set(translate(idx), a);
+ override def add(idx : Int, a : A) = Buffer.this.add(translate(idx), a);
+ override def remove(idx : Int) = Buffer.this.remove(translate(idx));
+ override def size = {
+ if (until != None) {
+ if (from != None) until.get - from.get;
+ else until.get;
+ } else super.size;
+ }
+ def elements : BufferIterator[Int,A] = new RangeIterator;
+ class RangeIterator extends BufferIterator[Int,A] {
+ val underlying = Buffer.this.elements;
+ if (from != None) underlying.seek(from.get);
+ def hasNext = underlying.hasNext &&
+ (until == None || underlying.nextIndex < until.get);
+ def hasPrevious = underlying.hasPrevious &&
+ (from == None || underlying.previousIndex >= from.get);
+ def next = {
+ if (until != None && underlying.nextIndex >= until.get) throw new NoSuchElementException;
+ underlying.next;
+ }
+ def previous = {
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.previous;
+ }
+ def add(a : A) = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.add(a);
+ if (until != None) until = Some(until.get + 1);
+ }
+ def set(a : A) = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.set(a);
+ }
+ def remove = {
+ if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException;
+ if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException;
+ underlying.remove;
+ }
+ def nextIndex = {
+ val ret = underlying.nextIndex;
+ if (until != None && ret >= until.get) throw new NoSuchElementException;
+ if (from != None) ret - from.get;
+ else ret;
+ }
+ def previousIndex = {
+ val ret = underlying.previousIndex;
+ if (from != None && ret < from.get) throw new NoSuchElementException;
+ if (from != None) ret - from.get;
+ else ret;
+ }
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/BufferIterator.scala b/src/dotnet-library/scala/collection/jcl/BufferIterator.scala
new file mode 100644
index 0000000000..3faeb0b354
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/BufferIterator.scala
@@ -0,0 +1,32 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** An iterator for a buffer that supports element update and insertion.
+ *
+ * @author Sean McDirmid
+ */
+trait BufferIterator[K,A] extends SeqIterator[K,A] {
+
+ /** Sets the element before this iterator's cursor to "a."
+ * Replaces either the last element returned by "next" or,
+ * if previous was called,
+ * the next element that would be return by "previous."
+ */
+ def set(a: A): Unit;
+
+ /** Inserts "a" after the iterator's cursor.
+ * If next was last called, "a" is inserted after the element returned.
+ * If previous was last called, "a" is inserted before the element returned.
+ */
+ def add(a: A): Unit;
+
+}
diff --git a/src/dotnet-library/scala/collection/jcl/BufferWrapper.scala b/src/dotnet-library/scala/collection/jcl/BufferWrapper.scala
new file mode 100644
index 0000000000..af97e9f03f
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/BufferWrapper.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Wraps Java lists.
+ *
+ * @author Sean McDirmid
+ */
+trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] {
+ protected def underlying : java.util.List;
+ override def elements : BufferIterator[Int,A] = new IteratorWrapper(underlying.listIterator);
+ override def remove(idx : Int) = underlying.remove(idx).asInstanceOf[A];
+ override def add(a : A) = underlying.add(a);
+ override def add(idx : Int, a : A) = underlying.add(idx,a);
+ override def addAll(idx : Int, that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.addAll(idx, that.underlying0); {}
+ case _ => super.addAll(idx, that);
+ }
+ override def indexOf(a : A) = {
+ val result = underlying.indexOf(a);
+ if (result == -1) None;
+ else Some(result);
+ }
+ override def apply(idx : Int) = underlying.get(idx).asInstanceOf[A];
+ override def set(idx : Int, a : A) = underlying.set(idx, a).asInstanceOf[A];
+ override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until);
+ protected class Range(from : Option[Int], until : Option[Int]) extends super.Range(from,until) with BufferWrapper[A] {
+ val underlying = {
+ val fromi = if (from == None) 0 else from.get;
+ val toi = if (until == None) BufferWrapper.this.size else until.get;
+ BufferWrapper.this.underlying.subList(fromi, toi);
+ }
+ override def elements = super[BufferWrapper].elements;
+ }
+ class IteratorWrapper(underlying : java.util.ListIterator) extends super.IteratorWrapper(underlying) with BufferIterator[Int,A] {
+ def add(a : A) = underlying.add(a);
+ def set(a : A) = underlying.set(a);
+ def hasPrevious = underlying.hasPrevious;
+ def previous = underlying.previous.asInstanceOf[A];
+ def previousIndex = underlying.previousIndex;
+ def nextIndex = underlying.nextIndex;
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Collection.scala b/src/dotnet-library/scala/collection/jcl/Collection.scala
new file mode 100644
index 0000000000..2f2dd646cb
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Collection.scala
@@ -0,0 +1,84 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+object Collection {
+ val DEFAULT_FILTER : Any => Boolean = x => true;
+}
+
+/** Analogous to a Java collection.
+ *
+ * @author Sean McDirmid
+ */
+trait Collection[A] extends MutableIterable[A] {
+ /** Type-safe version of containsAll.
+ **
+ ** @author Sean McDirmid
+ **/
+ def hasAll(i: Iterable[A]): Boolean = i.forall(elements.has);
+
+ /** Adds "a" to the collection, return true if "a" is actually added. */
+ def add(a: A): Boolean;
+
+ /** Adds all elements in "i" to the collection, return true if any elements are added. */
+ def addAll(i: Iterable[A]): Boolean = {
+ var changed = false;
+ i.foreach(t => changed = add(t) || changed);
+ changed;
+ }
+ /** Operator shortcut for addAll. */
+ def ++(that: Iterable[A]): this.type = {
+ addAll(that); this;
+ }
+
+ /** removes "a" from the collection. */
+ def -=(a : A) : Unit = remove(a);
+
+ /** adds "a" from the collection. */
+ def +=(t : A) : Unit = add(t);
+
+ /** adds "a" from the collection. Useful for chaining. */
+ def +(t : A) : this.type = { add(t); this; }
+
+ /** Transforms each element of the collection in-place according to
+ * <code>f</code>.
+ *
+ * @param f
+ * @return <code>true</code> if the collection is actually updated.
+ */
+ def transform(f: A => A): Boolean;
+
+ /** Used for non-strict filtered collection that only includes elements of this collection that are true for "p."
+ ** Any elements added to or removed from the resulting
+ ** filter will update this collection. Any changes to this collection
+ ** can update the filtered collection.
+ ** @return a non-strict filter of this collection.
+ **/
+ def pfilter(p : A => Boolean) : MutableIterable[A] = new Filter(p);
+
+ /** Base implementation of a filtered collection */
+ class Filter(p : A => Boolean) extends Collection[A] {
+ def transform(f : A => A) =
+ Collection.this.transform(a => if (p(a)) f(a) else a);
+ override def add(a : A) = {
+ if (!p(a)) throw new IllegalArgumentException;
+ Collection.this.add(a);
+ }
+ override def has(a : A) = if (!p(a)) false else Collection.this.has(a);
+ override def remove(a : A) = {
+ if (!p(a)) throw new IllegalArgumentException;
+ Collection.this.remove(a);
+ }
+ override def pfilter(p1 : A => Boolean) : MutableIterable[A] =
+ Collection.this.pfilter(a => p(a) && p1(a));
+ def elements = Collection.this.elements.filter(p);
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/CollectionWrapper.scala b/src/dotnet-library/scala/collection/jcl/CollectionWrapper.scala
new file mode 100644
index 0000000000..279e3f8a07
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/CollectionWrapper.scala
@@ -0,0 +1,41 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Used to wrap Java collections in Scala.
+ *
+ * @author Sean McDirmid
+ */
+trait CollectionWrapper[A] extends Collection[A] with IterableWrapper[A] {
+ /** Override to specify the collection being accessed through this wrapper.
+ ** Collection operations are then routed through the wrapped Java collection.
+ **/
+ protected def underlying : java.util.Collection;
+ private[jcl] final def underlying0 = underlying;
+ override def has(a : A) = underlying.contains(a);
+ override def elements : MutableIterator[A] = super.elements;
+
+ override def hasAll(that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.containsAll(that.underlying);
+ case _ => super.hasAll(that);
+ }
+ override def add(a : A) = underlying.add(a);
+ override def addAll(that : Iterable[A]) = that match {
+ case that : CollectionWrapper[_] => underlying.addAll(that.underlying);
+ case _ => super.addAll(that);
+ }
+ override def toString = underlying.toString;
+ override def hashCode = underlying.hashCode;
+ override def equals(that : Any) = that match {
+ case that: CollectionWrapper[_] => underlying == that.underlying;
+ case _ => super.equals(that);
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/HashMap.scala b/src/dotnet-library/scala/collection/jcl/HashMap.scala
new file mode 100644
index 0000000000..559255b070
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/HashMap.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A map that is backed by a Java hash map.
+ *
+ * @author Sean McDirmid
+ */
+class HashMap[K,E](override val underlying: java.util.HashMap) extends MapWrapper[K,E] {
+ def this() = this(new java.util.HashMap);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/HashSet.scala b/src/dotnet-library/scala/collection/jcl/HashSet.scala
new file mode 100644
index 0000000000..900b7008ac
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/HashSet.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A hash set that is backed by a Java hash set.
+ *
+ * @author Sean McDirmid
+ */
+class HashSet[A](override val underlying: java.util.HashSet) extends CollectionWrapper[A] with SetWrapper[A] {
+ /** Creates an underlying Java hash set. */
+ def this() = this(new java.util.HashSet);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/IdentityHashMap.scala b/src/dotnet-library/scala/collection/jcl/IdentityHashMap.scala
new file mode 100644
index 0000000000..a56a49c844
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/IdentityHashMap.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A map that is backed by a Java identity hash map, which compares keys
+ * by their reference-based identity as opposed to using equals and hashCode.
+ * An identity hash map will often perform better than traditional hash map
+ * because it can utilize linear probing.
+ *
+ * @author Sean McDirmid
+ */
+class IdentityHashMap[K,E](override val underlying : java.util.IdentityHashMap) extends MapWrapper[K,E] {
+ def this() = this(new java.util.IdentityHashMap);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/IterableWrapper.scala b/src/dotnet-library/scala/collection/jcl/IterableWrapper.scala
new file mode 100644
index 0000000000..b904342af6
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/IterableWrapper.scala
@@ -0,0 +1,39 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A wrapper around a Java collection that only supports remove mutations.
+ *
+ * @author Sean McDirmid
+ */
+trait IterableWrapper[A] extends MutableIterable[A] {
+ protected def underlying: java.util.Collection;
+ override def remove(a: A) = underlying.remove(a);
+ override def removeAll(that: Iterable[A]) = that match {
+ case that: IterableWrapper[_] => underlying.removeAll(that.underlying);
+ case _ => super.removeAll(that);
+ }
+ override def retainAll(that : Iterable[A]) = that match {
+ case that : IterableWrapper[_] => underlying.retainAll(that.underlying);
+ case _ => super.retainAll(that);
+ }
+ override def size = underlying.size;
+ override def isEmpty = underlying.isEmpty;
+ override def clear = underlying.clear;
+ override def elements : MutableIterator[A] = new IteratorWrapper(underlying.iterator);
+ class IteratorWrapper(underlying : java.util.Iterator) extends MutableIterator[A] {
+ // val underlying = IterableWrapper.this.underlying.iterator;
+ def hasNext = underlying.hasNext;
+ def next = underlying.next.asInstanceOf[A];
+ def remove = underlying.remove;
+ }
+
+}
diff --git a/src/dotnet-library/scala/collection/jcl/LinkedHashMap.scala b/src/dotnet-library/scala/collection/jcl/LinkedHashMap.scala
new file mode 100644
index 0000000000..b86b171fb8
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/LinkedHashMap.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A map that is backed by a Java linked hash map, which fixes iteration
+ * order in terms of insertion order.
+ *
+ * @author Sean McDirmid
+ */
+class LinkedHashMap[K,E](override val underlying: java.util.LinkedHashMap) extends MapWrapper[K,E] {
+ def this() = this(new java.util.LinkedHashMap);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/LinkedHashSet.scala b/src/dotnet-library/scala/collection/jcl/LinkedHashSet.scala
new file mode 100644
index 0000000000..3bd26a8b5b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/LinkedHashSet.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A set that is backed by a Java linked hash set, which fixes iteration
+ * order in terms of insertion order.
+ *
+ * @author Sean McDirmid
+ */
+class LinkedHashSet[A](override val underlying: java.util.LinkedHashSet) extends CollectionWrapper[A] with SetWrapper[A] {
+ def this() = this(new java.util.LinkedHashSet);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/LinkedList.scala b/src/dotnet-library/scala/collection/jcl/LinkedList.scala
new file mode 100644
index 0000000000..b744e72f79
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/LinkedList.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Creates a buffer backed by a Java linked list. Includes additional
+ * peek/poll/removeFirst/removeLast APIs that are useful in implementing
+ * queues and stacks.
+ *
+ * @author Sean McDirmid
+ */
+class LinkedList[A](override val underlying : java.util.LinkedList) extends CollectionWrapper[A] with BufferWrapper[A] {
+ def this() = this(new java.util.LinkedList);
+ override def elements = super[BufferWrapper].elements;
+ override def add(idx : Int, a : A) =
+ if (idx == 0) underlying.addFirst(a);
+ else super.add(idx, a);
+ //def peek = underlying.peek.asInstanceOf[A];
+ //def poll = underlying.poll.asInstanceOf[A];
+ //def removeFirst = underlying.removeFirst.asInstanceOf[A];
+ //def removeLast = underlying.removeLast.asInstanceOf[A];
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Map.scala b/src/dotnet-library/scala/collection/jcl/Map.scala
new file mode 100644
index 0000000000..1546831d23
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Map.scala
@@ -0,0 +1,97 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A mutable map that is compatible with Java maps.
+ *
+ * @author Sean McDirmid
+ */
+trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutable.Map[K,E] {
+ override def clear() = super[MutableIterable].clear;
+ override def isEmpty = super[MutableIterable].isEmpty;
+ override def keySet : Set[K] = new KeySet;
+ override final def keys = keySet.elements;
+ /** The values of this map as a projection, which means
+ removals from the returned collection will remove the element from this map.
+ @returns a projection of this map's elements. */
+ def valueSet : MutableIterable[E] = pmap(._2);
+ def put(key : K, elem : E) : Option[E];
+ def putAll(that : Iterable[Tuple2[K,E]]) : Unit =
+ that.foreach(p => put(p._1, p._2));
+ def remove(key : K) : Option[E] = {
+ val i = elements;
+ while (!i.hasNext) {
+ val result = i.next;
+ if (result._1 == key) {
+ i.remove;
+ return Some(result._2);
+ }
+ }
+ return None;
+ }
+ override def has(pair : Tuple2[K,E]) = get(pair._1) match {
+ case Some(e) if e == pair._2 => true;
+ case _ => false;
+ }
+ override def get(key : K) = elements.find(p => p._1 == key).map(._2);
+ override def update(key : K, e : E) : Unit = put(key,e);
+ override def +(pair : Tuple2[K,E]) : this.type = {
+ put(pair._1,pair._2); this;
+ }
+ override def +=(pair : Tuple2[K,E]) : Unit = put(pair._1, pair._2);
+ override def -(key : K) : this.type = {
+ remove(key); this;
+ }
+ override def -=(key : K) : Unit = remove(key);
+ override def elements : MutableIterator[Tuple2[K,E]];
+ /** Produces a filtered projection of this map that includes only entries of the map
+ * whose keys are true with respect to predicate "p."
+ */
+ def pfilter(p : K => Boolean) : jcl.Map[K,E] = new Filter(p);
+ /**
+ */
+ def lense[F](f : E => F, g : F => E) : jcl.Map[K,F] = new Lense[F](f,g);
+
+ protected class Lense[F](f : E => F, g : F => E) extends jcl.Map[K,F] {
+ override def elements = Map.this.elements.map(k => Tuple2(k._1, f(k._2)));
+ override def remove(key : K) = Map.this.remove(key).map(f);
+ override def put(key : K, elem : F) = Map.this.put(key, g(elem)).map(f);
+ override def get(key : K) = Map.this.get(key).map(f);
+ override def pfilter(p : K => Boolean) : jcl.Map[K,F] =
+ Map.this.pfilter(p).lense(f, g);
+ override def lense[G](f0 : F => G, g0 : G => F) : jcl.Map[K,G] =
+ Map.this.lense[G](x => f0(f(x)), y => g(g0(y)));
+ }
+ protected class Filter(p : K => Boolean) extends jcl.Map[K,E] {
+ override def elements = Map.this.elements.filter(k => p(k._1));
+ override def remove(key : K) = {
+ if (!p(key)) throw new IllegalArgumentException;
+ Map.this.remove(key);
+ }
+ override def contains(key : K) = p(key) && Map.this.contains(key);
+ override def put(key : K, elem : E) = {
+ if (!p(key)) throw new IllegalArgumentException;
+ Map.this.put(key, elem);
+ }
+ override def get(key : K) = {
+ if (!p(key)) None;
+ else Map.this.get(key);
+ }
+ override def pfilter(p0 : K => Boolean) : jcl.Map[K,E] =
+ Map.this.pfilter(k => p(k) && p0(k));
+ }
+ protected class KeySet extends Set[K] {
+ override def add(k : K) = Map.this.put(k, default(k)) == None;
+ override def elements = Map.this.elements.map(._1);
+ override def has(k : K) = Map.this.contains(k);
+ }
+
+}
diff --git a/src/dotnet-library/scala/collection/jcl/MapWrapper.scala b/src/dotnet-library/scala/collection/jcl/MapWrapper.scala
new file mode 100644
index 0000000000..80b219c95c
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/MapWrapper.scala
@@ -0,0 +1,66 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A wrapper around a Java map.
+ *
+ * @author Sean McDirmid
+ */
+trait MapWrapper[K,E] extends jcl.Map[K,E] {
+ protected def underlying : java.util.Map;
+ override def size = underlying.size;
+ override def isEmpty = underlying.isEmpty;
+ override def clear() = underlying.clear;
+ override def put(key : K, elem : E) = {
+ if (elem == null) throw new IllegalArgumentException;
+ val ret = underlying.put(key,elem);
+ if (ret == null) None else Some(ret.asInstanceOf[E]);
+ }
+ override def get(key : K) : Option[E] = {
+ val ret = underlying.get(key);
+ if (ret == null) None else Some(ret.asInstanceOf[E]);
+ }
+
+ override def putAll(that : Iterable[Tuple2[K,E]]) : Unit = that match {
+ case that : MapWrapper[_,_] => underlying.putAll(that.underlying);
+ case _ => super.putAll(that);
+ }
+ override def remove(key : K) = {
+ val ret = underlying.remove(key);
+ if (ret == null) None else Some(ret.asInstanceOf[E]);
+ }
+ override def contains(key : K) = underlying.containsKey(key);
+ override def keySet : Set[K] = new KeySet;
+ override def valueSet : MutableIterable[E] = new ValueSet;
+ override def elements : MutableIterator[Tuple2[K,E]] = new IteratorWrapper;
+ class IteratorWrapper extends MutableIterator[Tuple2[K,E]] {
+ val underlying = MapWrapper.this.underlying.entrySet.iterator;
+ def hasNext = underlying.hasNext;
+ def remove = underlying.remove;
+ def next = {
+ val next = underlying.next.asInstanceOf[java.util.Map.Entry];
+ Tuple2(next.getKey.asInstanceOf[K],next.getValue.asInstanceOf[E]);
+ }
+ }
+ class KeySet extends super.KeySet with SetWrapper[K] {
+ protected val underlying = MapWrapper.this.underlying.keySet;
+ }
+ class ValueSet extends IterableWrapper[E] {
+ val underlying = MapWrapper.this.underlying.values;
+ override def has(e : E) = MapWrapper.this.underlying.containsValue(e);
+ }
+ override def toString = underlying.toString;
+ override def hashCode = underlying.hashCode;
+ override def equals(that : Any) = that match {
+ case that: MapWrapper[_,_] => underlying == that.underlying;
+ case _ => super.equals(that);
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/MutableIterable.scala b/src/dotnet-library/scala/collection/jcl/MutableIterable.scala
new file mode 100644
index 0000000000..75f6b01717
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/MutableIterable.scala
@@ -0,0 +1,80 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/**
+ * An iterable collection that supports remove operations.
+ * Useful for representing projections of mutable collections that where only
+ * the remove operation makes sense.
+ *
+ * @author Sean McDirmid
+ */
+trait MutableIterable[A] extends Iterable[A] {
+ /** @return true if t is in the collection.
+ **/
+ def has(t : A ) : Boolean = elements.has(t);
+ /** @return true if t was removed from this collection.
+ **/
+ def remove(t : A ) : Boolean = elements.remove(t);
+ /** @return true if any element in that was removed from this collection.
+ **/
+ def removeAll(that : Iterable[A]) : Boolean = {
+ var changed = false;
+ that.foreach(t => changed = elements.remove(t) || changed);
+ changed;
+ }
+ /** Operator shortcut for removeAll. */
+ def --(that : Iterable[A]) : this.type = {
+ removeAll(that); this;
+ }
+
+ /** @return the collection that t was removed from.
+ **/
+ def -(t : A) : this.type = { remove(t); this; }
+ /** retain only elements in the collection that predicate p is true for.
+ **/
+ def retain(p : A => Boolean) : Unit = elements.retain(p);
+ /** retain only elements that are also in that.
+ **/
+ def retainAll(that : Iterable[A]) : Boolean = elements.retain(s => that.exists(t => t == s));
+ /** @return true if the element has no elements.
+ **/
+ def isEmpty : Boolean = !elements.hasNext;
+ /** @return the current number of elements in the collection.
+ **/
+ def size : Int = {
+ var count = 0;
+ val i = elements;
+ while (i.hasNext) { count = count + 1; i.next; }
+ count;
+ }
+ /** clear all elements from the collection.
+ **/
+ def clear(): Unit = {
+ val i = elements;
+ while (i.hasNext) {
+ i.next; i.remove;
+ }
+ }
+ /** Creates a non-strict map of this collection. Any removals from the returned
+ ** collection will remove from this collection, while any changes to this collection will also be
+ ** reflected in the mapped collection.
+ ** @return a non-strict map of this collection.
+ **/
+ def pmap[B](f : A => B) : MutableIterable[B] = new Map[B](f);
+ /** The default implementation of a map over mutable iterable collections.
+ **/
+ protected class Map[B](f : A => B) extends MutableIterable[B] {
+ override def elements = MutableIterable.this.elements.map(f);
+ override def toString = elements.toList.mkString("{", ", ", "}");
+ }
+ override def elements : MutableIterator[A];
+}
diff --git a/src/dotnet-library/scala/collection/jcl/MutableIterator.scala b/src/dotnet-library/scala/collection/jcl/MutableIterator.scala
new file mode 100644
index 0000000000..fadb45e5f5
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/MutableIterator.scala
@@ -0,0 +1,100 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** An iterator that supports the remove operation.
+ * These iterators wrap Java iterators, and so have the same fail fast
+ * behavior when dealing with concurrent modifications.
+ *
+ * @author Sean McDirmid
+ */
+trait MutableIterator[A] extends Iterator[A] {
+ def remove : Unit;
+
+ override def filter(f : A => Boolean) : MutableIterator[A] = {
+ val buffered = this.buffered0;
+ new buffered.Filter(f);
+ }
+
+ override def map[B](f: A => B) : MutableIterator[B] = new Map(f);
+ /** A type-safe version of contains.
+ **/
+ def has(a: A) = exists(b => a == a);
+
+ /** Finds and removes the first instance of "a" through the iterator.
+ * After execution, the iterator's cursor is located where the removed
+ * element existed.
+ *
+ * @param a ..
+ * @return <code>false</code> if "a" is not encountered in the iterator
+ * and the iterator's cursor is located at the end of its elements.
+ */
+ def remove(a: A): Boolean = {
+ while (hasNext)
+ if (next == a) { remove; return true; }
+ return false;
+ }
+ /** Removes all elements in the iterator that predicate "p" returns false on.
+ **/
+ def retain(p : A => Boolean) : Boolean = {
+ var changed = false;
+ while (hasNext)
+ if (!p(next)) { remove; changed = true; }
+ changed;
+ }
+
+ private[jcl] def buffered0 : MutableIterator[A]#Buffered = new BufferedImpl;
+
+ /** Standard implementation of a mapped iterator. **/
+ class Map[B](f : A => B) extends MutableIterator[B] {
+ def hasNext = MutableIterator.this.hasNext;
+ def next = f(MutableIterator.this.next);
+ def remove = MutableIterator.this.remove;
+ }
+
+ private[jcl] trait Buffered extends MutableIterator[A] {
+ private[jcl] override def buffered0 : this.type = this;
+ private[jcl] def peekNext : A;
+ private[jcl] def seekNext(f : A => Boolean) : Option[A] = {
+ while (hasNext && !f(peekNext)) next;
+ if (hasNext) Some(peekNext) else None;
+ }
+ class Filter(p : A => Boolean) extends MutableIterator[A] {
+ private[jcl] def peekNext = Buffered.this.seekNext(p) match {
+ case Some(result) => result;
+ case None => throw new NoSuchElementException;
+ }
+ override def next = {
+ val ret = peekNext; val ret0 = Buffered.this.next; assert(ret == ret0); ret;
+ }
+ override def hasNext : Boolean = seekNext(p) != None;
+ override def remove : Unit = Buffered.this.remove;
+ }
+ }
+
+ private[jcl] class BufferedImpl extends Buffered {
+ protected var head : A = _;
+ protected def underlying = MutableIterator.this;
+ private[jcl] def peekNext = {
+ if (head == null) head = underlying.next;
+ head;
+ }
+ override def hasNext = head != null || underlying.hasNext;
+ override def next = {
+ val ret = peekNext; head = null.asInstanceOf[A]; ret;
+ }
+ override def remove = {
+ if (head != null) throw new NoSuchElementException;
+ underlying.remove;
+ }
+ override def toString = "buffered[" + underlying + "]";
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/MutableSeq.scala b/src/dotnet-library/scala/collection/jcl/MutableSeq.scala
new file mode 100644
index 0000000000..a84f248966
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/MutableSeq.scala
@@ -0,0 +1,82 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A mutable sequence that supports the remove operation and is ordered.
+ *
+ * @author Sean McDirmid
+ */
+trait MutableSeq[A] extends MutableIterable[A] with Seq[A] {
+ override def elements : SeqIterator[Int,A];
+
+ override def isEmpty = super[MutableIterable].isEmpty;
+
+ override def length = size;
+
+ override def apply(idx : Int) = elements.seek(idx);
+
+ def pfilter(p : A => Boolean) : MutableSeq[A] = new Filter(p);
+
+ override def pmap[B](f : A => B) : MutableSeq[B] = new Map[B](f);
+
+ /** Find the index of "a" in this sequence.
+ * @returns None if the "a" is not in this sequence.
+ */
+ def indexOf(a : A) = elements.indexOf(a);
+
+ protected class Filter(p : A => Boolean) extends MutableSeq[A] {
+ def elements : SeqIterator[Int,A] = new FilterIterator(MutableSeq.this.elements);
+ class FilterIterator(underlying : SeqIterator[Int,A]) extends SeqIterator[Int,A] {
+ private var index = 0;
+ protected def seekNext : Option[A] = {
+ while (underlying.hasNext) {
+ val next = underlying.next;
+ if (p(next)) return Some(next);
+ }
+ return None;
+ }
+ protected def seekPrevious : Option[A] = {
+ while (underlying.hasPrevious) {
+ val previous = underlying.previous;
+ if (p(previous)) return Some(previous);
+ }
+ return None;
+ }
+ def hasNext : Boolean = seekNext match {
+ case None => false;
+ case Some(_) => underlying.previous; true;
+ }
+ def nextIndex = index;
+ def next = seekNext match {
+ case None => throw new NoSuchElementException;
+ case Some(result) => index = index + 1; result;
+ }
+ def hasPrevious : Boolean = seekPrevious match {
+ case None => false;
+ case Some(_) => underlying.previous; true;
+ }
+ def previousIndex = {
+ if (index == 0) throw new NoSuchElementException;
+ index - 1;
+ }
+ def previous = seekPrevious match {
+ case None => throw new NoSuchElementException;
+ case Some(result) => index = index - 1; result;
+ }
+ def remove = underlying.remove;
+ }
+ }
+
+ protected class Map[B](f : A => B) extends super.Map[B](f) with MutableSeq[B] {
+ override def elements = MutableSeq.this.elements.map(f);
+ override def apply(idx : Int) = f(MutableSeq.this.apply(idx));
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Ranged.scala b/src/dotnet-library/scala/collection/jcl/Ranged.scala
new file mode 100644
index 0000000000..51c5aba6a4
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Ranged.scala
@@ -0,0 +1,62 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Sorted.scala 9621 2007-01-17 14:29:25Z michelou $
+
+package scala.collection.jcl;
+
+/** Any collection (including maps) whose keys (or elements) are ordered.
+ *
+ * @author Sean McDirmid
+ */
+trait Ranged[K,A] extends MutableIterable[A] {
+ protected type SortedSelf <: Ranged[K,A];
+
+ /** Returns the first key of the collection. */
+ def first: K;
+
+ /** Returns the last key of the collection. */
+ def last: K;
+
+ /** Comparison function that orders keys. */
+ def compare(k0: K, k1: K): Int;
+
+ /** Creates a ranged projection of this collection. Any mutations in the
+ * ranged projection will update this collection and vice versa. Note: keys
+ * are not garuanteed to be consistent between this collection and the projection.
+ * This is the case for buffers where indexing is relative to the projection.
+ *
+ * @param from The lower-bound (inclusive) of the ranged projection.
+ * <code>None</code> if there is no lower bound.
+ * @param until The upper-bound (exclusive) of the ranged projection.
+ * <code>None</code> if there is no upper bound.
+ */
+ def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf;
+ /** Creates a ranged projection of this collection with no upper-bound.
+ ** @param from The lower-bound (inclusive) of the ranged projection.
+ **/
+ final def from(from: K): SortedSelf = rangeImpl(Some(from), None);
+ /** Creates a ranged projection of this collection with no lower-bound.
+ ** @param until The upper-bound (exclusive) of the ranged projection.
+ **/
+ final def until(until: K): SortedSelf = rangeImpl(None, Some(until));
+
+ /** Creates a ranged projection of this collection with both a lower-bound and an upper-bound.
+ ** @param from The upper-bound (exclusive) of the ranged projection.
+ **/
+ final def range(from: K, until: K) : SortedSelf = rangeImpl(Some(from),Some(until));
+
+ /** A wrapper around Java comparators. */
+ protected class Comparator[K <% Ordered[K]] extends java.util.Comparator {
+ def compare(x0 : Any, x1 : Any) = {
+ val k0 = x0.asInstanceOf[K];
+ val k1 = x1.asInstanceOf[K];
+ k0.compare(k1);
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SeqIterator.scala b/src/dotnet-library/scala/collection/jcl/SeqIterator.scala
new file mode 100644
index 0000000000..5461928735
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SeqIterator.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** An iterator for a sequence that can move both forwards and backwards.
+ * over a set of ordered keys.
+ *
+ * @author Sean McDirmid
+ */
+trait SeqIterator[K,A] extends MutableIterator[A] {
+ /** @returns The index at the iterator's cursor. */
+ def nextIndex: K;
+
+ /** @returns The index of the element before the iterator's cursor. */
+ def previousIndex: K;
+
+ /** @return The previous element, will move the iterator's cursor backwards. */
+ def previous: A;
+
+ /** @return True if and only if the iterator's cursor is not at the beging of the iteration. */
+ def hasPrevious : Boolean;
+
+ /** Winds the iteration forward until index "idx" is found */
+ def seek(idx: K) = {
+ while (nextIndex != idx) next;
+ next;
+ }
+ /** finds the index of the next "a" in this iteration.
+ *
+ * @param a ..
+ * @return <code>None</code> if "a" is not found in the iteration.
+ */
+ def indexOf(a: A): Option[K] = {
+ while (hasNext) {
+ val ret = next;
+ if (ret == a) return Some(previousIndex);
+ }
+ return None;
+ }
+
+ override def map[B](f: A => B) : SeqIterator[K,B] = new Map[B](f);
+ class Map[B](f: A => B) extends super.Map[B](f) with SeqIterator[K,B] {
+ override def hasPrevious = SeqIterator.this.hasPrevious;
+ override def previous = f(SeqIterator.this.previous);
+ override def previousIndex = SeqIterator.this.previousIndex;
+ override def nextIndex = SeqIterator.this.nextIndex;
+ override def map[C](g : B => C) : SeqIterator[K,C] =
+ SeqIterator.this.map(a => g(f(a)));
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Set.scala b/src/dotnet-library/scala/collection/jcl/Set.scala
new file mode 100644
index 0000000000..08d4013bd4
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Set.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Analogous to a Java set.
+ *
+ * @author Sean McDirmid
+ */
+trait Set[A] extends Collection[A] with scala.collection.mutable.Set[A] {
+
+ /** Add will return false if "a" already exists in the set. **/
+ override def add(a : A) : Boolean;
+
+ override def ++(i : Iterable[A]) : this.type = super[Collection].++(i);
+ override def --(i : Iterable[A]) : this.type = super[Collection].--(i);
+ override def +(t : A) : this.type = super[Collection].+(t);
+ override def -(t : A) : this.type = super[Collection].-(t);
+ override def retain(f : A => Boolean) = super[Collection].retain(f);
+ override def isEmpty = super[Collection].isEmpty;
+ override final def contains(a : A) = has(a);
+ override def clear() = super.clear()
+
+ override def transform(f : A => A) = {
+ var toAdd : List[A] = Nil;
+ val i = elements;
+ while (i.hasNext) {
+ val i0 = i.next;
+ val i1 = f(i0);
+ if (i0 != i1) {
+ i.remove; toAdd = i1 :: toAdd;
+ }
+ }
+ addAll(toAdd);
+ }
+
+ override def pfilter(p : A => Boolean) : Set[A] = new Filter(p);
+ class Filter(p : A => Boolean) extends super.Filter(p) with Set[A] {
+ override def filter(p : A => Boolean): scala.collection.mutable.Set[A] = {
+ super[Set].retain(p)
+ this
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SetWrapper.scala b/src/dotnet-library/scala/collection/jcl/SetWrapper.scala
new file mode 100644
index 0000000000..18f7e342b2
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SetWrapper.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Used to wrap Java sets.
+ *
+ * @author Sean McDirmid
+ */
+trait SetWrapper[A] extends CollectionWrapper[A] with Set[A] {
+ protected def underlying: java.util.Set;
+ override def isEmpty = super[CollectionWrapper].isEmpty;
+ override def clear() = super[CollectionWrapper].clear;
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Sorted.scala b/src/dotnet-library/scala/collection/jcl/Sorted.scala
new file mode 100644
index 0000000000..c9ff2b3990
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Sorted.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Any collection (including maps) whose keys (or elements) are ordered.
+ *
+ * @author Sean McDirmid
+ */
+trait Sorted[K,A] extends Ranged[K,A] {
+ override protected type SortedSelf <: Sorted[K,A];
+ /** return as a projection the set of keys in this collection */
+ def keySet : SortedSet[K];
+
+ /** Creates a ranged projection of this collection. Any mutations in the
+ * ranged projection will update this collection and vice versa. Keys
+ * are garuanteed to be consistent between the collection and its projection.
+ *
+ * @param from The lower-bound (inclusive) of the ranged projection.
+ * <code>None</code> if there is no lower bound.
+ * @param until The upper-bound (exclusive) of the ranged projection.
+ * <code>None</code> if there is no upper bound.
+ */
+ override def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf;
+
+ /** Create a range projection of this collection with no lower-bound.
+ ** @param to The upper-bound (inclusive) of the ranged projection.
+ **/
+ final def to(to : K): SortedSelf = {
+ // tough!
+ val i = keySet.from(to).elements;
+ if (!i.hasNext) return this.asInstanceOf[SortedSelf];
+ val next = i.next;
+ if (next == to) {
+ if (!i.hasNext) return this.asInstanceOf[SortedSelf];
+ else return until(i.next);
+ } else return until(next);
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SortedMap.scala b/src/dotnet-library/scala/collection/jcl/SortedMap.scala
new file mode 100644
index 0000000000..1449addf3b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SortedMap.scala
@@ -0,0 +1,90 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A map whose keys are sorted.
+ *
+ * @author Sean McDirmid
+ */
+trait SortedMap[K,E] extends Map[K,E] with Sorted[K,Tuple2[K,E]] {
+ final protected type SortedSelf = SortedMap[K,E];
+ override def compare(k0 : K, k1 : K) : Int;
+ override def first : K = elements.next._1;
+ override def last : K = {
+ val i = elements;
+ var last : K = i.next._1;
+ while (i.hasNext) last = i.next._1;
+ last;
+ }
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = Range(from, until);
+ override def keySet : SortedSet[K] = new KeySet;
+ override def pfilter(p : K => Boolean) : SortedMap[K,E] = new Filter(p);
+ override def lense[F](f : E => F, g : F => E) : jcl.SortedMap[K,F] = new Lense[F](f,g);
+
+ protected class Lense[F](f : E => F, g : F => E) extends super.Lense[F](f,g) with SortedMap[K,F] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1);
+ override def pfilter(p : K => Boolean) : jcl.SortedMap[K,F] =
+ SortedMap.this.pfilter(p).lense(f, g);
+ override def lense[G](f0 : F => G, g0 : G => F) : jcl.SortedMap[K,G] =
+ SortedMap.this.lense[G]({x:E => f0(f(x))}, {y:G => g(g0(y))});
+ override def rangeImpl(from : Option[K], until : Option[K]) =
+ SortedMap.this.rangeImpl(from,until).lense(f,g);
+ }
+ protected class KeySet extends super.KeySet with SortedSet[K] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ override def first = SortedMap.this.first;
+ override def last = SortedMap.this.last;
+ override def rangeImpl(from : Option[K], until : Option[K]) =
+ SortedMap.this.rangeImpl(from,until).keySet;
+ }
+ protected class SuperFilter(p : K => Boolean) extends super.Filter(p);
+ protected class Filter(p : K => Boolean) extends SuperFilter(p) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ override def pfilter(p0 : K => Boolean) : SortedMap[K,E] =
+ SortedMap.this.pfilter(k => p(k) && p0(k));
+
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] =
+ SortedMap.this.Range(from, until).pfilter(p);
+ }
+
+ protected def Range(from : Option[K], until : Option[K]) : SortedMap[K,E] = new Range(from,until);
+ protected class Range(from : Option[K], until : Option[K]) extends SuperFilter(key => {
+ ((from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0)));
+ }) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1);
+ private def contains0(key : K) =
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+
+ override def contains(key : K) = SortedMap.this.contains(key) && contains0(key);
+ override def get(key : K) = if (!contains0(key)) None else SortedMap.this.get(key);
+ override def put(key : K, elem : E) = {
+ if (!contains0(key)) throw new IllegalArgumentException;
+ SortedMap.this.put(key, elem);
+ }
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = {
+ if (this.from != None && from == None) return rangeImpl(this.from, until);
+ if (this.until != None && until == None) return rangeImpl(from, this.until);
+ if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until);
+ if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until);
+ SortedMap.this.Range(from, until);
+ }
+ override def pfilter(p : K => Boolean) : SortedMap[K,E] = new Filter(p);
+ protected class Filter(p : K => Boolean) extends SuperFilter(p) with SortedMap[K,E] {
+ def compare(k0 : K, k1 : K) = Range.this.compare(k0, k1);
+ override def pfilter(p0 : K => Boolean) =
+ Range.this.pfilter(key => p(key) && p0(key));
+ override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] =
+ Range.this.rangeImpl(from,until).pfilter(p);
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SortedMapWrapper.scala b/src/dotnet-library/scala/collection/jcl/SortedMapWrapper.scala
new file mode 100644
index 0000000000..62af69cfb0
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SortedMapWrapper.scala
@@ -0,0 +1,39 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A sorted map that wraps an underlying Java sorted map.
+ *
+ * @author Sean McDirmid
+ */
+trait SortedMapWrapper[K,E] extends SortedMap[K,E] with MapWrapper[K,E] {
+ protected override def underlying : java.util.SortedMap;
+ /** the comparator function of this sorted map is defined in terms
+ * of the underlying sorted map's comparator.
+ */
+ def compare(k0 : K, k1 : K) = underlying.comparator.compare(k0,k1);
+ override def first = underlying.firstKey.asInstanceOf[K];
+ override def last = underlying.lastKey.asInstanceOf[K];
+ override def keySet : SortedSet[K] = new KeySet;
+ override protected def Range(from : Option[K], until : Option[K]) = new Range(from,until);
+ protected class Range(from : Option[K], until : Option[K]) extends super.Range(from,until) with SortedMapWrapper[K,E] {
+ val underlying = Tuple2(from,until) match {
+ case Tuple2(None,None) => throw new IllegalArgumentException;
+ case Tuple2(Some(from),None) => SortedMapWrapper.this.underlying.tailMap(from);
+ case Tuple2(None,Some(until)) => SortedMapWrapper.this.underlying.headMap(until);
+ case Tuple2(Some(from),Some(until)) => SortedMapWrapper.this.underlying.subMap(from,until);
+ }
+ override def compare(k0 : K, k1 : K) = super[SortedMapWrapper].compare(k0, k1);
+ }
+ protected class KeySet extends super[SortedMap].KeySet with SetWrapper[K] {
+ protected val underlying = SortedMapWrapper.this.underlying.keySet;
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SortedSet.scala b/src/dotnet-library/scala/collection/jcl/SortedSet.scala
new file mode 100644
index 0000000000..729c778106
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SortedSet.scala
@@ -0,0 +1,75 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Analogous to a Java sorted set.
+ *
+ * @author Sean McDirmid
+ */
+trait SortedSet[A] extends jcl.Set[A] with Sorted[A,A] {
+ final protected type SortedSelf = SortedSet[A];
+ override def keySet = this;
+ def compare(a0 : A, a1 : A) : Int;
+ def first : A = {
+ val i = elements;
+ if (i.hasNext) i.next;
+ else throw new NoSuchElementException;
+ }
+ def last : A = {
+ var last : A = null.asInstanceOf[A];
+ val i = elements;
+ while (i.hasNext) last = i.next;
+ if (last == null) throw new NoSuchElementException;
+ else last;
+ }
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from, until);
+ override def pfilter(p : A => Boolean) : SortedSet[A] = new Filter(p);
+ protected class Filter(p : A => Boolean) extends super.Filter(p) with SortedSet[A] {
+ def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1);
+ }
+
+ protected class Range(from : Option[A], until : Option[A]) extends Filter(key => {
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+ }) with SortedSet[A] {
+ if (from == None && until == None) throw new IllegalArgumentException;
+ if (from != None && until != None && !(SortedSet.this.compare(from.get, until.get) < 0))
+ throw new IllegalArgumentException;
+ override def elements : MutableIterator[A] =
+ new RangeIterator(SortedSet.this.elements.buffered0);
+ private def contains1(key : A) =
+ (from == None || (compare(from.get,key) <= 0)) &&
+ (until == None || (compare(key,until.get) < 0));
+ override def has(elem : A) = contains1(elem) && SortedSet.this.has(elem);
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = {
+ if (this.from != None && from == None) return rangeImpl(this.from, until);
+ if (this.until != None && until == None) return rangeImpl(from, this.until);
+ if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until);
+ if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until);
+ SortedSet.this.rangeImpl(from, until);
+ }
+ class RangeIterator(underlying : MutableIterator[A]#Buffered) extends MutableIterator[A] {
+ if (from != None)
+ underlying.seekNext(a => compare(from.get, a) <= 0);
+
+ private def okNext(a : A) =
+ if (until == None) true;
+ else compare(a, until.get) < 0;
+
+ def hasNext = underlying.hasNext && okNext(underlying.peekNext);
+ def next = underlying.seekNext(okNext) match {
+ case Some(result) => underlying.next; result;
+ case None => throw new NoSuchElementException;
+ }
+ def remove = underlying.remove;
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/SortedSetWrapper.scala b/src/dotnet-library/scala/collection/jcl/SortedSetWrapper.scala
new file mode 100644
index 0000000000..7e1af55690
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/SortedSetWrapper.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** <p>
+ * A wrapper around a Java sorted set.
+ * </p>
+ * <p>
+ * The comparator of the sorted set matches the comparator of this set.
+ * </p>
+ *
+ * @author Sean McDirmid
+ */
+trait SortedSetWrapper[A] extends SortedSet[A] with SetWrapper[A] {
+ protected def underlying : java.util.SortedSet;
+ /** delegates to the comparator of the underlying Java sorted set */
+ override def compare(a0 : A, a1 : A) = underlying.comparator.compare(a0, a1);
+ override def first = underlying.first.asInstanceOf[A];
+ override def last = underlying.last .asInstanceOf[A];
+ override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from,until);
+ protected class Range(from : Option[A], until : Option[A]) extends super.Range(from, until) with SortedSetWrapper[A] {
+ val underlying = Tuple2(from,until) match {
+ case Tuple2(None,Some(until)) => SortedSetWrapper.this.underlying.headSet(until);
+ case Tuple2(Some(from),None) => SortedSetWrapper.this.underlying.tailSet(from);
+ case Tuple2(Some(from),Some(until)) => SortedSetWrapper.this.underlying.subSet(from,until);
+ case _ => throw new IllegalArgumentException;
+ }
+ override def elements : MutableIterator[A] = super[SortedSetWrapper].elements;
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/Tests.scala b/src/dotnet-library/scala/collection/jcl/Tests.scala
new file mode 100644
index 0000000000..779a04e399
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/Tests.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+private[jcl] object Tests {
+
+ def main(args : Array[String]) : Unit = {
+ hashSet;
+ treeSet;
+ treeMap;
+ }
+
+ def treeSet : Unit = {
+ val set = new TreeSet[String];
+ set + "aaa" + "bbb" + "ccc" + "ddd" + "eee" + "fff";
+ Console.println(set);
+ val rset : SortedSet[String] = set.range("b", "e");
+ Console.println(rset);
+ rset + "bad";
+ Console.println(rset);
+ Console.println(set);
+ val fset : SortedSet[String] = rset.pfilter(.endsWith("d"));
+ Console.println(fset);
+ fset += "cd";
+ Console.println(set);
+ set.pmap(.length).retain(x => x == 3);
+ Console.println(set);
+ Console.println(rset);
+ Console.println(fset);
+ }
+
+ def treeMap : Unit = {
+ val map = new TreeMap[String,Integer];
+ map + ("bb" -> 3) + ("cc" -> 4) + ("aa" -> 2) + ("dd" -> 5);
+ //Console.println(map);
+ val rmap : SortedMap[String,Integer] = map.range("b", "d");
+ rmap + ("bad" -> 10);
+ Console.println(rmap);
+ //Console.println(map);
+ val fmap : SortedMap[String,Integer] = rmap.pfilter(k => k.length == 2);
+ Console.println(fmap);
+ }
+
+ def hashSet = {
+ val set = new HashSet[String];
+ set + "hello" + "world" + "you" + "to";
+ Console.println(set);
+ val fset = set.pfilter(s => s.length <= 3);
+ Console.println(fset);
+ fset += "xxx";
+ Console.println(set);
+ try {
+ fset += "xxxx";
+ throw new Error;
+ } catch {
+ case e : IllegalArgumentException =>
+ case _ => throw new Error;
+ }
+ val mset : MutableIterable[Int] = set.pmap(s => s.length);
+ Console.println(mset);
+ mset.retain(n => n < 5);
+ Console.println(set);
+ val set1 = new HashSet[String] + "1" + "2" + "3";
+ set ++ (set1);
+ Console.println(set);
+ set.transform(s => "x_" + s);
+ Console.println(set);
+ }
+}
diff --git a/src/dotnet-library/scala/collection/jcl/TreeMap.scala b/src/dotnet-library/scala/collection/jcl/TreeMap.scala
new file mode 100644
index 0000000000..403ee6c5cf
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/TreeMap.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** A sorted map that is backed by a Java tree map.
+ *
+ * @author Sean McDirmid
+ */
+class TreeMap[K <% Ordered[K],E] extends SortedMapWrapper[K,E] {
+ val underlying = (new java.util.TreeMap(new Comparator[K]));
+}
diff --git a/src/dotnet-library/scala/collection/jcl/TreeSet.scala b/src/dotnet-library/scala/collection/jcl/TreeSet.scala
new file mode 100644
index 0000000000..4ce84fa79e
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/TreeSet.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** Creates a sorted set that is backed by an underlying Java tree set. Elements
+ * of the sorted set are ordered with respect to the ordered view bound of A.
+ *
+ * @author Sean McDirmid
+ */
+class TreeSet[A <% Ordered[A]] extends CollectionWrapper[A] with SortedSetWrapper[A] {
+ val underlying = new java.util.TreeSet(new Comparator[A]);
+}
diff --git a/src/dotnet-library/scala/collection/jcl/WeakHashMap.scala b/src/dotnet-library/scala/collection/jcl/WeakHashMap.scala
new file mode 100644
index 0000000000..c2d6239a80
--- /dev/null
+++ b/src/dotnet-library/scala/collection/jcl/WeakHashMap.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.jcl;
+
+/** <p>
+ * A map that is backed by a Java weak hash map, whose keys are maintained
+ * as weak references.
+ * </p>
+ * <p>
+ * Because keys are weak references, the garbage collector can collect
+ * them if they are not referred to elsewhere.
+ * </p>
+ * <p>
+ * Useful for implementing caches.
+ * </p>
+ *
+ * @author Sean McDirmid
+ */
+class WeakHashMap[K,E](override val underlying: java.util.WeakHashMap) extends MapWrapper[K,E] {
+ def this() = this(new java.util.WeakHashMap);
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ArrayBuffer.scala b/src/dotnet-library/scala/collection/mutable/ArrayBuffer.scala
new file mode 100644
index 0000000000..e506e95994
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ArrayBuffer.scala
@@ -0,0 +1,178 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+import Predef._
+
+/** An implementation of the <code>Buffer</code> class using an array to
+ * represent the assembled sequence internally.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 15/03/2004
+ */
+[serializable]
+class ArrayBuffer[A] extends Buffer[A] with ResizableArray[A] {
+
+ /** Appends a single element to this buffer and returns
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit = {
+ ensureSize(size+1)
+ array(size) = elem
+ size = size + 1
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ override def ++=(iter: Iterable[A]): Unit = iter copyToBuffer this
+
+ /** Appends a number of elements in an array
+ *
+ * @param src the array
+ * @param start the first element to append
+ * @param len the number of elements to append
+ */
+ override def ++=(src: Array[A], start: int, len: int): Unit = {
+ ensureSize(size + len)
+ Array.copy(src, start, array, size, len)
+ size = size + len
+ }
+
+ /** Prepends a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ * @return the updated buffer.
+ */
+ def +:(elem: A): Buffer[A] = {
+ ensureSize(size+1)
+ copy(0, 1, size)
+ array(0) = elem
+ size = size + 1
+ this
+ }
+
+ /** Returns the i-th element of this ArrayBuffer.
+ *
+ * @param i the specified index.
+ * @return the i-th element.
+ * @throws Predef.IndexOutOfBoundException if <code>i</code> is out of bounds.
+ */
+ override def apply(i: Int) = {
+ if ((i < 0) || (i >= size))
+ throw new IndexOutOfBoundsException(i.toString())
+ else
+ array(i)
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = { insertAll(0, iter); this }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit = {
+ if ((n < 0) || (n > size))
+ throw new IndexOutOfBoundsException("cannot insert element at " + n);
+ val xs = iter.elements.toList
+ val len = xs.length
+ ensureSize(size+len)
+ copy(n, n + len, size - n)
+ xs.copyToArray(array, n)
+ size = size + len
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def update(n: Int, newelem: A): Unit = {
+ if ((n < 0) || (n >= size))
+ throw new IndexOutOfBoundsException("cannot update element at " + n);
+ else {
+ val res = array(n)
+ array(n) = newelem
+ res
+ }
+ }
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ * @return the updated array buffer.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def remove(n: Int): A = {
+ if ((n < 0) || (n >= size))
+ throw new IndexOutOfBoundsException("cannot remove element at " + n);
+ val res = array(n);
+ copy(n + 1, n, size - n - 1);
+ size = size - 1;
+ res
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear(): Unit = {
+ size = 0
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = {
+ val res = new ArrayBuffer[A]
+ res ++= this
+ res
+ }
+
+ /** Checks if two buffers are structurally identical.
+ *
+ * @return true, iff both buffers contain the same sequence of elements.
+ */
+ override def equals(obj: Any): Boolean = obj match {
+ case that: ArrayBuffer[_] =>
+ this.length == that.length &&
+ elements.zip(that.elements).forall {
+ case {thiselem, thatelem} => thiselem == thatelem
+ }
+ case _ =>
+ false
+ }
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "ArrayBuffer"
+}
diff --git a/src/dotnet-library/scala/collection/mutable/BitSet.scala b/src/dotnet-library/scala/collection/mutable/BitSet.scala
new file mode 100644
index 0000000000..610b86e3ee
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/BitSet.scala
@@ -0,0 +1,100 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/**
+ * The class <code>BitSet</code> implements mutable, resizable Bit sets
+ *
+ * @author Burak Emir, Nikolay Mihaylov
+ * @version 1.1
+ *
+ * @param initSize: initial size in bits
+ */
+
+[serializable]
+class BitSet(initSize: Int) extends collection.BitSet with Set[Int] {
+
+ import compat.Platform.arraycopy
+
+ /** default constructor, initial size of 512 bits. */
+ def this() = this(0)
+
+ /** Ensures that this bitset can store at least <code>n</code> bits.
+ *
+ * @param n ...
+ */
+ def ensureCapacity(n: Int): Unit =
+ if (capacity < n) {
+ if (nbits(arr.length) < n) {
+ val newn = memsize(n)
+ var newsize = if (arr.length == 0) newn else arr.length * 2
+ while (newn > newsize)
+ newsize = newsize * 2;
+ val newarr = new Array[Int](newsize)
+ arraycopy(arr, 0, newarr, 0, arr.length)
+ arr = newarr
+ }
+ capacity = n
+ }
+
+ /**
+ * Sets <code>i-th</code> bit to true.
+ * No restriction on <code>i</code>
+ */
+ def +=(i: Int): Unit = {
+ ensureCapacity(i+1)
+ val oldInt = arr(offset(i))
+ val newInt = oldInt | mask(i)
+ if (oldInt != newInt) {
+ arr(offset(i)) = newInt
+ size = size + 1
+ }
+ }
+
+ /** Clears the <code>i</code>-th bit.
+ *
+ * @param i the <code>i</code>-th element of the bit set.
+ */
+ def -=(i: Int): Unit = {
+ if (i >= capacity) return;
+ val oldInt = arr(offset(i))
+ val newInt = oldInt & ~mask(i)
+ if (oldInt != newInt) {
+ arr(offset(i)) = newInt
+ size = size - 1
+ }
+ }
+
+ /** Clears all bits of the set.
+ */
+ override def clear(): Unit = {
+ java.util.Arrays.fill(arr, 0)
+ size = 0
+ }
+
+ def toImmutable: collection.immutable.BitSet =
+ new immutable.BitSet(size, capacity, arr, true)
+
+ override def clone(): BitSet = new BitSet(capacity) {
+ arraycopy(BitSet.this.arr, 0, arr, 0, arr.length)
+ size = BitSet.this.size
+ capacity = BitSet.this.capacity
+ }
+
+ var size: Int = 0
+
+ var capacity: Int = initSize
+
+ protected var arr: Array[Int] = new Array[Int](memsize(initSize))
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Buffer.scala b/src/dotnet-library/scala/collection/mutable/Buffer.scala
new file mode 100644
index 0000000000..fac9603438
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Buffer.scala
@@ -0,0 +1,245 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+import Predef._
+
+/** Buffers are used to create sequences of elements incrementally by
+ * appending, prepending, or inserting new elements. It is also
+ * possible to access and modify elements in a random access fashion
+ * via the index of the element in the current sequence.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 02/03/2004
+ */
+[cloneable]
+trait Buffer[A] extends AnyRef
+ with Seq[A]
+ with Scriptable[Message[{Location, A}]]
+{
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +(elem: A): Buffer[A] = { this += elem; this }
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +:(elem: A): Buffer[A]
+
+ /** Appends a number of elements provided by an iterator
+ *
+ * @param iter the iterator.
+ */
+ def ++=(iter: Iterator[A]): Unit = iter foreach +=
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def ++=(iter: Iterable[A]): Unit = ++=(iter.elements)
+
+ /** Appends a number of elements in an array
+ *
+ * @param src the array
+ * @param start the first element to append
+ * @param len the number of elements to append
+ */
+ def ++=(src: Array[A], start: int, len: int): Unit = {
+ var i = start
+ val end = i + len
+ while (i < end) {
+ this += src(i)
+ i = i + 1
+ }
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ def ++(iter: Iterable[A]): Buffer[A] = { this ++= iter; this }
+
+ /** Appends a number of elements provided by an iterator
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterator
+ * @return the updated buffer.
+ */
+ def ++(iter: Iterator[A]): Buffer[A] = { this ++= iter; this }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def ++:(iter: Iterable[A]): Buffer[A] = {
+ iter.elements.toList.reverse.foreach(e => e +: this)
+ this
+ }
+
+ /** Removes a single element from this buffer, at its first occurrence.
+ * If the list does not contain that element, it is unchanged
+ *
+ * @param x the element to remove.
+ */
+ def -= (x: A): Unit = {
+ val i = indexOf(x)
+ if(i != -1) remove(i)
+ }
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ def append(elems: A*): Unit = this ++= elems
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def appendAll(iter: Iterable[A]): Unit = this ++= iter
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ def prepend(elems: A*): Unit = elems ++: this
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def prependAll(iter: Iterable[A]): Unit = iter ++: this
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ def insert(n: Int, elems: A*): Unit = insertAll(n, elems)
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ def remove(n: Int): A
+
+ /** Removes the first <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the beginning
+ * of this buffer.
+ */
+ def trimStart(n: Int): Unit = {
+ var i = n
+ while (i > 0) { remove(0); i = i - 1 }
+ }
+
+ /** Removes the last <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the end
+ * of this buffer.
+ */
+ def trimEnd(n: Int): Unit = {
+ var i = n
+ while (i > 0) { remove(length - 1); i = i - 1 }
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear(): Unit
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ def <<(cmd: Message[{Location, A}]): Unit = cmd match {
+ case Include({l, elem}) => l match {
+ case Start => prepend(elem)
+ case End => append(elem)
+ case Index(n) => insert(n, elem)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Update({l, elem}) => l match {
+ case Start => update(0, elem)
+ case End => update(length - 1, elem)
+ case Index(n) => update(n, elem)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Remove({l, _}) => l match {
+ case Start => remove(0)
+ case End => remove(length - 1)
+ case Index(n) => remove(n)
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+ case Reset() => clear
+ case s: Script[_] => s.elements foreach <<
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return a buffer with the same elements.
+ */
+ override def clone(): Buffer[A] = super.clone().asInstanceOf[Buffer[A]]
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use buffers as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = throw new UnsupportedOperationException("unsuitable as hash key")
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "Buffer"
+}
diff --git a/src/dotnet-library/scala/collection/mutable/BufferProxy.scala b/src/dotnet-library/scala/collection/mutable/BufferProxy.scala
new file mode 100644
index 0000000000..adf7162954
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/BufferProxy.scala
@@ -0,0 +1,154 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This is a simple proxy class for <a href="Buffer.html"
+ * target="contentFrame"><code>scala.collection.mutable.Buffer</code></a>.
+ * It is most useful for assembling customized set abstractions
+ * dynamically using object composition and forwarding.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 16/04/2004
+ */
+trait BufferProxy[A] extends Buffer[A] with Proxy {
+
+ def self: Buffer[A]
+
+ def length: Int = self.length
+
+ def elements: Iterator[A] = self.elements
+
+ def apply(n: Int): A = self.apply(n)
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ * @return the updated buffer.
+ */
+ override def +(elem: A): Buffer[A] = self.+(elem)
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit = self.+=(elem)
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ * @return the updated buffer.
+ */
+ override def ++(iter: Iterable[A]): Buffer[A] = self.++(iter)
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++=(iter: Iterable[A]): Unit = self.++=(iter)
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ override def append(elems: A*): Unit = self.++=(elems)
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def appendAll(iter: Iterable[A]): Unit = self.appendAll(iter)
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +:(elem: A): Buffer[A] = self.+:(elem)
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = self.++:(iter)
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ override def prepend(elems: A*): Unit = self.prependAll(elems)
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def prependAll(elems: Iterable[A]): Unit = self.prependAll(elems)
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ override def insert(n: Int, elems: A*): Unit = self.insertAll(n, elems)
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit = self.insertAll(n, iter)
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit = self.update(n, newelem)
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ def remove(n: Int): A = self.remove(n)
+
+ /** Clears the buffer contents.
+ */
+ def clear(): Unit = self.clear
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ override def <<(cmd: Message[{Location, A}]): Unit = self << cmd
+
+ /** Return a clone of this buffer.
+ *
+ * @return a <code>Buffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = new BufferProxy[A] {
+ def self = BufferProxy.this.self.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/DefaultEntry.scala b/src/dotnet-library/scala/collection/mutable/DefaultEntry.scala
new file mode 100755
index 0000000000..876319a15d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/DefaultEntry.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: DefaultMapModel.scala 9554 2007-01-04 16:30:16 +0000 (Thu, 04 Jan 2007) odersky $
+
+
+package scala.collection.mutable
+
+import Predef._
+
+[serializable]
+final class DefaultEntry[A, B](val key: A, var value: B)
+ extends HashEntry[A, DefaultEntry[A, B]]
diff --git a/src/dotnet-library/scala/collection/mutable/DefaultMapModel.scala b/src/dotnet-library/scala/collection/mutable/DefaultMapModel.scala
new file mode 100644
index 0000000000..9bf8b803b5
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/DefaultMapModel.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+import Predef._
+
+/** This class is used internally. It implements the mutable <code>Map</code>
+ * class in terms of three functions: <code>findEntry</code>,
+ * <code>addEntry</code>, and <code>entries</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait DefaultMapModel[A, B] extends Map[A, B] {
+
+ type Entry = DefaultEntry[A, B]
+
+ protected def findEntry(key: A): Entry
+ protected def addEntry(e: Entry)
+ protected def entries: Iterator[Entry]
+
+ def get(key: A): Option[B] = {
+ val e = findEntry(key)
+ if (e == null) None
+ else Some(e.value);
+ }
+
+ def update(key: A, value: B) {
+ val e = findEntry(key)
+ if (e == null) addEntry(new Entry(key, value))
+ else e.value = value
+ }
+
+ def elements = entries map {e => {e.key, e.value}}
+}
+
diff --git a/src/dotnet-library/scala/collection/mutable/DoubleLinkedList.scala b/src/dotnet-library/scala/collection/mutable/DoubleLinkedList.scala
new file mode 100644
index 0000000000..5ed7a5dbb8
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/DoubleLinkedList.scala
@@ -0,0 +1,53 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This extensible class may be used as a basis for implementing double
+ * linked lists. Type variable <code>A</code> refers to the element type
+ * of the list, type variable <code>This</code> is used to model self
+ * types of linked lists.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+abstract class DoubleLinkedList[A, This >: Null <: DoubleLinkedList[A, This]]
+ requires This
+ extends SingleLinkedList[A, This]
+{
+
+ var prev: This
+
+ override def append(that: This): Unit =
+ if (that eq null)
+ ()
+ else if (next eq null) {
+ next = that
+ that.prev = this
+ } else
+ next.append(that)
+
+ override def insert(that: This): Unit = if (that ne null) {
+ that.append(next)
+ next = that
+ that.prev = this
+ }
+
+ def remove: Unit = {
+ if (next ne null)
+ next.prev = prev
+ if (prev ne null)
+ prev.next = next
+ prev = null
+ next = null
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/FlatHashTable.scala b/src/dotnet-library/scala/collection/mutable/FlatHashTable.scala
new file mode 100755
index 0000000000..6bb6af59f3
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/FlatHashTable.scala
@@ -0,0 +1,148 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2006 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: HashSet.scala 9235 2006-11-13 14:59:18 +0000 (Mon, 13 Nov 2006) mihaylov $
+
+package scala.collection.mutable
+
+import Predef._
+
+trait FlatHashTable[A] {
+
+ /** The load factor for the hash table; must be < 0.5f
+ */
+ protected def loadFactor: Float = 0.45f
+
+ /** The initial size of the hash table.
+ */
+ protected def initialSize: Int = 16
+
+ /** The actual hash table.
+ */
+ protected var table: Array[AnyRef] =
+ if (initialSize == 0) null else new Array(initialSize)
+
+ /** The number of mappings contained in this hash table.
+ */
+ protected var tableSize = 0
+
+ /** The next size value at which to resize (capacity * load factor).
+ */
+ protected var threshold: Int = newThreshold(initialSize)
+
+ /** Returns the number of entires in this hash table.
+ */
+ def size: Int = tableSize
+
+ def findEntry(elem: A): Option[A] = {
+ var h = index(elemHashCode(elem))
+ var entry = table(h)
+ while (null != entry && entry != elem) {
+ h = (h + 1) % table.length
+ entry = table(h)
+ }
+ if (null == entry) None else Some(entry.asInstanceOf[A])
+ }
+
+ def containsEntry(elem: A): Boolean = {
+ var h = index(elemHashCode(elem))
+ var entry = table(h)
+ while (null != entry && entry != elem) {
+ h = (h + 1) % table.length
+ entry = table(h)
+ }
+ null != entry
+ }
+
+ def addEntry(elem: A) {
+ var h = index(elemHashCode(elem))
+ var entry = table(h)
+ while (null != entry) {
+ if (entry == elem) return
+ h = (h + 1) % table.length
+ entry = table(h)
+ }
+ table(h) = elem.asInstanceOf[AnyRef]
+ tableSize = tableSize + 1
+ if (tableSize >= threshold) growTable()
+ }
+
+ def removeEntry(elem: A) {
+ def precedes(i: int, j: int) = {
+ val d = table.length >> 2
+ if (i <= j) j - i < d
+ else i - j > d
+ }
+ var h = index(elemHashCode(elem))
+ var entry = table(h)
+ while (null != entry) {
+ if (entry == elem) {
+ var h0 = h
+ var h1 = (h0 + 1) % table.length
+ while (null != table(h1)) {
+ val h2 = index(elemHashCode(table(h1).asInstanceOf[A]))
+ //Console.println("shift at "+h1+":"+table(h1)+" with h2 = "+h2+"?")
+ if (h2 != h1 && precedes(h2, h0)) {
+ //Console.println("shift "+h1+" to "+h0+"!")
+ table(h0) = table(h1)
+ h0 = h1
+ }
+ h1 = (h1 + 1) % table.length
+ }
+ table(h0) = null
+ tableSize = tableSize - 1
+ return
+ }
+ h = (h + 1) % table.length
+ entry = table(h)
+ }
+ }
+
+ def elements = new Iterator[A] {
+ private var i = 0
+ def hasNext: Boolean = {
+ while (i < table.length && (null == table(i))) i = i + 1;
+ i < table.length
+ }
+ def next: A =
+ if (hasNext) { i = i + 1; table(i - 1).asInstanceOf[A] }
+ else Iterator.empty.next
+ }
+
+ private def growTable() {
+ val oldtable = table
+ table = new Array[AnyRef](table.length * 2)
+ tableSize = 0
+ threshold = newThreshold(table.length)
+ var i = 0
+ while (i < oldtable.length) {
+ val entry = oldtable(i)
+ if (null != entry) addEntry(entry.asInstanceOf[A])
+ i = i + 1
+ }
+ }
+
+ protected def elemHashCode(elem: A) = elem.hashCode()
+
+ protected final def improve(hcode: Int) = {
+ var h: Int = hcode + ~(hcode << 9)
+ h = h ^ (h >>> 14)
+ h = h + (h << 4)
+ h ^ (h >>> 10)
+ }
+
+ protected final def index(hcode: Int) = improve(hcode) & (table.length - 1)
+
+ private def newThreshold(size: Int) = {
+ val lf = loadFactor
+ assert(lf < 0.5f, "loadFactor too large; must be < 0.5")
+ (size * lf).asInstanceOf[Int]
+ }
+
+ protected def clear() {
+ var i = table.length - 1
+ while (i >= 0) { table(i) = null; i = i - 1 }
+ tableSize = 0
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/HashMap.scala b/src/dotnet-library/scala/collection/mutable/HashMap.scala
new file mode 100644
index 0000000000..59a8b8a860
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/HashMap.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+import Predef._
+
+/** This class implements mutable maps using a hashtable.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+object HashMap {
+
+ /** The empty map of this type */
+ def empty[A, B] = new HashMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+[serializable]
+class HashMap[A, B] extends Map[A,B] with HashTable[A] with DefaultMapModel[A,B] {
+
+ def -= (key: A) { removeEntry(key) }
+
+ override def clear() = super.clear()
+
+ override def clone(): Map[A, B] = new HashMap[A, B] ++ this
+}
diff --git a/src/dotnet-library/scala/collection/mutable/HashSet.scala b/src/dotnet-library/scala/collection/mutable/HashSet.scala
new file mode 100644
index 0000000000..c1c6096fa9
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/HashSet.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+/** This class implements mutable sets using a hashtable.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+object HashSet {
+
+ /** The empty map of this type */
+ def empty[A] = new HashSet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A](elems: A*) = empty[A] ++ elems
+}
+
+[serializable]
+class HashSet[A] extends Set[A] with FlatHashTable[A] {
+
+ def contains(elem: A): Boolean = containsEntry(elem)
+
+ def +=(elem: A) { addEntry(elem) }
+
+ def -=(elem: A) { removeEntry(elem) }
+
+ override def clear() = super.clear()
+
+ override def clone(): Set[A] = new HashSet[A] ++ this
+}
+
diff --git a/src/dotnet-library/scala/collection/mutable/HashTable.scala b/src/dotnet-library/scala/collection/mutable/HashTable.scala
new file mode 100644
index 0000000000..e82a27e506
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/HashTable.scala
@@ -0,0 +1,168 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+/** This class can be used to construct data structures that are based
+ * on hashtables. Class <code>HashTable[A]</code> implements a hashtable
+ * that maps keys of type <code>A</code> to values of the fully abstract
+ * member type <code>Entry</code>. Classes that make use of <code>HashTable</code>
+ * have to provide an implementation for <code>Entry</code>
+ *
+ * There are mainly two parameters that affect the performance of a hashtable:
+ * the <i>initial size</i> and the <i>load factor</i>. The <i>size</i>
+ * refers to the number of <i>buckets</i> in the hashtable, and the <i>load
+ * factor</i> is a measure of how full the hashtable is allowed to get before
+ * its size is automatically doubled. Both parameters may be changed by
+ * overriding the corresponding values in class <code>HashTable</code>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+trait HashTable[A] extends AnyRef {
+
+ protected type Entry >: Null <: HashEntry[A, Entry]
+
+ /** The load factor for the hash table.
+ */
+ protected def loadFactor: Float = 0.75f
+
+ /** The initial size of the hash table.
+ */
+ protected def initialSize: Int = 16
+
+ /** The initial threshold
+ */
+ protected val initialThreshold: Int = newThreshold(initialSize)
+
+ /** The actual hash table.
+ */
+ protected var table: Array[Entry] =
+ if (initialSize == 0) null else new Array(initialSize)
+
+ /** The number of mappings contained in this hash table.
+ */
+ protected var tableSize: Int = 0
+
+ /** The next size value at which to resize (capacity * load factor).
+ */
+ protected var threshold: Int = initialThreshold
+
+ /** Returns the size of this hash table.
+ */
+ def size = tableSize
+
+ protected def findEntry(key: A): Entry = {
+ val h = index(elemHashCode(key))
+ var e = table(h)
+ while (e != null && !elemEquals(e.key, key)) e = e.next
+ e
+ }
+
+ protected def addEntry(e: Entry) {
+ val h = index(elemHashCode(e.key))
+ e.next = table(h)
+ table(h) = e
+ tableSize = tableSize + 1
+ if (tableSize > threshold)
+ resize(2 * table.length)
+ }
+
+ protected def removeEntry(key: A) {
+ val h = index(elemHashCode(key))
+ var e = table(h)
+ if (e != null) {
+ if (elemEquals(e.key, key)) {
+ table(h) = e.next
+ tableSize = tableSize - 1
+ } else {
+ var e1 = e.next
+ while (e1 != null && !elemEquals(e1.key, key)) {
+ e = e1
+ e1 = e1.next
+ }
+ if (e1 != null) {
+ e.next = e1.next
+ tableSize = tableSize - 1
+ }
+ }
+ }
+ }
+
+ protected def entries: Iterator[Entry] = new Iterator[Entry] {
+ val iterTable = table
+ var idx = table.length - 1
+ var es = iterTable(idx)
+ scan()
+ def hasNext = es != null
+ def next = {
+ val res = es
+ es = es.next
+ scan()
+ res
+ }
+ def scan() {
+ while (es == null && idx > 0) {
+ idx = idx - 1
+ es = iterTable(idx)
+ }
+ }
+ }
+
+ def clear() {
+ var i = table.length - 1
+ while (i >= 0) { table(i) = null; i = i - 1 }
+ tableSize = 0
+ }
+
+ private def newThreshold(size: Int) =
+ (size * loadFactor).asInstanceOf[Int]
+
+ private def resize(newSize: Int) = {
+ val oldTable = table
+ table = new Array(newSize)
+ var i = oldTable.length - 1
+ while (i >= 0) {
+ var e = oldTable(i)
+ while (e != null) {
+ val h = index(elemHashCode(e.key))
+ val e1 = e.next
+ e.next = table(h)
+ table(h) = e
+ e = e1
+ }
+ i = i - 1
+ }
+ threshold = newThreshold(newSize)
+ }
+
+ protected def elemEquals(key1: A, key2: A): Boolean = (key1 == key2)
+
+ protected def elemHashCode(key: A) = key.hashCode()
+
+ protected final def improve(hcode: Int) = {
+ var h: Int = hcode + ~(hcode << 9)
+ h = h ^ (h >>> 14)
+ h = h + (h << 4)
+ h ^ (h >>> 10)
+ }
+
+ protected final def index(hcode: Int) = improve(hcode) & (table.length - 1)
+}
+
+trait HashEntry[A, E] {
+ val key: A
+ var next: E = _
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/mutable/History.scala b/src/dotnet-library/scala/collection/mutable/History.scala
new file mode 100644
index 0000000000..dbafbf29dc
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/History.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** <code>History[A, B]</code> objects may subscribe to events of
+ * type <code>A</code> published by an object of type <code>B</code>.
+ * The history subscriber object records all published events
+ * up to maximum number of <code>maxHistory</code> events.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class History[A, B] extends AnyRef with Subscriber[A, B] with Iterable[{B, A}] {
+
+ protected val log: Queue[{B, A}] = new Queue[{B, A}]
+
+ val maxHistory: Int = 1000
+
+ /**
+ * @param pub ...
+ * @param event ...
+ */
+ def notify(pub: B, event: A): Unit = {
+ if (log.length >= maxHistory) {
+ val old = log.dequeue;
+ }
+ log.enqueue({pub, event})
+ }
+
+ def elements: Iterator[{B, A}] = log.elements
+
+ def events: Iterator[A] = log.elements.map { case {_, e} => e }
+
+ def size: Int = log.length
+
+ def clear(): Unit = log.clear
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/dotnet-library/scala/collection/mutable/ImmutableMapAdaptor.scala
new file mode 100644
index 0000000000..9328f19629
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ImmutableMapAdaptor.scala
@@ -0,0 +1,65 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class can be used as an adaptor to create mutable maps from
+ * immutable map implementations. Only method <code>empty</code> has
+ * to be redefined if the immutable map on which this mutable map is
+ * originally based is not empty. <code>empty</code> is supposed to
+ * return the representation of an empty map.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 01/01/2007
+ */
+[serializable]
+class ImmutableMapAdaptor[A, B](protected var imap: immutable.Map[A, B])
+extends Map[A, B]
+{
+
+ def size: Int = imap.size
+
+ def get(key: A): Option[B] = imap.get(key)
+
+ override def isEmpty: Boolean = imap.isEmpty
+
+ override def apply(key: A): B = imap.apply(key)
+
+ override def contains(key: A): Boolean = imap.contains(key)
+
+ override def isDefinedAt(key: A) = imap.isDefinedAt(key)
+
+ override def keys: Iterator[A] = imap.keys
+
+ override def keySet: collection.Set[A] = imap.keySet
+
+ override def values: Iterator[B] = imap.values
+
+ def elements: Iterator[{A, B}] = imap.elements
+
+ override def toList: List[{A, B}] = imap.toList
+
+ def update(key: A, value: B): Unit = { imap = imap.update(key, value) }
+
+ def -= (key: A): Unit = { imap = imap - key }
+
+ override def clear(): Unit = { imap = imap.empty }
+
+ override def transform(f: (A, B) => B): Unit = { imap = imap.transform(f) }
+
+ override def retain(p: (A, B) => Boolean): Unit = {
+ imap = imap.filter(xy => p(xy._1, xy._2))
+ }
+
+ override def toString() = imap.toString()
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/dotnet-library/scala/collection/mutable/ImmutableSetAdaptor.scala
new file mode 100644
index 0000000000..5c0b766303
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ImmutableSetAdaptor.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class can be used as an adaptor to create mutable sets from
+ * immutable set implementations. Only method <code>empty</code> has
+ * to be redefined if the immutable set on which this mutable set is
+ * originally based is not empty. <code>empty</code> is supposed to
+ * return the representation of an empty set.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+[serializable]
+class ImmutableSetAdaptor[A](protected var set: immutable.Set[A]) extends Set[A] {
+
+ def size: Int = set.size
+
+ override def isEmpty: Boolean = set.isEmpty
+
+ def contains(elem: A): Boolean = set.contains(elem)
+
+ override def foreach(f: A => Unit): Unit = set.foreach(f)
+
+ override def exists(p: A => Boolean): Boolean = set.exists(p)
+
+ override def toList: List[A] = set.toList
+
+ override def toString() = set.toString()
+
+ def elements: Iterator[A] = set.elements
+
+ def +=(elem: A): Unit = { set = set + elem }
+
+ def -=(elem: A): Unit = { set = set - elem }
+
+ override def clear(): Unit = { set = set.empty }
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/JavaMapAdaptor.scala b/src/dotnet-library/scala/collection/mutable/JavaMapAdaptor.scala
new file mode 100644
index 0000000000..825758b64b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/JavaMapAdaptor.scala
@@ -0,0 +1,68 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class can be used as an adaptor to create mutable maps from
+ * Java classes that implementat the <code>java.util.Map</code> interface.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+class JavaMapAdaptor[A, B](jmap: java.util.Map) extends Map[A, B] {
+
+ def size: Int = jmap.size()
+
+ def get(key: A): Option[B] =
+ if (jmap.containsKey(key)) Some(jmap.get(key).asInstanceOf[B]) else None
+
+ override def isEmpty: Boolean = jmap.isEmpty()
+
+ override def apply(key: A): B = jmap.get(key).asInstanceOf[B]
+
+ override def contains(key: A): Boolean = jmap.containsKey(key)
+
+ override def isDefinedAt(key: A) = jmap.containsKey(key)
+
+ override def keys: Iterator[A] = new Iterator[A] {
+ val iter = jmap.keySet().iterator()
+ def hasNext = iter.hasNext()
+ def next = iter.next().asInstanceOf[A]
+ }
+
+ override def values: Iterator[B] = new Iterator[B] {
+ val iter = jmap.values().iterator()
+ def hasNext = iter.hasNext()
+ def next = iter.next().asInstanceOf[B]
+ }
+
+ def elements: Iterator[{A, B}] = new Iterator[{A, B}] {
+ val iter = jmap.keySet().iterator()
+ def hasNext = iter.hasNext()
+ def next = {
+ val key = iter.next().asInstanceOf[A]
+ {key, apply(key)}
+ }
+ }
+
+ def update(key: A, value: B): Unit = { val x = jmap.put(key, value); }
+
+ def -= (key: A): Unit = { val x = jmap.remove(key); }
+
+ override def clear(): Unit = jmap.clear()
+
+ override def clone(): Map[A, B] = {
+ val res = new HashMap[A, B]
+ res ++= this
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/JavaSetAdaptor.scala b/src/dotnet-library/scala/collection/mutable/JavaSetAdaptor.scala
new file mode 100644
index 0000000000..45c49d58d7
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/JavaSetAdaptor.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class can be used as an adaptor to create mutable sets from
+ * Java classes that implement interface <code>java.util.Set</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 19/09/2003
+ */
+class JavaSetAdaptor[A](jset: java.util.Set) extends Set[A] {
+
+ def size: Int = jset.size()
+
+ override def isEmpty: Boolean = jset.isEmpty()
+
+ def contains(elem: A): Boolean = jset.contains(elem)
+
+ def elements: Iterator[A] = new Iterator[A] {
+ val iter = jset.iterator()
+ def hasNext = iter.hasNext()
+ def next = iter.next().asInstanceOf[A]
+ }
+
+ def +=(elem: A): Unit = { val x = jset.add(elem); }
+
+ def -=(elem: A): Unit = { val x = jset.remove(elem); }
+
+ override def clear(): Unit = jset.clear()
+
+ override def clone(): Set[A] = {
+ val res = new HashSet[A]
+ res ++= this
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/LinkedHashSet.scala b/src/dotnet-library/scala/collection/mutable/LinkedHashSet.scala
new file mode 100644
index 0000000000..e38a7151e9
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/LinkedHashSet.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2005-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.mutable
+
+/** This class...
+ *
+ * @author Sean McDirmid
+ * @version 1.0
+ */
+class LinkedHashSet[A](private val set0 : java.util.LinkedHashSet) extends Set[A] {
+
+ def this() = this(new java.util.LinkedHashSet)
+
+ private def this(set1 : java.util.Set, b : Boolean) =
+ this(new java.util.LinkedHashSet(set1))
+
+ def contains(elem: A): Boolean = set0.contains(elem)
+
+ def +=(elem: A): Unit = set0.add(elem)
+
+ def ++=(set: LinkedHashSet[A]) = set0.addAll(set.set0)
+ def --=(set: LinkedHashSet[A]) = set0.removeAll(set.set0)
+
+ def -=(elem: A): Unit = set0.remove(elem)
+
+ def elements = new Iterator[A] {
+ val i = set0.iterator
+ def hasNext = i.hasNext()
+ def next = i.next().asInstanceOf[A]
+ }
+
+ override def clear() = set0.clear()
+
+ def size = set0.size()
+
+ override def toString() = set0.toString()
+
+ override def clone(): Set[A] = {
+ val res = new LinkedHashSet[A](set0, true)
+ res ++= this
+ res
+ }
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/LinkedList.scala b/src/dotnet-library/scala/collection/mutable/LinkedList.scala
new file mode 100644
index 0000000000..80bebc4775
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/LinkedList.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+/** This class implements single linked lists where both the head (<code>elem</code>)
+ * and the tail (<code>next</code>) are mutable.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class LinkedList[A](var elem: A, var next: LinkedList[A])
+ extends SingleLinkedList[A, LinkedList[A]]
+{
+
+ override def equals(obj: Any): Boolean =
+ obj.isInstanceOf[LinkedList[A]] &&
+ toList.equals((obj.asInstanceOf[LinkedList[A]]).toList)
+
+ override protected def stringPrefix: String = "LinkedList"
+}
+
+
+
diff --git a/src/dotnet-library/scala/collection/mutable/ListBuffer.scala b/src/dotnet-library/scala/collection/mutable/ListBuffer.scala
new file mode 100644
index 0000000000..2f4b95f55f
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ListBuffer.scala
@@ -0,0 +1,283 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+import Predef._
+
+/** The class <code>ListBuffer</code> ..
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 15/03/2004
+ */
+final class ListBuffer[A] extends Buffer[A] {
+ private var start: List[A] = Nil
+ private var last: ::[A] = _
+ private var exported: boolean = false
+
+ /** Prepends a single element to this buffer.
+ *
+ * @param x the element to prepend.
+ * @return this buffer.
+ */
+ def +: (x: A): Buffer[A] = {
+ if (exported) copy()
+ val newElem = new scala.:: (x, start)
+ if (start.isEmpty) last = newElem
+ start = newElem
+ this
+ }
+
+ /** Appends a single element to this buffer.
+ *
+ * @param x the element to append.
+ */
+ override def += (x: A): unit = {
+ if (exported) copy()
+ if (start.isEmpty) {
+ last = new scala.:: (x, Nil)
+ start = last
+ } else {
+ val last1 = last
+ last = new scala.:: (x, Nil)
+ last1.tl = last
+ }
+ }
+
+ /** Removes a single element from the buffer and return
+ * the identity of the buffer. Same as <code>this -= x; this</code>
+ *
+ * @param x the element to remove.
+ * @return this buffer.
+ */
+ def - (x: A): Buffer[A] = { this -= x; this }
+
+ /** Remove a single element from this buffer.
+ *
+ * @param x the element to remove.
+ */
+ override def -= (x: A): unit = {
+ if (exported) copy()
+ if (start.isEmpty) {}
+ else if (start.head == x) start = start.tail
+ else {
+ var cursor = start
+ while (!cursor.tail.isEmpty && cursor.tail.head != x) { cursor = cursor.tail }
+ if (!cursor.tail.isEmpty) {
+ val z = cursor.asInstanceOf[scala.::[A]]
+ if(z.tl == last)
+ last = z
+ z.tl = cursor.tail.tail
+ }
+ }
+ }
+
+ /** Converts this buffer to a list
+ */
+ override def toList: List[A] = {
+ exported = !start.isEmpty
+ start
+ }
+
+ /** Prepends the elements of this buffer to a given list
+ *
+ * @param xs the list to which elements are prepended
+ */
+ def prependToList(xs: List[A]): List[A] =
+ if (start.isEmpty) xs
+ else { last.tl = xs; toList }
+
+ /** Clears the buffer contents.
+ */
+ def clear(): unit = {
+ start = Nil
+ exported = false
+ }
+
+ /** Copy contents of this buffer */
+ private def copy() = {
+ var cursor = start
+ val limit = last.tail
+ clear
+ while (cursor ne limit) {
+ this += cursor.head
+ cursor = cursor.tail
+ }
+ }
+
+ /** Returns the length of this buffer.
+ *
+ * @return the length of this buffer.
+ */
+ def length: int = start.length
+
+ /** Returns the n-th element of this list. This method
+ * yields an error if the element does not exist.
+ *
+ * @param n the position of the element to be returned.
+ * @return the n-th element of this buffer.
+ * @throws Predef.IndexOutOfBoundsException
+ */
+ def apply(n: Int): A = try {
+ start(n)
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** Replaces element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param x the new element.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def update(n: Int, x: A): unit = try {
+ if (exported) copy()
+ if (n == 0) {
+ val newElem = new scala.:: (x, start.tail);
+ if (last eq start) last = newElem
+ start = newElem
+ } else {
+ var cursor = start;
+ var i = 1;
+ while (i < n) {
+ cursor = cursor.tail
+ i = i + 1
+ }
+ val newElem = new scala.:: (x, cursor.tail.tail)
+ if (last eq cursor.tail) last = newElem
+ cursor.asInstanceOf[scala.::[A]].tl = newElem
+ }
+ } catch {
+ case ex: Exception => throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a new
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): unit = try {
+ if (exported) copy()
+ var elems = iter.elements.toList.reverse
+ if (n == 0) {
+ while (!elems.isEmpty) {
+ val newElem = new scala.:: (elems.head, start)
+ if (start.isEmpty) last = newElem
+ start = newElem
+ elems = elems.tail
+ }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i = i + 1
+ }
+ while (!elems.isEmpty) {
+ val newElem = new scala.:: (elems.head, cursor.tail)
+ if (cursor.tail.isEmpty) last = newElem
+ cursor.asInstanceOf[scala.::[A]].tl = newElem
+ elems = elems.tail
+ }
+ }
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ * @return n the element that was formerly at position <code>n</code>.
+ * @pre an element exists at position <code>n</code>
+ * @throws Predef.IndexOutOfBoundsException if <code>n</code> is out of bounds.
+ */
+ def remove(n: Int): A = try {
+ if (exported) copy()
+ var old = start.head;
+ if (n == 0) {
+ start = start.tail
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i = i + 1
+ }
+ old = cursor.tail.head
+ if (last eq cursor.tail) last = cursor.asInstanceOf[scala.::[A]]
+ cursor.asInstanceOf[scala.::[A]].tl = cursor.tail.tail
+ }
+ old
+ } catch {
+ case ex: Exception =>
+ throw new IndexOutOfBoundsException(n.toString())
+ }
+
+ /** <p>
+ * Returns an iterator over all elements of this list.
+ * </p>
+ * <blockquote>
+ * Note: the iterator can be affected by insertions, updates and
+ * deletions that are performed afterwards on the buffer. To get
+ * iterator an over the current buffer snapshot, use
+ * <code>toList.elements</code>.
+ * </blockquote>
+ *
+ * @throws Predef.NoSuchElementException if buffer is empty
+ */
+ override def elements = new Iterator[A] {
+ var cursor: List[A] = null
+ def hasNext: Boolean = !start.isEmpty && cursor != last
+ def next: A =
+ if (!hasNext) {
+ throw new NoSuchElementException("next on empty Iterator")
+ } else {
+ if (cursor eq null) cursor = start else cursor = cursor.tail
+ cursor.head
+ }
+ }
+
+ /** Returns a clone of this buffer.
+ *
+ * @return a <code>ListBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this
+
+ /** Checks if two buffers are structurally identical.
+ *
+ * @return <code>true</code>, iff both buffers contain the same sequence
+ * of elements.
+ */
+ override def equals(obj: Any): Boolean = obj match {
+ case that: ListBuffer[_] =>
+ (this.length == that.length &&
+ elements.zip(that.elements).forall {
+ case {thiselem, thatelem} => thiselem == thatelem
+ })
+ case _ =>
+ false
+ }
+
+ /** Defines the prefix of the string representation.
+ *
+ * @return the string representation of this buffer.
+ */
+ override protected def stringPrefix: String = "ListBuffer"
+}
+
diff --git a/src/dotnet-library/scala/collection/mutable/Location.scala b/src/dotnet-library/scala/collection/mutable/Location.scala
new file mode 100644
index 0000000000..efa329f4f1
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Location.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** Class <code>Location</code> describes locations in messages implemented
+ * by class <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+abstract class Location
+
+case object NA extends Location
+
+case object Start extends Location
+
+case object End extends Location
+
+case class Index(n: Int) extends Location
diff --git a/src/dotnet-library/scala/collection/mutable/Map.scala b/src/dotnet-library/scala/collection/mutable/Map.scala
new file mode 100644
index 0000000000..8b0342e5d6
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Map.scala
@@ -0,0 +1,240 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+import Predef._
+
+//import Predef.UnsupportedOperationException
+
+/** This class represents mutable maps. Concrete map implementations
+ * just have to provide functionality for the abstract methods in
+ * <code>scala.collection.Map</code> as well as for <code>update</code>,
+ * and <code>-=</code>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+
+object Map {
+
+ /** The empty map of this type; this is implemented as a hashtable */
+ def empty[A, B]: Map[A, B] = new HashMap[A, B]
+
+ /** The canonical factory for this type
+ */
+ def apply[A, B](elems: {A, B}*) = empty[A, B] ++ elems
+}
+
+[cloneable]
+trait Map[A, B] extends AnyRef
+ with collection.Map[A, B]
+ with Scriptable[Message[{A, B}]]
+{
+ /** This method allows one to add a new mapping from <code>key</code>
+ * to <code>value</code> to the map. If the map already contains a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ *
+ * @param key The key to update
+ * @param value The new value
+ */
+ def update(key: A, value: B)
+
+ /** Add a key/value pair to this map.
+ * @param kv the key/value pair.
+ */
+ def += (kv: {A, B}) { update(kv._1, kv._2) }
+
+ /** Add two or more key/value pairs to this map.
+ * @param kv1 the first key/value pair.
+ * @param kv2 the second key/value pair.
+ * @param kvs the remaining key/value pairs.
+ */
+ def += (kv1: {A, B}, kv2: {A, B}, kvs: {A, B}*) { this += kv1; this += kv2; this ++= kvs }
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterable object containing all key/value pairs.
+ */
+ def ++= (kvs: Iterable[{A, B}]) { this ++= kvs.elements }
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterator containing all key/value pairs.
+ */
+ def ++= (kvs: Iterator[{A, B}]) { kvs foreach += }
+
+ /** Add a key/value pair to this map.
+ * @param kv the key/value pair.
+ * @return The map itself with the new binding added in place.
+ */
+ def + (kv: {A, B}): Map[A, B] = { this += kv; this }
+
+ /** Add two or more key/value pairs to this map.
+ * @param kv1 the first key/value pair.
+ * @param kv2 the second key/value pair.
+ * @param kvs the remaining key/value pairs.
+ * @return The map itself with the new bindings added in place.
+ */
+ def + (kv1: {A, B}, kv2: {A, B}, kvs: {A, B}*): Map[A, B] = {
+ this.+=(kv1, kv2, kvs: _*); this
+ }
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterable object containing all key/value pairs.
+ * @return The itself map with the new bindings added in place.
+ */
+ def ++ (kvs: Iterable[{A, B}]): Map[A, B] = { this ++= kvs; this }
+
+ /** Add a sequence of key/value pairs to this map.
+ * @param kvs the iterator containing all key/value pairs.
+ * @return The itself map with the new bindings added in place.
+ */
+ def ++ (kvs: Iterator[{A, B}]): Map[A, B] = { this ++= kvs; this }
+
+ /** Remove a key from this map, noop if key is not present.
+ * @param key the key to be removed
+ */
+ def -= (key: A)
+
+ /** Remove two or more keys from this map
+ * @param key1 the first key to be removed
+ * @param key2 the second key to be removed
+ * @param keys the remaining keys to be removed
+ */
+ def -= (key1: A, key2: A, keys: A*) { this -= key1; this -= key2; this --= keys }
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ */
+ def --= (keys: Iterable[A]) { this --= keys.elements }
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ */
+ def --= (keys: Iterator[A]) { keys foreach -= }
+
+ /** Remove a key from this map
+ * @param key the key to be removed
+ * @return The map itself with the binding for <code>key</code> removed if
+ * it existed.
+ */
+ def - (key: A): Map[A, B] = { this -= key; this }
+
+ /** Remove two or more keys from this map
+ * @param key1 the first key to be removed
+ * @param key2 the second key to be removed
+ * @param keys the remaining keys to be removed
+ * @return The map itself with all bindings for the given keys removed.
+ */
+ def - (key1: A, key2: A, keys: A*): Map[A, B] = { this.-=(key1, key2, keys: _*); this }
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ * @return The map itself with all bindings for <code>keys</code> removed.
+ */
+ def -- (keys: Iterable[A]): Map[A, B] = { this --= keys; this }
+
+ /** Remove a sequence of keys from this map
+ * @param keys the keys to be removed
+ * @return The map itself with all bindings for <code>keys</code> removed.
+ */
+ def -- (keys: Iterator[A]): Map[A, B] = { this --= keys; this }
+
+ /** Removes all mappings from the map. After this operation is
+ * completed, the map is empty.
+ */
+ def clear(): Unit = keys foreach -=
+
+ /** This function transforms all the values of mappings contained
+ * in this map with function <code>f</code>.
+ *
+ * @param f The transformation to apply
+ */
+ def transform(f: (A, B) => B) {
+ elements foreach {
+ case {key, value} => update(key, f(key, value))
+ }
+ }
+
+ /** This method retains only those mappings for which the predicate
+ * <code>p</code> returns <code>true</code>.
+ *
+ * @param p The test predicate
+ */
+ def retain(p: (A, B) => Boolean): Unit = toList foreach {
+ case {key, value} => if (!p(key, value)) -=(key)
+ }
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ def <<(cmd: Message[{A, B}]): Unit = cmd match {
+ case Include({k, v}) => update(k, v)
+ case Update({k, v}) => update(k, v)
+ case Remove({k, _}) => this -= k
+ case Reset() => clear
+ case s: Script[_] => s.elements foreach <<
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+
+ /** Return a clone of this map.
+ *
+ * @return a map with the same elements.
+ */
+ override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]]
+
+ /** This method defines syntactic sugar for adding or modifying
+ * mappings. It is typically used in the following way:
+ * <pre>
+ * map += key -> value;
+ * </pre>
+ * @deprecated use <code>+={key, value}</code>
+ */
+ [deprecated] def +=(key: A): MapTo = new MapTo(key)
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that a mapping is represented
+ * by a <code>Pair</code> object who's first component denotes the
+ * key, and who's second component refers to the value.
+ *
+ * @param mappings
+ * @deprecated use <code>+=</code>
+ */
+ [deprecated] def incl(mappings: {A, B}*): Unit = this ++= mappings.elements
+
+ /** This method will remove all the mappings for the given sequence
+ * of keys from the map.
+ *
+ * @param keys
+ * @deprecated use <code>-=</code>
+ */
+ [deprecated] def excl(keys: A*): Unit = this --= keys.elements
+
+ /** This method removes all the mappings for which the predicate
+ * <code>p</code> returns <code>false</code>.
+ *
+ * @deprecated use retain instead
+ * @param p
+ */
+ [deprecated] override def filter(p: {A, B} => Boolean): Iterable[{A, B}] = {
+ toList foreach {
+ case kv @ {key, _} => if (!p(kv)) -=(key)
+ }
+ this
+ }
+
+ [deprecated] class MapTo(key: A) {
+ def ->(value: B): Unit = update(key, value)
+ }
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/MapProxy.scala b/src/dotnet-library/scala/collection/mutable/MapProxy.scala
new file mode 100644
index 0000000000..deea498609
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/MapProxy.scala
@@ -0,0 +1,56 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** <p>
+ * This is a simple wrapper class for <a href="Map.html"
+ * target="contentFrame"><code>scala.collection.mutable.Map</code></a>.
+ * </p>
+ * <p>
+ * It is most useful for assembling customized map abstractions
+ * dynamically using object composition and forwarding.
+ * </p>
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+trait MapProxy[A, B] extends Map[A, B] with collection.MapProxy[A, B] {
+
+ def self: Map[A, B]
+
+ override def update(key: A, value: B): Unit = self.update(key, value)
+ override def += (kv: {A, B}) = self += kv
+ override def += (kv1: {A, B}, kv2: {A, B}, kvs: {A, B}*) = self.+=(kv1, kv2, kvs: _*)
+ override def ++= (kvs: Iterable[{A, B}]) = self ++= kvs
+ override def ++= (kvs: Iterator[{A, B}]) = self ++= kvs
+ override def + (kv: {A, B}): Map[A, B] = self + kv
+ override def + (kv1: {A, B}, kv2: {A, B}, kvs: {A, B}*): Map[A, B] = self.+(kv1, kv2, kvs: _*)
+ override def ++ (kvs: Iterable[{A, B}]): Map[A, B] = self ++ kvs
+ override def ++ (kvs: Iterator[{A, B}]): Map[A, B] = self ++ kvs
+ override def -= (key: A) = self -= key
+ override def -= (key1: A, key2: A, keys: A*) = self.-=(key1, key2, keys: _*)
+ override def --= (keys: Iterable[A]) = self --= keys
+ override def --= (keys: Iterator[A]) = self --= keys
+ override def - (key: A): Map[A, B] = self - key
+ override def - (key1: A, key2: A, keys: A*): Map[A, B] = self.-(key1, key2, keys: _*)
+ override def -- (keys: Iterable[A]): Map[A, B] = self -- keys
+ override def -- (keys: Iterator[A]): Map[A, B] = self -- keys
+ override def clear(): Unit = self.clear
+ override def transform(f: (A, B) => B) = self transform f
+ override def retain(p: (A, B) => Boolean): Unit = self retain p
+ override def <<(cmd: Message[{A, B}]): Unit = self << cmd
+ override def clone(): Map[A, B] = self.clone()
+ [deprecated] override def incl(mappings: {A, B}*): Unit = self.incl(mappings: _*)
+ [deprecated] override def excl(keys: A*): Unit = self.excl(keys: _*)
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Message.scala b/src/dotnet-library/scala/collection/mutable/Message.scala
new file mode 100644
index 0000000000..09b3dbd527
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Message.scala
@@ -0,0 +1,82 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+import Predef.UnsupportedOperationException
+
+/** Class <code>Message</code> represents messages that are issued by observable
+ * collection classes whenever a data structure is changed. Class <code>Message</code>
+ * has several subclasses for the various kinds of events: <code>Update</code>
+ * <code>Remove</code>, <code>Include</code>, <code>Reset</code>, and
+ * <code>Script</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Message[+A]
+
+/** This observable update refers to inclusion operations that add new elements
+ * to collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Include[+I](elem: I) extends Message[I]
+
+/** This observable update refers to destructive modification operations
+ * of elements from collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Update[+A](elem: A) extends Message[A]
+
+/** This observable update refers to removal operations of elements
+ * from collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Remove[+A](elem: A) extends Message[A]
+
+/** This command refers to reset operations.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Reset[+A]() extends Message[A]
+
+/** Objects of this class represent compound messages consisting
+ * of a sequence of other messages.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+class Script[A] extends ArrayBuffer[Message[A]] with Message[A] {
+
+ override def toString(): String = {
+ var res = "Script("
+ var it = elements
+ var i = 1
+ while (it.hasNext) {
+ if (i > 1)
+ res = res + ", "
+ res = res + "[" + i + "] " + it.next
+ i = i + 1
+ }
+ res + ")"
+ }
+
+ override def hashCode(): Int =
+ throw new UnsupportedOperationException("scripts are not suitable as hash keys")
+}
diff --git a/src/dotnet-library/scala/collection/mutable/MultiMap.scala b/src/dotnet-library/scala/collection/mutable/MultiMap.scala
new file mode 100644
index 0000000000..35628e7673
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/MultiMap.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class is typically used as a mixin. It turns maps which map <code>A</code>
+ * to <code>Set[B]</code> objects into multi maps which map <code>A</code> to
+ * <code>B</code> objects.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait MultiMap[A, B] extends Map[A, Set[B]] {
+ protected def makeSet: Set[B] = new HashSet[B]
+
+ def add(key: A, value: B): Unit = get(key) match {
+ case None =>
+ val set = makeSet
+ set += value
+ this(key) = set
+ case Some(set) =>
+ set += value
+ }
+
+ def remove(key: A, value: B) = get(key) match {
+ case None =>
+ case Some(set) => set -= value
+ }
+
+ def entryExists(key: A, p: B => Boolean): Boolean = get(key) match {
+ case None => false
+ case Some(set) => set exists p
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/MutableList.scala b/src/dotnet-library/scala/collection/mutable/MutableList.scala
new file mode 100644
index 0000000000..8983949aaa
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/MutableList.scala
@@ -0,0 +1,80 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+//import Predef.NoSuchElementException
+
+/** This class is used internally to represent mutable lists. It is the
+ * basis for the implementation of the classes <code>Buffer</code>,
+ * <code>Stack</code>, and <code>Queue</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait MutableList[A] extends Seq[A] with PartialFunction[Int, A] {
+
+ protected var first: LinkedList[A] = null
+ protected var last: LinkedList[A] = null
+ protected var len: Int = 0
+
+ /** Returns the length of this list.
+ */
+ def length: Int = len
+
+ /** Returns the <code>n</code>th element of this list. This method
+ * yields an error if the element does not exist.
+ */
+ def apply(n: Int): A = get(n) match {
+ case None => throw new NoSuchElementException("element not found")
+ case Some(value) => value
+ }
+
+ /** Returns the <code>n</code>th element of this list or <code>None</code>
+ * if this element does not exist.
+ */
+ def get(n: Int): Option[A] = first.get(n)
+
+ protected def prependElem(elem: A): Unit = {
+ first = new LinkedList[A](elem, first)
+ if (len == 0)
+ last = first
+ len = len + 1
+ }
+
+ protected def appendElem(elem: A): Unit =
+ if (len == 0)
+ prependElem(elem)
+ else {
+ last.next = new LinkedList[A](elem, null)
+ last = last.next
+ len = len + 1
+ }
+
+ protected def reset: Unit = {
+ first = null
+ last = null
+ len = 0
+ }
+
+ /** Returns an iterator over all elements of this list.
+ */
+ def elements: Iterator[A] =
+ if (first eq null) Nil.elements else first.elements
+
+ /** Returns an instance of <code>scala.List</code> containing the same
+ * sequence of elements.
+ */
+ override def toList: List[A] = if (first eq null) Nil else first.toList
+
+ override protected def stringPrefix: String = "MutableList"
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ObservableBuffer.scala b/src/dotnet-library/scala/collection/mutable/ObservableBuffer.scala
new file mode 100644
index 0000000000..0aa15611a6
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ObservableBuffer.scala
@@ -0,0 +1,82 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+//import Predef.UnsupportedOperationException
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Buffer</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableBuffer</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait ObservableBuffer[A, This <: ObservableBuffer[A, This]] requires This
+ extends Buffer[A]
+ with Publisher[Message[{Location, A}]
+ with Undoable, This]
+{
+
+ abstract override def +(element: A): Buffer[A] = {
+ super.+(element)
+ publish(new Include({End, element}) with Undoable {
+ def undo: Unit = trimEnd(1)
+ })
+ this
+ }
+
+ abstract override def +:(element: A): Buffer[A] = {
+ super.+:(element);
+ publish(new Include({Start, element}) with Undoable {
+ def undo: Unit = trimStart(1)
+ })
+ this
+ }
+
+ abstract override def insertAll(n: Int, iter: Iterable[A]): Unit = {
+ super.insertAll(n, iter)
+ var i = n
+ val it = iter.elements
+ while (it.hasNext) {
+ publish(new Include({Index(i), it.next}) with Undoable {
+ def undo: Unit = remove(i);
+ })
+ i = i + 1
+ }
+ }
+
+ abstract override def update(n: Int, newelement: A): Unit = {
+ val oldelement = apply(n)
+ super.update(n, newelement)
+ publish(new Update({Index(n), newelement}) with Undoable {
+ def undo: Unit = update(n, oldelement)
+ })
+ }
+
+ abstract override def remove(n: Int): A = {
+ val oldelement = apply(n)
+ super.remove(n)
+ publish(new Remove({Index(n), oldelement}) with Undoable {
+ def undo: Unit = insert(n, oldelement)
+ })
+ oldelement
+ }
+
+ abstract override def clear(): Unit = {
+ super.clear
+ publish(new Reset with Undoable {
+ def undo: Unit = throw new UnsupportedOperationException("cannot undo")
+ })
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ObservableMap.scala b/src/dotnet-library/scala/collection/mutable/ObservableMap.scala
new file mode 100644
index 0000000000..626129343c
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ObservableMap.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Map</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableMap</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+trait ObservableMap[A, B, This <: ObservableMap[A, B, This]] requires This
+ extends Map[A, B]
+ with Publisher[Message[{A, B}]
+ with Undoable, This]
+{
+
+ abstract override def update(key: A, value: B): Unit = get(key) match {
+ case None =>
+ super.update(key, value)
+ publish(new Include({key, value}) with Undoable {
+ def undo = -=(key)
+ })
+ case Some(old) =>
+ super.update(key, value)
+ publish(new Update({key, value}) with Undoable {
+ def undo = update(key, old)
+ })
+ }
+
+ abstract override def -= (key: A): Unit = get(key) match {
+ case None =>
+ case Some(old) =>
+ super.-=(key)
+ publish(new Remove({key, old}) with Undoable {
+ def undo = update(key, old)
+ })
+ }
+
+ abstract override def clear(): Unit = {
+ super.clear
+ publish(new Reset with Undoable {
+ def undo: Unit = throw new UnsupportedOperationException("cannot undo")
+ })
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ObservableSet.scala b/src/dotnet-library/scala/collection/mutable/ObservableSet.scala
new file mode 100644
index 0000000000..46140275c9
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ObservableSet.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Set</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableSet</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait ObservableSet[A, This <: ObservableSet[A, This]] requires This
+ extends Set[A]
+ with Publisher[Message[A]
+ with Undoable, This]
+{
+
+ abstract override def +=(elem: A): Unit = if (!contains(elem)) {
+ super.+=(elem)
+ publish(new Include(elem) with Undoable { def undo = -=(elem) })
+ }
+
+ abstract override def -=(elem: A): Unit = if (contains(elem)) {
+ super.-=(elem)
+ publish(new Remove(elem) with Undoable { def undo = +=(elem) })
+ }
+
+ abstract override def clear(): Unit = {
+ super.clear
+ publish(new Reset with Undoable {
+ def undo: Unit = throw new UnsupportedOperationException("cannot undo")
+ })
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/PriorityQueue.scala b/src/dotnet-library/scala/collection/mutable/PriorityQueue.scala
new file mode 100644
index 0000000000..64a5ea0ddc
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/PriorityQueue.scala
@@ -0,0 +1,193 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+//import Predef.{NoSuchElementException, UnsupportedOperationException}
+
+/** This class implements priority queues using a heap. The
+ * elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> class.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+
+[serializable, cloneable]
+class PriorityQueue[A <% Ordered[A]] extends ResizableArray[A] {
+ size = size + 1 // we do not use array(0)
+
+ protected def fixUp(as: Array[A], m: Int): Unit = {
+ var k: Int = m
+ while ((k > 1) && (as(k / 2) < as(k))) {
+ swap(k, k / 2)
+ k = k / 2
+ }
+ }
+
+ protected def fixDown(as: Array[A], m: Int, n: Int): Unit = {
+ var k: Int = m
+ var loop: Boolean = true
+ while (loop && (n >= 2 * k)) {
+ var j = 2 * k
+ if ((j < n) && (as(j) < as(j + 1)))
+ j = j + 1;
+ if (!(as(k) < as(j)))
+ loop = false
+ else {
+ val h = as(k)
+ as(k) = as(j)
+ as(j) = h
+ k = j
+ }
+ }
+ }
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = size < 2
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ def +=(elem: A): Unit = {
+ ensureSize(size+1)
+ array(size) = elem
+ fixUp(array, size)
+ size = size + 1
+ }
+
+ def +(elem: A): PriorityQueue[A] = { this += elem; this }
+
+ /** Add two or more elements to this set.
+ * @param elem1 the first element.
+ * @param kv2 the second element.
+ * @param kvs the remaining elements.
+ */
+ def += (elem1: A, elem2: A, elems: A*) { this += elem1; this += elem2; this ++= elems }
+
+ def + (elem1: A, elem2: A, elems: A*) = { this.+=(elem1, elem2, elems: _*); this }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach { e => this += e }
+
+ def ++(iter: Iterable[A]): PriorityQueue[A] = { this ++= iter; this }
+
+ def ++(iter: Iterator[A]): PriorityQueue[A] = { this ++= iter; this }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ def enqueue(elems: A*): Unit = (this ++= elems)
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the element with the highest priority.
+ */
+ def dequeue: A =
+ if (size > 1) {
+ size = size - 1
+ swap(1, size)
+ fixDown(array, 1, size - 1)
+ array(size)
+ } else
+ throw new NoSuchElementException("no element to remove from heap")
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ def max: A = if (size > 1) array(1) else throw new NoSuchElementException("queue is empty")
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ def clear(): Unit = { size = 1 }
+
+ /** Returns an iterator which yiels all the elements of the priority
+ * queue in descending priority order.
+ *
+ * @return an iterator over all elements sorted in descending order.
+ */
+ override def elements: Iterator[A] = new Iterator[A] {
+ val as: Array[A] = new Array[A](size)
+ Array.copy(array, 0, as, 0, size)
+ var i = size - 1
+ def hasNext: Boolean = i > 0
+ def next: A = {
+ val res = as(1)
+ as(1) = as(i)
+ i = i - 1
+ fixDown(as, 1, i)
+ res
+ }
+ }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean =
+ that.isInstanceOf[PriorityQueue[A]] &&
+ { val other = that.asInstanceOf[PriorityQueue[A]]
+ elements.zip(other.elements).forall {
+ case {thiselem, thatelem} => thiselem == thatelem
+ }}
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = throw new UnsupportedOperationException("unsuitable as hash key")
+
+ /** Returns a regular queue containing the same elements.
+ */
+ def toQueue: Queue[A] = {
+ val res = new Queue[A]
+ res ++= this
+ res
+ }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString() = toList.mkString("PriorityQueue(", ", ", ")")
+
+ /** This method clones the priority queue.
+ *
+ * @return a priority queue with the same elements.
+ */
+ override def clone(): PriorityQueue[A] = {
+ val res = new PriorityQueue[A]
+ res ++= this
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/PriorityQueueProxy.scala b/src/dotnet-library/scala/collection/mutable/PriorityQueueProxy.scala
new file mode 100644
index 0000000000..869caf805a
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/PriorityQueueProxy.scala
@@ -0,0 +1,100 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class implements priority queues using a heap. The
+ * elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> class.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+abstract class PriorityQueueProxy[A <% Ordered[A]] extends PriorityQueue[A]
+ with SeqProxy[A]
+{
+
+ def self: PriorityQueue[A]
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ override def elements: Iterator[A] = self.elements
+
+ /** Returns the length of this priority queue.
+ */
+ override def length: Int = self.length
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = self.isEmpty
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = self += elem
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = self ++= elems
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue: A = self.dequeue
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def max: A = self.max
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = self.clear
+
+ /** Returns a regular queue containing the same elements.
+ */
+ override def toQueue: Queue[A] = self.toQueue
+
+ /** This method clones the priority queue.
+ *
+ * @return a priority queue with the same elements.
+ */
+ override def clone(): PriorityQueue[A] = new PriorityQueueProxy[A] {
+ def self = PriorityQueueProxy.this.self.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Publisher.scala b/src/dotnet-library/scala/collection/mutable/Publisher.scala
new file mode 100644
index 0000000000..7e6e386fb8
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Publisher.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** <code>Publisher[A,This]</code> objects publish events of type <code>A</code>
+ * to all registered subscribers. When subscribing, a subscriber may specify
+ * a filter which can be used to constrain the number of events sent to the
+ * subscriber. Subscribers may suspend their subscription, or reactivate a
+ * suspended subscription. Class <code>Publisher</code> is typically used
+ * as a mixin. The type variable <code>This</code> models self types.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Publisher[A, This <: Publisher[A, This]] requires This {
+ private val filters = new HashMap[Subscriber[A, This],
+ scala.collection.mutable.Set[A => Boolean]]
+ with MultiMap[Subscriber[A, This], A => Boolean]
+ private val suspended = new HashSet[Subscriber[A, This]]
+
+ def subscribe(sub: Subscriber[A, This]): Unit =
+ subscribe(sub, event => true)
+
+ def subscribe(sub: Subscriber[A, This], filter: A => Boolean): Unit =
+ filters.add(sub, filter)
+
+ def suspendSubscription(sub: Subscriber[A, This]): Unit = suspended += sub
+
+ def activateSubscription(sub: Subscriber[A, This]): Unit = suspended -= sub
+
+ def removeSubscription(sub: Subscriber[A, This]): Unit = filters -= sub
+
+ def removeSubscriptions: Unit = filters.clear
+
+ protected def publish(event: A): Unit =
+ filters.keys.foreach(sub =>
+ if (filters.entryExists(sub, p => p(event))) sub.notify(this, event))
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Queue.scala b/src/dotnet-library/scala/collection/mutable/Queue.scala
new file mode 100644
index 0000000000..e2b4d8d913
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Queue.scala
@@ -0,0 +1,196 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+//import Predef.{NoSuchElementException, UnsupportedOperationException}
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+[serializable, cloneable]
+class Queue[A] extends MutableList[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = (first eq null)
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ def +=(elem: A): Unit = appendElem(elem)
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param it an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach appendElem
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ def enqueue(elems: A*): Unit = (this ++= elems)
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the first element of the queue.
+ */
+ def dequeue: A =
+ if (first eq null)
+ throw new NoSuchElementException("queue empty")
+ else {
+ val res = first.elem
+ first = first.next
+ if (first eq null) last = null
+ len = len - 1
+ res
+ }
+
+ /** Returns the first element in the queue which satisfies the
+ * given predicate, and removes this element from the queue.
+ *
+ * @param p the predicate used for choosing the first element
+ * @return the first element of the queue for which p yields true
+ */
+ def dequeueFirst(p: A => Boolean): Option[A] =
+ if (first eq null)
+ None
+ else if (p(first.elem)) {
+ val res: Option[A] = Some(first.elem)
+ first = first.next
+ len = len - 1
+ if (first eq null) {
+ last = null
+ } else if (first.next eq null) {
+ last = first
+ }
+ res
+ } else
+ extractFirst(first, p) match {
+ case None => None
+ case Some(cell) => Some(cell.elem)
+ }
+
+ /** Returns all elements in the queue which satisfy the
+ * given predicate, and removes those elements from the queue.
+ *
+ * @param p the predicate used for choosing elements
+ * @return a sequence of all elements in the queue for which
+ * p yields true.
+ */
+ def dequeueAll(p: A => Boolean): Seq[A] = {
+ val res = new ArrayBuffer[A]
+ if (first eq null)
+ res
+ else {
+ while (p(first.elem)) {
+ res += first.elem
+ first = first.next
+ len = len - 1
+ if (first eq null) {
+ last = null
+ } else if (first.next eq null) {
+ last = first
+ }
+ }
+ var cell: Option[LinkedList[A]] = extractFirst(first, p)
+ while (!cell.isEmpty) {
+ res += cell.get.elem
+ cell = extractFirst(cell.get, p)
+ }
+ res
+ }
+ }
+
+ private def extractFirst(start: LinkedList[A], p: A => Boolean): Option[LinkedList[A]] = {
+ var cell = start
+ while ((cell.next ne null) && !p(cell.next.elem)) {
+ cell = cell.next
+ }
+ if (cell.next eq null)
+ None
+ else {
+ val res: Option[LinkedList[A]] = Some(cell.next)
+ cell.next = cell.next.next
+ if (cell.next eq null)
+ last = cell
+ len = len - 1
+ res
+ }
+ }
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @return the first element.
+ */
+ def front: A = first.elem
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ def clear(): Unit = reset
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean =
+ that.isInstanceOf[Queue[A]] &&
+ { val other = that.asInstanceOf[Queue[A]]
+ elements.zip(other.elements).forall {
+ case {thiselem, thatelem} => thiselem == thatelem
+ }}
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @throws Predef.UnsupportedOperationException
+ * @return never.
+ */
+ override def hashCode(): Int = throw new UnsupportedOperationException("unsuitable as hash key")
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString() = toList.mkString("Queue(", ", ", ")")
+
+ /** This method clones the queue.
+ *
+ * @return a queue with the same elements.
+ */
+ override def clone(): Queue[A] = {
+ val res = new Queue[A]
+ res ++= this
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/QueueProxy.scala b/src/dotnet-library/scala/collection/mutable/QueueProxy.scala
new file mode 100644
index 0000000000..e882303db2
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/QueueProxy.scala
@@ -0,0 +1,101 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+trait QueueProxy[A] extends Queue[A] with SeqProxy[A] {
+
+ def self: Queue[A]
+
+ /** Access element number <code>n</code>.
+ *
+ * @return the element at index <code>n</code>.
+ */
+ override def apply(n: Int): A = self.apply(n)
+
+ /** Returns the length of this queue.
+ */
+ override def length: Int = self.length
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = self.isEmpty
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = self += elem
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = self ++= elems
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @return the first element of the queue.
+ */
+ override def dequeue: A = self.dequeue
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @return the first element.
+ */
+ override def front: A = self.front
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = self.clear
+
+ /** Returns an iterator over all elements on the queue.
+ *
+ * @return an iterator over all queue elements.
+ */
+ override def elements: Iterator[A] = self.elements
+
+ /** This method clones the queue.
+ *
+ * @return a queue with the same elements.
+ */
+ override def clone(): Queue[A] = new QueueProxy[A] {
+ def self = QueueProxy.this.self.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/ResizableArray.scala b/src/dotnet-library/scala/collection/mutable/ResizableArray.scala
new file mode 100644
index 0000000000..acd8d53179
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/ResizableArray.scala
@@ -0,0 +1,85 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+/** This class is used internally to implement data structures that
+ * are based on resizable arrays.
+ * //todo enrich with more efficient operations
+ *
+ * @author Matthias Zenger, Burak Emir
+ * @version 1.0, 03/05/2004
+ */
+trait ResizableArray[A] extends Seq[A] {
+
+ protected val initialSize: Int = 16
+ protected var array: Array[A] = new Array[A](initialSize)
+ protected var size: Int = 0
+
+ //##########################################################################
+ // implement/override methods of Seq[A]
+
+ /** Returns the length of this resizable array.
+ */
+ def length: Int = size
+
+ def apply(i: Int) = array(i)
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ */
+ override def copyToArray[B >: A](xs: Array[B], start: Int): Unit =
+ Array.copy(array, 0, xs, start, size)
+
+ /** Copy all elements to a buffer
+ * @param The buffer to which elements are copied
+ */
+ override def copyToBuffer[B >: A](dest: Buffer[B]): Unit =
+ dest.++=(array.asInstanceOf[Array[B]], 0, size)
+
+ /** Returns a new iterator over all elements of this resizable array.
+ */
+ def elements: Iterator[A] = new Iterator[A] {
+ var i = 0
+ def hasNext: Boolean = i < size
+ def next: A = { i = i + 1; array(i - 1) }
+ }
+
+ //##########################################################################
+
+ /** ensure that the internal array has at n cells */
+ protected def ensureSize(n: Int): Unit =
+ if (n > array.length) {
+ var newsize = array.length * 2
+ while (n > newsize)
+ newsize = newsize * 2
+ val newar: Array[A] = new Array(newsize)
+ Array.copy(array, 0, newar, 0, size)
+ array = newar
+ }
+
+ /** Swap two elements of this array.
+ */
+ protected def swap(a: Int, b: Int): Unit = {
+ val h = array(a)
+ array(a) = array(b)
+ array(b) = h
+ }
+
+ /** Move parts of the array.
+ */
+ protected def copy(m: Int, n: Int, len: Int) =
+ Array.copy(array, m, array, n, len)
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/RevertableHistory.scala b/src/dotnet-library/scala/collection/mutable/RevertableHistory.scala
new file mode 100644
index 0000000000..f9fcb635b6
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/RevertableHistory.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** A revertable history is a <code>History</code> object which supports
+ * an undo operation. Type variable <code>A</code> refers to the type
+ * of the published events, <code>B</code> denotes the publisher type.
+ * Type <code>B</code> is typically a subtype of <code>Publisher</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class RevertableHistory[A <: Undoable, B] extends History[A, B] with Undoable {
+
+ /** Rollback the full history.
+ */
+ def undo: Unit = {
+ val old = log.toList.reverse
+ clear
+ old.foreach { case {sub, event} => event.undo }
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Scriptable.scala b/src/dotnet-library/scala/collection/mutable/Scriptable.scala
new file mode 100644
index 0000000000..313450ce6d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Scriptable.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** Classes that mix in the <code>Scriptable</code> class allow
+ * messages to be sent to objects of that class.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 09/05/2004
+ */
+trait Scriptable[A] {
+
+ /** Send a message to this scriptable object.
+ */
+ def <<(cmd: A): Unit
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Set.scala b/src/dotnet-library/scala/collection/mutable/Set.scala
new file mode 100644
index 0000000000..16b1b8440b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Set.scala
@@ -0,0 +1,211 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class represents mutable sets. Concrete set implementations
+ * just have to provide functionality for the abstract methods in
+ * <a href="../Set.html" target="contentFrame">
+ * <code>scala.collection.Set</code></a> as well as for <code>+=</code>,
+ * <code>-= and <code>clear</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 09/05/2004
+ */
+object Set {
+
+ /** The empty map of this type; this is implemented as a hashtable */
+ def empty[A]: Set[A] = new HashSet[A]
+
+ /** The canonical factory for this type
+ */
+ def apply[A](elems: A*) = empty[A] ++ elems
+}
+
+[cloneable]
+trait Set[A] extends collection.Set[A] with Scriptable[Message[A]] {
+
+ /** This method allows one to add or remove an element <code>elem</code>
+ * from this set depending on the value of parameter <code>included</code>.
+ * Typically, one would use the following syntax:
+ * <pre>set(elem) = true</pre>
+ *
+ */
+ def update(elem: A, included: Boolean): Unit =
+ if (included) this += elem else this -= elem
+
+ /** Add a new element to the set.
+ *
+ * @param elem the element to be added
+ */
+ def +=(elem: A)
+
+ /** Add two or more elements to this set.
+ * @param elem1 the first element.
+ * @param kv2 the second element.
+ * @param kvs the remaining elements.
+ */
+ def += (elem1: A, elem2: A, elems: A*) { this += elem1; this += elem2; this ++= elems }
+
+ /** Add all the elements provided by an iterator
+ * of the iterable object <code>that</code> to the set.
+ * @param elems the iterable object containing the elements to be added
+ */
+ def ++=(elems: Iterable[A]): Unit = ++=(elems.elements)
+
+ /** Add all the elements provided by an iterator
+ * <code>elems</code> to the set.
+ * @param elems the iterator containing the elements to be added
+ */
+ def ++=(elems: Iterator[A]): Unit = elems foreach +=
+
+ /** Add a new element to the set.
+ * @return the set itself with the element added.
+ *
+ * @param elem the element to be added
+ */
+ def + (elem: A): Set[A] = { +=(elem); this }
+
+ /** Add two or more elements to this set.
+ * @param elem1 the first element.
+ * @param kv2 the second element.
+ * @param kvs the remaining elements.
+ * @return the set itself with the elements added.
+ */
+ def + (elem1: A, elem2: A, elems: A*): Set[A] = { this.+=(elem1, elem2, elems: _*); this }
+
+ /** Add all the elements provided by an iterator
+ * of the iterable object <code>elems</code> to the set.
+ *
+ * @param elems the iterable object containing the elements to be added
+ * @return the set itself with the elements added.
+ */
+ def ++ (elems: Iterable[A]): Set[A] = { this ++= elems; this }
+
+ /** Add all the elements provided by an iterator
+ * <code>elems</code> to the set.
+ * @param elems the iterator containing the elements to be added
+ */
+ def ++ (elems: Iterator[A]): Set[A] = { this ++= elems; this }
+
+ /** <code>incl</code> can be used to add many elements to the set
+ * at the same time.
+ * @deprecated use <code>++=</code> instead
+ */
+ [deprecated] def incl(elems: A*): Unit = ++=(elems.elements)
+
+ /** Removes a single element from a set.
+ * @param elem The element to be removed.
+ */
+ def -=(elem: A)
+
+ /** Remove two or more elements from this set.
+ * @param elem1 the first element.
+ * @param elem2 the second element.
+ * @param elems the remaining elements.
+ */
+ def -= (elem1: A, elem2: A, elems: A*) { this -= elem1; this -= elem2; this --= elems }
+
+ /** Remove all the elements provided by an iterator
+ * of the iterable object <code>elems</code> from the set.
+ */
+ def --=(elems: Iterable[A]): Unit = --=(elems.elements)
+
+ /** Remove all the elements provided by an iterator
+ * <code>elems</code> from the set.
+ */
+ def --=(elems: Iterator[A]): Unit = elems foreach -=
+
+ /** Remove a new element from the set.
+ * @return the set itself with the element removed.
+ *
+ * @param elem the element to be removed
+ */
+ def - (elem: A): Set[A] = { -=(elem); this }
+
+ /** Remove two or more elements from this set.
+ * @param elem1 the first element.
+ * @param elem2 the second element.
+ * @param elems the remaining elements.
+ * @return the set itself with the elements removed.
+ */
+ def - (elem1: A, elem2: A, elems: A*): Set[A] = { this.-=(elem1, elem2, elems: _*); this }
+
+ /** Remove all the elements provided by an iterator
+ * of the iterable object <code>elems</code> from the set.
+ *
+ * @param elems An iterable object containing the elements to remove from the set.
+ * @return the set itself with the elements removed.
+ */
+ def -- (elems: Iterable[A]): Set[A] = { this --= elems; this }
+
+ /** Remove all the elements provided by an iterator
+ * <code>elems</code> from the set.
+ * @param elems An iterator containing the elements to remove from the set.
+ * @return the set itself with the elements removed.
+ */
+ def -- (elems: Iterator[A]): Set[A] = { this --= elems; this }
+
+ /** <code>excl</code> removes many elements from the set.
+ */
+ [deprecated] def excl(elems: A*): Unit = --=(elems.elements)
+
+ /** This method computes an intersection with set <code>that</code>.
+ * It removes all the elements that are not present in <code>that</code>.
+ *
+ * @param that the set to intersect with.
+ */
+ def intersect(that: Set[A]): Unit = retain(that.contains)
+
+ /** Method <code>filter</code> removes all elements from the set for
+ * which the predicate <code>p</code> yields the value <code>false</code>.
+ * @deprecated use retain instead
+ */
+ [deprecated] override def filter(p: A => Boolean): Set[A] = {
+ toList.foreach {
+ elem => if (!p(elem)) -=(elem)
+ }
+ this
+ }
+
+ /** Method <code>retain removes all elements from the set for
+ * which the predicate <code>p</code> yields the value <code>false</code>.
+ */
+ def retain(p: A => Boolean): Unit = toList.foreach {
+ elem => if (!p(elem)) -=(elem)
+ }
+
+ /** Removes all elements from the set. After this operation is completed,
+ * the set will be empty.
+ */
+ def clear(): Unit = elements foreach -=
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ * @throws <code>Predef.UnsupportedOperationException</code>
+ * if the message was not understood.
+ */
+ def <<(cmd: Message[A]): Unit = cmd match {
+ case Include(elem) => this += elem
+ case Remove(elem) => this -= elem
+ case Reset() => clear
+ case s: Script[_] => s.elements foreach <<
+ case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
+ }
+
+ /** Return a clone of this set.
+ *
+ * @return a set with the same elements.
+ */
+ override def clone(): Set[A] = super.clone().asInstanceOf[Set[A]]
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SetProxy.scala b/src/dotnet-library/scala/collection/mutable/SetProxy.scala
new file mode 100644
index 0000000000..0cba74da40
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SetProxy.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This is a simple wrapper class for <a href="Set.html"
+ * target="contentFrame"><code>scala.collection.mutable.Set</code></a>.
+ * It is most useful for assembling customized set abstractions
+ * dynamically using object composition and forwarding.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 09/05/2004
+ */
+trait SetProxy[A] extends Set[A] with collection.SetProxy[A] {
+
+ def self: Set[A]
+
+ override def update(elem: A, included: Boolean): Unit = self(elem) = included
+
+ def +=(elem: A): Unit = self += elem
+
+ override def ++=(that: Iterable[A]): Unit = self ++= that
+
+ override def ++=(it: Iterator[A]): Unit = self ++= it
+
+ override def incl(elems: A*): Unit = self ++= elems
+
+ def -=(elem: A): Unit = self -= elem
+
+ override def --=(that: Iterable[A]): Unit = self --= that
+
+ override def --=(it: Iterator[A]): Unit = self --= it
+
+ override def excl(elems: A*): Unit = self --= elems
+
+ override def intersect(that: Set[A]): Unit = self.intersect(that)
+
+ override def clear(): Unit = self.clear
+
+ override def retain(p: A => Boolean): Unit = self.retain(p)
+
+ [deprecated] override def filter(p: A => Boolean) = self.filter(p)
+
+ override def <<(cmd: Message[A]): Unit = self << cmd
+
+ override def clone(): Set[A] = new SetProxy[A] {
+ def self = SetProxy.this.self.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SingleLinkedList.scala b/src/dotnet-library/scala/collection/mutable/SingleLinkedList.scala
new file mode 100644
index 0000000000..2fc51ad9a2
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SingleLinkedList.scala
@@ -0,0 +1,63 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+/** This extensible class may be used as a basis for implementing linked
+ * list. Type variable <code>A</code> refers to the element type of the
+ * list, type variable <code>This</code> is used to model self types of
+ * linked lists.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+abstract class SingleLinkedList[A, This >: Null <: SingleLinkedList[A, This]]
+ requires This
+ extends AnyRef with Seq[A]
+{
+
+ var elem: A
+
+ var next: This
+
+ def length: Int = 1 + (if (next eq null) 0 else next.length)
+
+ def append(that: This): Unit =
+ if (next eq null) next = that else next.append(that)
+
+ def insert(that: This): Unit = if (that ne null) {
+ that.append(next)
+ next = that
+ }
+
+ def apply(n: Int): A =
+ if (n == 0) elem
+ else if (next eq null) throw new IndexOutOfBoundsException("unknown element")
+ else next.apply(n - 1)
+
+ def get(n: Int): Option[A] =
+ if (n == 0) Some(elem)
+ else if (next eq null) None
+ else next.get(n - 1)
+
+ def elements: Iterator[A] = new Iterator[A] {
+ var elems = SingleLinkedList.this
+ def hasNext = (elems ne null)
+ def next = {
+ val res = elems.elem
+ elems = elems.next
+ res;
+ }
+ }
+
+ override def toList: List[A] = elements toList
+
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Stack.scala b/src/dotnet-library/scala/collection/mutable/Stack.scala
new file mode 100644
index 0000000000..1aee74148e
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Stack.scala
@@ -0,0 +1,133 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** A stack implements a data structure which allows to store and retrieve
+ * objects in a last-in-first-out (LIFO) fashion.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+[serializable, cloneable]
+class Stack[A] extends MutableList[A] {
+
+ /** Checks if the stack is empty.
+ *
+ * @return true, iff there is no element on the stack
+ */
+ override def isEmpty: Boolean = (first eq null)
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ def +=(elem: A): Unit = prependElem(elem)
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach { e => prependElem(e) }
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ def push(elems: A*): Unit = (this ++= elems)
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the top element
+ */
+ def top: A = if (first eq null) throw new NoSuchElementException("stack empty") else first.elem
+
+ /** Removes the top element from the stack.
+ *
+ * @throws Predef.NoSuchElementException
+ * @return the top element
+ */
+ def pop: A =
+ if (first ne null) {
+ val res = first.elem
+ first = first.next
+ len = len - 1;
+ res
+ } else
+ throw new NoSuchElementException("stack empty")
+
+ /**
+ * Removes all elements from the stack. After this operation completed,
+ * the stack will be empty.
+ */
+ def clear(): Unit = reset
+
+ /** Returns an iterator over all elements on the stack. This iterator
+ * is stable with respect to state changes in the stack object; i.e.
+ * such changes will not be reflected in the iterator. The iterator
+ * issues elements in the order they were inserted into the stack
+ * (FIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ override def elements: Iterator[A] = toList.elements
+
+ /** Creates a list of all stack elements in FIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = super[MutableList].toList.reverse
+
+ /** Checks if two stacks are structurally identical.
+ *
+ * @return true, iff both stacks contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean =
+ that.isInstanceOf[Stack[A]] &&
+ { val other = that.asInstanceOf[Stack[A]];
+ elements.zip(other.elements).forall {
+ case {thiselem, thatelem} => thiselem == thatelem
+ }}
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable stacks as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = throw new UnsupportedOperationException("unsuitable as hash key")
+
+ /** This method clones the stack.
+ *
+ * @return a stack with the same elements.
+ */
+ override def clone(): Stack[A] = {
+ val res = new Stack[A]
+ res ++= this
+ res
+ }
+
+ override protected def stringPrefix: String = "Stack"
+}
diff --git a/src/dotnet-library/scala/collection/mutable/StackProxy.scala b/src/dotnet-library/scala/collection/mutable/StackProxy.scala
new file mode 100644
index 0000000000..24b8d743e3
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/StackProxy.scala
@@ -0,0 +1,111 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** A stack implements a data structure which allows to store and retrieve
+ * objects in a last-in-first-out (LIFO) fashion.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+trait StackProxy[A] extends Stack[A] with SeqProxy[A] {
+
+ def self: Stack[A]
+
+ /** Access element number <code>n</code>.
+ *
+ * @return the element at index <code>n</code>.
+ */
+ override def apply(n: Int): A = self.apply(n)
+
+ /** Returns the length of this stack.
+ */
+ override def length: Int = self.length
+
+ /** Checks if the stack is empty.
+ *
+ * @return true, iff there is no element on the stack
+ */
+ override def isEmpty: Boolean = self.isEmpty
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ override def +=(elem: A): Unit = self += elem
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ override def push(elems: A*): Unit = self ++= elems
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @return the top element
+ */
+ override def top: A = self.top
+
+ /** Removes the top element from the stack.
+ */
+ override def pop: A = self.pop
+
+ /**
+ * Removes all elements from the stack. After this operation completed,
+ * the stack will be empty.
+ */
+ override def clear(): Unit = self.clear
+
+ /** Returns an iterator over all elements on the stack. This iterator
+ * is stable with respect to state changes in the stack object; i.e.
+ * such changes will not be reflected in the iterator. The iterator
+ * issues elements in the order they were inserted into the stack
+ * (FIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ override def elements: Iterator[A] = self.elements
+
+ /** Creates a list of all stack elements in FIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = self.toList
+
+ /** This method clones the stack.
+ *
+ * @return a stack with the same elements.
+ */
+ override def clone(): Stack[A] = new StackProxy[A] {
+ def self = StackProxy.this.self.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Subscriber.scala b/src/dotnet-library/scala/collection/mutable/Subscriber.scala
new file mode 100644
index 0000000000..b6c33a8b1b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Subscriber.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** <code>Subscriber[A, B]</code> objects may subscribe to events of
+ * type <code>A</code> published by an object of type <code>B</code>.
+ * <code>B</code> is typically a subtype of <a href="Publisher.html"
+ * target="contentFrame"><code>Publisher</code></a>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Subscriber[-A, -B] {
+ def notify(pub: B, event: A): Unit
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedBuffer.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedBuffer.scala
new file mode 100644
index 0000000000..b86f7d401b
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedBuffer.scala
@@ -0,0 +1,191 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class should be used as a mixin. It synchronizes the <code>Buffer</code>
+ * methods of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait SynchronizedBuffer[A] extends Buffer[A] {
+
+ abstract override def length: Int = synchronized {
+ super.length
+ }
+
+ abstract override def elements: Iterator[A] = synchronized {
+ super.elements
+ }
+
+ abstract override def apply(n: Int): A = synchronized {
+ super.apply(n)
+ }
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ override def +(elem: A): Buffer[A] = synchronized {
+ super.+(elem)
+ }
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ abstract override def +=(elem: A): Unit = synchronized {
+ super.+=(elem)
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++(iter: Iterable[A]): Buffer[A] = synchronized {
+ super.++(iter)
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized {
+ super.++=(iter)
+ }
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ override def append(elems: A*): Unit = synchronized {
+ super.++=(elems)
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def appendAll(iter: Iterable[A]): Unit = synchronized {
+ super.appendAll(iter)
+ }
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ abstract override def +:(elem: A): Buffer[A] = synchronized {
+ super.+:(elem)
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = synchronized {
+ super.++:(iter)
+ }
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ override def prepend(elems: A*): Unit = synchronized {
+ super.prependAll(elems)
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def prependAll(elems: Iterable[A]): Unit = synchronized {
+ super.prependAll(elems)
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ override def insert(n: Int, elems: A*): Unit = synchronized {
+ super.insertAll(n, elems)
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ abstract override def insertAll(n: Int, iter: Iterable[A]): Unit = synchronized {
+ super.insertAll(n, iter)
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ abstract override def update(n: Int, newelem: A): Unit = synchronized {
+ super.update(n, newelem)
+ }
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ abstract override def remove(n: Int): A = synchronized {
+ super.remove(n)
+ }
+
+ /** Clears the buffer contents.
+ */
+ abstract override def clear(): Unit = synchronized {
+ super.clear
+ }
+
+ override def <<(cmd: Message[{Location, A}]): Unit = synchronized {
+ super.<<(cmd)
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = synchronized {
+ super.clone()
+ }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use buffers as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized {
+ super.hashCode()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedMap.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedMap.scala
new file mode 100644
index 0000000000..da317123f0
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedMap.scala
@@ -0,0 +1,157 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class should be used as a mixin. It synchronizes the <code>Map</code>
+ * functions of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @author Martin Odersky
+ * @version 2.0, 31/12/2006
+ */
+trait SynchronizedMap[A, B] extends Map[A, B] {
+
+ abstract override def size: Int = synchronized {
+ super.size
+ }
+
+ abstract override def get(key: A): Option[B] = synchronized {
+ super.get(key)
+ }
+
+ override def isEmpty: Boolean = synchronized {
+ super.isEmpty
+ }
+
+ override def apply(key: A): B = synchronized {
+ super.apply(key)
+ }
+
+ override def contains(key: A): Boolean = synchronized {
+ super.contains(key)
+ }
+
+ override def isDefinedAt(key: A) = synchronized {
+ super.isDefinedAt(key)
+ }
+
+ override def keys: Iterator[A] = synchronized {
+ super.keys
+ }
+
+ override def keySet: collection.Set[A] = synchronized {
+ super.keySet
+ }
+
+ override def values: Iterator[B] = synchronized {
+ super.values
+ }
+
+ abstract override def elements: Iterator[{A, B}] = synchronized {
+ super.elements
+ }
+
+ override def toList: List[{A, B}] = synchronized {
+ super.toList
+ }
+
+ abstract override def update(key: A, value: B): Unit = synchronized {
+ super.update(key, value)
+ }
+
+ override def += (kv: {A, B}): Unit = synchronized {
+ super.+=(kv)
+ }
+
+ /** Add two or more key/value pairs to this map.
+ * @param kv1 the key/first value pair.
+ * @param kv2 the second key/first value pair.
+ * @param kvs the remaining key/first value pairs.
+ */
+ override def += (kv1: {A, B}, kv2: {A, B}, kvs: {A, B}*): Unit = synchronized {
+ super.+=(kv1, kv2, kvs: _*)
+ }
+
+ override def ++=(map: Iterable[{A, B}]): Unit = synchronized {
+ super.++=(map)
+ }
+
+ override def ++=(it: Iterator[{A, B}]): Unit = synchronized {
+ super.++=(it)
+ }
+
+ [deprecated] override def incl(mappings: {A, B}*): Unit = synchronized {
+ super.incl(mappings: _*)
+ }
+
+ abstract override def -=(key: A): Unit = synchronized {
+ super.-=(key)
+ }
+
+ override def -= (key1: A, key2: A, keys: A*): Unit = synchronized {
+ super.-=(key1, key2, keys: _*)
+ }
+
+ override def --=(keys: Iterable[A]): Unit = synchronized {
+ super.--=(keys)
+ }
+
+ override def --=(it: Iterator[A]): Unit = synchronized {
+ super.--=(it)
+ }
+
+ [deprecated] override def excl(keys: A*): Unit = synchronized {
+ super.excl(keys: _*)
+ }
+
+ override def clear(): Unit = synchronized {
+ super.clear
+ }
+
+ override def transform(f: (A, B) => B): Unit = synchronized {
+ super.transform(f)
+ }
+
+ [deprecated] override def map[C](f: {A, B} => C) = synchronized {
+ super.map(f)
+ }
+
+ override def retain(p: (A, B) => Boolean): Unit = synchronized {
+ super.retain(p)
+ }
+
+ /** @deprecated use retain instead */
+ [deprecated] override def filter(p: {A, B} => Boolean) = synchronized {
+ super.filter(p)
+ }
+
+ override def toString() = synchronized {
+ super.toString()
+ }
+
+ override def equals(that: Any): Boolean = synchronized {
+ super.equals(that)
+ }
+
+ override def hashCode(): int = synchronized {
+ super.hashCode()
+ }
+
+ override def <<(cmd: Message[{A, B}]): Unit = synchronized {
+ super.<<(cmd)
+ }
+
+ override def clone(): Map[A, B] = synchronized {
+ super.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedPriorityQueue.scala
new file mode 100644
index 0000000000..26edf0d68d
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedPriorityQueue.scala
@@ -0,0 +1,99 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class implements synchronized priority queues using a heap.
+ * The elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> class.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedPriorityQueue[A <% Ordered[A]] extends PriorityQueue[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem) }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter) }
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it) }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = synchronized { super.++=(elems) }
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue: A = synchronized { super.dequeue }
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def max: A = synchronized { super.max }
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = synchronized { super.clear }
+
+ /** Returns an iterator which yiels all the elements of the priority
+ * queue in descending priority order.
+ *
+ * @return an iterator over all elements sorted in descending order.
+ */
+ override def elements: Iterator[A] = synchronized { super.elements }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that) }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode() }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString(): String = synchronized { super.toString() }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedQueue.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedQueue.scala
new file mode 100644
index 0000000000..19f4813301
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedQueue.scala
@@ -0,0 +1,95 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This is a synchronized version of the <code>Queue[T]</code> class. It
+ * implements a data structure that allows one to insert and retrieve
+ * elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedQueue[A] extends Queue[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem) }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter) }
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it) }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = synchronized { super.++=(elems) }
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @return the first element of the queue.
+ */
+ override def dequeue: A = synchronized { super.dequeue }
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @return the first element.
+ */
+ override def front: A = synchronized { super.front }
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear(): Unit = synchronized { super.clear }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that) }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode() }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString() = synchronized { super.toString() }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedSet.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedSet.scala
new file mode 100644
index 0000000000..9c11519ba4
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedSet.scala
@@ -0,0 +1,110 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This class should be used as a mixin. It synchronizes the <code>Set</code>
+ * functions of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait SynchronizedSet[A] extends Set[A] {
+
+ abstract override def size: Int = synchronized {
+ super.size
+ }
+
+ override def isEmpty: Boolean = synchronized {
+ super.isEmpty
+ }
+
+ abstract override def contains(elem: A) = synchronized {
+ super.contains(elem)
+ }
+
+ abstract override def update(elem: A, included: Boolean): Unit = synchronized {
+ super.update(elem, included)
+ }
+
+ abstract override def +=(elem: A): Unit = synchronized {
+ super.+=(elem)
+ }
+
+ override def ++=(that: Iterable[A]) = synchronized {
+ super.++=(that)
+ }
+
+ override def ++=(it: Iterator[A]) = synchronized {
+ super.++=(it)
+ }
+
+ override def incl(elems: A*): Unit = synchronized {
+ super.++=(elems)
+ }
+
+ abstract override def -=(elem: A): Unit = synchronized {
+ super.-=(elem)
+ }
+
+ override def --=(that: Iterable[A]) = synchronized {
+ super.--=(that)
+ }
+
+ override def --=(it: Iterator[A]) = synchronized {
+ super.--=(it)
+ }
+
+ override def excl(elems: A*): Unit = synchronized {
+ super.--=(elems)
+ }
+
+ override def intersect(that: Set[A]) = synchronized {
+ super.intersect(that)
+ }
+
+ abstract override def clear(): Unit = synchronized {
+ super.clear
+ }
+
+ override def subsetOf(that: scala.collection.Set[A]) = synchronized {
+ super.subsetOf(that)
+ }
+
+ override def foreach(f: A => Unit) = synchronized {
+ super.foreach(f)
+ }
+
+ [deprecated] override def filter(p: A => Boolean) = synchronized {
+ super.filter(p)
+ }
+
+ override def retain(p: A => Boolean) = synchronized {
+ super.retain(p)
+ }
+
+ override def toList: List[A] = synchronized {
+ super.toList
+ }
+
+ override def toString() = synchronized {
+ super.toString()
+ }
+
+ override def <<(cmd: Message[A]): Unit = synchronized {
+ super.<<(cmd)
+ }
+
+ override def clone(): Set[A] = synchronized {
+ super.clone()
+ }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/SynchronizedStack.scala b/src/dotnet-library/scala/collection/mutable/SynchronizedStack.scala
new file mode 100644
index 0000000000..c1acb68792
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/SynchronizedStack.scala
@@ -0,0 +1,111 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** This is a synchronized version of the <code>Stack[T]</code> class. It
+ * implements a data structure which allows to store and retrieve
+ * objects in a last-in-first-out (LIFO) fashion.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedStack[A] extends Stack[A] {
+
+ /** Checks if the stack is empty.
+ *
+ * @return true, iff there is no element on the stack
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem) }
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter) }
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it) }
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ override def push(elems: A*): Unit = synchronized { super.++=(elems) }
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @return the top element
+ */
+ override def top: A = synchronized { super.top }
+
+ /** Removes the top element from the stack.
+ */
+ override def pop: A = synchronized { super.pop }
+
+ /**
+ * Removes all elements from the stack. After this operation completed,
+ * the stack will be empty.
+ */
+ override def clear(): Unit = synchronized { super.clear }
+
+ /** Returns an iterator over all elements on the stack. This iterator
+ * is stable with respect to state changes in the stack object; i.e.
+ * such changes will not be reflected in the iterator. The iterator
+ * issues elements in the order they were inserted into the stack
+ * (FIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ override def elements: Iterator[A] = synchronized { super.elements }
+
+ /** Creates a list of all stack elements in FIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = synchronized { super.toList }
+
+ /** Checks if two stacks are structurally identical.
+ *
+ * @return true, iff both stacks contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that) }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable stacks as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode() }
+
+ /** Returns a textual representation of a stack as a string.
+ *
+ * @return the string representation of this stack.
+ */
+ override def toString() = synchronized { super.toString() }
+}
diff --git a/src/dotnet-library/scala/collection/mutable/Undoable.scala b/src/dotnet-library/scala/collection/mutable/Undoable.scala
new file mode 100644
index 0000000000..302273595a
--- /dev/null
+++ b/src/dotnet-library/scala/collection/mutable/Undoable.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.collection.mutable
+
+
+/** Classes that mix in the <code>Undoable</code> class provide an operation
+ * <code>undo</code> which can be used to undo the last operation.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Undoable {
+
+ /** Undo the last operation.
+ */
+ def undo: Unit
+}
diff --git a/src/dotnet-library/scala/compat/Math.scala b/src/dotnet-library/scala/compat/Math.scala
new file mode 100644
index 0000000000..183d2aa09d
--- /dev/null
+++ b/src/dotnet-library/scala/compat/Math.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.compat;
+
+
+object Math {
+ val MIN_BYTE = java.lang.Byte.MIN_VALUE
+ val MAX_BYTE = java.lang.Byte.MAX_VALUE
+ val MIN_SHORT = java.lang.Short.MIN_VALUE
+ val MAX_SHORT = java.lang.Short.MAX_VALUE
+ val MIN_CHAR = java.lang.Character.MIN_VALUE
+ val MAX_CHAR = java.lang.Character.MAX_VALUE
+ val MIN_INT = java.lang.Integer.MIN_VALUE
+ val MAX_INT = java.lang.Integer.MAX_VALUE
+ val MIN_LONG = java.lang.Long.MIN_VALUE
+ val MAX_LONG = java.lang.Long.MAX_VALUE
+
+ val MIN_FLOAT = -java.lang.Float.MAX_VALUE
+ val EPS_FLOAT = java.lang.Float.MIN_VALUE
+ val MAX_FLOAT = java.lang.Float.MAX_VALUE
+ val NaN_FLOAT = java.lang.Float.NaN
+ val NEG_INF_FLOAT = java.lang.Float.NEGATIVE_INFINITY
+ val POS_INF_FLOAT = java.lang.Float.POSITIVE_INFINITY
+
+ val MIN_DOUBLE = -java.lang.Double.MAX_VALUE
+ val EPS_DOUBLE = java.lang.Double.MIN_VALUE
+ val MAX_DOUBLE = java.lang.Double.MAX_VALUE
+ val NaN_DOUBLE = java.lang.Double.NaN
+ val NEG_INF_DOUBLE = java.lang.Double.NEGATIVE_INFINITY
+ val POS_INF_DOUBLE = java.lang.Double.POSITIVE_INFINITY
+
+ val E = java.lang.Math.E
+ val PI = java.lang.Math.PI
+
+ def min(x: Int, y: Int): Int = java.lang.Math.min(x, y)
+ def max(x: Int, y: Int): Int = java.lang.Math.max(x, y)
+
+ def ceil (x: Double): Double = java.lang.Math.ceil(x)
+ def floor(x: Double): Double = java.lang.Math.floor(x)
+ def log (x: Double): Double = java.lang.Math.log(x)
+ def sqrt (x: Double): Double = java.lang.Math.sqrt(x)
+}
diff --git a/src/dotnet-library/scala/compat/Platform.scala b/src/dotnet-library/scala/compat/Platform.scala
new file mode 100644
index 0000000000..11e90a0789
--- /dev/null
+++ b/src/dotnet-library/scala/compat/Platform.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.compat;
+
+
+import java.lang.System
+import Predef.Class
+
+object Platform {
+
+ type StackOverflowError = java.lang.StackOverflowError
+
+ def arraycopy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int): Unit =
+ System.arraycopy(src, srcPos, dest, destPos, length)
+
+ /** create array of the same type as arrayInstance with the given length */
+ def createArray(elemClass: Class, length: Int): AnyRef =
+ java.lang.reflect.Array.newInstance(elemClass, length)
+
+ def getClassForName(name: String): Class = java.lang.Class.forName(name)
+
+ val EOL = System.getProperty("line.separator", "\n")
+
+ def currentTime: Long = System.currentTimeMillis()
+
+ def collectGarbage: Unit = System.gc()
+
+}
diff --git a/src/dotnet-library/scala/compat/StringBuilder.scala b/src/dotnet-library/scala/compat/StringBuilder.scala
new file mode 100644
index 0000000000..d64ec65ff7
--- /dev/null
+++ b/src/dotnet-library/scala/compat/StringBuilder.scala
@@ -0,0 +1,59 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.compat
+
+import java.lang.StringBuffer
+
+final class StringBuilder(str: StringBuffer) {
+
+ def this() = this(new StringBuffer())
+ def this(n: Int) = this(new StringBuffer(n))
+ def this(s: String) = this(new StringBuffer(s))
+
+ def charAt(i: Int): Char = str.charAt(i)
+
+ def setCharAt(index: Int, c: Char): Unit = str.setCharAt(index, c)
+
+ def append(x: Any): StringBuilder = { str.append(x); this }
+ def append(x: Boolean): StringBuilder = { str.append(x); this }
+ def append(x: Byte): StringBuilder = { str.append(x); this }
+ def append(x: Short): StringBuilder = { str.append(x); this }
+ def append(x: Char): StringBuilder = { str.append(x); this }
+ def append(x: Int): StringBuilder = { str.append(x); this }
+ def append(x: Long): StringBuilder = { str.append(x); this }
+ def append(x: Float): StringBuilder = { str.append(x); this }
+ def append(x: Double): StringBuilder = { str.append(x); this }
+ def append(x: String): StringBuilder = { str.append(x); this }
+ def append(x: Array[Char]): StringBuilder = { str.append(x); this }
+ def append(x: Array[Char], start: Int, length: Int): StringBuilder =
+ { str.append(x, start, length); this }
+
+ def insert(at: Int, x: Any): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Boolean): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Byte): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Short): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Char): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Int): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Long): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Float): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Double): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: String): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Array[Char]): StringBuilder = { str.insert(at, x); this }
+ def insert(at: Int, x: Array[Char], start: Int, length: Int): StringBuilder =
+ { str.insert(at, x, start, length); this }
+
+ def length(): Int = str.length()
+
+ def setLength(i: Int) = str.setLength(i)
+
+ override def toString() = str.toString()
+}
diff --git a/src/dotnet-library/scala/concurrent/Actor.scala b/src/dotnet-library/scala/concurrent/Actor.scala
new file mode 100644
index 0000000000..15b77bf3fd
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/Actor.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+import java.lang.Thread
+
+/**
+ * The class <code>Actor</code> ...
+ *
+ * @author Martin Odersky
+ * @version 1.0
+ */
+abstract class Actor extends Thread {
+ private val in = new MailBox
+
+ def send(msg: in.Message) =
+ in.send(msg)
+
+ def receive[a](f: PartialFunction[in.Message, a]): a =
+ if (currentThread == this) in.receive(f)
+ else throw new IllegalArgumentException("receive called not on own process")
+
+ def receiveWithin[a](msec: long)(f: PartialFunction[in.Message, a]): a =
+ if (currentThread == this) in.receiveWithin(msec)(f)
+ else throw new IllegalArgumentException("receiveWithin called not on own process")
+
+ private var pid: Pid = null
+
+ def self = {
+ if (pid eq null) pid = new Pid(this)
+ pid
+ }
+
+ def self_= (p: Pid) = pid = p
+}
+
+
+
diff --git a/src/dotnet-library/scala/concurrent/Channel.scala b/src/dotnet-library/scala/concurrent/Channel.scala
new file mode 100644
index 0000000000..bab6345ab9
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/Channel.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/** This class ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 10/03/2003
+ */
+class Channel[a] {
+ class LinkedList[a] {
+ var elem: a = _
+ var next: LinkedList[a] = null
+ }
+ private var written = new LinkedList[a] // FIFO buffer, realized through
+ private var lastWritten = written // aliasing of a linked list
+ private var nreaders = 0
+
+ /**
+ * @param x ...
+ */
+ def write(x: a) = synchronized {
+ lastWritten.elem = x
+ lastWritten.next = new LinkedList[a]
+ lastWritten = lastWritten.next
+ if (nreaders > 0) notify()
+ }
+
+ def read: a = synchronized {
+ if (null == written.next) {
+ nreaders = nreaders + 1; wait(); nreaders = nreaders - 1
+ }
+ val x = written.elem
+ written = written.next
+ x
+ }
+}
diff --git a/src/dotnet-library/scala/concurrent/Lock.scala b/src/dotnet-library/scala/concurrent/Lock.scala
new file mode 100644
index 0000000000..d20f3806d7
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/Lock.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/** This class ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 10/03/2003
+ */
+class Lock {
+ var available = true
+
+ def acquire = synchronized {
+ while (!available) wait()
+ available = false
+ }
+
+ def release = synchronized {
+ available = true
+ notify()
+ }
+}
diff --git a/src/dotnet-library/scala/concurrent/MailBox.scala b/src/dotnet-library/scala/concurrent/MailBox.scala
new file mode 100644
index 0000000000..b6ba205fa2
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/MailBox.scala
@@ -0,0 +1,176 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/** This class ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 12/03/2003
+ */
+//class MailBox with Monitor with LinkedListQueueCreator {
+class MailBox extends AnyRef with ListQueueCreator {
+
+ type Message = AnyRef
+
+ private abstract class PreReceiver {
+ var msg: Message = null
+ def isDefinedAt(msg: Message): boolean
+ }
+
+ private class Receiver[a](receiver: PartialFunction[Message, a]) extends PreReceiver {
+
+ def isDefinedAt(msg: Message) = receiver.isDefinedAt(msg)
+
+ def receive(): a = synchronized {
+ while (msg eq null) wait()
+ receiver(msg)
+ }
+
+ def receiveWithin(msec: long): a = synchronized {
+ if (msg eq null) wait(msec)
+ receiver(if (msg ne null) msg else TIMEOUT)
+ }
+ }
+
+ private val messageQueue = queueCreate[Message]
+ private val receiverQueue = queueCreate[PreReceiver]
+
+ /** Unconsumed messages. */
+ private var sent = messageQueue.make
+
+ /** Pending receivers. */
+ private var receivers = receiverQueue.make
+
+ /**
+ * Check whether the receiver can be applied to an unconsumed message.
+ * If yes, the message is extracted and associated with the receiver.
+ * Otherwise the receiver is appended to the list of pending receivers.
+ */
+ private def scanSentMsgs[a](receiver: Receiver[a]): unit = synchronized {
+ messageQueue.extractFirst(sent, msg => receiver.isDefinedAt(msg)) match {
+ case None => receivers = receiverQueue.append(receivers, receiver)
+ case Some{msg, withoutMsg} => {
+ sent = withoutMsg
+ receiver.msg = msg
+ }
+ }
+ }
+
+ /**
+ * First check whether a pending receiver is applicable to the sent
+ * message. If yes, the receiver is notified. Otherwise the message
+ * is appended to the linked list of sent messages.
+ */
+ def send(msg: Message): unit = synchronized {
+ receiverQueue.extractFirst(receivers, r => r.isDefinedAt(msg)) match {
+ case None => sent = messageQueue.append(sent, msg)
+ case Some{receiver, withoutReceiver} => {
+ receivers = withoutReceiver
+ receiver.msg = msg
+ receiver synchronized { receiver.notify() }
+ }
+ }
+ }
+
+ /**
+ * Block until there is a message in the mailbox for which the processor
+ * <code>f</code> is defined.
+ */
+ def receive[a](f: PartialFunction[Message, a]): a = {
+ val r = new Receiver(f)
+ scanSentMsgs(r)
+ r.receive()
+ }
+
+ /**
+ * Block until there is a message in the mailbox for which the processor
+ * <code>f</code> is defined or the timeout is over.
+ */
+ def receiveWithin[a](msec: long)(f: PartialFunction[Message, a]): a = {
+ val r = new Receiver(f)
+ scanSentMsgs(r)
+ r.receiveWithin(msec)
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////
+
+/**
+* Module for dealing with queues.
+*/
+trait QueueModule[a] {
+ /** Type of queues. */
+ type t
+ /** Create an empty queue. */
+ def make: t
+ /** Append an element to a queue. */
+ def append(l: t, x: a): t
+ /** Extract an element satisfying a predicate from a queue. */
+ def extractFirst(l: t, p: a => boolean): Option[{a, t}]
+}
+
+/** Inefficient but simple queue module creator. */
+trait ListQueueCreator {
+ def queueCreate[a]: QueueModule[a] = new QueueModule[a] {
+ type t = List[a]
+ def make: t = Nil
+ def append(l: t, x: a): t = l ::: x :: Nil
+ def extractFirst(l: t, p: a => boolean): Option[{a, t}] =
+ l match {
+ case Nil => None
+ case head :: tail =>
+ if (p(head))
+ Some{head, tail}
+ else
+ extractFirst(tail, p) match {
+ case None => None
+ case Some{x, without_x} => Some{x, head :: without_x}
+ }
+ }
+ }
+}
+
+/** Efficient queue module creator based on linked lists. */
+trait LinkedListQueueCreator {
+ import scala.collection.mutable.LinkedList
+ def queueCreate[a >: Null <: AnyRef]: QueueModule[a] = new QueueModule[a] {
+ type t = {LinkedList[a], LinkedList[a]} // fst = the list, snd = last elem
+ def make: t = {
+ val l = new LinkedList[a](null, null)
+ {l, l}
+ }
+ def append(l: t, x: a): t = {
+ val atTail = new LinkedList(x, null)
+ l._2 append atTail;
+ {l._1, atTail}
+ }
+ def extractFirst(l: t, p: a => boolean): Option[{a, t}] = {
+ var xs = l._1
+ var xs1 = xs.next
+ while ((xs1 ne null) && !p(xs1.elem)) {
+ xs = xs1
+ xs1 = xs1.next
+ }
+ if (xs1 ne null) {
+ xs.next = xs1.next
+ if (xs.next eq null)
+ Some(Pair(xs1.elem, Pair(l._1, xs)))
+ else
+ Some{xs1.elem, l}
+ }
+ else
+ None
+ }
+ }
+}
+
diff --git a/src/dotnet-library/scala/concurrent/NameServer.scala b/src/dotnet-library/scala/concurrent/NameServer.scala
new file mode 100644
index 0000000000..bb15def799
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/NameServer.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+/**
+ * @author Erik Stenman
+ * @version 1.0, 01/10/2003
+ */
+object NameServer {
+
+ val names = new scala.collection.mutable.HashMap[Symbol, Process]
+
+ /**
+ * @param name ...
+ * @param proc ...
+ */
+ def register(name: Symbol, proc: Process) = {
+ if (names contains name) throw new IllegalArgumentException("Name:" + name + " already registred")
+ names += name -> proc
+ }
+
+ def unregister(name: Symbol) =
+ if (names contains name) names -= name
+ else throw new IllegalArgumentException("Name:" + name + " not registred")
+
+ /**
+ * @param name ...
+ * @return ...
+ */
+ def whereis(name: Symbol): Option[Process] =
+ names.get(name)
+
+ def send(name: Symbol, msg: MailBox#Message) =
+ names(name).send(msg)
+
+}
diff --git a/src/dotnet-library/scala/concurrent/Pid.scala b/src/dotnet-library/scala/concurrent/Pid.scala
new file mode 100644
index 0000000000..6fa1f24123
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/Pid.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/**
+ * The class <code>Pid</code> provides process identifiers
+ * to thread-based actors.
+ *
+ * @author Philipp Haller
+ * @version 1.0
+ */
+class Pid(actor: Actor) {
+ private var target = actor
+
+ def !(msg: MailBox#Message) = target send msg
+
+ def spawn(body: Actor => Unit): Pid = {
+ val a = new Actor {
+ override def run: Unit = body(this)
+ }
+ a.start
+ a.self
+ }
+
+ def spawnReceive(cases: PartialFunction[MailBox#Message, Unit]) = {
+ val a = new Actor {
+ override def run: Unit = receive(cases)
+ }
+ a.start
+ a.self
+ }
+
+ override def hashCode() = target.hashCode()
+
+ override def equals(that: Any) =
+ this.hashCode() == that.hashCode()
+
+ override def toString() = "Pid(" + target + ")"
+}
diff --git a/src/dotnet-library/scala/concurrent/Process.scala b/src/dotnet-library/scala/concurrent/Process.scala
new file mode 100644
index 0000000000..3e8589e7ef
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/Process.scala
@@ -0,0 +1,93 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+/** This object ...
+ *
+ * @author Erik Stenman
+ * @version 1.0, 01/10/2003
+ */
+object Process {
+
+ def spawn(body: => Unit): Process = {
+ val p = new Process(body)
+ p.start()
+ p
+ }
+
+ def spawn_link(body: => Unit): Process =
+ self.spawn_link(body)
+
+ def send(p: Process, msg: MailBox#Message) =
+ p.send(msg)
+
+ def receive[a](f: PartialFunction[MailBox#Message, a]): a =
+ self.receive(f)
+
+ def receiveWithin[a](msec: long)(f: PartialFunction[MailBox#Message, a]): a =
+ self.receiveWithin(msec)(f)
+
+ /**
+ * @return the self process
+ * @throws Predef.UnsupportedOperationException if self called outside a process.
+ */
+ def self: Process =
+ if (currentThread.isInstanceOf[Process])
+ currentThread.asInstanceOf[Process]
+ else
+ throw new UnsupportedOperationException("Self called outside a process")
+
+ def exit(p: Process, reason: AnyRef) =
+ p.exit(reason)
+
+}
+
+class Process(body: => Unit) extends Actor() {
+ private var exitReason: AnyRef = null
+ private var links: List[Process] = Nil
+
+ override def run() =
+ try {
+ body
+ }
+ catch {
+ case _: java.lang.InterruptedException =>
+ signal(exitReason)
+ case (exitSignal) =>
+ signal(exitSignal)
+ }
+
+ private def signal(s: MailBox#Message) =
+ links.foreach { p: Process => p.send({'EXIT, this, s}) }
+
+ def !(msg: MailBox#Message) =
+ send(msg)
+
+ def link(p: Process) =
+ links = p::links
+
+ def spawn_link(body: => Unit) = {
+ val p = new Process(body)
+ p.link(this)
+ p.start()
+ p
+ }
+
+ //def self = this
+
+ def exit(reason: AnyRef): Unit = {
+ exitReason = reason
+ interrupt()
+ }
+
+}
diff --git a/src/dotnet-library/scala/concurrent/SyncChannel.scala b/src/dotnet-library/scala/concurrent/SyncChannel.scala
new file mode 100644
index 0000000000..afbf067881
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/SyncChannel.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/** The class <code>SyncChannel</code> ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 10/03/2003
+ */
+class SyncChannel[a] {
+ private var data: a = _
+ private var reading = false
+ private var writing = false
+
+ def await(cond: => Boolean) = while (!cond) wait()
+
+ def write(x: a) = synchronized {
+ await(!writing)
+ data = x
+ writing = true
+ if (reading) notifyAll()
+ else await(reading)
+ }
+
+ def read: a = synchronized {
+ await(!reading)
+ reading = true
+ await(writing)
+ val x = data
+ writing = false
+ reading = false
+ notifyAll()
+ x
+ }
+}
diff --git a/src/dotnet-library/scala/concurrent/SyncVar.scala b/src/dotnet-library/scala/concurrent/SyncVar.scala
new file mode 100644
index 0000000000..796133fc00
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/SyncVar.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+/** The class <code>SyncVar</code> ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 10/03/2003
+ */
+class SyncVar[a] {
+ private var isDefined: Boolean = false
+ private var value: a = _
+
+ def get = synchronized {
+ if (!isDefined) wait()
+ value
+ }
+
+ def set(x: a) = synchronized {
+ value = x
+ isDefined = true
+ notifyAll()
+ }
+
+ def isSet: Boolean = synchronized {
+ isDefined
+ }
+
+ def unset = synchronized {
+ isDefined = false
+ }
+
+}
diff --git a/src/dotnet-library/scala/concurrent/TIMEOUT.scala b/src/dotnet-library/scala/concurrent/TIMEOUT.scala
new file mode 100644
index 0000000000..055a81d70e
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/TIMEOUT.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+/**
+ * The message sent to a message box when the period specified in
+ * <code>receiveWithin</code> expires.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 10/03/2003
+ */
+case object TIMEOUT
diff --git a/src/dotnet-library/scala/concurrent/jolib.scala b/src/dotnet-library/scala/concurrent/jolib.scala
new file mode 100644
index 0000000000..afa23c0cb3
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/jolib.scala
@@ -0,0 +1,80 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+/**
+ * Library for using join-calculus concurrent primitives in Scala.
+ *
+ * @author Vincent Cremet
+ * @version 1.0, 17/10/2003
+ */
+object jolib {
+
+ type Pattern = List[Signal]
+
+ type Rule = PartialFunction[List[Any], unit]
+
+ /////////////////// JOIN DEFINITION /////////////////////////
+
+ class Join {
+
+ private var ruls: List[{Pattern, Rule}] = null
+
+ def canMatch(p: Pattern) =
+ p forall { s => !s.queue.isEmpty }
+
+ def values(p: Pattern): List[Any] =
+ p map { s => s.queue.dequeue: Any }
+
+ def rules(rs: {Pattern, Rule}*) =
+ ruls = rs.asInstanceOf[List[{Pattern, Rule}]]
+
+ def tryMatch =
+ (ruls find { case {p, _} => canMatch(p) }) match {
+ case None => () => ()
+ case Some{p, r} => {
+ val args = values(p)
+ () => concurrent.ops.spawn(r(args))
+ }
+ }
+
+ }
+
+ /////////////////// SIGNALS /////////////////////////
+
+ abstract class Signal(join: Join) {
+ type C
+ val queue = new collection.mutable.Queue[C]
+ def tryReduction(x: C): unit = {
+ val continuation = join synchronized {
+ queue.enqueue(x)
+ join.tryMatch
+ }
+ continuation()
+ }
+ }
+
+ abstract class Asynchr(join: Join) extends Signal(join) {
+ def apply(x: C): unit = tryReduction(x)
+ }
+
+ abstract class Synchr[a](join: Join) extends Signal(join) {
+ type C <: SyncVar[a]
+ def apply(x: C): a = {
+ tryReduction(x)
+ x.get
+ }
+ }
+
+}
+
diff --git a/src/dotnet-library/scala/concurrent/ops.scala b/src/dotnet-library/scala/concurrent/ops.scala
new file mode 100644
index 0000000000..1c5b0e1713
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/ops.scala
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+import java.lang.Thread
+
+/** The object <code>ops</code> ...
+ *
+ * @author Martin Odersky
+ * @version 1.0, 12/03/2003
+ */
+object ops {
+
+ /**
+ * @param p ...
+ */
+ def spawn(p: => Unit) = {
+ val t = new Thread() { override def run() = p }
+ t.start()
+ }
+
+ /**
+ * @param p ...
+ * @return ...
+ */
+ def future[a](p: => a): () => a = {
+ val result = new SyncVar[a]
+ spawn { result set p }
+ () => result.get
+ }
+
+ /**
+ * @param xp ...
+ * @param yp ...
+ * @return ...
+ */
+ def par[a, b](xp: => a, yp: => b): {a, b} = {
+ val y = new SyncVar[b]
+ spawn { y set yp }
+ {xp, y.get}
+ }
+
+ /**
+ * @param start ...
+ * @param end ...
+ * @param p ...
+ */
+ def replicate(start: Int, end: Int)(p: Int => Unit): Unit = {
+ if (start == end)
+ ()
+ else if (start + 1 == end)
+ p(start)
+ else {
+ val mid = (start + end) / 2
+ spawn { replicate(start, mid)(p) }
+ replicate(mid, end)(p)
+ }
+ }
+
+/*
+ def parMap[a,b](f: a => b, xs: Array[a]): Array[b] = {
+ val results = new Array[b](xs.length);
+ replicate(0, xs.length) { i => results(i) = f(xs(i)) }
+ results
+ }
+*/
+
+}
diff --git a/src/dotnet-library/scala/concurrent/pilib.scala b/src/dotnet-library/scala/concurrent/pilib.scala
new file mode 100644
index 0000000000..bc76821884
--- /dev/null
+++ b/src/dotnet-library/scala/concurrent/pilib.scala
@@ -0,0 +1,205 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.concurrent
+
+
+/** <p>
+ * Library for using Pi-calculus concurrent primitives in Scala. As an
+ * example, the definition of a two-place buffer using the <code>pilib</code>
+ * library looks like:
+ * </p><pre>
+ * <b>def</b> Buffer[a](put: Chan[a], get: Chan[a]): unit = {
+ * <b>def</b> B0: unit = choice ( put * { x => B1(x) } );
+ * <b>def</b> B1(x: a): unit = choice ( get(x) * B0, put * { y => B2(x, y) } )
+ * <b>def</b> B2(x: a, y: a): unit = choice ( get(x) * B1(y) )
+ * B0
+ * }
+ * </pre>
+ *
+ * @see <a href="http://scala-lang.org/docu/related.html">PiLib: A Hosted Language for Pi-Calculus Style Concurrency</a>
+ * @author Vincent Cremet, Martin Odersky
+ * @version 1.0
+ */
+object pilib {
+
+ /////////////////////////// SPAWN //////////////////////////////
+
+ /**
+ * Run several processes in parallel using the following syntax:
+ * <code>spawn &lt; p_1 | ... | p_n &gt;</code>
+ */
+ abstract class Spawn {
+ def <(p: => unit): Spawn
+ def |(p: => unit): Spawn
+ def > : unit
+ }
+ val spawn = new Spawn {
+ //object spawn extends Spawn { // BUG !
+ def <(p: => unit): Spawn = { scala.concurrent.ops.spawn(p); this }
+ def |(p: => unit): Spawn = { scala.concurrent.ops.spawn(p); this }
+ def > : unit = ()
+ }
+
+ //////////////////////// GUARDED PROCESSES /////////////////////////
+
+ /** Untyped channel. */
+ class UChan {
+ /** Default log function. */
+ var log = (x: Any) => ()
+ }
+
+ /** An untyped guarded process.
+ *
+ * @param n channel name
+ * @param polarity input (true) or output (false)
+ * @param v transmitted value
+ * @param c continuation
+ */
+ case class UGP(n: UChan, polarity: boolean, v: Any, c: Any => Any)
+
+ /** Typed guarded process. */
+ class GP[a](n: UChan, polarity: boolean, v: Any, c: Any => a) {
+ val untyped = UGP(n, polarity, v, c)
+ }
+
+ ////////////////////////// CHANNELS //////////////////////////////
+
+ /**
+ * Name on which one can emit, receive or that can be emitted or received
+ * during a communication.
+ */
+ class Chan[a] extends UChan with Function1[a, Product[a]] {
+
+ var defaultValue: a = _
+
+ /** Creates an input guarded process. */
+ def input[b](c: a => b) =
+ new GP(this, true, (), x => c(x.asInstanceOf[a]))
+
+ /** Creates an input guarded process. */
+ def output[b](v: a, c: () => b) =
+ new GP(this, false, v, x => c())
+
+ /** Blocking read. */
+ def read = {
+ var res: a = defaultValue
+ choice ( input(x => res = x) )
+ res
+ }
+
+ /** Blocking write. */
+ def write(x: a) =
+ choice ( output(x, () => ()) )
+
+ /** Syntactic sugar for input. */
+ def *[b](f: a => b) =
+ input(f);
+
+ /** Syntactic sugar for output. */
+ def apply(v: a) =
+ new Product(this, v)
+
+ /** Attach a function to be evaluated at each communication event
+ * on this channel. Replace previous attached function.
+ */
+ def attach(f: a => unit) =
+ log = x => f(x.asInstanceOf[a])
+ }
+
+ class Product[a](c: Chan[a], v: a) {
+ def *[b](f: => b) = c.output(v, () => f)
+ }
+
+ //////////////////// SUM OF GUARDED PROCESSES //////////////////////
+
+ case class Sum(gs: List[UGP]) {
+
+ /** Continuation of the sum. */
+ var cont: () => Any = _
+
+ var initialized = false
+
+ /** Block if not initialized otherwise continue with the
+ * continuation.
+ */
+ def continue = synchronized {
+ if (!initialized) wait()
+ cont()
+ }
+
+ /** Set the values of parameters and awake the sleeping sum.
+ *
+ * @param f ...
+ */
+ def set(f: () => Any) = synchronized {
+ cont = f
+ initialized = true
+ notify()
+ }
+ }
+
+ /////////////////////////// COMMUNICATION //////////////////////////
+
+ private var sums: List[Sum] = Nil
+
+ /** Test if two lists of guarded processes can communicate.
+ *
+ * @param gs1 ...
+ * @param gs2 ...
+ * @return ...
+ */
+ private def matches(gs1: List[UGP], gs2: List[UGP]): Option[{() => unit, () => Any, () => Any}] =
+ {gs1, gs2} match {
+ case {Nil, _} => None
+ case {_, Nil} => None
+ case {UGP(a1, d1, v1, c1) :: rest1, UGP(a2, d2, v2, c2) :: rest2} =>
+ if (a1 == a2 && d1 == !d2)
+ Some{(() => if (d1) a1.log(v2) else a1.log(v1)), (() => c1(v2)), (() => c2(v1))}
+ else matches(gs1, rest2) match {
+ case None => matches(rest1, gs2)
+ case Some(t) => Some(t)
+ }
+ }
+
+ /** Test if the given sum can react with one of the pending sums.
+ * If yes then do the reaction otherwise append the sum at the end
+ * of the pending sums.
+ *
+ * @param s1 ...
+ * @param ss ...
+ * @return ...
+ */
+ private def compare(s1: Sum, ss: List[Sum]): List[Sum] =
+ ss match {
+ case Nil => ss ::: List(s1)
+ case s2 :: rest => matches(s1.gs, s2.gs) match {
+ case None => s2 :: compare(s1, rest)
+ case Some{log, c1, c2} =>
+ log()
+ s1.set(c1)
+ s2.set(c2)
+ rest
+ }
+ }
+
+ /** Pi-calculus non-deterministic choice.
+ *
+ * @param s ...
+ * @return ...
+ */
+ def choice[a](s: GP[a]*): a = {
+ val sum = Sum(s.toList map { x => x.untyped })
+ synchronized { sums = compare(sum, sums) }
+ (sum.continue).asInstanceOf[a]
+ }
+
+}
diff --git a/src/dotnet-library/scala/deprecated.scala b/src/dotnet-library/scala/deprecated.scala
new file mode 100755
index 0000000000..b642d92f8d
--- /dev/null
+++ b/src/dotnet-library/scala/deprecated.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: remote.scala 9400 2006-11-28 17:22:45 +0000 (Tue, 28 Nov 2006) michelou $
+
+
+package scala
+
+/**
+ * An attribute that designates the definition to which it is applied as deprecated.
+ * Access to the member then generates a deprecated warning.
+ */
+class deprecated extends StaticAttribute {}
diff --git a/src/dotnet-library/scala/io/BytePickle.scala b/src/dotnet-library/scala/io/BytePickle.scala
new file mode 100644
index 0000000000..831f4671d0
--- /dev/null
+++ b/src/dotnet-library/scala/io/BytePickle.scala
@@ -0,0 +1,318 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.io
+
+
+import scala.collection.mutable.{HashMap,ArrayBuffer}
+
+/**
+ * Pickler combinators.
+ * Based on a Haskell library by Andrew Kennedy,
+ * see <a href="http://research.microsoft.com/~akenn/fun/"
+ * target="_top">http://research.microsoft.com/~akenn/fun/</a>.
+ *
+ * @author Philipp Haller (philipp.haller&lt;at&gt;epfl.ch)
+ * @version 1.0
+ */
+object BytePickle {
+ abstract class SPU[t] {
+ def appP(a: t, state: PicklerState): PicklerState
+ def appU(state: UnPicklerState): Pair[t, UnPicklerState]
+ }
+
+ def pickle[t](p: SPU[t], a: t): Array[byte] =
+ p.appP(a, new PicklerState(new Array[byte](0), new PicklerEnv)).stream
+
+ def unpickle[t](p: SPU[t], stream: Array[byte]): t =
+ p.appU(new UnPicklerState(stream, new UnPicklerEnv))._1
+
+ abstract class PU[t] {
+ def appP(a: t, state: Array[byte]): Array[byte]
+ def appU(state: Array[byte]): Pair[t, Array[byte]]
+ }
+
+ def upickle[t](p: PU[t], a: t): Array[byte] =
+ p.appP(a, new Array[byte](0))
+
+ def uunpickle[t](p: PU[t], stream: Array[byte]): t =
+ p.appU(stream)._1
+
+ class PicklerEnv extends HashMap[Any, int] {
+ private var cnt: int = 64
+ def nextLoc() = { cnt = cnt + 1; cnt }
+ }
+
+ class UnPicklerEnv extends HashMap[int, Any] {
+ private var cnt: int = 64
+ def nextLoc() = { cnt = cnt + 1; cnt }
+ }
+
+ class PicklerState(val stream: Array[byte], val dict: PicklerEnv)
+ class UnPicklerState(val stream: Array[byte], val dict: UnPicklerEnv)
+
+ abstract class RefDef
+ case class Ref() extends RefDef
+ case class Def() extends RefDef
+
+ def refDef: PU[RefDef] = new PU[RefDef] {
+ def appP(b: RefDef, s: Array[byte]): Array[byte] =
+ b match {
+ case Ref() => Array.concat(s, (List[byte](0)).toArray)
+ case Def() => Array.concat(s, (List[byte](1)).toArray)
+ };
+ def appU(s: Array[byte]): Pair[RefDef, Array[byte]] =
+ if (s(0) == 0) Pair(Ref(), s.subArray(1, s.length))
+ else Pair(Def(), s.subArray(1, s.length));
+ }
+
+ val REF = 0
+ val DEF = 1
+
+ def unat: PU[int] = new PU[int] {
+ def appP(n: int, s: Array[byte]): Array[byte] =
+ Array.concat(s, nat2Bytes(n));
+ def appU(s: Array[byte]): Pair[int, Array[byte]] = {
+ var num = 0
+ def readNat: int = {
+ var b = 0;
+ var x = 0;
+ do {
+ b = s(num)
+ num = num + 1
+ x = (x << 7) + (b & 0x7f);
+ } while ((b & 0x80) != 0);
+ x
+ }
+ Pair(readNat, s.subArray(num, s.length))
+ }
+ }
+
+ def share[a](pa: SPU[a]): SPU[a] = new SPU[a] {
+ def appP(v: a, state: PicklerState): PicklerState = {
+ /*
+ - is there some value equal to v associated with a location l in the pickle environment?
+ - yes: write REF-tag to outstream together with l
+ - no:
+ write DEF-tag to outstream
+ record current location l of outstream
+ --> serialize value
+ add entry to pickle environment, mapping v onto l
+ */
+ val pe = state.dict
+ pe.get(v) match {
+ case None =>
+ val sPrime = refDef.appP(Def(), state.stream)
+ val l = pe.nextLoc()
+
+ val sPrimePrime = pa.appP(v, new PicklerState(sPrime, pe))
+
+ pe.update(v, l)
+
+ return sPrimePrime
+ case Some(l) =>
+ val sPrime = refDef.appP(Ref(), state.stream)
+
+ return new PicklerState(unat.appP(l, sPrime), pe)
+ }
+ }
+ def appU(state: UnPicklerState): Pair[a, UnPicklerState] = {
+ /*
+ - first, read tag (i.e. DEF or REF)
+ - if REF:
+ read location l
+ look up resulting value in unpickler environment
+ - if DEF:
+ record location l of input stream
+ --> deserialize value v with argument deserializer
+ add entry to unpickler environment, mapping l onto v
+ */
+ val upe = state.dict
+ val res = refDef.appU(state.stream)
+ res._1 match {
+ case Def() =>
+ val l = upe.nextLoc
+ val res2 = pa.appU(new UnPicklerState(res._2, upe))
+ upe.update(l, res2._1)
+ return res2
+ case Ref() =>
+ val res2 = unat.appU(res._2) // read location
+ upe.get(res2._1) match { // lookup value in unpickler env
+ case None => throw new IllegalArgumentException("invalid unpickler environment"); return null
+ case Some(v) => return Pair(v.asInstanceOf[a], new UnPicklerState(res2._2, upe))
+ }
+ }
+ }
+ }
+
+ def ulift[t](x: t): PU[t] = new PU[t] {
+ def appP(a: t, state: Array[byte]): Array[byte] =
+ if (x != a) { throw new IllegalArgumentException("value to be pickled (" + a + ") != " + x); state }
+ else state;
+ def appU(state: Array[byte]) = Pair(x, state);
+ }
+
+ def lift[t](x: t): SPU[t] = new SPU[t] {
+ def appP(a: t, state: PicklerState): PicklerState =
+ if (x != a) { /*throw new IllegalArgumentException("value to be pickled (" + a + ") != " + x);*/ state }
+ else state;
+ def appU(state: UnPicklerState) = Pair(x, state);
+ }
+
+ def usequ[t,u](f: u => t, pa: PU[t], k: t => PU[u]): PU[u] = new PU[u] {
+ def appP(b: u, s: Array[byte]): Array[byte] = {
+ val a = f(b)
+ val sPrime = pa.appP(a, s)
+ val pb = k(a)
+ val sPrimePrime = pb.appP(b, sPrime)
+ sPrimePrime
+ }
+ def appU(s: Array[byte]): Pair[u, Array[byte]] = {
+ val resPa = pa.appU(s)
+ val a = resPa._1
+ val sPrime = resPa._2
+ val pb = k(a)
+ pb.appU(sPrime)
+ }
+ }
+
+ def sequ[t,u](f: u => t, pa: SPU[t], k: t => SPU[u]): SPU[u] = new SPU[u] {
+ def appP(b: u, s: PicklerState): PicklerState = {
+ val a = f(b)
+ val sPrime = pa.appP(a, s)
+ val pb = k(a)
+ pb.appP(b, sPrime)
+ }
+ def appU(s: UnPicklerState): Pair[u, UnPicklerState] = {
+ val resPa = pa.appU(s)
+ val a = resPa._1
+ val sPrime = resPa._2
+ val pb = k(a)
+ pb.appU(sPrime)
+ }
+ }
+
+ def upair[a,b](pa: PU[a], pb: PU[b]): PU[Pair[a,b]] = {
+ def fst(p: Pair[a,b]): a = p._1
+ def snd(p: Pair[a,b]): b = p._2
+ usequ(fst, pa, (x: a) => usequ(snd, pb, (y: b) => ulift(Pair(x, y))))
+ }
+
+ def pair[a,b](pa: SPU[a], pb: SPU[b]): SPU[Pair[a,b]] = {
+ def fst(p: Pair[a,b]): a = p._1
+ def snd(p: Pair[a,b]): b = p._2
+ sequ(fst, pa, (x: a) => sequ(snd, pb, (y: b) => lift(Pair(x, y))))
+ }
+
+ def triple[a,b,c](pa: SPU[a], pb: SPU[b], pc: SPU[c]): SPU[Triple[a,b,c]] = {
+ def fst(p: Triple[a,b,c]): a = p._1
+ def snd(p: Triple[a,b,c]): b = p._2
+ def trd(p: Triple[a,b,c]): c = p._3
+
+ sequ(fst, pa,
+ (x: a) => sequ(snd, pb,
+ (y: b) => sequ(trd, pc,
+ (z: c) => lift(Triple(x, y, z)))))
+ }
+
+ def uwrap[a,b](i: a => b, j: b => a, pa: PU[a]): PU[b] =
+ usequ(j, pa, (x: a) => ulift(i(x)))
+
+ def wrap[a,b](i: a => b, j: b => a, pa: SPU[a]): SPU[b] =
+ sequ(j, pa, (x: a) => lift(i(x)))
+
+ def appendByte(a: Array[byte], b: int): Array[byte] =
+ Array.concat(a, (List[byte](b.asInstanceOf[byte])).toArray)
+
+ def nat2Bytes(x: int): Array[byte] = {
+ val buf = new ArrayBuffer[byte]
+ def writeNatPrefix(x: int): unit = {
+ val y = x >>> 7;
+ if (y != 0) writeNatPrefix(y);
+ buf += ((x & 0x7f) | 0x80).asInstanceOf[byte];
+ }
+ val y = x >>> 7;
+ if (y != 0) writeNatPrefix(y);
+ buf += (x & 0x7f).asInstanceOf[byte];
+ buf.toArray
+ }
+
+ def nat: SPU[int] = new SPU[int] {
+ def appP(n: int, s: PicklerState): PicklerState = {
+ new PicklerState(Array.concat(s.stream, nat2Bytes(n)), s.dict);
+ }
+ def appU(s: UnPicklerState): Pair[int,UnPicklerState] = {
+ var num = 0
+ def readNat: int = {
+ var b = 0
+ var x = 0
+ do {
+ b = s.stream(num)
+ num = num + 1
+ x = (x << 7) + (b & 0x7f);
+ } while ((b & 0x80) != 0);
+ x
+ }
+ Pair(readNat, new UnPicklerState(s.stream.subArray(num, s.stream.length), s.dict))
+ }
+ }
+
+ def byte: SPU[byte] = new SPU[byte] {
+ def appP(b: byte, s: PicklerState): PicklerState =
+ new PicklerState(Array.concat(s.stream, (List[byte](b)).toArray), s.dict);
+ def appU(s: UnPicklerState): Pair[byte, UnPicklerState] =
+ Pair(s.stream(0), new UnPicklerState(s.stream.subArray(1, s.stream.length), s.dict));
+ }
+
+ def string: SPU[String] =
+ share(wrap((a:Array[byte]) => UTF8Codec.decode(a, 0, a.length), (s:String) => UTF8Codec.encode(s), bytearray));
+
+ def bytearray: SPU[Array[byte]] = {
+ wrap((l:List[byte]) => l.toArray, .toList, list(byte))
+ }
+
+ def bool: SPU[boolean] = {
+ def toEnum(b: boolean) = if (b) 1 else 0
+ def fromEnum(n: int) = if (n == 0) false else true
+ wrap(fromEnum, toEnum, nat)
+ }
+
+ def ufixedList[a](pa: PU[a])(n: int): PU[List[a]] = {
+ def pairToList(p: Pair[a,List[a]]): List[a] =
+ p._1 :: p._2;
+ def listToPair(l: List[a]): Pair[a,List[a]] =
+ l match { case x :: xs => Pair(x, xs) }
+
+ if (n == 0) ulift(Nil)
+ else
+ uwrap(pairToList, listToPair, upair(pa, ufixedList(pa)(n-1)))
+ }
+
+ def fixedList[a](pa: SPU[a])(n: int): SPU[List[a]] = {
+ def pairToList(p: Pair[a,List[a]]): List[a] =
+ p._1 :: p._2;
+ def listToPair(l: List[a]): Pair[a,List[a]] =
+ l match { case x :: xs => Pair(x, xs) }
+
+ if (n == 0) lift(Nil)
+ else
+ wrap(pairToList, listToPair, pair(pa, fixedList(pa)(n-1)))
+ }
+
+ def list[a](pa: SPU[a]): SPU[List[a]] =
+ sequ((l: List[a])=>l.length, nat, fixedList(pa));
+
+ def ulist[a](pa: PU[a]): PU[List[a]] =
+ usequ((l:List[a]) => l.length, unat, ufixedList(pa));
+
+ def data[a](tag: a => int, ps: List[()=>SPU[a]]): SPU[a] =
+ sequ(tag, nat, (x: int)=> ps.apply(x)());
+}
diff --git a/src/dotnet-library/scala/io/Position.scala b/src/dotnet-library/scala/io/Position.scala
new file mode 100644
index 0000000000..b31b22c71c
--- /dev/null
+++ b/src/dotnet-library/scala/io/Position.scala
@@ -0,0 +1,108 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.io
+
+
+import compat.StringBuilder
+
+/** <p>
+ * The object <code>Position</code> provides convenience methods to encode
+ * line and column number in one single integer. The encode line (column)
+ * numbers range from 0 to <code>LINE_MASK</code>
+ * (<code>COLUMN_MASK</code>), where 0 indicates that the line (column) is
+ * the undefined and 1 represents the first line (column). Line (Column)
+ * numbers greater than <code>LINE_MASK</code>
+ * (<code>COLUMN_MASK</code>) are replaced by <code>LINE_MASK</code>
+ * (<code>COLUMN_MASK</code>). Furthermore, if the encoded line number is
+ * <code>LINE_MASK</code>, the column number is always set to 0.
+ * </p>
+ * <p>
+ * The following properties hold:
+ * </p>
+ * <ul>
+ * <li>
+ * the undefined position is 0: <code>encode(0,0) == 0</code>
+ * </li>
+ * <li>
+ * encodings are non-negative : <code>encode(line,column) >= 0</code>
+ * </li>
+ * <li>
+ * position order is preserved:
+ * <code>(line1 &lt; line2) || (line1 == line2 &amp;&amp; column1 &lt; column2)</code>
+ * <div>implies</div>
+ * <code>encode(line1,column1) &lt;= encode(line2,column2)</code>
+ * </li>
+ * </ul>
+ *
+ * @author Burak Emir (translated from work by Matthias Zenger and others)
+ */
+object Position {
+
+ /** Number of bits used to encode the line number */
+ final val LINE_BITS = 20
+ /** Number of bits used to encode the column number */
+ final val COLUMN_BITS = 31 - LINE_BITS // no negatives => 31
+
+ /** Mask to decode the line number */
+ final val LINE_MASK = (1 << LINE_BITS) - 1
+ /** Mask to decode the column number */
+ final val COLUMN_MASK = (1 << COLUMN_BITS) - 1
+
+ /** The undefined position */
+ final val NOPOS = 0
+
+ /** The first position in a source file */
+ final val FIRSTPOS = encode(1, 1)
+
+ //########################################################################
+ // Public Functions
+
+ /** Encodes a position into a single integer. */
+ final def encode(line: Int, column: Int): Int = {
+ var line1, column1 = 0
+ if (line < 0)
+ throw new IllegalArgumentException(line + " < 0")
+ if ((line == 0) && (column != 0))
+ throw new IllegalArgumentException(line + "," + column + " not allowed")
+ if (column < 0)
+ throw new IllegalArgumentException(line + "," + column + " not allowed")
+
+ {if (line >= LINE_MASK) {
+ line1 = LINE_MASK
+ column1 = 0
+ } else {
+ line1 = line
+ if (column > COLUMN_MASK)
+ column1 = COLUMN_MASK
+ else
+ column1 = column
+ }}
+ {(line1 << COLUMN_BITS) | column1;}
+ }
+
+ /** Returns the line number of the encoded position. */
+ final def line(pos: Int): Int =
+ (pos >> COLUMN_BITS) & LINE_MASK
+
+ /** Returns the column number of the encoded position. */
+ final def column(pos: Int): Int =
+ pos & COLUMN_MASK
+
+ /** Returns a string representation of the encoded position. */
+ def toString(pos: Int): String = {
+ val sb = new StringBuilder()
+ sb.append(line(pos))
+ sb.append(':')
+ sb.append(column(pos))
+ sb.toString()
+ }
+}
diff --git a/src/dotnet-library/scala/io/Source.scala b/src/dotnet-library/scala/io/Source.scala
new file mode 100644
index 0000000000..ff72873f86
--- /dev/null
+++ b/src/dotnet-library/scala/io/Source.scala
@@ -0,0 +1,371 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.io
+
+
+import java.io.{File, FileInputStream, InputStream, PrintStream}
+
+import compat.StringBuilder
+
+/** This object provides convenience methods to create an iterable
+ * representation of a source file.
+ *
+ * @author Burak Emir
+ * @version 1.0, 19/08/2004
+ */
+object Source {
+
+ /** Creates a <code>Source</code> instance from the given array of bytes,
+ * with empty description.
+ *
+ * @param bytes ...
+ * @return the created <code>Source</code> instance.
+ */
+ def fromBytes(bytes: Array[Byte]): Source =
+ fromString(new String(bytes))
+
+ /** Creates Source from array of bytes with given encoding, with
+ * empty description.
+ *
+ * @param bytes ...
+ * @param enc ...
+ * @return ...
+ */
+ def fromBytes(bytes: Array[Byte], enc: String): Source =
+ fromString(new String(bytes, enc))
+
+ /** Creates a <code>Source</code> instance from a single character.
+ *
+ * @param c ...
+ * @return the create <code>Source</code> instance.
+ */
+ def fromChar(c: Char): Source = {
+ val it = Iterator.single(c)
+ new Source {
+ def reset = fromChar(c)
+ val iter = it
+ }
+ }
+
+ /** creates Source from array of characters, with empty description.
+ *
+ * @param chars ...
+ * @return ...
+ */
+ def fromChars(chars: Array[Char]): Source = {
+ val it = Iterator.fromArray(chars)
+ new Source {
+ def reset = fromChars(chars)
+ val iter = it
+ }
+ }
+
+ /** creates Source from string, with empty description.
+ *
+ * @param s ...
+ * @return ...
+ */
+ def fromString(s: String): Source = {
+ val it = Iterator.fromString(s)
+ new Source {
+ def reset = fromString(s)
+ val iter = it
+ }
+ }
+
+ /** creates Source from file with given name, setting its description to
+ * filename.
+ */
+ def fromFile(name: String): Source =
+ fromFile(new File(name))
+
+ /** creates Source from file with given name, using given encoding, setting
+ * its description to filename.
+ */
+ def fromFile(name: String, enc: String): Source =
+ fromFile(new File(name), enc)
+
+ /** creates Source from file with given file: URI
+ */
+ def fromFile(uri: java.net.URI): Source =
+ fromFile(new File(uri))
+
+ /** creates Source from file, using default character encoding, setting its
+ * description to filename.
+ */
+ def fromFile(file: java.io.File): Source = {
+ val arr: Array[Byte] = new Array[Byte](file.length().asInstanceOf[Int])
+ val is = new FileInputStream(file)
+ is.read(arr)
+ val s = fromBytes(arr)
+ return setFileDescriptor(file, s)
+ }
+
+ /** Creates Source from file, using given character encoding, setting its
+ * description to filename.
+ *
+ * @param file ...
+ * @param enc ...
+ * @return ...
+ */
+ def fromFile(file: java.io.File, enc: String): Source = {
+ val arr: Array[Byte] = new Array[Byte](file.length().asInstanceOf[Int])
+ val is = new FileInputStream(file)
+ is.read(arr)
+ val s = fromBytes(arr, enc)
+ s.descr = file.getName()
+ return setFileDescriptor(file, s)
+ }
+
+ /**
+ * @param file ...
+ * @param s ...
+ * @return ...
+ */
+ def setFileDescriptor(file: File, s: Source): Source = {
+ s.descr = new StringBuilder().append( "file:" ).append(file.getAbsolutePath()).toString();
+ s
+ }
+
+ /**
+ * @param s ...
+ * @return ...
+ */
+ def fromURL(s: String): Source =
+ fromURL(new java.net.URL(s))
+
+ /**
+ * @param url ...
+ * @return ...
+ */
+ def fromURL(url: java.net.URL): Source = {
+ val it = new Iterator[Char] {
+ var data: Int = _
+ def hasNext = {data != -1}
+ def next = {val x = data.asInstanceOf[char]; data = bufIn.read(); x}
+ val in = url.openStream()
+ val bufIn = new java.io.BufferedInputStream(in)
+ data = bufIn.read()
+ }
+ val s = new Source {
+ def reset = fromURL(url)
+ val iter = it
+ }
+ s.descr = url.toString()
+ s
+ }
+
+ /** reads data from inputstream into a byte array, and calls fromBytes with given encoding.
+ * If maxlen is given, reads not more bytes than maxlen. if maxlen was not given, or was <= 0, then
+ * whole inputstream is read and closed afterwards.
+ *
+ * @param istream the input stream from which to read
+ * @param enc the encoding to apply to the bytes
+ * @param maxlen optionally, a positive int specifying maximum number of bytes to read
+ */
+ def fromInputStream(istream: InputStream, enc: String, maxlen: Option[Int]): Source = {
+ val BUFSIZE = 1024
+ val limit = maxlen match { case Some(i) => i; case None => 0 }
+ val bi = new java.io.BufferedInputStream(istream, BUFSIZE)
+ val bytes = new collection.mutable.ArrayBuffer[Byte]()
+ var b = 0
+ var i = 0
+ while( {b = bi.read; i = i + 1; b} != -1 && (limit <= 0 || i < limit)) {
+ bytes += b.toByte;
+ }
+ if(limit <= 0) bi.close
+ fromBytes(bytes.toArray, enc)
+ }
+
+ /** same as fromInputStream(is, enc, None) */
+ def fromInputStream(is: InputStream, enc: String): Source =
+ fromInputStream(is, enc, None)
+
+ /** same as fromInputStream(is, "utf-8", None) */
+ def fromInputStream(is: InputStream): Source =
+ fromInputStream(is, "utf-8", None)
+
+}
+
+/** The class <code>Source</code> implements an iterable representation
+ * of source files. Calling method <code>reset</code> returns an identical,
+ * resetted source.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class Source extends Iterator[Char] {
+
+ // ------ protected values
+
+ /** the actual iterator */
+ protected val iter: Iterator[Char]
+
+ protected var cline = 1
+ protected var ccol = 1
+
+ // ------ public values
+
+ /** position of last character returned by next*/
+ var pos = 0
+
+ /** the last character returned by next.
+ * the value before the first call to next is undefined.
+ */
+ var ch: Char = _
+
+ /** description of this source, default empty */
+ var descr: String = ""
+
+ var nerrors = 0
+ var nwarnings = 0
+
+ /** default col increment for tabs '\t', set to 4 initially
+ */
+ var tabinc = 4
+
+ //
+ // -- methods
+ //
+
+ /** convenience method, returns given line (not including newline)
+ * from Source.
+ *
+ * @param line the line index.
+ * @return the character string of the specified line.
+ * @throws scala.compat.Platform.IllegalArgumentException
+ */
+ def getLine(line: Int): String = { // faster than getLines.drop(line).next
+ val buf = new StringBuilder()
+ val it = reset
+ var i = 0
+
+ while (it.hasNext && i < (line-1))
+ if ('\n' == it.next)
+ i = i + 1;
+
+ if (!it.hasNext) // this should not happen
+ throw new IllegalArgumentException(
+ "line " + line + " does not exist?!"
+ );
+
+ var ch = it.next
+ while (it.hasNext && '\n' != ch) {
+ buf.append(ch)
+ ch = it.next
+ }
+ val res = buf.toString()
+ buf.setLength(0) // hopefully help collector to deallocate StringBuilder
+ res
+ }
+
+ /** returns an iterator who returns lines (including newline character).
+ * a line ends in \n.
+ */
+ def getLines: Iterator[String] = new Iterator[String] {
+ val buf = new StringBuilder
+ def next = {
+ var ch = iter.next
+ while(ch != '\n' && iter.hasNext) {
+ buf.append(ch)
+ ch = iter.next
+ }
+ buf.append(ch)
+ val res = buf.toString()
+ buf.setLength(0) // clean things up for next call of "next"
+ res
+ }
+ def hasNext = iter.hasNext
+ }
+ /** Returns <code>true</code> if this source has more characters.
+ */
+ def hasNext = iter.hasNext
+
+ /** returns next character and has the following side-effects: updates
+ * position (ccol and cline) and assigns the character to ch
+ */
+ def next = {
+ ch = iter.next
+ pos = Position.encode(cline,ccol)
+ ch match {
+ case '\n' =>
+ ccol = 1
+ cline = cline + 1
+ case '\t' =>
+ ccol = ccol + tabinc
+ case _ =>
+ ccol = ccol + 1
+ }
+ ch
+ }
+
+ /** Reports an error message to console.
+ *
+ * @param pos ...
+ * @param msg the error message to report
+ */
+ def reportError(pos: Int, msg: String): Unit =
+ reportError(pos, msg, java.lang.System.out)
+
+ /** Reports an error message to the output stream <code>out</code>.
+ *
+ * @param pos ...
+ * @param msg the error message to report
+ * @param out ...
+ */
+ def reportError(pos: Int, msg: String, out: PrintStream): Unit = {
+ nerrors = nerrors + 1
+ report(pos, msg, out)
+ }
+
+ /**
+ * @param pos ...
+ * @param msg the error message to report
+ * @param out ...
+ */
+ def report(pos: Int, msg: String, out: PrintStream): Unit = {
+ val buf = new StringBuilder
+ val line = Position.line(pos)
+ val col = Position.column(pos)
+ buf.append(descr + ":" + line + ":" + col + ": " + msg)
+ buf.append(getLine(line))
+ var i = 1
+ while (i < col) {
+ buf.append(' ')
+ i = i + 1
+ }
+ buf.append('^')
+ out.println(buf.toString)
+ }
+
+ /** Reports a warning message to <code>java.lang.System.out</code>.
+ *
+ * @param pos ...
+ * @param msg the warning message to report
+ */
+ def reportWarning(pos: Int, msg: String): Unit =
+ reportWarning(pos, msg, java.lang.System.out)
+
+ /**
+ * @param pos ...
+ * @param msg the warning message to report
+ * @param out ...
+ */
+ def reportWarning(pos: Int, msg: String, out: PrintStream): Unit = {
+ nwarnings = nwarnings + 1
+ report(pos, "warning! " + msg, out)
+ }
+
+ /** the actual reset method */
+ def reset: Source
+
+}
diff --git a/src/dotnet-library/scala/io/UTF8Codec.scala b/src/dotnet-library/scala/io/UTF8Codec.scala
new file mode 100644
index 0000000000..a1d688cb1e
--- /dev/null
+++ b/src/dotnet-library/scala/io/UTF8Codec.scala
@@ -0,0 +1,83 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.io
+
+/**
+ * @author Martin Odersky
+ * @version 1.0, 04/10/2004
+ */
+object UTF8Codec {
+
+ def encode(src: Array[Char], from: Int, dst: Array[Byte], to: Int, len: Int): Int = {
+ var i = from
+ var j = to
+ val end = from + len
+ while (i < end) {
+ val ch = src(i)
+ i = i + 1
+ if (ch < 128) {
+ dst(j) = ch.toByte
+ j = j + 1
+ }
+ else if (ch <= 0x3FF) {
+ dst(j) = (0xC0 | (ch >> 6)).toByte
+ dst(j+1) = (0x80 | (ch & 0x3F)).toByte
+ j = j + 2
+ } else {
+ dst(j) = (0xE0 | (ch >> 12)).toByte
+ dst(j+1) = (0x80 | ((ch >> 6) & 0x3F)).toByte
+ dst(j+2) = (0x80 | (ch & 0x3F)).toByte
+ j = j + 3
+ }
+ }
+ j
+ }
+
+ def encode(s: String, dst: Array[Byte], to: Int): Int =
+ encode(s.toCharArray(), 0, dst, to, s.length())
+
+
+ def encode(s: String): Array[Byte] = {
+ val dst = new Array[Byte](s.length() * 3)
+ val len = encode(s, dst, 0)
+ dst.subArray(0, len)
+ }
+
+ def decode(src: Array[Byte], from: Int,
+ dst: Array[Char], to: Int, len: Int): Int =
+ {
+ var i = from
+ var j = to
+ val end = from + len
+ while (i < end) {
+ var b = src(i) & 0xFF
+ i = i + 1
+ if (b >= 0xE0) {
+ b = ((b & 0x0F) << 12) | (src(i) & 0x3F) << 6
+ b = b | (src(i+1) & 0x3F)
+ i = i + 2
+ } else if (b >= 0xC0) {
+ b = ((b & 0x1F) << 6) | (src(i) & 0x3F)
+ i = i + 1
+ }
+ dst(j) = b.toChar
+ j = j + 1
+ }
+ j
+ }
+
+ def decode(src: Array[Byte], from: Int, len: Int): String = {
+ val cs = new Array[Char](len)
+ new String(cs, 0, decode(src, 0, cs, 0, len))
+ }
+
+}
diff --git a/src/dotnet-library/scala/mobile/Code.scala b/src/dotnet-library/scala/mobile/Code.scala
new file mode 100644
index 0000000000..2f2b6c3832
--- /dev/null
+++ b/src/dotnet-library/scala/mobile/Code.scala
@@ -0,0 +1,234 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.mobile
+
+
+import java.lang.reflect.{Constructor, Method, Modifier}
+import java.lang.NoSuchMethodException
+
+/** The class <code>Code</code> provides <code>apply</code> methods
+ * with different arities (actually up to 9 parameters) to invoke
+ * a function simply by specifying its name and argument types.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> url = <b>new</b> URL("http://scala-lang.org/classes/examples.jar");
+ * <b>val</b> obj = <b>new</b> Location(url) create "examples.sort";
+ * <b>val</b> 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);</pre>
+ *
+ * @see <a href="Location.html">Location</a>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Code(clazz: java.lang.Class) {
+
+ private type JObject = java.lang.Object
+
+ private var instance: JObject = _
+
+ ///////////////////////////// apply methods ///////////////////////////////
+
+ def apply[R](funName: String) =
+ () => {
+ val args = Array[JObject]()
+ val types = Array[Class]()
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, R](funName: String) =
+ (_0: A0) => {
+ val p = boxValue(_0)
+ val args = Array(p._1)
+ val types = Array(p._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, R](funName: String) =
+ (_0: A0, _1: A1) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val args = Array(p0._1, p1._1)
+ val types = Array(p0._2, p1._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val args = Array(p0._1, p1._1, p2._1)
+ val types = Array(p0._2, p1._2, p2._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val args = Array(p0._1, p1._1, p2._1, p3._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, A4, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val p4 = boxValue(_4)
+ val args = Array(p0._1, p1._1, p2._1, p3._1, p4._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2, p4._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, A4, A5, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val p4 = boxValue(_4)
+ val p5 = boxValue(_5)
+ val args = Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val p4 = boxValue(_4)
+ val p5 = boxValue(_5)
+ val p6 = boxValue(_6)
+ val args = Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, A7, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6, _7: A7) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val p4 = boxValue(_4)
+ val p5 = boxValue(_5)
+ val p6 = boxValue(_6)
+ val p7 = boxValue(_7)
+ val args = Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2, p7._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ def apply[A0, A1, A2, A3, A4, A5, A6, A7, A8, R](funName: String) =
+ (_0: A0, _1: A1, _2: A2, _3: A3, _4: A4, _5: A5, _6: A6, _7: A7, _8: A8) => {
+ val p0 = boxValue(_0)
+ val p1 = boxValue(_1)
+ val p2 = boxValue(_2)
+ val p3 = boxValue(_3)
+ val p4 = boxValue(_4)
+ val p5 = boxValue(_5)
+ val p6 = boxValue(_6)
+ val p7 = boxValue(_7)
+ val p8 = boxValue(_8)
+ val args = Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1, p8._1)
+ val types = Array(p0._2, p1._2, p2._2, p3._2, p4._2, p5._2, p6._2, p7._2, p8._2)
+ applyFun(funName, args, types).asInstanceOf[R]
+ }
+
+ ////////////////////// private functions ///////////////////////
+
+ private def boxValue(value: Any) = value match {
+ case x: Byte => {new java.lang.Byte(x), java.lang.Byte.TYPE}
+ case x: Boolean => {new java.lang.Boolean(x), java.lang.Boolean.TYPE}
+ case x: Char => {new java.lang.Character(x), java.lang.Character.TYPE}
+ case x: Short => {new java.lang.Short(x), java.lang.Short.TYPE}
+ case x: Int => {new java.lang.Integer(x), java.lang.Integer.TYPE}
+ case x: Long => {new java.lang.Long(x), java.lang.Long.TYPE}
+ case x: Float => {new java.lang.Float(x), java.lang.Float.TYPE}
+ case x: Double => {new java.lang.Double(x), java.lang.Double.TYPE}
+ case _ =>
+ val x = value.asInstanceOf[JObject]
+ {x, x.getClass()}
+ }
+
+ private def isConstructorName(methName: String) = {
+ var className = clazz.getName()
+ val classInx = className.lastIndexOf(".")
+ val methInx = methName.lastIndexOf(".")
+ if (classInx > 0 && methInx < 0)
+ className = className.substring(classInx + 1, className.length())
+ methName.equals(className)
+ }
+
+ private def applyFun(methName: String, args: Array[JObject], argTypes: Array[Class]): JObject = {
+ try {
+ val method = clazz.getMethod(methName, argTypes)
+ var obj: JObject = null
+ if (! Modifier.isStatic(method.getModifiers())) {
+ if (instance eq null) {
+ instance = try {
+ clazz.newInstance()
+ } catch { case _ =>
+ val cs = clazz.getConstructors()
+//Console.println("cs.length=" + cs.length);
+ if (cs.length > 0) {
+ cs(0).newInstance(Array(""))
+ } else {
+ error("class " + clazz.getName() + " has no public constructor")
+ null
+ }
+ }
+ }
+ obj = instance
+ }
+ val result = method.invoke(obj, args)
+ if (result eq null) ().asInstanceOf[JObject] else result
+ }
+ catch {
+ case me: NoSuchMethodException =>
+ if (isConstructorName(methName)) {
+ try {
+ val cstr = clazz.getConstructor(argTypes)
+ instance = cstr.newInstance(args)
+ instance
+ }
+ catch {
+ case e: Exception =>
+ Console.println(e.getMessage())
+ e.printStackTrace()
+ }
+ }
+ else {
+ Console.println(me.getMessage())
+ me.printStackTrace()
+ }
+ null
+ case e: Exception =>
+ Console.println(e.getMessage())
+ e.printStackTrace()
+ null
+ }
+ }
+
+}
+
diff --git a/src/dotnet-library/scala/mobile/Location.scala b/src/dotnet-library/scala/mobile/Location.scala
new file mode 100644
index 0000000000..bcb66387e5
--- /dev/null
+++ b/src/dotnet-library/scala/mobile/Location.scala
@@ -0,0 +1,100 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.mobile
+
+
+import java.lang.ClassLoader
+import java.net._
+
+import scala.collection.mutable._
+
+/** The class <code>Location</code> provides a <code>create</code>
+ * method to instantiate objects from a network location by
+ * specifying the URL address of the jar/class file.<p/>
+ *
+ * An update of the jar/class file should not break your code as far
+ * as the used class names and method signatures are the same.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> url = <b>new</b> URL("http://scala-lang.org/classes/examples.jar");
+ * <b>val</b> obj = <b>new</b> Location(url) create "examples.sort";</pre>
+ *
+ * @see <a href="Code.html">Code</a>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Location(url: URL) {
+
+ /** A cache containing all class loaders of this location.
+ */
+ private var lcache: Map[URL, ClassLoader] = new HashMap
+
+ /** The class loader associated with this location.
+ */
+ private val loader = if (url eq null)
+ ClassLoader.getSystemClassLoader()
+ else
+ lcache.get(url) match {
+ case Some(cl) =>
+ cl
+ case _ =>
+ val cl = new URLClassLoader(Array(url))
+ lcache(url) = cl
+ cl
+ }
+
+ /** A cache containing all classes of this location.
+ */
+ private var ccache: Map[String, java.lang.Class] = new HashMap
+
+ /** Return the code description for the string <code>className</code>
+ * at this location.
+ *
+ * @param classname the name of the class
+ * @return the code description corresponding to
+ * <code>className</code>.
+ */
+ def create(className: String) = new Code(
+ ccache.get(className) match {
+ case Some(clazz) =>
+ clazz
+ case _ =>
+ val clazz = if (loader.loadClass(className).isInterface()) {
+ // Scala source: class A { ... };
+ // Java bytecode: interface A.class + class A$class.class
+ loader.loadClass(className + "$class")
+ }
+ else {
+ // Scala source: object A { ... };
+ // Java bytecode: interface A.class + class A$.class
+ loader.loadClass(className + "$")
+ }
+ ccache(className) = clazz
+ clazz
+ }
+ )
+
+}
+
+/** The object <code>Location</code> can be used to instantiate
+ * objects on the same Java VM. It is just provided to illustrate
+ * the special case where resources are available locally.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> obj = Location.create("xcode.Math");
+ * <b>val</b> x = obj[Int, Int]("square")(5);</pre>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+object Location extends Location(null)
diff --git a/src/dotnet-library/scala/reflect/BeanProperty.scala b/src/dotnet-library/scala/reflect/BeanProperty.scala
new file mode 100644
index 0000000000..beba9fa418
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/BeanProperty.scala
@@ -0,0 +1,34 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+*/
+
+// $Id$
+
+
+package scala.reflect
+
+/**
+ * This attribute adds a setter and a getter method, following the
+ Java Bean convention (first letter of the property is capitalized) used
+by popular Java web frameworks.
+For example
+<pre>
+ [BeanProperty]
+ var status = ""
+</pre>
+<p> adds the following methods to the <b>generated</b> code </p>
+<pre>
+ def setStatus(s:String): Unit = { this.status = s }
+ def getStatus: String = { this.status }
+</pre>
+ *
+ <p>
+ However, you cannot call <code>setStatus</code> from Scala, you should
+ use the normal Scala access and assignment.
+ </p>
+ */
+class BeanProperty extends Attribute
diff --git a/src/dotnet-library/scala/reflect/Code.scala b/src/dotnet-library/scala/reflect/Code.scala
new file mode 100644
index 0000000000..780bd5518c
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/Code.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+
+import Predef.Error
+
+class Code[Type](val tree: Tree)
+
+object Code {
+ def lift[A](tree: A): Code[A] =
+ throw new Error("Code was not lifted by compiler")
+}
diff --git a/src/dotnet-library/scala/reflect/Print.scala b/src/dotnet-library/scala/reflect/Print.scala
new file mode 100644
index 0000000000..166a2631c1
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/Print.scala
@@ -0,0 +1,98 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+object Print extends Function1[Any, String] {
+
+ def apply (any: Any): String =
+ if (any.isInstanceOf[Code[Any]])
+ apply(any.asInstanceOf[Code[Any]])
+ else if (any.isInstanceOf[Tree])
+ apply(any.asInstanceOf[Tree])
+ else if (any.isInstanceOf[Symbol])
+ apply(any.asInstanceOf[Symbol])
+ else if (any.isInstanceOf[Type])
+ apply(any.asInstanceOf[Type])
+ else "UnknownAny"
+
+ def apply(code: Code[Any]): String =
+ Print(code.tree)
+
+ def apply(tree: Tree): String = tree match {
+ case reflect.Ident(sym) => Print(sym)
+ case reflect.Select(qual, sym) => Print(qual) + "." + Print(sym)
+ case reflect.Literal(value) => value match {
+ case s:String => "\"" + s + "\""
+ case _ => value.toString
+ }
+ case reflect.Apply(fun, args) =>
+ Print(fun) + args.map(Print).mkString("(", ", ", ")")
+ case reflect.TypeApply(fun, args) =>
+ Print(fun) + args.map(Print).mkString("[", ", ", "]")
+ case reflect.Function(params, body) =>
+ params.map(Print).mkString("(", ", ", ")") + " => " + Print(body)
+ case reflect.This(sym) => Print(sym)
+ case reflect.Block(stats, expr) =>
+ (stats ::: List(expr)).map(Print).mkString("{\n", ";\n", "\n}")
+ case reflect.New(tpt) => "new " + Print(tpt)
+ case reflect.If(condition, trueCase, falseCase) =>
+ "if (" + Print(condition) + ") " + Print(trueCase) + " else " + Print(falseCase)
+ case reflect.Assign(destination: Tree, source: Tree) =>
+ Print(destination) + " = " + Print(source)
+ case reflect.Target(sym, body) =>
+ "target " + Print(sym) + " {\n" + Print(body) + "\n}"
+ case reflect.Goto(target) =>
+ "goto " + Print(target)
+ case _ => "???"
+ }
+
+ def apply(symbol: Symbol): String = symbol match {
+ case reflect.Class(name) => name.substring(name.lastIndexOf('.')+1)
+ case reflect.Method(name, datatype) =>
+ name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.Field(name, datatype) =>
+ name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.TypeField(name, datatype) =>
+ name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.LocalValue(owner, name, datatype) =>
+ name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.LocalMethod(owner, name, datatype) =>
+ name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.NoSymbol => "NoSymbol"
+ case reflect.RootSymbol => "RootSymbol"
+ case reflect.LabelSymbol(name) => name
+ case _ => "???"
+ }
+
+ def apply(datatype: Type): String = datatype match {
+ case reflect.NoPrefix => "NoPrefix"
+ case reflect.NoType => "NoType"
+ case reflect.NamedType(name) => "(named: " + name + ")"
+ case reflect.PrefixedType(prefix, symbol) =>
+ "(" + Print(prefix) + "." + Print(symbol) + ")"
+ case reflect.SingleType(prefix, symbol) =>
+ "(" + Print(prefix) + "." + Print(symbol) + ")"
+ case reflect.ThisType(clazz) => "(" + Print(clazz) + ".this.type)"
+ case reflect.AppliedType(datatype, args) =>
+ Print(datatype) + args.map(Print).mkString("[", ", ", "]")
+ case reflect.TypeBounds(lo, hi) =>
+ "[" + Print(lo) + " ... " + Print(hi) + "]"
+ case reflect.MethodType(formals, resultType) =>
+ formals.map(Print).mkString("(", ", ", ")") + " => " + Print(resultType)
+ case reflect.PolyType(typeParams, typeBounds, resultType) =>
+ (List.map2(typeParams, typeBounds)
+ ((tp, tb) => "[" + Print(tb._1) + " :> " + Print(tp) + " :> " + Print(tb._2) + "]")).
+ mkString("[", ", ", "]") + " -> " + Print(resultType)
+ case _ => "???"
+ }
+
+}
diff --git a/src/dotnet-library/scala/reflect/Symbol.scala b/src/dotnet-library/scala/reflect/Symbol.scala
new file mode 100644
index 0000000000..a7fd8eda44
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/Symbol.scala
@@ -0,0 +1,62 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+
+abstract class Symbol {
+ val owner: Symbol
+ val name: String
+ val tpe: Type
+}
+
+abstract class GlobalSymbol(val fullname: String) extends Symbol {
+ private val pointIndex = fullname.lastIndexOf(".")
+ val owner: Symbol =
+ if (pointIndex < 0) RootSymbol
+ else Class(fullname.substring(0, pointIndex))
+ val name: String =
+ if (pointIndex < 0) fullname
+ else fullname.substring(pointIndex, fullname.length())
+}
+
+abstract class LocalSymbol extends Symbol
+
+case class Class(override val fullname: String) extends GlobalSymbol(fullname) {
+ val tpe = NamedType(fullname)
+}
+
+case class Method(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname)
+
+case class Field(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname)
+
+case class TypeField(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname)
+
+case class LocalValue(owner: Symbol, name: String, tpe: Type) extends LocalSymbol
+
+case class LocalMethod(owner: Symbol, name: String, tpe: Type) extends LocalSymbol
+
+case object NoSymbol extends Symbol {
+ val owner = null
+ val name = null
+ val tpe = NoType
+}
+
+case object RootSymbol extends Symbol {
+ val owner = NoSymbol
+ val name = "<root>"
+ val tpe = NoPrefix
+}
+
+case class LabelSymbol(val name: String) extends Symbol {
+ val owner = NoSymbol
+ val tpe = NamedType("scala.Unit")
+}
diff --git a/src/dotnet-library/scala/reflect/Tree.scala b/src/dotnet-library/scala/reflect/Tree.scala
new file mode 100644
index 0000000000..971df24c83
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/Tree.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+abstract class Tree
+
+case class Ident(sym: Symbol) extends Tree
+case class Select(qual: Tree, sym: Symbol) extends Tree
+case class Literal(value: Any) extends Tree
+case class Apply(fun: Tree, args: List[Tree]) extends Tree
+case class TypeApply(fun: Tree, args: List[Type]) extends Tree
+case class Function(params: List[Symbol], body: Tree) extends Tree
+case class This(sym: Symbol) extends Tree
+case class Block(stats: List[Tree], expr: Tree) extends Tree
+case class New(sym: Tree) extends Tree
+case class If(condition: Tree, trueCase: Tree, falseCase: Tree) extends Tree
+case class Assign(destination: Tree, source: Tree) extends Tree
+case class Target(sym: LabelSymbol, body: Tree) extends Tree
+case class Goto(target: LabelSymbol) extends Tree
+case class ValDef(sym: Symbol, rhs: Tree) extends Tree
+
+//Monomorphic
+case class ClassDef(sym: Symbol, tpe: Type, impl: Template) extends Tree
+case class DefDef(sym: Symbol, vparamss: List[List[Tree]], ret: Type, rhs: Tree) extends Tree
+case class Super(psym: Symbol) extends Tree
+case class Template(parents: List[Type], body: List[Tree]) extends Tree
diff --git a/src/dotnet-library/scala/reflect/Type.scala b/src/dotnet-library/scala/reflect/Type.scala
new file mode 100644
index 0000000000..fb1acbc650
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/Type.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+import Predef.Pair
+
+abstract class Type
+
+case object NoPrefix extends Type
+case object NoType extends Type
+
+/** fullname */
+case class NamedType(fullname: String) extends Type
+
+/** pre # sym */
+case class PrefixedType(pre: Type, sym: Symbol) extends Type
+
+/** pre.type # sym == pre.sym */
+case class SingleType(pre: Type, sym: Symbol) extends Type
+
+/** clazz.this */
+case class ThisType(clazz: Symbol) extends Type
+
+/** clazz.super[superClazz] */
+/** <code>tpe[args1, ..., argsn]</code> */
+case class AppliedType(tpe: Type, args: List[Type]) extends Type
+
+/** [a &lt;: lo &gt;: hi] */
+case class TypeBounds(lo: Type, hi: Type) extends Type
+
+/** <code>(formals1 ... formalsn) restpe</code> */
+case class MethodType(formals: List[Type], restpe: Type) extends Type
+
+/** */
+case class PolyType(typeParams: List[Symbol], typeBounds: List[{Type, Type}], resultType: Type) extends Type
+
+/** */
+class ImplicitMethodType(formals: List[Type], restpe: Type)
+extends MethodType(formals, restpe)
diff --git a/src/dotnet-library/scala/reflect/TypedCode.scala b/src/dotnet-library/scala/reflect/TypedCode.scala
new file mode 100644
index 0000000000..0833fb204e
--- /dev/null
+++ b/src/dotnet-library/scala/reflect/TypedCode.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.reflect
+
+// This file is OBSOLETE, delete when build bootstraps without it
+class TypedCode[T](val code: Any)
diff --git a/src/dotnet-library/scala/remote.scala b/src/dotnet-library/scala/remote.scala
new file mode 100644
index 0000000000..590cce82a2
--- /dev/null
+++ b/src/dotnet-library/scala/remote.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/**
+ * An attribute that designates the class to which it is applied as remotable.
+ *
+ * @see Method <a href="ScalaObject.html#$tag()">$tag</a> in trait
+ * <a href="ScalaObject.html">scala.ScalaObject</a>.
+ */
+class remote extends Attribute {}
diff --git a/src/dotnet-library/scala/runtime/BooleanRef.java b/src/dotnet-library/scala/runtime/BooleanRef.java
new file mode 100644
index 0000000000..b3e3f0e58f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BooleanRef.java
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class BooleanRef implements java.io.Serializable {
+ public boolean elem;
+ public BooleanRef(boolean elem) { this.elem = elem; }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedAnyArray.scala b/src/dotnet-library/scala/runtime/BoxedAnyArray.scala
new file mode 100644
index 0000000000..431b3f0be5
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedAnyArray.scala
@@ -0,0 +1,255 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+import compat.Platform
+
+/**
+ * Arrays created by <code>new Array[T](length)</code> where <code>T</code>
+ * is a type variable.
+ */
+[serializable]
+final class BoxedAnyArray(val length: Int) extends BoxedArray {
+
+ private var boxed = new Array[AnyRef](length)
+ private val hash = boxed.hashCode()
+ private var unboxed: AnyRef = null
+ private var elemClass: Class = null
+
+ def apply(index: Int): Any = synchronized {
+ if (unboxed eq null)
+ boxed(index);
+ else if (elemClass eq ScalaRunTime.IntTYPE)
+ Int.box(unboxed.asInstanceOf[Array[Int]](index))
+ else if (elemClass eq ScalaRunTime.DoubleTYPE)
+ Double.box(unboxed.asInstanceOf[Array[Double]](index))
+ else if (elemClass eq ScalaRunTime.FloatTYPE)
+ Float.box(unboxed.asInstanceOf[Array[Float]](index))
+ else if (elemClass eq ScalaRunTime.LongTYPE)
+ Long.box(unboxed.asInstanceOf[Array[Long]](index))
+ else if (elemClass eq ScalaRunTime.CharTYPE)
+ Char.box(unboxed.asInstanceOf[Array[Char]](index))
+ else if (elemClass eq ScalaRunTime.ByteTYPE)
+ Byte.box(unboxed.asInstanceOf[Array[Byte]](index))
+ else if (elemClass eq ScalaRunTime.ShortTYPE)
+ Short.box(unboxed.asInstanceOf[Array[Short]](index))
+ else if (elemClass eq ScalaRunTime.BooleanTYPE)
+ Boolean.box(unboxed.asInstanceOf[Array[Boolean]](index))
+ else
+ unboxed.asInstanceOf[Array[AnyRef]](index)
+ }
+
+ def update(index: Int, _elem: Any): Unit = synchronized {
+ val elem = _elem.asInstanceOf[AnyRef]
+ if (unboxed eq null)
+ boxed(index) = elem
+ else if (elemClass eq ScalaRunTime.IntTYPE)
+ unboxed.asInstanceOf[Array[Int]](index) = Int.unbox(elem)
+ else if (elemClass eq ScalaRunTime.DoubleTYPE)
+ unboxed.asInstanceOf[Array[Double]](index) = Double.unbox(elem)
+ else if (elemClass eq ScalaRunTime.FloatTYPE)
+ unboxed.asInstanceOf[Array[Float]](index) = Float.unbox(elem)
+ else if (elemClass eq ScalaRunTime.LongTYPE)
+ unboxed.asInstanceOf[Array[Long]](index) = Long.unbox(elem)
+ else if (elemClass eq ScalaRunTime.CharTYPE)
+ unboxed.asInstanceOf[Array[Char]](index) = Char.unbox(elem)
+ else if (elemClass eq ScalaRunTime.ByteTYPE)
+ unboxed.asInstanceOf[Array[Byte]](index) = Byte.unbox(elem)
+ else if (elemClass eq ScalaRunTime.ShortTYPE)
+ unboxed.asInstanceOf[Array[Short]](index) = Short.unbox(elem)
+ else if (elemClass eq ScalaRunTime.BooleanTYPE)
+ unboxed.asInstanceOf[Array[Boolean]](index) = Boolean.unbox(elem)
+ else
+ unboxed.asInstanceOf[Array[AnyRef]](index) = elem
+ }
+
+ def unbox(elemTag: String): AnyRef =
+ if (elemTag eq ScalaRunTime.IntTag) unbox(ScalaRunTime.IntTYPE)
+ else if (elemTag eq ScalaRunTime.DoubleTag) unbox(ScalaRunTime.DoubleTYPE)
+ else if (elemTag eq ScalaRunTime.FloatTag) unbox(ScalaRunTime.FloatTYPE)
+ else if (elemTag eq ScalaRunTime.LongTag) unbox(ScalaRunTime.LongTYPE)
+ else if (elemTag eq ScalaRunTime.CharTag) unbox(ScalaRunTime.CharTYPE)
+ else if (elemTag eq ScalaRunTime.ByteTag) unbox(ScalaRunTime.ByteTYPE)
+ else if (elemTag eq ScalaRunTime.ShortTag) unbox(ScalaRunTime.ShortTYPE)
+ else if (elemTag eq ScalaRunTime.BooleanTag) unbox(ScalaRunTime.BooleanTYPE)
+ else unbox(Platform.getClassForName(elemTag))
+
+ def unbox(elemClass: Class): AnyRef = synchronized {
+ if (unboxed eq null) {
+ this.elemClass = elemClass;
+ if (elemClass eq ScalaRunTime.IntTYPE) {
+ val newvalue = new Array[Int](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Int.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue
+ } else if (elemClass eq ScalaRunTime.DoubleTYPE) {
+ val newvalue = new Array[Double](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Double.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass eq ScalaRunTime.FloatTYPE) {
+ val newvalue = new Array[Float](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Float.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass eq ScalaRunTime.LongTYPE) {
+ val newvalue = new Array[Long](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Long.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass eq ScalaRunTime.CharTYPE) {
+ val newvalue = new Array[Char](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Char.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue
+ } else if (elemClass eq ScalaRunTime.ByteTYPE) {
+ val newvalue = new Array[Byte](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Byte.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass eq ScalaRunTime.ShortTYPE) {
+ val newvalue = new Array[Short](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Short.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass eq ScalaRunTime.BooleanTYPE) {
+ val newvalue = new Array[Boolean](length)
+ var i = 0
+ while (i < length) {
+ newvalue(i) = Boolean.unbox(boxed(i))
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemClass == boxed.getClass().getComponentType()) {
+ // todo: replace with ScalaRunTime.AnyRef.class
+ unboxed = boxed
+ } else {
+ unboxed = Platform.createArray(elemClass, length);
+ Platform.arraycopy(boxed, 0, unboxed, 0, length);
+ }
+ boxed = null
+ }
+ unboxed
+ }
+
+ override def equals(other: Any): Boolean = (
+ other.isInstanceOf[BoxedAnyArray] && (this eq (other.asInstanceOf[BoxedAnyArray])) ||
+ (if (unboxed eq null) boxed == other else unboxed == other)
+ )
+
+ override def hashCode(): Int = hash
+
+ def value: AnyRef = {
+ if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value")
+ unboxed
+ }
+
+ private def adapt(other: AnyRef): AnyRef =
+ if (this.unboxed eq null)
+ other match {
+ case that: BoxedAnyArray =>
+ if (that.unboxed eq null) {
+ that.boxed
+ } else {
+ if (ScalaRunTime.isValueClass(that.elemClass)) unbox(that.elemClass);
+ that.unboxed
+ }
+ case that: BoxedArray =>
+ adapt(that.value)
+ case that: Array[Int] =>
+ unbox(ScalaRunTime.IntTag); that
+ case that: Array[Double] =>
+ unbox(ScalaRunTime.DoubleTag); that
+ case that: Array[Float] =>
+ unbox(ScalaRunTime.FloatTag); that
+ case that: Array[Long] =>
+ unbox(ScalaRunTime.LongTag); that
+ case that: Array[Char] =>
+ unbox(ScalaRunTime.CharTag); that
+ case that: Array[Short] =>
+ unbox(ScalaRunTime.ShortTag); that
+ case that: Array[Byte] =>
+ unbox(ScalaRunTime.ByteTag); that
+ case that: Array[Boolean] =>
+ unbox(ScalaRunTime.BooleanTag); that
+ case _ =>
+ other
+ }
+ else
+ other match {
+ case that: BoxedAnyArray =>
+ if (that.unboxed ne null) that.unboxed
+ else if (ScalaRunTime.isValueClass(this.elemClass)) that.unbox(this.elemClass)
+ else that.boxed
+ case that: BoxedArray =>
+ adapt(that.value)
+ case _ =>
+ other
+ }
+
+ override def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit = {
+ val src1 = adapt(src)
+ Array.copy(src1, from, if (unboxed ne null) unboxed else boxed, to, len)
+ }
+
+ override def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = {
+ var dest1 = adapt(dest)
+ Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len)
+ }
+
+ override def subArray(start: Int, end: Int): AnyRef = {
+ val result = new BoxedAnyArray(end - start);
+ Array.copy(this, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](length)
+ var len = 0
+ var i = 0
+ while (i < length) {
+ if (p(this(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new BoxedAnyArray(len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = this(i); len = len + 1 }
+ i = i + 1
+ }
+ result
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedArray.scala b/src/dotnet-library/scala/runtime/BoxedArray.scala
new file mode 100644
index 0000000000..3ba9433f8a
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedArray.scala
@@ -0,0 +1,125 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+import Predef.Error
+import collection.mutable.ArrayBuffer
+
+/**
+ * <p>A class representing <code>Array[T]</code></p>
+ */
+abstract class BoxedArray extends Seq[Any] {
+ /** The length of the array */
+ def length: Int
+
+ /** The element at given index */
+ def apply(index: Int): Any
+
+ /** Update element at given index */
+ def update(index: Int, elem: Any): Unit
+
+ /** Convert to Java array.
+ * @param elemTag Either one of the tags ".N" where N is the name of a primitive type
+ * (@see ScalaRunTime), or a full class name.
+ */
+ //todo: remove
+ def unbox(elemTag: String): AnyRef
+
+ def unbox(elemClass: Class): AnyRef
+
+ override def isDefinedAt(x: Int): Boolean = 0 <= x && x < length
+
+ def elements = new Iterator[Any] {
+ var index = 0
+ def hasNext: Boolean = index < length
+ def next: Any = { val i = index; index = i + 1; apply(i) }
+ }
+
+ /** The underlying array value
+ */
+ def value: AnyRef
+
+ def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit =
+ Array.copy(src, from, value, to, len)
+
+ def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = {
+ Array.copy(value, from, dest, to, len)
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @pre the array must be large enough to hold all elements.
+ */
+ override def copyToArray[B](xs: Array[B], start: Int): Unit =
+ copyTo(0, xs, start, length)
+
+ // todo: add a copyToBuffer
+
+ // todo: eliminate
+ def subArray(from: Int, end: Int): AnyRef
+
+ override def slice(from: Int, end: Int): Seq[Object] =
+ subArray(from, end).asInstanceOf[Seq[Object]]
+
+ final override def map[b](f: Any => b): Array[b] = {
+ val len = length
+ val result = new Array[b](len)
+ var i = 0
+ while (i < len) {
+ result(i) = f(apply(i))
+ i = i + 1
+ }
+ result
+ }
+
+ final override def flatMap[b](f: Any => Iterable[b]): Array[b] = {
+ val buf = new ArrayBuffer[b]
+ val len = length
+ var i = 0
+ while (i < len) {
+ buf ++= f(apply(i))
+ i = i + 1
+ }
+ buf.toArray
+ }
+
+ final def zip[b](that: Array[b]): Array[Tuple2[Any,b]] = {
+ val len = length
+ if(len != that.length)
+ throw new Error("zipping arrays of different length")
+ val result = new Array[Tuple2[Any,b]](len)
+ var i = 0
+ while (i < len) {
+ result(i) = new Tuple2(this(i), that(i))
+ i = i + 1
+ }
+ result
+ }
+
+ final def zipWithIndex: Array[Tuple2[Any,Int]] = {
+ val len = length
+ val result = new Array[Tuple2[Any,Int]](len)
+ var i = 0
+ while (i < len) {
+ result(i) = new Tuple2(this(i), i)
+ i = i + 1
+ }
+ result
+ }
+
+ override final def stringPrefix: String = "Array"
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedBoolean.java b/src/dotnet-library/scala/runtime/BoxedBoolean.java
new file mode 100644
index 0000000000..54a0fb8aa4
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedBoolean.java
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public final class BoxedBoolean
+ implements java.io.Serializable
+{
+
+ private final static BoxedBoolean TRUE = new BoxedBoolean(true);
+ private final static BoxedBoolean FALSE = new BoxedBoolean(false);
+
+ public static BoxedBoolean box(boolean value) {
+ return (value ? TRUE : FALSE);
+ }
+
+ public final boolean value;
+
+ private BoxedBoolean(boolean value) { this.value = value; }
+
+ public final boolean booleanValue() { return value; }
+
+ public boolean equals(java.lang.Object other) {
+ return this == other;
+ }
+
+ public int hashCode() {
+ return value ? 1 : 0;
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedBooleanArray.scala b/src/dotnet-library/scala/runtime/BoxedBooleanArray.scala
new file mode 100644
index 0000000000..1dbf6bb987
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedBooleanArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Boolean.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Boolean.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedBooleanArray] && value == other.asInstanceOf[BoxedBooleanArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Boolean] = {
+ val result = new Array[Boolean](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Boolean](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedBooleanArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedByte.java b/src/dotnet-library/scala/runtime/BoxedByte.java
new file mode 100644
index 0000000000..2ab7d7dc29
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedByte.java
@@ -0,0 +1,57 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public final class BoxedByte extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ private static final int MinHashed = -128;
+ private static final int MaxHashed = 127;
+ private static BoxedByte[] canonical = new BoxedByte[MaxHashed - MinHashed + 1];
+
+ static {
+ for (int i = MinHashed; i <= MaxHashed; i++)
+ canonical[i - MinHashed] = new BoxedByte((byte)i);
+ }
+
+ public static BoxedByte box(byte value) {
+ return canonical[value - MinHashed];
+ }
+
+ public final byte value;
+
+ private BoxedByte(byte value) { this.value = value; }
+
+ public byte byteValue() { return (byte)value; }
+ public short shortValue() { return (short)value; }
+ public char charValue() { return (char)value; }
+ public int intValue() { return (int)value; }
+ public long longValue() { return (long)value; }
+ public float floatValue() { return (float)value; }
+ public double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).byteValue();
+ }
+
+ public int hashCode() {
+ return value;
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedByteArray.scala b/src/dotnet-library/scala/runtime/BoxedByteArray.scala
new file mode 100644
index 0000000000..62407d6974
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedByteArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Byte.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Byte.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedByteArray] && value == other.asInstanceOf[BoxedByteArray].value
+
+ override def hashCode(): Int = value.hashCode();
+
+ def subArray(start: Int, end: Int): Array[Byte] = {
+ val result = new Array[Byte](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Byte](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedByteArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedChar.java b/src/dotnet-library/scala/runtime/BoxedChar.java
new file mode 100644
index 0000000000..0a6d0b5582
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedChar.java
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class BoxedChar extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ private static final int MinHashed = 0;
+ private static final int MaxHashed = 255;
+ private static BoxedChar[] canonical = new BoxedChar[MaxHashed - MinHashed + 1];
+
+ static {
+ for (int i = MinHashed; i <= MaxHashed; i++)
+ canonical[i - MinHashed] = new BoxedChar((char)i);
+ }
+
+ public static BoxedChar box(char value) {
+ if (MinHashed <= value && value <= MaxHashed) return canonical[value - MinHashed];
+ else return new BoxedChar(value);
+ }
+
+ public final char value;
+
+ private BoxedChar(char value) { this.value = value; }
+
+ public byte byteValue() { return (byte)value; }
+ public short shortValue() { return (short)value; }
+ public char charValue() { return (char)value; }
+ public int intValue() { return (int)value; }
+ public long longValue() { return (long)value; }
+ public float floatValue() { return (float)value; }
+ public double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).charValue();
+ }
+
+ public int hashCode() {
+ return value;
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedCharArray.scala b/src/dotnet-library/scala/runtime/BoxedCharArray.scala
new file mode 100644
index 0000000000..1f823853eb
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedCharArray.scala
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedCharArray(val value: Array[Char]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Any = Char.box(value(index));
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Char.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value;
+ def unbox(elemClass: Class): AnyRef = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedCharArray] && value == other.asInstanceOf[BoxedCharArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+
+ def subArray(start: Int, end: Int): Array[Char] = {
+ val result = new Array[Char](end - start);
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length);
+ var len = 0;
+ var i = 0;
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Char](len);
+ len = 0;
+ i = 0;
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedCharArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedDouble.java b/src/dotnet-library/scala/runtime/BoxedDouble.java
new file mode 100644
index 0000000000..5fd896e6cd
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedDouble.java
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class BoxedDouble extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ public static BoxedDouble box(double value) {
+ return new BoxedDouble(value);
+ }
+
+ public final double value;
+
+ private BoxedDouble(double value) { this.value = value; }
+
+ public final byte byteValue() { return (byte)value; }
+ public final short shortValue() { return (short)value; }
+ public final char charValue() { return (char)value; }
+ public final int intValue() { return (int)value; }
+ public final long longValue() { return (long)value; }
+ public final float floatValue() { return (float)value; }
+ public final double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).doubleValue();
+ }
+
+ public int hashCode() {
+ long bits = java.lang.Double.doubleToLongBits(value);
+ return (int)(bits ^ (bits >>> 32));
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedDoubleArray.scala b/src/dotnet-library/scala/runtime/BoxedDoubleArray.scala
new file mode 100644
index 0000000000..eca804d76c
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedDoubleArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Double.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Double.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedDoubleArray] && value == other.asInstanceOf[BoxedDoubleArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Double] = {
+ val result = new Array[Double](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Double](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedDoubleArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedFloat.java b/src/dotnet-library/scala/runtime/BoxedFloat.java
new file mode 100644
index 0000000000..d2f66e5aa1
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedFloat.java
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class BoxedFloat extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ public static BoxedFloat box(float value) {
+ return new BoxedFloat(value);
+ }
+
+ public final float value;
+
+ private BoxedFloat(float value) { this.value = value; }
+
+ public final byte byteValue() { return (byte)value; }
+ public final short shortValue() { return (short)value; }
+ public final char charValue() { return (char)value; }
+ public final int intValue() { return (int)value; }
+ public final long longValue() { return (long)value; }
+ public final float floatValue() { return (float)value; }
+ public final double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).floatValue();
+ }
+
+ public int hashCode() {
+ return java.lang.Float.floatToIntBits(value);
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedFloatArray.scala b/src/dotnet-library/scala/runtime/BoxedFloatArray.scala
new file mode 100644
index 0000000000..0505a2545d
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedFloatArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Float.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Float.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedFloatArray] && value == other.asInstanceOf[BoxedFloatArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Float] = {
+ val result = new Array[Float](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Float](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedFloatArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedInt.java b/src/dotnet-library/scala/runtime/BoxedInt.java
new file mode 100644
index 0000000000..fa4135c041
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedInt.java
@@ -0,0 +1,57 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public final class BoxedInt extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ private static final int MinHashed = -128;
+ private static final int MaxHashed = 1024;
+ private static BoxedInt[] canonical = new BoxedInt[MaxHashed - MinHashed + 1];
+
+ static {
+ for (int i = MinHashed; i <= MaxHashed; i++)
+ canonical[i - MinHashed] = new BoxedInt(i);
+ }
+
+ public static BoxedInt box(int value) {
+ if (MinHashed <= value && value <= MaxHashed) return canonical[value - MinHashed];
+ else return new BoxedInt(value);
+ }
+
+ public final int value;
+
+ private BoxedInt(int value) { this.value = value; }
+
+ public final byte byteValue() { return (byte)value; }
+ public final short shortValue() { return (short)value; }
+ public final char charValue() { return (char)value; }
+ public final int intValue() { return (int)value; }
+ public final long longValue() { return (long)value; }
+ public final float floatValue() { return (float)value; }
+ public final double doubleValue() { return (double)value; }
+
+ public final boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).intValue();
+ }
+
+ public final int hashCode() {
+ return value;
+ }
+
+ public final String toString() {
+ return String.valueOf(value);
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedIntArray.scala b/src/dotnet-library/scala/runtime/BoxedIntArray.scala
new file mode 100644
index 0000000000..2519075a3a
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedIntArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedIntArray(val value: Array[Int]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Int.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Int.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedIntArray] && value == other.asInstanceOf[BoxedIntArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Int] = {
+ val result = new Array[Int](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Int](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedIntArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedLong.java b/src/dotnet-library/scala/runtime/BoxedLong.java
new file mode 100644
index 0000000000..680a50d402
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedLong.java
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class BoxedLong extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ public static BoxedLong box(long value) {
+ return new BoxedLong(value);
+ }
+
+ public final long value;
+
+ private BoxedLong(long value) { this.value = value; }
+
+ public final byte byteValue() { return (byte)value; }
+ public final short shortValue() { return (short)value; }
+ public final char charValue() { return (char)value; }
+ public final int intValue() { return (int)value; }
+ public final long longValue() { return (long)value; }
+ public final float floatValue() { return (float)value; }
+ public final double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).longValue();
+ }
+
+ public int hashCode() {
+ long bits = value;
+ return (int)(bits ^ (bits >>> 32));
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedLongArray.scala b/src/dotnet-library/scala/runtime/BoxedLongArray.scala
new file mode 100644
index 0000000000..f82d1711e1
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedLongArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedLongArray(val value: Array[Long]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Long.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Long.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedLongArray] && value == other.asInstanceOf[BoxedLongArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Long] = {
+ val result = new Array[Long](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Long](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedLongArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedNumber.java b/src/dotnet-library/scala/runtime/BoxedNumber.java
new file mode 100644
index 0000000000..a51c42c02e
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedNumber.java
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public abstract class BoxedNumber {
+ public abstract byte byteValue();
+ public abstract short shortValue();
+ public abstract char charValue();
+ public abstract int intValue();
+ public abstract long longValue();
+ public abstract float floatValue();
+ public abstract double doubleValue();
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedObjectArray.scala b/src/dotnet-library/scala/runtime/BoxedObjectArray.scala
new file mode 100644
index 0000000000..e60cf7f585
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedObjectArray.scala
@@ -0,0 +1,65 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.Class
+import compat.Platform.createArray
+
+[serializable]
+final class BoxedObjectArray(val value: Array[AnyRef]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = value(index)
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = elem.asInstanceOf[AnyRef]
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any): Boolean =
+ value == other ||
+ other.isInstanceOf[BoxedObjectArray] && value == other.asInstanceOf[BoxedObjectArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ private def create(length: Int): Array[AnyRef] = {
+ createArray(value.getClass().getComponentType(), length).asInstanceOf[Array[AnyRef]]
+ }
+
+ override def subArray(start: Int, end: Int): Array[AnyRef] = {
+ val result = create(end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = create(len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedObjectArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedShort.java b/src/dotnet-library/scala/runtime/BoxedShort.java
new file mode 100644
index 0000000000..89c79f4bde
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedShort.java
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public final class BoxedShort extends BoxedNumber
+ implements java.io.Serializable
+{
+
+ private static final int MinHashed = -128;
+ private static final int MaxHashed = 127;
+ private static BoxedShort[] canonical = new BoxedShort[MaxHashed - MinHashed + 1];
+
+ static {
+ for (int i = MinHashed; i <= MaxHashed; i++)
+ canonical[i - MinHashed] = new BoxedShort((short)i);
+ }
+
+ public static BoxedShort box(short value) {
+ if (MinHashed <= value && value <= MaxHashed) return canonical[value - MinHashed];
+ else return new BoxedShort(value);
+ }
+
+ public final short value;
+
+ private BoxedShort(short value) { this.value = value; }
+
+ public byte byteValue() { return (byte)value; }
+ public short shortValue() { return (short)value; }
+ public char charValue() { return (char)value; }
+ public int intValue() { return (int)value; }
+ public long longValue() { return (long)value; }
+ public float floatValue() { return (float)value; }
+ public double doubleValue() { return (double)value; }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedNumber &&
+ value == ((BoxedNumber) other).shortValue();
+ }
+
+ public int hashCode() {
+ return value;
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedShortArray.scala b/src/dotnet-library/scala/runtime/BoxedShortArray.scala
new file mode 100644
index 0000000000..c3bc7a6125
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedShortArray.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+import Predef.Class
+
+[serializable]
+final class BoxedShortArray(val value: Array[Short]) extends BoxedArray {
+
+ def length: Int = value.length
+
+ def apply(index: Int): Any = Short.box(value(index))
+
+ def update(index: Int, elem: Any): Unit = {
+ value(index) = Short.unbox(elem.asInstanceOf[AnyRef])
+ }
+
+ def unbox(elemTag: String): AnyRef = value
+ def unbox(elemClass: Class): AnyRef = value
+
+ override def equals(other: Any) =
+ value == other ||
+ other.isInstanceOf[BoxedShortArray] && value == other.asInstanceOf[BoxedShortArray].value
+
+ override def hashCode(): Int = value.hashCode()
+
+ def subArray(start: Int, end: Int): Array[Short] = {
+ val result = new Array[Short](end - start)
+ Array.copy(value, start, result, 0, end - start)
+ result
+ }
+
+ final override def filter(p: Any => Boolean): BoxedArray = {
+ val include = new Array[Boolean](value.length)
+ var len = 0
+ var i = 0
+ while (i < value.length) {
+ if (p(value(i))) { include(i) = true; len = len + 1 }
+ i = i + 1
+ }
+ val result = new Array[Short](len)
+ len = 0
+ i = 0
+ while (len < result.length) {
+ if (include(i)) { result(len) = value(i); len = len + 1 }
+ i = i + 1
+ }
+ new BoxedShortArray(result)
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/BoxedUnit.java b/src/dotnet-library/scala/runtime/BoxedUnit.java
new file mode 100644
index 0000000000..7ed7c6f1d8
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/BoxedUnit.java
@@ -0,0 +1,34 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public final class BoxedUnit
+ implements java.io.Serializable
+{
+
+ public final static BoxedUnit UNIT = new BoxedUnit();
+
+ private BoxedUnit() { }
+
+ public boolean equals(java.lang.Object other) {
+ return this == other;
+ }
+
+ public int hashCode() {
+ return 0;
+ }
+
+ public String toString() {
+ return "()";
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/ByteRef.java b/src/dotnet-library/scala/runtime/ByteRef.java
new file mode 100644
index 0000000000..f53f82199c
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ByteRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class ByteRef implements java.io.Serializable {
+ public byte elem;
+ public ByteRef(byte elem) { this.elem = elem; }
+ public String toString() { return Byte.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/CharRef.java b/src/dotnet-library/scala/runtime/CharRef.java
new file mode 100644
index 0000000000..97108a0c3d
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/CharRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class CharRef implements java.io.Serializable {
+ public char elem;
+ public CharRef(char elem) { this.elem = elem; }
+ public String toString() { return Character.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/DoubleRef.java b/src/dotnet-library/scala/runtime/DoubleRef.java
new file mode 100644
index 0000000000..2ade540f8f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/DoubleRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class DoubleRef implements java.io.Serializable {
+ public double elem;
+ public DoubleRef(double elem) { this.elem = elem; }
+ public String toString() { return Double.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/ExceptionHandling.java b/src/dotnet-library/scala/runtime/ExceptionHandling.java
new file mode 100644
index 0000000000..b44070d106
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ExceptionHandling.java
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public abstract class ExceptionHandling {
+
+ public static Throwable tryCatch(Runnable runnable) {
+ try {
+ runnable.run();
+ return null;
+ } catch (Throwable exception) {
+ return exception;
+ }
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/FloatRef.java b/src/dotnet-library/scala/runtime/FloatRef.java
new file mode 100644
index 0000000000..9a437b1753
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/FloatRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class FloatRef implements java.io.Serializable {
+ public float elem;
+ public FloatRef(float elem) { this.elem = elem; }
+ public String toString() { return Float.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/IntRef.java b/src/dotnet-library/scala/runtime/IntRef.java
new file mode 100644
index 0000000000..1c072c16e5
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/IntRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class IntRef implements java.io.Serializable {
+ public int elem;
+ public IntRef(int elem) { this.elem = elem; }
+ public String toString() { return Integer.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/LongRef.java b/src/dotnet-library/scala/runtime/LongRef.java
new file mode 100644
index 0000000000..4b3ddb6442
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/LongRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class LongRef implements java.io.Serializable {
+ public long elem;
+ public LongRef(long elem) { this.elem = elem; }
+ public String toString() { return Long.toString(elem); }
+}
diff --git a/src/dotnet-library/scala/runtime/NonLocalReturnException.scala b/src/dotnet-library/scala/runtime/NonLocalReturnException.scala
new file mode 100644
index 0000000000..8043b6de81
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/NonLocalReturnException.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+class NonLocalReturnException[T](val key: AnyRef, val value: T) extends RuntimeException
diff --git a/src/dotnet-library/scala/runtime/Nothing$.scala b/src/dotnet-library/scala/runtime/Nothing$.scala
new file mode 100644
index 0000000000..c101637ff7
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/Nothing$.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+/**
+ * Dummy class which exist only to satisfy the JVM. It corresponds
+ * to <code>scala.Nothing</code>. If such type appears in method
+ * signatures, it is erased to this one.
+ */
+
+sealed abstract class Nothing$
diff --git a/src/dotnet-library/scala/runtime/Null$.scala b/src/dotnet-library/scala/runtime/Null$.scala
new file mode 100644
index 0000000000..b27dd848e8
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/Null$.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+/**
+ * Dummy class which exist only to satisfy the JVM. It corresponds
+ * to <code>scala.Null</code>. If such type appears in method
+ * signatures, it is erased to this one.
+ */
+
+sealed abstract class Null$
diff --git a/src/dotnet-library/scala/runtime/ObjectRef.java b/src/dotnet-library/scala/runtime/ObjectRef.java
new file mode 100644
index 0000000000..246a7730d9
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ObjectRef.java
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class ObjectRef implements java.io.Serializable {
+ public Object elem;
+ public ObjectRef(Object elem) { this.elem = elem; }
+ public String toString() { return "" + elem; }
+}
diff --git a/src/dotnet-library/scala/runtime/RichBoolean.scala b/src/dotnet-library/scala/runtime/RichBoolean.scala
new file mode 100644
index 0000000000..ab47a97748
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichBoolean.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichBoolean(x: Boolean) extends Proxy with Ordered[Boolean] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Boolean].compare
+ def compare (y: Boolean): Int = if (x == y) 0 else if (x) 1 else -1
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichByte.scala b/src/dotnet-library/scala/runtime/RichByte.scala
new file mode 100644
index 0000000000..5d3cca2aa3
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichByte.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichByte(x: Byte) extends Proxy with Ordered[Byte] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Byte].compare
+ def compare (y: Byte): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichChar.scala b/src/dotnet-library/scala/runtime/RichChar.scala
new file mode 100644
index 0000000000..571bb75d5a
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichChar.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import java.lang.Character
+import Predef.NoSuchElementException
+
+final class RichChar(x: Char) extends Proxy with Ordered[Char] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Char].compare
+ def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def asDigit: Int = Character.digit(x, Character.MAX_RADIX)
+
+ def isControl: Boolean = Character.isISOControl(x)
+ def isDigit: Boolean = Character.isDigit(x)
+ def isLetter: Boolean = Character.isLetter(x)
+ def isLetterOrDigit: Boolean = Character.isLetterOrDigit(x)
+ def isLowerCase: Boolean = Character.isLowerCase(x)
+ def isUpperCase: Boolean = Character.isUpperCase(x)
+ def isWhitespace: Boolean = Character.isWhitespace(x)
+
+ def toLowerCase: Char = Character.toLowerCase(x)
+ def toUpperCase: Char = Character.toUpperCase(x)
+
+ def to(y: Char): Iterator[Char] = new BufferedIterator[Char] {
+ private var ch = x
+ def hasNext: Boolean = ch < y
+ def next: Char =
+ if (hasNext) { val j = ch; ch = (ch + 1).toChar; j }
+ else throw new NoSuchElementException("next on empty iterator")
+ def head: Char =
+ if (hasNext) ch
+ else throw new NoSuchElementException("head on empty iterator")
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichDouble.scala b/src/dotnet-library/scala/runtime/RichDouble.scala
new file mode 100644
index 0000000000..8db1fd6b35
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichDouble.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichDouble(x: Double) extends Proxy with Ordered[Double] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Double].compare
+ def compare (y: Double): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Double): Double = Math.min(x, y)
+ def max(y: Double): Double = Math.max(x, y)
+ def abs: Double = Math.abs(x)
+
+ // isNaN is provided by the implicit conversion to java.lang.Double
+ // def isNaN: Boolean = java.lang.Double.isNaN(x)
+ def isInfinity: Boolean = java.lang.Double.isInfinite(x)
+ def isPosInfinity: Boolean = isInfinity && x > 0.0
+ def isNegInfinity: Boolean = isInfinity && x < 0.0
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichException.scala b/src/dotnet-library/scala/runtime/RichException.scala
new file mode 100644
index 0000000000..ff2a93771f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichException.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+import compat.StringBuilder
+import compat.Platform.EOL
+
+final class RichException(exc: Throwable) {
+
+ def getStackTraceString: String = {
+ val s = new StringBuilder()
+ for (val trElem <- exc.getStackTrace()) {
+ s.append(trElem.toString())
+ s.append(EOL)
+ }
+ s.toString()
+ }
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichFloat.scala b/src/dotnet-library/scala/runtime/RichFloat.scala
new file mode 100644
index 0000000000..8c6a3f6523
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichFloat.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichFloat(x: Float) extends Proxy with Ordered[Float] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Float].compare
+ def compare (y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Float) = Math.min(x, y)
+ def max(y: Float) = Math.max(x, y)
+ def abs: Float = Math.abs(x)
+
+ // isNaN is provided by the implicit conversion to java.lang.Float
+ // def isNaN: Boolean = java.lang.Float.isNaN(x)
+ def isInfinity: Boolean = java.lang.Float.isInfinite(x)
+ def isPosInfinity: Boolean = isInfinity && x > 0.0f
+ def isNegInfinity: Boolean = isInfinity && x < 0.0f
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichInt.scala b/src/dotnet-library/scala/runtime/RichInt.scala
new file mode 100644
index 0000000000..ef6f330e71
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichInt.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime
+
+final class RichInt(x: Int) extends Proxy with Ordered[Int] {
+
+ // Proxy
+ def self: Any = x
+
+ // Ordered[Int]
+ def compare (y: Int): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def until(y: Int): Iterator[Int] = Iterator.range(x, y)
+ def to(y: Int): Iterator[Int] = Iterator.range(x, y + 1)
+
+ def min(y: Int): Int = if (x < y) x else y
+ def max(y: Int): Int = if (x > y) x else y
+ def abs: Int = if (x < 0) -x else x
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichLong.scala b/src/dotnet-library/scala/runtime/RichLong.scala
new file mode 100644
index 0000000000..4a58b71e16
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichLong.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichLong(x: Long) extends Proxy with Ordered[Long] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Long].compare
+ def compare (y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+ def min(y: Long): Long = if (x < y) x else y
+ def max(y: Long): Long = if (x > y) x else y
+ def abs: Long = if (x < 0) -x else x
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichShort.scala b/src/dotnet-library/scala/runtime/RichShort.scala
new file mode 100644
index 0000000000..4615dec610
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichShort.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+final class RichShort(x: Short) extends Proxy with Ordered[Short] {
+
+ // Proxy.self
+ def self: Any = x
+
+ // Ordered[Short].compare
+ def compare (y: Short): Int = if (x < y) -1 else if (x > y) 1 else 0
+
+}
diff --git a/src/dotnet-library/scala/runtime/RichString.scala b/src/dotnet-library/scala/runtime/RichString.scala
new file mode 100644
index 0000000000..8016b59adf
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/RichString.scala
@@ -0,0 +1,145 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef._
+
+final class RichString(val self: String) extends Proxy with Seq[Char] with Ordered[String] {
+
+ // Ordered[String]
+ def compare(other: String) = self compareTo other
+
+ // Seq[Char]
+ def length = self.length()
+ def elements = Iterator.fromString(self)
+
+ /** Retrieve the n-th character of the string
+ *
+ * @param index into the string
+ * @return the character at position <code>index</code>.
+ */
+ def apply(n: Int) = self charAt n
+
+ private final val LF: Char = 0x0A
+ private final val FF: Char = 0x0C
+ private final val CR: Char = 0x0D
+ private final val SU: Char = 0x1A
+
+ private def isLineBreak(c: Char) = c == LF || c == FF
+
+ /** <p>
+ * Strip trailing line end character from this string if it has one.
+ * A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ * <p>
+ * If a line feed character LF is preceded by a carriage return CR
+ * (0x0D hex), the CR character is also stripped (Windows convention).
+ * </p>
+ */
+ def stripLineEnd: String = {
+ val len = self.length
+ if (len == 0) self
+ else {
+ val last = apply(len - 1)
+ if (isLineBreak(last))
+ self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1)
+ else
+ self
+ }
+ }
+
+ /** <p>
+ * Return all lines in this string in an iterator, including trailing
+ * line end characters.
+ * </p>
+ * <p>
+ * The number of strings returned is one greater than the number of line
+ * end characters in this string. For an empty string, a single empty
+ * line is returned. A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ */
+ def linesWithSeparators = new Iterator[String] {
+ val len = self.length
+ var index = 0
+ def hasNext: Boolean = index <= len
+ def next: String = {
+ if (index >= len) throw new NoSuchElementException("next on empty iterator")
+ val start = index
+ while (index < len && !isLineBreak(apply(index))) index = index + 1
+ index = index + 1
+ self.substring(start, index min len)
+ }
+ }
+
+ /** Return all lines in this string in an iterator, excluding trailing line
+ * end characters, i.e. apply <code>.stripLineEnd</code> to all lines
+ * returned by <code>linesWithSeparators</code>.
+ */
+ def lines: Iterator[String] =
+ linesWithSeparators map (line => new RichString(line).stripLineEnd)
+
+ /** Returns this string with first character converted to upper case */
+ def capitalize: String = {
+ val chars = self.toCharArray
+ chars(0) = chars(0).toUpperCase
+ new String(chars)
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>marginChar</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin(marginChar: Char): String = {
+ val buf = new scala.compat.StringBuilder()
+ for (val line <- linesWithSeparators) {
+ val len = line.length
+ var index = 0;
+ while (index < len && line.charAt(index) <= ' ') index = index + 1
+ buf append
+ (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line)
+ }
+ buf.toString
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>|</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin: String = stripMargin('|')
+
+ def split(separator: Char): Array[String] = self.split(separator.toString())
+
+ def toByte: Byte = java.lang.Byte.parseByte(self)
+ def toShort: Short = java.lang.Short.parseShort(self)
+ def toInt: Int = java.lang.Integer.parseInt(self)
+ def toLong: Long = java.lang.Long.parseLong(self)
+ def toFloat: Float = java.lang.Float.parseFloat(self)
+ def toDouble: Double = java.lang.Double.parseDouble(self)
+
+}
diff --git a/src/dotnet-library/scala/runtime/ScalaRunTime.scala b/src/dotnet-library/scala/runtime/ScalaRunTime.scala
new file mode 100644
index 0000000000..248904c0e1
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ScalaRunTime.scala
@@ -0,0 +1,148 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+
+import Predef.{Class, Throwable}
+import java.lang.Runnable
+
+/* The object <code>ScalaRunTime</code> provides ...
+ */
+object ScalaRunTime {
+
+ /** Names for primitive types, used by array unboxing */
+ val ByteTag = ".Byte"
+ val ShortTag = ".Short"
+ val CharTag = ".Char"
+ val IntTag = ".Int"
+ val LongTag = ".Long"
+ val FloatTag = ".Float"
+ val DoubleTag = ".Double"
+ val BooleanTag = ".Boolean"
+
+ val ByteTYPE = java.lang.Byte.TYPE
+ val ShortTYPE = java.lang.Short.TYPE
+ val CharTYPE = java.lang.Character.TYPE
+ val IntTYPE = java.lang.Integer.TYPE
+ val LongTYPE = java.lang.Long.TYPE
+ val FloatTYPE = java.lang.Float.TYPE
+ val DoubleTYPE = java.lang.Double.TYPE
+ val BooleanTYPE = java.lang.Boolean.TYPE
+ val UnitTYPE = java.lang.Void.TYPE
+
+ def isArray(x:AnyRef): Boolean = x.getClass.isArray
+ def isValueTag(tag: String) = tag.charAt(0) == '.'
+ def isValueClass(clazz: Class) = clazz.isPrimitive()
+
+ abstract class Try[a] {
+ def Catch[b >: a](handler: PartialFunction[Throwable, b]): b
+ def Finally(handler: Unit): a
+ }
+
+ def Try[a](block: => a): Try[a] = new Try[a] with Runnable {
+ var result: a = _
+ var exception: Throwable = ExceptionHandling.tryCatch(this)
+
+ def run(): Unit = result = block
+
+ def Catch[b >: a](handler: PartialFunction[Throwable, b]): b =
+ if (exception eq null)
+ result.asInstanceOf[b]
+ // !!! else if (exception is LocalReturn)
+ // !!! // ...
+ else if (handler isDefinedAt exception)
+ handler(exception)
+ else
+ throw exception
+
+ def Finally(handler: Unit): a =
+ if (exception eq null)
+ result.asInstanceOf[a]
+ else
+ throw exception
+ }
+
+ def caseFields(x: Product): List[Any] = {
+ val arity = x.arity
+ def fields(from: Int): List[Any] =
+ if (from == arity) List()
+ else x.element(from) :: fields(from + 1)
+ fields(0)
+ }
+
+ def _toString(x: Product): String =
+ caseFields(x).mkString(x.productPrefix + "(", ",", ")")
+
+ def _hashCode(x: Product): Int = {
+ var code = x.getClass().hashCode()
+ val arr = x.arity
+ var i = 0
+ while (i < arr) {
+ code = code * 41 + x.element(i).hashCode()
+ i = i + 1
+ }
+ code
+ }
+
+ def _equals(x: Product, y: Any): Boolean = y match {
+ case y1: Product if x.arity == y1.arity =>
+ val arity = x.arity
+ var i = 0
+ while (i < arity && x.element(i) == y1.element(i))
+ i = i + 1
+ i == arity
+ case _ =>
+ false
+ }
+
+ def _equalsWithVarArgs(x: Product, y: Any): Boolean = y match {
+ case y1: Product if x.arity == y1.arity =>
+ val arity = x.arity
+ var i = 0
+ while (i < arity - 1 && x.element(i) == y1.element(i))
+ i = i + 1;
+ i == arity - 1 && {
+ x.element(i) match {
+ case xs: Seq[_] =>
+ y1.element(i) match {
+ case ys: Seq[_] => xs sameElements ys
+ }
+ }
+ }
+ case _ =>
+ false
+ }
+
+ //def checkDefined[T >: Null](x: T): T =
+ // if (x == null) throw new UndefinedException else x
+
+ def Seq[a](xs: a*): Seq[a] = null // interpreted specially by new backend.
+
+ def arrayValue(x: BoxedArray, elemTag: String): AnyRef =
+ if (x eq null) null else x.unbox(elemTag)
+
+ def arrayValue(x: BoxedArray, elemClass: Class): AnyRef =
+ if (x eq null) null else x.unbox(elemClass)
+
+ def boxArray(value: AnyRef): BoxedArray = value match {
+ case x: Array[Byte] => new BoxedByteArray(x)
+ case x: Array[Short] => new BoxedShortArray(x)
+ case x: Array[Char] => new BoxedCharArray(x)
+ case x: Array[Int] => new BoxedIntArray(x)
+ case x: Array[Long] => new BoxedLongArray(x)
+ case x: Array[Float] => new BoxedFloatArray(x)
+ case x: Array[Double] => new BoxedDoubleArray(x)
+ case x: Array[Boolean] => new BoxedBooleanArray(x)
+ case x: Array[AnyRef] => new BoxedObjectArray(x)
+ case x: BoxedArray => x
+ }
+}
diff --git a/src/dotnet-library/scala/runtime/ShortRef.java b/src/dotnet-library/scala/runtime/ShortRef.java
new file mode 100644
index 0000000000..acb001e39f
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/ShortRef.java
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime;
+
+
+public class ShortRef implements java.io.Serializable {
+ public short elem;
+ public ShortRef(short elem) { this.elem = elem; }
+}
diff --git a/src/dotnet-library/scala/runtime/StringAdd.scala b/src/dotnet-library/scala/runtime/StringAdd.scala
new file mode 100644
index 0000000000..a1a6a88d11
--- /dev/null
+++ b/src/dotnet-library/scala/runtime/StringAdd.scala
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+package scala.runtime
+
+final class StringAdd(self: Any) {
+ def +(other: String) = self.toString + other
+}
diff --git a/src/dotnet-library/scala/serializable.scala b/src/dotnet-library/scala/serializable.scala
new file mode 100644
index 0000000000..ba6c1dd45b
--- /dev/null
+++ b/src/dotnet-library/scala/serializable.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+/**
+ * An attribute that designates the class to which it is applied as serializable
+ */
+class serializable extends Attribute {}
diff --git a/src/dotnet-library/scala/testing/Benchmark.scala b/src/dotnet-library/scala/testing/Benchmark.scala
new file mode 100644
index 0000000000..6cbe587b46
--- /dev/null
+++ b/src/dotnet-library/scala/testing/Benchmark.scala
@@ -0,0 +1,87 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.testing
+
+
+import compat.Platform
+
+/** <code>Benchmark</code> can be used to quickly turn an existing
+ * class into a benchmark. Here is a short example:
+ *
+ * <pre>
+ * <b>object</b> sort1 <b>extends</b> Sorter <b>with</b> Benchmark {
+ * <b>def</b> run = sort(List.range(1, 1000))
+ * }
+ * </pre>
+ * <p>
+ * The run method has to be defined by the user, who will perform
+ * the timed operation there.
+ * Run the benchmark as follows:
+ * </p>
+ * <pre>
+ * &gt; scala sort1 5 times.log
+ * </pre>
+ * <p>
+ * This will run the benchmark 5 times and log the execution times in
+ * a file called <code>times.log</code>
+ * </p>
+ */
+trait Benchmark {
+
+ /** this method should be implemented by the concrete benchmark */
+ def run: Unit
+
+ var multiplier = 1
+
+ /** Run the benchmark the specified number of times
+ * and return a list with the execution times in milliseconds
+ * in reverse order of the execution
+ *
+ * @param noTimes ...
+ * @return ...
+ */
+ def runBenchmark(noTimes: Int): List[Long] =
+ for (val i <- List.range(1, noTimes + 1)) yield {
+ val startTime = Platform.currentTime
+ var i = 0; while(i < multiplier) {
+ run
+ i = i + 1
+ }
+ val stopTime = Platform.currentTime
+ Platform.collectGarbage
+
+ stopTime - startTime
+ }
+
+ /**
+ * The entry point. It takes two arguments: the number of
+ * consecutive runs, and the name of a log file where to
+ * append the times.
+ */
+ def main(args: Array[String]): Unit = {
+ if (args.length > 1) {
+ val logFile = new java.io.FileWriter(args(1), true) // append, not overwrite
+ if(args.length >= 3)
+ multiplier = args(2).toInt
+ logFile.write(getClass().getName())
+ for (val t <- runBenchmark(args(0).toInt))
+ logFile.write("\t\t" + t)
+
+ logFile.write(Platform.EOL)
+ logFile.flush()
+ } else {
+ Console.println("Usage: scala benchmarks.program <runs> <logfile>")
+ Console.println(" or: scala benchmarks.program <runs> <logfile> <multiplier>")
+ }
+ }
+}
+
diff --git a/src/dotnet-library/scala/testing/SUnit.scala b/src/dotnet-library/scala/testing/SUnit.scala
new file mode 100644
index 0000000000..dfacdf48a0
--- /dev/null
+++ b/src/dotnet-library/scala/testing/SUnit.scala
@@ -0,0 +1,195 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.testing
+
+import scala.collection.mutable.ArrayBuffer
+import compat.StringBuilder
+
+/**
+ * <p>
+ * Unit testing methods in the spirit of
+ * <a href="http://www.junit.org/" target="_top">JUnit</a> framework.
+ * </p>
+ * <p>
+ * Use these classes like this:
+ * </p>
+ * <pre>
+ * <b>import</b> scala.testing.SUnit
+ * <b>import</b> SUnit._
+ *
+ * <b>class</b> MyTest(n: String) <b>extends</b> TestCase(n) {
+ *
+ * <b>override def</b> runTest() = n <b>match</b> {
+ * <b>case</b> "myTest1" => assertTrue(<b>true</b>)
+ * <b>case</b> "myTest2" => assertTrue("hello", <b>false</b>)
+ * }
+ * }
+ *
+ * <b>val</b> r = <b>new</b> TestResult()
+ * suite.run(r)
+ * <b>for</b> (<b>val</b> tf &lt;- r.failures()) {
+ * Console.println(tf.toString())
+ * }
+ * </pre>
+ */
+object SUnit {
+
+ /** a Test can be run with its result being collected */
+ trait Test {
+ def run(r: TestResult): Unit
+ }
+
+ /** The class <code>TestCase</code> defines the fixture to run multiple
+ * tests.
+ *
+ * @param name ...
+ */
+ class TestCase(val name: String) extends Test with Assert {
+
+ protected def createResult() = new TestResult()
+
+ protected def runTest(): Unit = {}
+
+ def run(r: TestResult): Unit =
+ try {
+ runTest()
+ } catch {
+ case t:Throwable => r.addFailure(this, t)
+ }
+
+ def run(): Unit = run(createResult())
+
+ def setUp() = {}
+
+ def tearDown() = {}
+
+ override def toString() = name
+ }
+
+ /** The class <code>TestFailure</code> collects a failed test together
+ * with the thrown exception.
+ */
+ class TestFailure(val failedTest: Test, val thrownException: Throwable) {
+
+ def this(p: Pair[Test, Throwable]) = this(p._1, p._2)
+
+ override def toString() =
+ failedTest.toString() + " failed due to " + thrownException.toString()
+
+ def trace(): String = thrownException.getStackTraceString
+
+ }
+
+ /** a TestResult collects the result of executing a test case */
+ class TestResult {
+ val buf = new ArrayBuffer[Pair[Test, Throwable]]()
+
+ def addFailure(test:Test, t:Throwable) =
+ buf += Pair(test, t)
+
+ def failureCount() =
+ buf.length
+
+ def failures() =
+ buf.elements map { x => new TestFailure(x) }
+ }
+
+ /** The class <code>TestSuite</code> runs a composite of test cases.
+ */
+ class TestSuite(tests:Test*) extends Test {
+
+ def this(names: Seq[String], constr: String => Test) =
+ this((names.toList map constr):_*)
+
+ val buf = new ArrayBuffer[Test]()
+
+ buf ++= tests
+
+ def addTest(t: Test) =
+ buf += t
+
+ def run(r: TestResult): Unit =
+ for(val t <- buf) {
+ t.run(r)
+ }
+
+ }
+
+ /** an AssertFailed is thrown for a failed assertion */
+ case class AssertFailed(msg: String) extends java.lang.RuntimeException {
+ override def toString() = "failed assertion:" + msg
+ }
+
+ /** this class defined useful assert methods */
+ trait Assert {
+ /** equality */
+ def assertEquals[A](msg: String, expected: A, actual: => A): Unit =
+ if (expected != actual) fail(msg)
+
+ /** equality */
+ def assertEquals[A](expected: A, actual: => A): Unit =
+ assertEquals("(no message)", expected, actual)
+
+ /** falseness */
+ def assertFalse(msg: String, actual: => Boolean): Unit =
+ assertEquals(msg, false, actual)
+
+ /** falseness */
+ def assertFalse(actual: => Boolean): Unit =
+ assertFalse("(no message)", actual)
+
+ /** not null */
+ def assertNotNull(msg:String, actual: => AnyRef): Unit =
+ if (null == actual) fail(msg)
+
+ /** not null */
+ def assertNotNull(actual: => AnyRef): Unit =
+ assertNotNull("(no message)", actual)
+
+ /** reference inequality */
+ def assertNotSame(msg: String, expected: => AnyRef, actual: => AnyRef): Unit =
+ if (expected.eq(actual)) fail(msg)
+
+ /** reference inequality */
+ def assertNotSame(expected: => AnyRef, actual: => AnyRef): Unit =
+ assertNotSame("(no message)", expected, actual)
+
+ /** null */
+ def assertNull(msg: String, actual: => AnyRef): Unit =
+ if (null != actual) fail(msg)
+
+ /** null */
+ def assertNull(actual: => AnyRef): Unit =
+ assertNull("(no message)", actual)
+
+ /** reference equality */
+ def assertSame(msg: String, expected: => AnyRef, actual: => AnyRef): Unit =
+ if(!expected.eq(actual)) fail(msg)
+
+ /** reference equality */
+ def assertSame(expected: => AnyRef, actual: => AnyRef): Unit =
+ assertSame("(no message)", expected, actual)
+
+ /** trueness */
+ def assertTrue(msg: String, actual: => Boolean): Unit =
+ assertEquals(msg, true, actual)
+
+ /** trueness */
+ def assertTrue(actual: => Boolean): Unit =
+ assertTrue("(no message)", actual)
+
+ /** throws <code>AssertFailed</code> with given message <code>msg</code>.
+ */
+ def fail(msg: String): Unit =
+ throw new AssertFailed(msg)
+ }
+}
diff --git a/src/dotnet-library/scala/testing/UnitTest.scala b/src/dotnet-library/scala/testing/UnitTest.scala
new file mode 100644
index 0000000000..302ab6dc4a
--- /dev/null
+++ b/src/dotnet-library/scala/testing/UnitTest.scala
@@ -0,0 +1,85 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.testing
+
+
+/**
+ * Some simple methods to support unit testing with assertions
+ * to contain more JUnit style assertions which use Scala's features.
+ */
+object UnitTest {
+
+ class Report(report_ok: () => Unit, report_fail: (String,String) => Unit) {
+ def ok: Unit = report_ok()
+ def fail(actual: String, expected: String): Unit =
+ report_fail(actual, expected)
+ }
+
+ var report = new Report(
+ { () => Console.println("passed ok") },
+ { (actual: String, expected: String) =>
+ Console.print("failed! we got")
+ Console.print( "\""+ actual +"\"" )
+ Console.println(" but expected \"" + expected + "\"") })
+
+ /**
+ * @param r ...
+ */
+ def setReporter(r: Report) = {
+ this.report = r
+ }
+
+ /**
+ * @param actual ...
+ * @param expected ...
+ */
+ def assertSameElements[a](actual: Seq[a], expected: Seq[a]): Unit =
+ if (actual.sameElements(expected))
+ report.ok
+ else
+ report.fail(actual.toString(), expected.toString())
+
+ /**
+ * @param actual ...
+ * @param expected ...
+ */
+ def assertEquals[a](actual: a, expected: a): Unit =
+ if (actual == expected)
+ report.ok
+ else
+ report.fail(actual.toString(), expected.toString())
+
+ def assertTrue(actual: Boolean): Unit = assertEquals(actual, true)
+ def assertFalse(actual: Boolean): Unit = assertEquals(actual, false)
+
+ def assertNull(actual: AnyRef): Unit =
+ if (actual eq null)
+ report.ok
+ else
+ report.fail(actual.toString, "null")
+
+ def assertNonNull(actual: AnyRef): Unit =
+ if (actual ne null)
+ report.ok
+ else
+ report.fail(actual.toString, "null")
+
+
+ def assertNotEquals[a]( actual: a, expected: a): Unit =
+ if (actual != expected)
+ report.ok
+ else
+ report.fail(actual.toString(), "x != "+expected.toString())
+
+ //def test[a](def doit: a, expected: a): Unit = assertEquals(doit, expected)
+
+} // unitTest
diff --git a/src/dotnet-library/scala/text/Document.scala b/src/dotnet-library/scala/text/Document.scala
new file mode 100644
index 0000000000..4818c342fd
--- /dev/null
+++ b/src/dotnet-library/scala/text/Document.scala
@@ -0,0 +1,123 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.text
+
+
+import java.io.Writer
+
+case object DocNil extends Document
+case object DocBreak extends Document
+case class DocText(txt: String) extends Document
+case class DocGroup(doc: Document) extends Document
+case class DocNest(indent: Int, doc: Document) extends Document
+case class DocCons(hd: Document, tl: Document) extends Document
+
+/**
+ * A basic pretty-printing library, based on Lindig's strict version
+ * of Wadler's adaptation of Hughes' pretty-printer.
+ *
+ * @version 1.0
+ * @author Michel Schinz
+ */
+
+abstract class Document {
+ def ::(hd: Document): Document = DocCons(hd, this)
+ def ::(hd: String): Document = DocCons(DocText(hd), this)
+ def :/:(hd: Document): Document = hd :: DocBreak :: this
+ def :/:(hd: String): Document = hd :: DocBreak :: this
+
+ /**
+ * Format this document on WRITER and try to set line breaks so that
+ * the result fits in WIDTH columns.
+ *
+ * @param width ...
+ * @param writer ...
+ */
+ def format(width: Int, writer: Writer): Unit = {
+ type FmtState = Triple[Int,Boolean,Document]
+
+ def fits(w: Int, state: List[FmtState]): boolean = state match {
+ case _ if w < 0 =>
+ false
+ case List() =>
+ true
+ case {_, _, DocNil} :: z =>
+ fits(w, z)
+ case {i, b, DocCons(h, t)} :: z =>
+ fits(w, {i,b,h} :: {i,b,t} :: z)
+ case {_, _, DocText(t)} :: z =>
+ fits(w - t.length(), z)
+ case {i, b, DocNest(ii, d)} :: z =>
+ fits(w, {i + ii, b, d} :: z)
+ case {_, false, DocBreak} :: z =>
+ fits(w - 1, z)
+ case {_, true, DocBreak} :: z =>
+ true
+ case {i, _, DocGroup(d)} :: z =>
+ fits(w, {i, false, d} :: z)
+ }
+
+ def spaces(n: Int): Unit = {
+ var rem = n
+ while (rem >= 16) { writer write " "; rem = rem - 16 }
+ if (rem >= 8) { writer write " "; rem = rem - 8 }
+ if (rem >= 4) { writer write " "; rem = rem - 4 }
+ if (rem >= 2) { writer write " "; rem = rem - 2}
+ if (rem == 1) { writer write " " }
+ }
+
+ def fmt(k: Int, state: List[FmtState]): Unit = state match {
+ case List() => ()
+ case {_, _, DocNil} :: z =>
+ fmt(k, z)
+ case {i, b, DocCons(h, t)} :: z =>
+ fmt(k, {i, b, h} :: {i, b, t} :: z)
+ case {i, _, DocText(t)} :: z =>
+ writer write t
+ fmt(k + t.length(), z)
+ case {i, b, DocNest(ii, d)} :: z =>
+ fmt(k, {i + ii, b, d} :: z)
+ case {i, true, DocBreak} :: z =>
+ writer write "\n"
+ spaces(i);
+ fmt(i, z)
+ case {i, false, DocBreak} :: z =>
+ writer write " "
+ fmt(k + 1, z)
+ case {i, b, DocGroup(d)} :: z =>
+ val fitsFlat = fits(width - k, {i, false, d} :: z)
+ fmt(k, {i, !fitsFlat, d} :: z)
+ }
+
+ fmt(0, {0, false, DocGroup(this)} :: Nil)
+ }
+}
+
+object Document {
+ /** The empty document */
+ def empty = DocNil
+
+ /** A break, which will either be turned into a space or a line break */
+ def break = DocBreak
+
+ /** A document consisting of some text literal */
+ def text(s: String): Document = DocText(s)
+
+ /**
+ * A group, whose components will either be printed with all breaks
+ * rendered as spaces, or with all breaks rendered as line breaks.
+ */
+ def group(d: Document): Document = DocGroup(d)
+
+ /** A nested document, which will be indented as specified. */
+ def nest(i: Int, d: Document): Document = DocNest(i, d)
+}
diff --git a/src/dotnet-library/scala/throws.scala b/src/dotnet-library/scala/throws.scala
new file mode 100644
index 0000000000..b9c23b6a5f
--- /dev/null
+++ b/src/dotnet-library/scala/throws.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+*/
+
+// $Id$
+
+
+package scala
+
+/**
+ * Attribute for specifying the exceptions thrown by a method.
+ * <p>
+ * Example:
+ * </p>
+ * <pre>
+ * <b>class</b> Reader(fname: String) {
+ * <b>private val</b> in =
+ * <b>new</b> BufferedReader(<b>new</b> FileReader(fname))
+ * [throws(classOf[IOException])]
+ * <b>def</b> read() = in.read()
+ * }</pre>
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0, 19/05/2006
+ */
+class throws(clazz: java.lang.Class) extends Attribute
diff --git a/src/dotnet-library/scala/transient.scala b/src/dotnet-library/scala/transient.scala
new file mode 100644
index 0000000000..024dccbf01
--- /dev/null
+++ b/src/dotnet-library/scala/transient.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala;
+
+
+class transient extends Attribute {}
diff --git a/src/dotnet-library/scala/util/Fluid.scala b/src/dotnet-library/scala/util/Fluid.scala
new file mode 100644
index 0000000000..ebfefada35
--- /dev/null
+++ b/src/dotnet-library/scala/util/Fluid.scala
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util
+
+
+import java.lang.InheritableThreadLocal
+
+/** Fluids provide a binding mechanism where the current
+ * value is found through <em>dynamic scope</em>, but where
+ * access to the fluid itself is resolved through </em>static
+ * binding</em> to a variable referencing the fluid.
+ *
+ * The current value can be retrieved with the
+ * <code>value</code> method. New values can be
+ * pushed using the <code>withValue</code> method.
+ * Values pushed via <code>withValue</code> only
+ * stay valid while the <code>withValue</code>'s
+ * <em>second</em> argument, a parameterless closure,
+ * executes. When the second argument finishes,
+ * the fluid reverts to the previous value.
+ *
+ * Usage of <code>withValue</code> looks like this:
+ * <blockquote><pre>
+ * someFluid.withValue(newValue) {
+ * // ... code called in here that calls value ...
+ * // ... will be given back the newValue ...
+ * }
+ * </pre></blockquote>
+ *
+ * Each thread gets its own stack of bindings. When a
+ * new thread is created, the fluid gets a copy of
+ * the stack of bindings from the parent thread, and
+ * from then on the bindings for the new thread
+ * are independent of those for the original thread.
+ *
+ * @author Lex Spoon
+ * @version 1.0, 21/03/2006
+ */
+class Fluid[T](init: T) {
+ private val tl = new InheritableThreadLocal {
+ override def initialValue = init.asInstanceOf[AnyRef]
+ }
+
+ /** Retrieve the current value */
+ def value: T = tl.get.asInstanceOf[T]
+
+
+ /** Set the value of the fluid while executing the specified
+ * thunk.
+ *
+ * @param newval The value to which to set the fluid
+ * @param thunk The code to evaluate under the new setting
+ */
+ def withValue[S](newval: T)(thunk: =>S): S = {
+ val oldval = value
+ tl.set(newval)
+
+ try { thunk } finally {
+ tl.set(oldval)
+ }
+ }
+
+ /** Change the currently bound value, discarding the old value.
+ * Usually withValue() gives better semantics.
+ */
+ def value_=(newval: T) = { tl.set(newval) }
+
+ override def toString: String = "Fluid(" + value +")"
+}
diff --git a/src/dotnet-library/scala/util/Sorting.scala b/src/dotnet-library/scala/util/Sorting.scala
new file mode 100644
index 0000000000..24f0de23c1
--- /dev/null
+++ b/src/dotnet-library/scala/util/Sorting.scala
@@ -0,0 +1,519 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, Ross Judson **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: $
+
+
+package scala.util
+
+/** <p>
+ * The Sorting object provides functions that can sort various kinds of
+ * objects. You can provide a comparison function, or you can request a sort
+ * of items that are viewable as <code>Ordered</code>. Some sorts that
+ * operate directly on a subset of value types are also provided. These
+ * implementations are derived from those in the Sun JDK.
+ * </p>
+ * <p>
+ * Note that stability doesn't matter for value types, so use the quickSort
+ * variants for those. <code>stableSort</code> is intended to be used with
+ * objects when the prior ordering should be preserved, where possible.
+ * </p>
+ *
+ * @author Ross Judson
+ * @version 1.0
+ */
+object Sorting {
+
+ /** Provides implicit access to sorting on arbitrary sequences of orderable
+ * items. This doesn't quite work the way that I want yet -- K should be
+ * bounded as viewable, but the compiler rejects that.
+ */
+ implicit def seq2RichSort[K <: Ordered[K]](s: Seq[K]) = new RichSorting[K](s)
+
+ /** Quickly sort an array of Doubles. */
+ def quickSort(a: Array[Double]) = sort1(a, 0, a.length)
+
+ /** Quickly sort an array of items that are viewable as ordered. */
+ def quickSort[K <% Ordered[K]](a: Array[K]) = sort1(a, 0, a.length)
+
+ /** Quickly sort an array of Ints. */
+ def quickSort(a: Array[Int]) = sort1(a, 0, a.length)
+
+ /** Quickly sort an array of Floats. */
+ def quickSort(a: Array[Float]) = sort1(a, 0, a.length)
+
+ /** Sort an array of K where K is Ordered, preserving the existing order
+ where the values are equal. */
+ def stableSort[K <% Ordered[K]](a: Array[K]): Unit =
+ stableSort(a, 0, a.length-1, new Array[K](a.length), (a:K, b:K) => a < b)
+
+ /** Sorts an array of <code>K</code> given an ordering function
+ * <code>f</code>. <code>f</code> should return <code>true</code> iff
+ * its first parameter is strictly less than its second parameter.
+ */
+ def stableSort[K](a: Array[K], f: (K,K) => Boolean): Unit =
+ stableSort(a, 0, a.length-1, new Array[K](a.length), f)
+
+ /** Sorts an arbitrary sequence into an array, given a comparison function
+ * that should return <code>true</code> iff parameter one is strictly less
+ * than parameter two.
+ *
+ * @param a the sequence to be sorted.
+ * @param f the comparison function.
+ * @return the sorted sequence of items.
+ */
+ def stableSort[K](a: Seq[K], f: (K,K) => Boolean): Array[K] = {
+ val ret = a.toArray
+ stableSort(ret, f)
+ ret
+ }
+
+ /** Sorts an arbitrary sequence of items that are viewable as ordered. */
+ def stableSort[K <% Ordered[K]](a: Seq[K]): Array[K] =
+ stableSort(a, (a:K, b:K) => a < b)
+
+ /** Stably sorts a sequence of items given an extraction function that will
+ * return an ordered key from an item.
+ *
+ * @param a the sequence to be sorted.
+ * @param f the comparison function.
+ * @return the sorted sequence of items.
+ */
+ def stableSort[K, M <% Ordered[M]](a: Seq[K], f: K => M): Array[K] =
+ stableSort(a, (a: K, b: K) => f(a) < f(b))
+
+ private def sort1[K <% Ordered[K]](x: Array[K], off: Int, len: Int) {
+ def swap(a: Int, b: Int) {
+ val t = x(a)
+ x(a) = x(b)
+ x(b) = t
+ }
+ def vecswap(_a: Int, _b: Int, n: Int) {
+ var a = _a
+ var b = _b
+ var i = 0
+ while (i < n) {
+ swap(a, b)
+ i = i + 1
+ a = a + 1
+ b = b + 1
+ }
+ }
+ def med3(a: Int, b: Int, c: Int) = {
+ if (x(a) < x(b)) {
+ if (x(b) < x(c)) b else if (x(a) < x(c)) c else a
+ } else {
+ if (x(b) > x(c)) b else if (x(a) > x(c)) c else a
+ }
+ }
+ // Insertion sort on smallest arrays
+ if (len < 7) {
+ var i = off
+ while (i < len + off) {
+ var j = i
+ while (j > off && x(j-1) > x(j)) {
+ swap(j, j-1)
+ j = j - 1
+ }
+ i = i + 1
+ }
+ } else {
+ // Choose a partition element, v
+ var m = off + (len >> 1) // Small arrays, middle element
+ if (len > 7) {
+ var l = off
+ var n = off + len - 1
+ if (len > 40) { // Big arrays, pseudomedian of 9
+ var s = len / 8
+ l = med3(l, l+s, l+2*s)
+ m = med3(m-s, m, m+s)
+ n = med3(n-2*s, n-s, n)
+ }
+ m = med3(l, m, n) // Mid-size, med of 3
+ }
+ val v = x(m)
+
+ // Establish Invariant: v* (<v)* (>v)* v*
+ var a = off
+ var b = a
+ var c = off + len - 1
+ var d = c;
+ var done = false
+ while(!done) {
+ while (b <= c && x(b) <= v) {
+ if (x(b) == v) {
+ swap(a, b)
+ a = a + 1
+ }
+ b = b + 1
+ }
+ while (c >= b && x(c) >= v) {
+ if (x(c) == v) {
+ swap(c, d)
+ d = d - 1
+ }
+ c = c - 1
+ }
+ if (b > c) {
+ done = true
+ } else {
+ swap(b, c)
+ c = c - 1
+ b = b + 1
+ }
+ }
+
+ // Swap partition elements back to middle
+ val n = off + len
+ var s = Math.min(a-off, b-a)
+ vecswap(off, b-s, s)
+ s = Math.min(d-c, n-d-1)
+ vecswap(b, n-s, s)
+
+ // Recursively sort non-partition-elements
+ s = b-a
+ if (s > 1)
+ sort1(x, off, s)
+ s = d-c
+ if (s > 1)
+ sort1(x, n-s, s)
+ }
+ }
+
+ private def sort1(x: Array[Int], off: Int, len: Int) {
+ def swap(a: Int, b: Int) {
+ val t = x(a)
+ x(a) = x(b)
+ x(b) = t
+ }
+ def vecswap(_a: Int, _b: Int, n: Int) {
+ var a = _a
+ var b = _b
+ var i = 0
+ while (i < n) {
+ swap(a,b)
+ i = i + 1
+ a = a + 1
+ b = b + 1
+ }
+ }
+ def med3(a: Int, b: Int, c: Int) = {
+ if (x(a) < x(b)) {
+ if (x(b) < x(c)) b else if (x(a) < x(c)) c else a
+ } else {
+ if (x(b) > x(c)) b else if (x(a) > x(c)) c else a
+ }
+ }
+ // Insertion sort on smallest arrays
+ if (len < 7) {
+ var i = off
+ while (i < len + off) {
+ var j = i
+ while (j > off && x(j-1) > x(j)) {
+ swap(j, j-1)
+ j = j - 1
+ }
+ i = i + 1
+ }
+ } else {
+ // Choose a partition element, v
+ var m = off + (len >> 1) // Small arrays, middle element
+ if (len > 7) {
+ var l = off
+ var n = off + len - 1
+ if (len > 40) { // Big arrays, pseudomedian of 9
+ var s = len/8;
+ l = med3(l, l+s, l+2*s)
+ m = med3(m-s, m, m+s)
+ n = med3(n-2*s, n-s, n)
+ }
+ m = med3(l, m, n) // Mid-size, med of 3
+ }
+ val v = x(m)
+
+ // Establish Invariant: v* (<v)* (>v)* v*
+ var a = off
+ var b = a
+ var c = off + len - 1
+ var d = c
+ var done = false
+ while(!done) {
+ while (b <= c && x(b) <= v) {
+ if (x(b) == v) {
+ swap(a, b)
+ a = a + 1
+ }
+ b = b + 1
+ }
+ while (c >= b && x(c) >= v) {
+ if (x(c) == v) {
+ swap(c, d)
+ d = d - 1
+ }
+ c = c - 1
+ }
+ if (b > c) {
+ done = true
+ } else {
+ swap(b, c)
+ c = c - 1
+ b = b + 1
+ }
+ }
+
+ // Swap partition elements back to middle
+ val n = off + len;
+ var s = Math.min(a-off, b-a)
+ vecswap(off, b-s, s)
+ s = Math.min(d-c, n-d-1)
+ vecswap(b, n-s, s)
+
+ // Recursively sort non-partition-elements
+ s = b - a
+ if (s > 1)
+ sort1(x, off, s)
+ s = d-c
+ if (s > 1)
+ sort1(x, n-s, s)
+ }
+ }
+
+ private def sort1(x: Array[Double], off: Int, len: Int) {
+ def swap(a: Int, b: Int) {
+ val t = x(a)
+ x(a) = x(b)
+ x(b) = t
+ }
+ def vecswap(_a: Int, _b: Int, n: Int) {
+ var a = _a
+ var b = _b
+ var i = 0
+ while (i < n) {
+ swap(a, b)
+ i = i + 1
+ a = a + 1
+ b = b + 1
+ }
+ }
+ def med3(a: Int, b: Int, c: Int) =
+ if (x(a) < x(b)) {
+ if (x(b) < x(c)) b else if (x(a) < x(c)) c else a
+ } else {
+ if (x(b) > x(c)) b else if (x(a) > x(c)) c else a
+ }
+
+ // Insertion sort on smallest arrays
+ if (len < 7) {
+ var i = off
+ while (i < len + off) {
+ var j = i
+ while (j>off && x(j-1)>x(j)) {
+ swap(j,j-1)
+ j = j - 1
+ }
+ i = i + 1
+ }
+ } else {
+ // Choose a partition element, v
+ var m = off + (len >> 1) // Small arrays, middle element
+ if (len > 7) {
+ var l = off
+ var n = off + len - 1
+ if (len > 40) { // Big arrays, pseudomedian of 9
+ var s = len / 8
+ l = med3(l, l+s, l+2*s)
+ m = med3(m-s, m, m+s)
+ n = med3(n-2*s, n-s, n)
+ }
+ m = med3(l, m, n) // Mid-size, med of 3
+ }
+ val v = x(m)
+
+ // Establish Invariant: v* (<v)* (>v)* v*
+ var a = off
+ var b = a
+ var c = off + len - 1
+ var d = c
+ var done = false
+ while(!done) {
+ while (b <= c && x(b) <= v) {
+ if (x(b) == v) {
+ swap(a, b)
+ a = a + 1
+ }
+ b = b + 1
+ }
+ while (c >= b && x(c) >= v) {
+ if (x(c) == v) {
+ swap(c, d)
+ d = d - 1
+ }
+ c = c - 1
+ }
+ if (b > c) {
+ done = true
+ } else {
+ swap(b, c)
+ c = c - 1
+ b = b + 1
+ }
+ }
+
+ // Swap partition elements back to middle
+ val n = off + len
+ var s = Math.min(a-off, b-a)
+ vecswap(off, b-s, s)
+ s = Math.min(d-c, n-d-1)
+ vecswap(b, n-s, s)
+
+ // Recursively sort non-partition-elements
+ s = b-a
+ if (s > 1)
+ sort1(x, off, s)
+ s = d-c
+ if (s > 1)
+ sort1(x, n-s, s)
+ }
+ }
+
+ private def sort1(x: Array[Float], off: Int, len: Int) {
+ def swap(a: Int, b: Int) {
+ val t = x(a)
+ x(a) = x(b)
+ x(b) = t
+ }
+ def vecswap(_a: Int, _b: Int, n: Int) {
+ var a = _a
+ var b = _b
+ var i = 0
+ while (i < n) {
+ swap(a,b)
+ i = i + 1
+ a = a + 1
+ b = b + 1
+ }
+ }
+ def med3(a: Int, b: Int, c: Int) =
+ if (x(a) < x(b)) {
+ if (x(b) < x(c)) b else if (x(a) < x(c)) c else a
+ } else {
+ if (x(b) > x(c)) b else if (x(a) > x(c)) c else a
+ }
+
+ // Insertion sort on smallest arrays
+ if (len < 7) {
+ var i = off
+ while (i < len + off) {
+ var j = i
+ while (j > off && x(j-1) > x(j)) {
+ swap(j, j-1)
+ j = j - 1
+ }
+ i = i + 1
+ }
+ } else {
+ // Choose a partition element, v
+ var m = off + (len >> 1) // Small arrays, middle element
+ if (len > 7) {
+ var l = off
+ var n = off + len - 1
+ if (len > 40) { // Big arrays, pseudomedian of 9
+ var s = len/8;
+ l = med3(l, l+s, l+2*s)
+ m = med3(m-s, m, m+s)
+ n = med3(n-2*s, n-s, n)
+ }
+ m = med3(l, m, n) // Mid-size, med of 3
+ }
+ val v = x(m)
+
+ // Establish Invariant: v* (<v)* (>v)* v*
+ var a = off
+ var b = a
+ var c = off + len - 1
+ var d = c
+ var done = false
+ while(!done) {
+ while (b <= c && x(b) <= v) {
+ if (x(b) == v) {
+ swap(a, b)
+ a = a + 1
+ }
+ b = b + 1
+ }
+ while (c >= b && x(c) >= v) {
+ if (x(c) == v) {
+ swap(c, d)
+ d = d - 1
+ }
+ c = c - 1
+ }
+ if (b > c) {
+ done = true
+ } else {
+ swap(b, c)
+ c = c - 1
+ b = b + 1
+ }
+ }
+
+ // Swap partition elements back to middle
+ val n = off + len
+ var s = Math.min(a-off, b-a)
+ vecswap(off, b-s, s)
+ s = Math.min(d-c, n-d-1)
+ vecswap(b, n-s, s)
+
+ // Recursively sort non-partition-elements
+ s = b - a
+ if (s > 1)
+ sort1(x, off, s)
+ s = d-c
+ if (s > 1)
+ sort1(x, n-s, s)
+ }
+ }
+
+ private def stableSort[K](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) {
+ if (lo < hi) {
+ val mid = (lo+hi) / 2
+ stableSort(a, lo, mid, scratch, f)
+ stableSort(a, mid+1, hi, scratch, f)
+ var k, t_lo = lo
+ var t_hi = mid + 1
+ while (k <= hi) {
+ if ((t_lo <= mid) && ((t_hi > hi) || (f(a(t_lo), a(t_hi))))) {
+ scratch(k) = a(t_lo)
+ t_lo = t_lo + 1
+ } else {
+ scratch(k) = a(t_hi)
+ t_hi = t_hi + 1
+ }
+ k = k + 1
+ }
+ k = lo
+ while (k <= hi) {
+ a(k) = scratch(k)
+ k = k + 1
+ }
+ }
+ }
+}
+
+/** <p>
+ * A <code>RichSorting</code> object is generally created implicitly through
+ * the use of the <code>sort</code> function on an arbitrary sequence, where
+ * the items are ordered.
+ * </p>
+ */
+class RichSorting[K <: Ordered[K]](s: Seq[K]) {
+
+ /** Returns an array with a sorted copy of the RichSorting's sequence.
+ */
+ def sort = Sorting.stableSort(s)
+}
diff --git a/src/dotnet-library/scala/util/automata/BaseBerrySethi.scala b/src/dotnet-library/scala/util/automata/BaseBerrySethi.scala
new file mode 100644
index 0000000000..2d590a0edf
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/BaseBerrySethi.scala
@@ -0,0 +1,198 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata
+
+
+import scala.util.regexp.Base
+
+import scala.collection.mutable
+import scala.collection.immutable
+
+/** this turns a regexp over A into a NondetWorkAutom over A using the
+ * celebrated position automata construction (also called Berry-Sethi or
+ * Glushkov)
+ */
+abstract class BaseBerrySethi {
+
+ val lang: Base
+ import lang.{Alt,Eps,Meta,RegExp,Sequ,Star}
+
+ protected var pos = 0
+
+ protected var globalFirst: immutable.Set[Int] = _
+
+ // results which hold all info for the NondetWordAutomaton
+ protected var follow: mutable.HashMap[Int, immutable.Set[Int]] = _
+
+ protected var finalTag: Int = _
+
+ protected var finals: immutable.TreeMap[int,int] = _ // final states
+
+ // constants --------------------------
+
+ final val emptySet:immutable.Set[Int] = new immutable.TreeSet[Int]()
+
+ /** computes first( r ) for the word regexp r */
+ protected def compFirst(r: RegExp): immutable.Set[Int] = r match {
+ case x:Alt =>
+ var tmp = emptySet
+ val it = x.rs.elements // union
+ while (it.hasNext) { tmp = tmp incl compFirst(it.next) }
+ tmp
+ case Eps => emptySet
+ //case x:Letter => emptySet + posMap(x); // singleton set
+ case x:Meta => compFirst(x.r)
+ case x:Sequ =>
+ var tmp = emptySet;
+ val it = x.rs.elements; // union
+ while (it.hasNext) {
+ val z = it.next
+ tmp = tmp incl compFirst(z)
+ if (!z.isNullable)
+ return tmp
+ }
+ tmp
+ case Star(t) => compFirst(t)
+ case _ =>
+ throw new IllegalArgumentException("unexpected pattern " + r.getClass())
+ }
+
+ /** computes last( r ) for the regexp r */
+ protected def compLast(r: RegExp): immutable.Set[Int] = r match {
+ case x:Alt =>
+ var tmp = emptySet
+ val it = x.rs.elements // union
+ while (it.hasNext) { tmp = tmp incl compFirst(it.next) }
+ tmp
+ case Eps => emptySet
+ //case x:Letter => emptySet + posMap(x) // singleton set
+ case x:Meta => compLast(x.r)
+ case x:Sequ =>
+ var tmp = emptySet
+ val it = x.rs.elements.toList.reverse.elements // union
+ while (it.hasNext) {
+ val z = it.next
+ tmp = tmp incl compLast(z)
+ if (!z.isNullable)
+ return tmp
+ }
+ tmp
+ case Star(t) => compLast(t)
+ case _ =>
+ throw new IllegalArgumentException("unexpected pattern " + r.getClass())
+ }
+
+ /** Starts from the right-to-left
+ * precondition: pos is final
+ * pats are successor patterns of a Sequence node
+ *
+ * @param r ...
+ * @return ...
+ */
+ protected def compFollow(r: Seq[RegExp]): immutable.Set[Int] = {
+ //Console.println("compFollow( "+r.toList)
+ var first = emptySet
+ var fol = emptySet
+ if (r.length > 0) {//non-empty expr
+
+ val it = r.elements.toList.reverse.elements
+
+ fol = fol + pos // don't modify pos !
+ while (it.hasNext) {
+ val p = it.next
+ //Console.println(" p now = "+p)
+ first = compFollow1(fol, p)
+ //Console.println(" first = "+first)
+ //Console.println(" fol before = "+fol)
+ fol =
+ if (p.isNullable) fol incl first
+ else first
+ //Console.println(" fol after = "+fol)
+ }
+ }
+ this.follow.update(0, fol /*first*/)
+ //Console.println("follow(0) = "+fol)
+ fol
+ }
+
+ /** returns the first set of an expression, setting the follow set along
+ * the way.
+ *
+ * @param fol1 ...
+ * @param r ...
+ * @return ...
+ */
+ protected def compFollow1(fol1: immutable.Set[Int], r: RegExp): immutable.Set[Int] = {
+ var fol = fol1
+ //System.out.println("compFollow1("+fol+","+r+")")
+ r match {
+
+ case x:Alt =>
+ var first = emptySet
+ val it = x.rs.elements.toList.reverse.elements
+ while (it.hasNext)
+ first = first incl compFollow1(fol, it.next);
+ first
+
+ /*
+ case x:Letter =>
+ val i = posMap( x );
+ this.follow.update( i, fol );
+ emptySet + i;
+ */
+ case x:Meta =>
+ compFollow1(fol1, x.r)
+
+ case x:Star =>
+ fol = fol incl compFirst(x.r)
+ compFollow1(fol, x.r)
+
+ case x:Sequ =>
+ var first = emptySet
+ val it = x.rs.elements.toList.reverse.elements
+ while (it.hasNext) {
+ val p = it.next
+ first = compFollow1(fol, p)
+ fol =
+ if (p.isNullable) fol incl first
+ else first
+ }
+ first
+
+ case _ =>
+ throw new IllegalArgumentException("unexpected pattern: " + r.getClass())
+ }
+ }
+
+ /** returns "Sethi-length" of a pattern, creating the set of position
+ * along the way.
+ *
+ * @param r ...
+ */
+ // todo: replace global variable pos with acc
+ protected def traverse(r: RegExp): Unit = r match {
+ // (is tree automaton stuff, more than Berry-Sethi)
+ case x:Alt =>
+ val it = x.rs.elements
+ while (it.hasNext) traverse(it.next)
+ case x:Sequ =>
+ val it = x.rs.elements
+ while (it.hasNext) traverse(it.next)
+ case x:Meta =>
+ traverse(x.r)
+ case Star(t) =>
+ traverse(t)
+ case _ =>
+ throw new IllegalArgumentException("unexp pattern " + r.getClass())
+ }
+
+}
diff --git a/src/dotnet-library/scala/util/automata/DetWordAutom.scala b/src/dotnet-library/scala/util/automata/DetWordAutom.scala
new file mode 100644
index 0000000000..e0075e5bc8
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/DetWordAutom.scala
@@ -0,0 +1,84 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata
+
+
+import scala.collection.{Set, Map}
+
+/** A deterministic automaton. States are integers, where
+ * 0 is always the only initial state. Transitions are represented
+ * in the delta function. A default transitions is one that
+ * is taken when no other transition can be taken.
+ * All states are reachable. Accepting states are those for which
+ * the partial function 'finals' is defined.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class DetWordAutom[T <: AnyRef] {
+
+ val nstates: Int
+ val finals: Array[Int]
+ val delta: Array[Map[T,Int]]
+ val default: Array[Int]
+
+ /**
+ * @param q ...
+ * @return ...
+ */
+ def isFinal(q: Int) = finals(q) != 0
+
+ /**
+ * @param q ...
+ * @return ...
+ */
+ def isSink(q: Int) = delta(q).isEmpty && default(q) == q
+
+ /**
+ * @param q ...
+ * @param label ...
+ * @return ...
+ */
+ def next(q: Int, label: T) = {
+ delta(q).get(label) match {
+ case Some(p) => p
+ case _ => default(q)
+ }
+ }
+
+ override def toString() = {
+ val sb = new compat.StringBuilder()
+ sb.append("[DetWordAutom nstates=")
+ sb.append(nstates)
+ sb.append(" finals=")
+ var map = new scala.collection.immutable.ListMap[Int,Int]
+ var j = 0; while( j < nstates ) {
+ if (j < finals.length)
+ map = map.update(j, finals(j))
+ j = j + 1
+ }
+ sb.append(map.toString())
+ sb.append(" delta=\n")
+ for (val i <- 0 until nstates) {
+ sb.append( i )
+ sb.append("->")
+ sb.append(delta(i).toString())
+ sb.append('\n')
+ if (i < default.length) {
+ sb.append("_>")
+ sb.append(default(i).toString())
+ sb.append('\n')
+ }
+ }
+ sb.toString()
+ }
+}
diff --git a/src/dotnet-library/scala/util/automata/Inclusion.scala b/src/dotnet-library/scala/util/automata/Inclusion.scala
new file mode 100644
index 0000000000..eb8beb47b3
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/Inclusion.scala
@@ -0,0 +1,72 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata
+
+
+/** A fast test of language inclusion between minimal automata.
+ * inspired by the AMoRE automata library
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+trait Inclusion[A <: AnyRef] {
+
+ val labels: Seq[A]
+
+ /** Returns true if dfa1 is included in dfa2.
+ *
+ * @param dfa1 ...
+ * @param dfa2 ...
+ */
+ def inclusion(dfa1: DetWordAutom[A], dfa2: DetWordAutom[A]) = {
+
+ def encode(q1:Int, q2:Int) = 1 + q1 + q2 * dfa1.nstates
+ def decode2(c:Int) = (c-1) / (dfa1.nstates) //integer division
+ def decode1(c:Int) = (c-1) % (dfa1.nstates)
+
+ var q1 = 0 //dfa1.initstate; // == 0
+ var q2 = 0 //dfa2.initstate; // == 0
+
+ val max = 1 + dfa1.nstates * dfa2.nstates
+ val mark = new Array[Int](max)
+
+ var result = true
+ var current = encode(q1, q2)
+ var last = current
+ mark(last) = max // mark (q1,q2)
+ while (current != 0 && result) {
+ //Console.println("current = [["+q1+" "+q2+"]] = "+current);
+ for (val letter <- labels) {
+ val r1 = dfa1.next(q1,letter)
+ val r2 = dfa2.next(q2,letter)
+ if (dfa1.isFinal(r1) && !dfa2.isFinal(r2))
+ result = false
+ val test = encode(r1, r2)
+ //Console.println("test = [["+r1+" "+r2+"]] = "+test);
+ if (mark(test) == 0) {
+ mark(last) = test
+ mark(test) = max
+ last = test
+ }
+ }
+ val ncurrent = mark(current)
+ if( ncurrent != max ) {
+ q1 = decode1(ncurrent)
+ q2 = decode2(ncurrent)
+ current = ncurrent
+ } else {
+ current = 0
+ }
+ }
+ result
+ }
+}
diff --git a/src/dotnet-library/scala/util/automata/NondetWordAutom.scala b/src/dotnet-library/scala/util/automata/NondetWordAutom.scala
new file mode 100644
index 0000000000..660ebc1c99
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/NondetWordAutom.scala
@@ -0,0 +1,113 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata
+
+
+import scala.collection.{immutable, mutable, Set, Map}
+
+/** A nondeterministic automaton. States are integers, where
+ * 0 is always the only initial state. Transitions are represented
+ * in the delta function. Default transitions are transitions that
+ * are taken when no other transitions can be applied.
+ * All states are reachable. Accepting states are those for which
+ * the partial function 'finals' is defined.
+ */
+abstract class NondetWordAutom[T <: AnyRef] {
+
+ val nstates: Int
+ val labels: Seq[T]
+
+ val finals: Array[Int] // 0 means not final
+ val delta: Array[Map[T, immutable.BitSet]]
+ val default: Array[immutable.BitSet]
+
+ /** returns true if the state is final */
+ final def isFinal(state: Int) = finals(state) > 0
+
+ /** returns tag of final state */
+ final def finalTag(state: Int) = finals(state)
+
+ /** returns true if the set of states contains at least one final state */
+ final def containsFinal(Q: immutable.BitSet): Boolean = {
+ val it = Q.elements
+ while (it.hasNext)
+ if (isFinal(it.next))
+ return true
+ return false
+ }
+
+ /** returns true if there are no accepting states */
+ final def isEmpty = {
+ var r = true
+ var j = 0; while(r && (j < nstates)) {
+ if (isFinal(j))
+ r = false
+ }
+ r
+ }
+
+ /** returns a bitset with the next states for given state and label */
+ def next(q: Int, a: T): immutable.BitSet = {
+ delta(q).get(a) match {
+ case Some(bs) => bs
+ case _ => default(q)
+ }
+ }
+
+ /** returns a bitset with the next states for given state and label */
+ def next(Q: immutable.BitSet, a: T): immutable.BitSet = {
+ val x = new mutable.BitSet(nstates)
+ for (val q <- Q) {
+ for (val i <- next(q,a)) {
+ x += i
+ }
+ }
+ x.toImmutable
+ }
+
+
+ def nextDefault(Q: immutable.BitSet): immutable.BitSet = {
+ val x = new mutable.BitSet(nstates)
+ for (val q <- Q) {
+ for (val i <- default(q)) { //@todo: OR
+ x += i
+ }
+ }
+ x.toImmutable;
+ }
+
+ override def toString() = {
+ val sb = new compat.StringBuilder()
+ sb.append("[NondetWordAutom nstates=")
+ sb.append(nstates)
+ sb.append(" finals=")
+ var map = new scala.collection.immutable.ListMap[Int,Int]
+ var j = 0; while (j < nstates) {
+ if (isFinal(j))
+ map = map.update(j, finals(j));
+ j = j + 1
+ }
+ sb.append(map.toString())
+ sb.append(" delta=\n")
+ for (val i <- 0 until nstates) {
+ sb.append(" ")
+ sb.append( i )
+ sb.append("->")
+ sb.append(delta(i).toString())
+ sb.append("\n ")
+ sb.append(" _>")
+ sb.append(default(i).toString())
+ sb.append('\n')
+ }
+ sb.toString()
+ }
+}
diff --git a/src/dotnet-library/scala/util/automata/SubsetConstruction.scala b/src/dotnet-library/scala/util/automata/SubsetConstruction.scala
new file mode 100644
index 0000000000..8786ada85c
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/SubsetConstruction.scala
@@ -0,0 +1,178 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata ;
+
+
+class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) {
+ //import nfa.{ _labelT, labels };
+ import nfa.labels ;
+ import scala.collection.{immutable, mutable, Map} ;
+
+ import immutable.{ BitSet, TreeMap, TreeSet } ;
+
+ implicit def toOrdered(bs: BitSet): Ordered[BitSet] = new Ordered[BitSet] {
+ def compare (that: BitSet): Int = {
+ val it1 = bs.elements;
+ val it2 = that.elements;
+ var res = 0;
+ while((0 == res) && it1.hasNext) {
+ while((0 == res) && it2.hasNext) {
+ if (!it1.hasNext)
+ res = -1
+ else {
+ val i1 = it1.next;
+ val i2 = it2.next;
+ if (i1 < i2)
+ res = -1
+ else if (i1 > i2)
+ res = 1
+ }
+ }
+ if (it1.hasNext)
+ res = 1
+ }
+ if (it2.hasNext)
+ res = -1;
+ res
+ }
+
+ //case _ => -(other.compare(this))
+ }
+
+ /** the set {0} */
+ final val _initialBitSet = {
+ val rbs = new mutable.BitSet(1);
+ rbs += 0;
+ rbs.toImmutable;
+ }
+
+ /** the set {} */
+ final val _sinkBitSet = new mutable.BitSet(1).toImmutable;
+
+ final val _emptyBitSet = new scala.collection.mutable.BitSet(1).toImmutable;
+
+ def selectTag(Q:BitSet, finals:Array[Int]) = {
+ val it = Q.elements;
+ var mintag = compat.Math.MAX_INT;
+ while(it.hasNext) {
+ val tag = finals(it.next);
+ if((0 < tag) && (tag < mintag))
+ mintag = tag
+ }
+ mintag
+ }
+
+ def determinize: DetWordAutom[ T ] = {
+
+ // for assigning numbers to bitsets
+ var indexMap = new TreeMap[ BitSet, Int ];
+ var invIndexMap = new TreeMap[ Int, BitSet ];
+ var ix = 0;
+
+ // we compute the dfa with states = bitsets
+ var states = new TreeSet[BitSet]();
+ val delta = new mutable.HashMap[BitSet,
+ mutable.HashMap[T, BitSet]];
+ var deftrans = new TreeMap[BitSet, BitSet];
+ var finals = new TreeMap[BitSet, Int];
+
+ val q0 = _initialBitSet;
+ states = states + q0;
+
+ val sink = _emptyBitSet;
+ states = states + sink;
+
+ deftrans = deftrans.update(q0,sink);
+ deftrans = deftrans.update(sink,sink);
+
+ val rest = new mutable.Stack[BitSet]();
+
+ def add(Q: BitSet): Unit = {
+ if(!states.contains(Q)) {
+ states = states + Q;
+ rest.push(Q);
+ if(nfa.containsFinal(Q))
+ finals = finals.update(Q, selectTag(Q,nfa.finals));
+ }
+ }
+ rest.push( sink );
+ val sinkIndex = 1;
+ rest.push( q0 );
+ while(!rest.isEmpty) {
+ // assign a number to this bitset
+ val P = rest.pop;
+ indexMap = indexMap.update(P,ix);
+ invIndexMap = invIndexMap.update(ix,P);
+ ix = ix + 1;
+
+ // make transitiion map
+ val Pdelta = new mutable.HashMap[T, BitSet];
+ delta.update( P, Pdelta );
+
+ val it = labels.elements; while(it.hasNext) {
+ val label = it.next;
+
+ val Q = nfa.next(P,label);
+
+ Pdelta.update( label, Q );
+
+ add(Q);
+ }
+
+ // collect default transitions
+ val Pdef = nfa.nextDefault(P);
+ deftrans = deftrans.update(P,Pdef);
+ add(Pdef);
+ };
+
+ // create DetWordAutom, using indices instead of sets
+ val nstatesR = states.size;
+ val deltaR = new Array[Map[T,Int]](nstatesR);
+ val defaultR = new Array[Int](nstatesR);
+ val finalsR = new Array[Int](nstatesR);
+
+ for(val w <- states) {
+ val Q = w;
+ val q = indexMap(Q);
+ val trans = delta(Q);
+ val transDef = deftrans(Q);
+ val qDef = indexMap(transDef);
+ val ntrans = new mutable.HashMap[T,Int]();
+ val it = trans.keys; while(it.hasNext) {
+ val label = it.next;
+ val p = indexMap(trans(label));
+ if( p != qDef )
+ ntrans.update(label, p)
+ }
+ deltaR.update(q, ntrans);
+ defaultR.update(q, qDef);
+
+ //cleanup? leave to garbage collector?
+ //delta.remove(Q);
+ //default.remove(Q);
+
+ }
+
+ for(val fQ <- finals.keys) {
+ finalsR(indexMap(fQ)) = finals(fQ);
+ }
+
+ new DetWordAutom [ T ] {
+
+ //type _labelT = SubsetConstruction.this.nfa._labelT;
+ val nstates = nstatesR;
+ val delta = deltaR;
+ val default = defaultR;
+ val finals = finalsR;
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/util/automata/WordBerrySethi.scala b/src/dotnet-library/scala/util/automata/WordBerrySethi.scala
new file mode 100644
index 0000000000..90fad21452
--- /dev/null
+++ b/src/dotnet-library/scala/util/automata/WordBerrySethi.scala
@@ -0,0 +1,297 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.automata
+
+import scala.collection.{immutable, mutable, Map}
+import scala.util.regexp.WordExp
+
+
+/** This class turns a regexp into a NondetWordAutom using the
+ * celebrated position automata construction (also called Berry-Sethi or
+ * Glushkov)
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class WordBerrySethi extends BaseBerrySethi {
+
+ override val lang: WordExp
+
+ type _labelT = this.lang._labelT
+
+ import lang.{Alt, Eps, Letter, Meta, RegExp, Sequ, Star}
+
+
+ protected var labels:mutable.HashSet[_labelT] = _
+ // don't let this fool you, only labelAt is a real, surjective mapping
+ protected var labelAt: immutable.TreeMap[Int, _labelT] = _ // new alphabet "gamma"
+
+ protected var deltaq: Array[mutable.HashMap[_labelT,List[Int]]] = _ // delta
+
+ protected var defaultq: Array[List[Int]] = _ // default transitions
+
+ protected var initials:immutable.Set[Int] = _
+ //NondetWordAutom revNfa
+
+ // maps a letter to an Integer ( the position )
+ // is not *really* needed (preorder determines position!)
+ //protected var posMap: mutable.HashMap[RegExp, Int] = _;
+
+ /** Computes <code>first(r)</code> where the word regexp <code>r</code>.
+ *
+ * @param r the regular expression
+ * @return the computed set <code>first(r)</code>
+ */
+ protected override def compFirst(r: RegExp): immutable.Set[Int] = r match {
+ case x:Letter => emptySet + x.pos //posMap(x); // singleton set
+ case Eps => emptySet /*ignore*/
+ case _ => super.compFirst(r)
+ }
+
+ /** Computes <code>last(r)</code> where the word regexp <code>r</code>.
+ *
+ * @param r the regular expression
+ * @return the computed set <code>last(r)</code>
+ */
+ protected override def compLast(r: RegExp): immutable.Set[Int] = r match {
+ case x:Letter => emptySet + x.pos //posMap(x) // singleton set
+ case Eps => emptySet /*ignore*/
+ case _ => super.compLast(r)
+ }
+
+ /** Returns the first set of an expression, setting the follow set along
+ * the way.
+ *
+ * @param fol1 ...
+ * @param r the regular expression
+ * @return the computed set
+ */
+ protected override def compFollow1(fol1: immutable.Set[Int], r: RegExp): immutable.Set[Int] =
+ r match {
+ case x:Letter =>
+ //val i = posMap(x)
+ val i = x.pos
+ this.follow.update(i, fol1)
+ emptySet + i
+ case Eps =>
+ emptySet /*ignore*/
+ case _ =>
+ super.compFollow1(fol1, r)
+ }
+
+ /** returns "Sethi-length" of a pattern, creating the set of position
+ * along the way
+ */
+
+
+ /** called at the leaves of the regexp */
+ protected def seenLabel(r: RegExp, i: Int, label: _labelT): Unit = {
+ //Console.println("seenLabel (1)");
+ //this.posMap.update(r, i)
+ this.labelAt = this.labelAt.update(i, label)
+ //@ifdef if( label != Wildcard ) {
+ this.labels += label
+ //@ifdef }
+ }
+
+ // overriden in BindingBerrySethi
+ protected def seenLabel(r: RegExp, label: _labelT): Int = {
+ //Console.println("seenLabel (2)");
+ pos = pos + 1
+ seenLabel(r, pos, label)
+ pos
+ }
+
+ // todo: replace global variable pos with acc
+ override def traverse(r: RegExp): Unit = r match {
+ case a @ Letter(label) => a.pos = seenLabel(r, label)
+ case Eps => /*ignore*/
+ case _ => super.traverse(r)
+ }
+
+
+ protected def makeTransition(src: Int, dest: Int, label: _labelT ): Unit = {
+ //@ifdef compiler if( label == Wildcard )
+ //@ifdef compiler defaultq.update(src, dest::defaultq( src ))
+ //@ifdef compiler else
+ val q = deltaq( src );
+ q.update(label, dest::(q.get(label) match {
+ case Some(x) => x
+ case _ => Nil
+ }));
+ }
+
+ protected def initialize(subexpr: Seq[RegExp]): Unit = {
+ //this.posMap = new mutable.HashMap[RegExp,Int]()
+ this.labelAt = new immutable.TreeMap[Int, _labelT]()
+ this.follow = new mutable.HashMap[Int, immutable.Set[Int]]()
+ this.labels = new mutable.HashSet[_labelT]()
+
+ this.pos = 0
+
+ // determine "Sethi-length" of the regexp
+ //activeBinders = new Vector()
+ var it = subexpr.elements
+ while (it.hasNext)
+ traverse(it.next)
+
+ //assert(activeBinders.isEmpty())
+ this.initials = emptySet + 0
+ }
+
+ protected def initializeAutom(): Unit = {
+ finals = immutable.TreeMap.empty[Int, Int] // final states
+ deltaq = new Array[mutable.HashMap[_labelT, List[Int]]](pos) // delta
+ defaultq = new Array[List[Int]](pos) // default transitions
+
+ var j = 0
+ while (j < pos) {
+ deltaq(j) = new mutable.HashMap[_labelT,List[Int]]()
+ defaultq(j) = Nil
+ j = j + 1
+ }
+ }
+
+ protected def collectTransitions(): Unit = { // make transitions
+ //Console.println("WBS.collectTrans, this.follow.keys = "+this.follow.keys)
+ //Console.println("WBS.collectTrans, pos = "+this.follow.keys)
+ var j = 0; while (j < pos) {
+ //Console.println("WBS.collectTrans, j = "+j)
+ val fol = this.follow(j)
+ val it = fol.elements
+ while (it.hasNext) {
+ val k = it.next
+ if (pos == k)
+ finals = finals.update(j, finalTag)
+ else
+ makeTransition( j, k, labelAt(k))
+ }
+ j = j + 1
+ }
+ }
+
+ def automatonFrom(pat: RegExp, finalTag: Int): NondetWordAutom[_labelT] = {
+ this.finalTag = finalTag
+
+ pat match {
+ case x:Sequ =>
+ // (1,2) compute follow + first
+ initialize(x.rs)
+ pos = pos + 1
+ globalFirst = compFollow(x.rs)
+
+ //System.out.print("someFirst:");debugPrint(someFirst);
+ // (3) make automaton from follow sets
+ initializeAutom()
+ collectTransitions()
+
+ if (x.isNullable) // initial state is final
+ finals = finals.update(0, finalTag)
+
+ var delta1: immutable.TreeMap[Int, Map[_labelT, List[Int]]] =
+ new immutable.TreeMap[Int, Map[_labelT, List[Int]]]
+
+ var i = 0
+ while (i < deltaq.length) {
+ delta1 = delta1.update(i, deltaq(i))
+ i = i + 1
+ }
+ val finalsArr = new Array[Int](pos)
+ {
+ var k = 0; while (k < pos) {
+ finalsArr(k) = finals.get(k) match {
+ case Some(z) => z
+ case None => 0 // 0 == not final
+ };
+ k = k + 1
+ }
+ }
+
+ val initialsArr = new Array[Int](initials.size)
+ val it = initials.elements
+ {
+ var k = 0; while (k < initials.size) {
+ initialsArr(k) = it.next
+ k = k + 1
+ }
+ }
+
+ val deltaArr = new Array[Map[_labelT, immutable.BitSet]](pos)
+ {
+ var k = 0; while(k < pos) {
+ val labels = delta1(k).keys
+ val hmap =
+ new mutable.HashMap[_labelT, immutable.BitSet]
+ for (val lab <- labels) {
+ val trans = delta1(k)
+ val x = new mutable.BitSet(pos)
+ for (val q <- trans(lab))
+ x += q
+ hmap.update(lab, x.toImmutable)
+ }
+ deltaArr(k) = hmap
+ k = k + 1
+ }
+ }
+ val defaultArr = new Array[immutable.BitSet](pos)
+ {
+ var k = 0; while(k < pos) {
+ val x = new mutable.BitSet(pos)
+ for (val q <- defaultq(k))
+ x += q
+ defaultArr(k) = x.toImmutable
+ k = k + 1
+ }
+ }
+
+ new NondetWordAutom[_labelT] {
+ type _labelT = WordBerrySethi.this._labelT
+ val nstates = pos
+ val labels = WordBerrySethi.this.labels.toList
+ val initials = initialsArr
+ val finals = finalsArr
+ val delta = deltaArr
+ val default = defaultArr
+ }
+ case z =>
+ val z1 = z.asInstanceOf[this.lang._regexpT]
+ automatonFrom(Sequ(z1), finalTag)
+ }
+ }
+
+ /*
+ void print1() {
+ System.out.println("after sethi-style processing");
+ System.out.println("#positions:" + pos);
+ System.out.println("posMap:");
+
+ for( Iterator it = this.posMap.keySet().iterator();
+ it.hasNext(); ) {
+ Tree t = (Tree) it.next();
+ switch(t) {
+ case Literal( _ ):
+ System.out.print( "(" + t.toString() + " -> ");
+ String s2 = ((Integer) posMap.get(t)).toString();
+ System.out.print( s2 +") ");
+ }
+ }
+ System.out.println("\nfollow: ");
+ for( int j = 1; j < pos; j++ ) {
+ TreeSet fol = (TreeSet) this.follow.get(new Integer(j));
+ System.out.print("("+j+" -> "+fol.toString()+") ");
+ //debugPrint( fol );
+ System.out.println();
+ }
+
+ }
+ */
+}
diff --git a/src/dotnet-library/scala/util/grammar/HedgeRHS.scala b/src/dotnet-library/scala/util/grammar/HedgeRHS.scala
new file mode 100644
index 0000000000..fa57919b73
--- /dev/null
+++ b/src/dotnet-library/scala/util/grammar/HedgeRHS.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.grammar
+
+abstract class HedgeRHS
+
+/** right hand side of a hedge production, deriving a single tree */
+case class ConsRHS(tnt: Int, hnt: Int) extends HedgeRHS
+
+/** right hand side of a hedge production, deriving any hedge */
+case object AnyHedgeRHS extends HedgeRHS
+
+/** right hand side of a hedge production, deriving the empty hedge */
+case object EmptyHedgeRHS extends HedgeRHS
diff --git a/src/dotnet-library/scala/util/grammar/TreeRHS.scala b/src/dotnet-library/scala/util/grammar/TreeRHS.scala
new file mode 100644
index 0000000000..9181112b4d
--- /dev/null
+++ b/src/dotnet-library/scala/util/grammar/TreeRHS.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.grammar
+
+/** right hand side of a tree production */
+abstract class TreeRHS
+
+/** right hand side of a tree production, labelled with a letter from an alphabet */
+case class LabelledRHS[A](label: A, hnt: Int) extends TreeRHS
+
+case object AnyTreeRHS extends TreeRHS
diff --git a/src/dotnet-library/scala/util/logging/ConsoleLogger.scala b/src/dotnet-library/scala/util/logging/ConsoleLogger.scala
new file mode 100644
index 0000000000..15f166d814
--- /dev/null
+++ b/src/dotnet-library/scala/util/logging/ConsoleLogger.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.logging
+
+/**
+ * The trait <code>ConsoleLogger</code> is mixed into a concrete class who
+ * has class <code>Logged</code> among its base classes.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+trait ConsoleLogger {
+
+ /** logs argument to Console using <code>Console.println</code>
+ *
+ * @param msg ...
+ */
+ def log(msg: String): Unit = Console.println(msg)
+}
diff --git a/src/dotnet-library/scala/util/logging/Logged.scala b/src/dotnet-library/scala/util/logging/Logged.scala
new file mode 100644
index 0000000000..5c8aa2808a
--- /dev/null
+++ b/src/dotnet-library/scala/util/logging/Logged.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.logging
+
+/** <p>
+ * Mixing in the class <code>Logged</code> indicates that a class provides
+ * support for logging. For instance, the developer of a library writes
+ * </p>
+ * <pre>
+ * <b>class</b> MyClass <b>with</b> Logged { /* do stuff, call log */ }
+ * </pre>
+ * <p>
+ * The user of the library instantiates:
+ * </p>
+ * <pre>
+ * <b>val</b> x = <b>new</b> MyClass() <b>with</b> ConsoleLogger
+ * </pre>
+ * <p>
+ * and the logging will be sent to the <a href="../../Console$object.html"
+ * target="contentFrame"><code>Console</code></a> object.
+ * </p>
+ */
+trait Logged {
+
+ /** This method should log the message given as argument somewhere
+ * as a side-effect.
+ *
+ * @param msg ...
+ */
+ def log(msg: String): Unit = {}
+}
diff --git a/src/dotnet-library/scala/util/parsing/CharInputStreamIterator.scala b/src/dotnet-library/scala/util/parsing/CharInputStreamIterator.scala
new file mode 100644
index 0000000000..d08fa20b6d
--- /dev/null
+++ b/src/dotnet-library/scala/util/parsing/CharInputStreamIterator.scala
@@ -0,0 +1,46 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.parsing
+
+
+import java.io.InputStream
+import java.io.{IOException, EOFException}
+
+/** This class ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+class CharInputStreamIterator(in: InputStream) extends Iterator[char] {
+
+ private var ch: int = _
+ private var chSet = false
+ private var error: IOException = null
+
+ private def lookahead: unit = try {
+ ch = in.read(); chSet = ch >= 0
+ } catch {
+ case ex: EOFException => ch = -1
+ case ex: IOException => ch = 1; error = ex
+ }
+
+ def hasNext: boolean = {
+ if (!chSet) lookahead
+ chSet
+ }
+
+ def next: char = {
+ if (!chSet) lookahead
+ chSet = false
+ ch.asInstanceOf[char]
+ }
+}
diff --git a/src/dotnet-library/scala/util/parsing/Parsers.scala b/src/dotnet-library/scala/util/parsing/Parsers.scala
new file mode 100644
index 0000000000..6bc3f4a3ba
--- /dev/null
+++ b/src/dotnet-library/scala/util/parsing/Parsers.scala
@@ -0,0 +1,85 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.parsing
+
+/** Documentation for this class is currently missing.
+ * However, the Scala By Examples document contains a
+ * chapter on combinator parsing that comes close.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class Parsers {
+
+ type inputType
+
+ abstract class 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 not[a](p: Parser[a]) = new Parser[unit] {
+ def apply(in: inputType): Result = p.apply(in) match {
+ case None => Some(Pair((), in))
+ case Some(_) => None
+ }
+ }
+
+ 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 repWith[a, b](p: Parser[a], sep: Parser[b]): Parser[List[a]] =
+ for (val x <- p; val xs <- rep(sep &&& p)) yield x :: xs
+
+ def opt[a](p: Parser[a]): Parser[List[a]] =
+ (for (val x <- p) yield List(x)) ||| succeed(List())
+}
diff --git a/src/dotnet-library/scala/util/parsing/SimpleTokenizer.scala b/src/dotnet-library/scala/util/parsing/SimpleTokenizer.scala
new file mode 100644
index 0000000000..b7bab36e81
--- /dev/null
+++ b/src/dotnet-library/scala/util/parsing/SimpleTokenizer.scala
@@ -0,0 +1,65 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.parsing
+
+import compat.StringBuilder
+
+/** This class ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+class SimpleTokenizer(in: Iterator[char], delimiters: String) extends Iterator[String] {
+
+ private def max(x: int, y: char): int = if (x > y) x else y
+
+ val tracing = false
+
+ private def delimArray: Array[boolean] = {
+ val ds = List.fromString(delimiters)
+ val da = new Array[boolean]((0 /: ds)(max) + 1)
+ for (val ch <- ds) { da(ch) = true }
+ da
+ }
+
+ private val isdelim = delimArray
+ private def isDelimiter(ch: int) = ch >= 0 && ch < isdelim.length && isdelim(ch)
+
+ private val EOI = -1
+
+ private def nextChar: int = if (in.hasNext) in.next else EOI
+
+ private var ch: int = nextChar
+
+ private val buf = new StringBuilder()
+
+ def hasNext: boolean = ch != EOI
+
+ def next: String = {
+ while (ch <= ' ' && ch != EOI) ch = nextChar
+ if (ch == EOI) ""
+ else {
+ buf.setLength(0)
+ if (isDelimiter(ch)) {
+ buf append ch.asInstanceOf[char]; ch = nextChar
+ } else {
+ while (ch > ' ' && ch != EOI && !isDelimiter(ch)) {
+ buf append ch.asInstanceOf[char]
+ ch = nextChar
+ }
+ }
+ if (tracing) Console.println("<" + buf.toString() + ">")
+ buf.toString()
+ }
+ }
+}
+
diff --git a/src/dotnet-library/scala/util/regexp/Base.scala b/src/dotnet-library/scala/util/regexp/Base.scala
new file mode 100644
index 0000000000..92195eff42
--- /dev/null
+++ b/src/dotnet-library/scala/util/regexp/Base.scala
@@ -0,0 +1,76 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.regexp
+
+/** Basic regular expressions.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class Base {
+
+ type _regexpT <: RegExp
+
+ abstract class RegExp {
+ val isNullable: Boolean
+ }
+
+ /** Alt( R,R,R* ) */
+ case class Alt(rs: _regexpT*) extends RegExp {
+
+ // check rs \in R,R,R*
+ // @todo: flattening
+ if ({ val it = rs.elements; !it.hasNext || {it.next; !it.hasNext }})
+ throw new SyntaxError("need at least 2 branches in Alt");
+
+ final val isNullable = {
+ val it = rs.elements
+ while (it.hasNext && it.next.isNullable) {}
+ !it.hasNext
+ }
+ }
+
+ case class Sequ(rs: _regexpT*) extends RegExp {
+ // @todo: flattening
+ // check rs \in R,R*
+ if ({ val it = rs.elements; !it.hasNext })
+ throw new SyntaxError("need at least 1 item in Sequ")
+
+ final val isNullable = {
+ val it = rs.elements
+ while (it.hasNext && it.next.isNullable) {}
+ !it.hasNext
+ }
+ }
+
+ case class Star(r: _regexpT) extends RegExp {
+ final val isNullable = true
+ }
+
+ case object Eps extends RegExp {
+ final val isNullable = true
+ override def toString() = "Eps"
+ }
+
+ /** this class can be used to add meta information to regexps */
+ class Meta(r1: _regexpT) extends RegExp {
+ final val isNullable = r1.isNullable
+ def r = r1
+ }
+
+ final def mkSequ(rs: _regexpT *): RegExp =
+ if (!rs.elements.hasNext)
+ Eps
+ else
+ Sequ(rs:_*)
+
+}
diff --git a/src/dotnet-library/scala/util/regexp/PointedHedgeExp.scala b/src/dotnet-library/scala/util/regexp/PointedHedgeExp.scala
new file mode 100644
index 0000000000..2d87639fdf
--- /dev/null
+++ b/src/dotnet-library/scala/util/regexp/PointedHedgeExp.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.regexp
+
+/** pointed regular hedge expressions, a useful subclass of
+ * regular hedge expressions.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class PointedHedgeExp extends Base {
+
+ type _regexpT <: RegExp
+ type _labelT
+
+ case class Node(label: _labelT, r: _regexpT) extends RegExp {
+ final val isNullable = false
+ }
+
+ case class TopIter(r1: _regexpT, r2: _regexpT) extends RegExp {
+ final val isNullable = r1.isNullable && r2.isNullable //?
+ }
+
+ case object Point extends RegExp {
+ final val isNullable = false
+ }
+
+}
diff --git a/src/dotnet-library/scala/util/regexp/SyntaxError.scala b/src/dotnet-library/scala/util/regexp/SyntaxError.scala
new file mode 100644
index 0000000000..b1282f7fb6
--- /dev/null
+++ b/src/dotnet-library/scala/util/regexp/SyntaxError.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.regexp
+
+/** This runtime exception is thrown if an attempt to instantiate a
+ * syntactically incorrect expression is detected.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+class SyntaxError(e: String) extends java.lang.RuntimeException(e)
diff --git a/src/dotnet-library/scala/util/regexp/WordExp.scala b/src/dotnet-library/scala/util/regexp/WordExp.scala
new file mode 100644
index 0000000000..e4cfbe0dfb
--- /dev/null
+++ b/src/dotnet-library/scala/util/regexp/WordExp.scala
@@ -0,0 +1,56 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.util.regexp
+
+/** This class provides regular word expressions. Users have to instantiate
+ * type member <code>_regexpT &lt;: RegExp</code> (from class <code>Base</code>)
+ * and a type member <code>_labelT &lt;: Label</code>.
+ * Here is a little example:
+ * <pre>
+ * <b>import</b> scala.util.regexp._
+ * <b>import</b> scala.util.automata._
+ * <b>object</b> MyLang <b>extends</b> WordExp {
+ * <b>type</b> _regexpT = RegExp
+ * <b>type</b> _labelT = MyChar
+ *
+ * <b>case class</b> MyChar(c:Char) <b>extends</b> Label
+ * }
+ * <b>import</b> MyLang._
+ * // (a* | b)*
+ * <b>val</b> rex = Star(Alt(Star(Letter(MyChar('a'))),Letter(MyChar('b'))))
+ * <b>object</b> MyBerriSethi <b>extends</b> WordBerrySethi {
+ * <b>override val</b> lang = MyLang
+ * }
+ * <b>val</b> nfa = MyBerriSethi.automatonFrom(Sequ(rex), 1)
+ * </pre>
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class WordExp extends Base {
+
+ abstract class Label
+
+ type _regexpT <: RegExp
+ type _labelT <: Label
+
+ case class Letter(a: _labelT) extends RegExp {
+ final val isNullable = false
+ var pos = -1
+ }
+
+ case class Wildcard() extends RegExp {
+ final val isNullable = false
+ var pos = -1
+ }
+}
+
diff --git a/src/dotnet-library/scala/volatile.scala b/src/dotnet-library/scala/volatile.scala
new file mode 100644
index 0000000000..3d40f25756
--- /dev/null
+++ b/src/dotnet-library/scala/volatile.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+
+class volatile extends Attribute
diff --git a/src/dotnet-library/scala/xml/Atom.scala b/src/dotnet-library/scala/xml/Atom.scala
new file mode 100644
index 0000000000..deea2c00e8
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Atom.scala
@@ -0,0 +1,55 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** The class <code>Atom</code> provides an XML node for text (PCDATA).
+ * It is used in both non-bound and bound XML representations.
+ *
+ * @author Burak Emir
+ * @param text the text contained in this node, may not be <code>null</code>.
+ */
+[serializable]
+class Atom[+A](val data: A) extends SpecialNode {
+
+ data.asInstanceOf[AnyRef] match {
+ case null => new IllegalArgumentException("cannot construct Atom(null)")
+ case _ =>
+ }
+ final override def typeTag$: Int = -1
+
+ /** the constant "#PCDATA"
+ */
+ def label = "#PCDATA"
+
+ override def equals(x: Any) = x match {
+ case s:Atom[_] => data == s.data
+ case _ => false
+ }
+
+ /** hashcode for this Text */
+ override def hashCode() =
+ data.hashCode()
+
+ /** Returns text, with some characters escaped according to the XML
+ * specification.
+ *
+ * @param sb ...
+ * @return ...
+ */
+ def toString(sb: StringBuilder) =
+ Utility.escape(data.toString(), sb)
+
+ override def text: String = data.toString()
+
+}
diff --git a/src/dotnet-library/scala/xml/Comment.scala b/src/dotnet-library/scala/xml/Comment.scala
new file mode 100644
index 0000000000..95926f1c39
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Comment.scala
@@ -0,0 +1,47 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+import compat.StringBuilder
+
+/** The class <code>Comment</code> implements an XML node for comments.
+ *
+ * @author Burak Emir
+ * @param text the text contained in this node, may not contain "--"
+ */
+case class Comment(commentText: String) extends SpecialNode {
+
+ final override def typeTag$: Int = -3
+
+ if (commentText.indexOf("--") != -1)
+ throw new IllegalArgumentException("text containts \"--\"")
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ case Comment(x) => x.equals(commentText)
+ case _ => false
+ }
+
+ /** the constant &quot;#REM&quot; */
+ def label = "#REM"
+
+ /** hashcode for this Comment */
+ override def hashCode() = commentText.hashCode()
+
+ override def text = ""
+
+ /** Appends &quot;<!-- text -->&quot; to this string buffer.
+ */
+ override def toString(sb: StringBuilder) =
+ sb.append("<!--").append(commentText).append("-->")
+}
diff --git a/src/dotnet-library/scala/xml/Document.scala b/src/dotnet-library/scala/xml/Document.scala
new file mode 100644
index 0000000000..40b97ae20f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Document.scala
@@ -0,0 +1,89 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+/** A document information item (according to InfoSet spec). The comments
+ * are copied from the Infoset spec, only augmented with some information
+ * on the Scala types for definitions that might have no value.
+ * also plays the role of an <code>XMLEvent</code> for pull parsing
+ *
+ * @author Burak Emir
+ * @version 1.0, 26/04/2005
+ */
+class Document extends NodeSeq with pull.XMLEvent {
+
+ /** An ordered list of child information items, in document
+ * order. The list contains exactly one element information item. The
+ * list also contains one processing instruction information item for
+ * each processing instruction outside the document element, and one
+ * comment information item for each comment outside the document
+ * element. Processing instructions and comments within the DTD are
+ * excluded. If there is a document type declaration, the list also
+ * contains a document type declaration information item.
+ */
+ var children: Seq[Node] = _
+
+ /** The element information item corresponding to the document element. */
+ var docElem: Node = _
+
+ /** The dtd that comes with the document, if any */
+ var dtd: scala.xml.dtd.DTD = _
+
+ /** An unordered set of notation information items, one for each notation
+ * declared in the DTD. If any notation is multiply declared, this property
+ * has no value.
+ */
+ def notations: Seq[scala.xml.dtd.NotationDecl] =
+ dtd.notations
+
+ /** An unordered set of unparsed entity information items, one for each
+ * unparsed entity declared in the DTD.
+ */
+ def unparsedEntities: Seq[scala.xml.dtd.EntityDecl] =
+ dtd.unparsedEntities
+
+ /** The base URI of the document entity. */
+ var baseURI: String = _
+
+ /** The name of the character encoding scheme in which the document entity
+ * is expressed.
+ */
+ var encoding: Option[String] = _
+
+ /** An indication of the standalone status of the document, either
+ * true or false. This property is derived from the optional standalone
+ * document declaration in the XML declaration at the beginning of the
+ * document entity, and has no value (<code>None</code>) if there is no
+ * standalone document declaration.
+ */
+ var standAlone: Option[Boolean] = _
+
+ /** A string representing the XML version of the document. This
+ * property is derived from the XML declaration optionally present at
+ * the beginning of the document entity, and has no value (<code>None</code>)
+ * if there is no XML declaration.
+ */
+ var version: Option[String] = _
+
+ /** 9. This property is not strictly speaking part of the infoset of
+ * the document. Rather it is an indication of whether the processor
+ * has read the complete DTD. Its value is a boolean. If it is false,
+ * then certain properties (indicated in their descriptions below) may
+ * be unknown. If it is true, those properties are never unknown.
+ */
+ var allDeclarationsProcessed = false
+
+ // methods for NodeSeq
+
+ def theSeq: Seq[Node] = this.docElem
+
+}
diff --git a/src/dotnet-library/scala/xml/Elem.scala b/src/dotnet-library/scala/xml/Elem.scala
new file mode 100644
index 0000000000..c5794dbcd0
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Elem.scala
@@ -0,0 +1,70 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+/** The case class <code>Elem</code> extends the <code>Node</code> class,
+ * providing an immutable data object representing an XML element.
+ *
+ * @author Burak Emir
+ *
+ * @param prefix (may be null)
+ * @param label the element name
+ * @param attribute the attribute map
+ * @param child the children of this node
+ */
+// "val" is redundant for non-overriding arguments
+case class Elem(override val prefix: String,
+ val label: String,
+ override val attributes: MetaData,
+ override val scope: NamespaceBinding,
+ val child: Node*) extends Node {
+
+ if ((null != prefix) && 0 == prefix.length())
+ throw new IllegalArgumentException("prefix of zero length, use null instead")
+
+ if (null == scope)
+ throw new IllegalArgumentException("scope is null, try xml.TopScope for empty scope")
+
+ //@todo: copy the children,
+ // setting namespace scope if necessary
+ // cleaning adjacent text nodes if necessary
+
+ final override def typeTag$: Int = 0
+
+ override def hashCode(): Int =
+ Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child)
+
+ /** Returns a new element with updated attributes.
+ *
+ * @param attrs ...
+ * @return a new symbol with updated attributes
+ */
+ final def %(attrs: MetaData): Elem =
+ Elem(prefix,
+ label,
+ attrs.append(attributes),
+ scope,
+ child:_*)
+
+ /** Returns concatenation of <code>text(n)</code> for each child
+ * <code>n</code>.
+ */
+ override def text = {
+ val sb = new compat.StringBuilder()
+ val it = child.elements
+ while (it.hasNext)
+ sb.append(it.next.text)
+ sb.toString()
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/EntityRef.scala b/src/dotnet-library/scala/xml/EntityRef.scala
new file mode 100644
index 0000000000..8426e15031
--- /dev/null
+++ b/src/dotnet-library/scala/xml/EntityRef.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** The class <code>EntityRef</code> implements an XML node for entity
+ * references.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ * @param text the text contained in this node.
+ */
+case class EntityRef(entityName: String) extends SpecialNode {
+
+ final override def typeTag$: Int = -5
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ case EntityRef(x) => x.equals(entityName)
+ case _ => false
+ }
+
+ /** the constant "#ENTITY"
+ */
+ def label = "#ENTITY"
+
+ override def hashCode() = entityName.hashCode()
+
+ /** ...
+ */
+ override def text = entityName match {
+ case "lt" => "<"
+ case "gt" => ">"
+ case "amp" => "&"
+ case "apos" => "'"
+ case "quot" => "\""
+ case _ => val sb = new StringBuilder(); toString(sb).toString()
+ }
+
+ /** Appends "&amp; entityName;" to this string buffer.
+ *
+ * @param sb the string buffer.
+ * @return the modified string buffer <code>sb</code>.
+ */
+ override def toString(sb: StringBuilder) =
+ sb.append("&").append(entityName).append(";")
+
+}
diff --git a/src/dotnet-library/scala/xml/Group.scala b/src/dotnet-library/scala/xml/Group.scala
new file mode 100644
index 0000000000..e7c8313db5
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Group.scala
@@ -0,0 +1,74 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+import compat.StringBuilder
+
+/** A hack to group XML nodes in one node for output.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+[serializable]
+case class Group(val nodes: Seq[Node]) extends Node {
+
+ override def theSeq = nodes
+
+ /** structural equality */
+ override def equals(x: Any) = x match {
+ case z:Group => (length == z.length) && sameElements(z)
+ case z:Node => (length == 1) && z == apply(0)
+ case z:Seq[_] => sameElements(z)
+ case z:String => text == z
+ case _ => false
+ }
+
+ /**
+ * @throws Predef.UnsupportedOperationException (always)
+ */
+ final def label =
+ throw new UnsupportedOperationException("class Group does not support method 'label'")
+
+ /**
+ * @throws Predef.UnsupportedOperationException (always)
+ */
+ final override def attributes =
+ throw new UnsupportedOperationException("class Group does not support method 'attributes'")
+
+ /**
+ * @throws Predef.UnsupportedOperationException (always)
+ */
+ final override def namespace =
+ throw new UnsupportedOperationException("class Group does not support method 'namespace'")
+
+ /**
+ * @throws Predef.UnsupportedOperationException (always)
+ */
+ final override def child =
+ throw new UnsupportedOperationException("class Group does not support method 'child'")
+
+ /**
+ * @throws Predef.UnsupportedOperationException (always)
+ */
+ def toString(sb: StringBuilder) =
+ throw new UnsupportedOperationException(
+ "class Group does not support method toString(StringBuilder)")
+
+ override def text = { // same impl as NodeSeq
+ val sb = new StringBuilder()
+ val it = elements
+ while (it.hasNext)
+ sb.append(it.next.text)
+ sb.toString()
+ }
+}
diff --git a/src/dotnet-library/scala/xml/MalformedAttributeException.scala b/src/dotnet-library/scala/xml/MalformedAttributeException.scala
new file mode 100644
index 0000000000..0437006583
--- /dev/null
+++ b/src/dotnet-library/scala/xml/MalformedAttributeException.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+case class MalformedAttributeException(msg: String) extends java.lang.RuntimeException(msg)
diff --git a/src/dotnet-library/scala/xml/MetaData.scala b/src/dotnet-library/scala/xml/MetaData.scala
new file mode 100644
index 0000000000..0eb572a801
--- /dev/null
+++ b/src/dotnet-library/scala/xml/MetaData.scala
@@ -0,0 +1,215 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** <p>
+ * Attribute information item, and linked list of attribute information items.
+ * These are triples consisting of <code>prefix,key,value</code>. To obtain
+ * the namespace, <code>getNamespace</code> must be called with the parent.
+ * If next is null, this is the last attribute in the MetaData list.
+ * </p>
+ * <p>
+ * Either an UnprefixedAttribute or a PrefixedAttribute
+ * </p>
+ *
+ * @todo _vlue should be a normalized attribute value
+ */
+[serializable]
+abstract class MetaData extends Iterable[MetaData] {
+
+ /** appends given MetaData items to this MetaData list.
+ *
+ * @param m ...
+ * @return ...
+ */
+ def append(m: MetaData): MetaData =
+ next.append(copy(m))
+
+ /**
+ * Gets value of unqualified (unprefixed) attribute with given key, null if not found
+ *
+ * @param key
+ * @return value as Seq[Node] if key is found, null otherwise
+ */
+ def apply(key: String): Seq[Node]
+
+ /** convenience method, same as <code>apply(namespace, owner.scope, key)</code>.
+ *
+ * @param namespace ...
+ * @param owner ...
+ * @param key ...
+ * @return ...
+ */
+ final def apply(namespace: String, owner: Node, key: String): Seq[Node] =
+ apply(namespace, owner.scope, key)
+
+ /**
+ * Gets value of prefixed attribute with given key and namespace, null if not found
+ *
+ * @param uri namespace of key
+ * @param scp a namespace scp (usually of the element owning this attribute list)
+ * @param key to be looked fore
+ * @return value as Seq[Node] if key is found, null otherwise
+ */
+ def apply(uri:String, scp:NamespaceBinding, k:String): Seq[Node]
+
+ /**
+ * @param m ...
+ * @return <code>true</code> iff ...
+ */
+ def containedIn1(m: MetaData): Boolean =
+ m.equals1(this) || containedIn1(m.next)
+
+ /** returns a copy of this MetaData item with next field set to argument.
+ *
+ * @param next ...
+ * @return ...
+ */
+ def copy(next: MetaData): MetaData
+
+ /** if owner is the element of this metadata item, returns namespace */
+ def getNamespace(owner: Node): String
+
+ def hasNext = (Null != next)
+
+ def length: Int = length(0)
+
+ def length(i: Int): Int = next.length(i + 1)
+
+ def isPrefixed: Boolean
+
+ /** deep equals method */
+ override def equals(that: Any) =
+ that match {
+ case m: MetaData =>
+ var res = (this.length == m.length) && (this.hashCode() == m.hashCode())
+ val it = this.elements
+ while (res && it.hasNext) { res = it.next.containedIn1(m) }
+ res
+ case _ =>
+ false
+ }
+
+ /** returns an iterator on attributes */
+ def elements: Iterator[MetaData] = new Iterator[MetaData] {
+ var x: MetaData = MetaData.this
+ def hasNext = Null != x
+ def next = {
+ val y = x
+ x = x.next
+ y
+ }
+ }
+
+ /** shallow equals method */
+ def equals1(that: MetaData): Boolean
+
+ /** filters this sequence of meta data */
+ override def filter(f: MetaData => Boolean): MetaData = {
+ if (f(this)) copy(next filter f) else next filter f
+ }
+
+ /** returns key of this MetaData item */
+ def key: String
+
+ /** returns value of this MetaData item */
+ def value: Seq[Node]
+
+ /** maps this sequence of meta data */
+ def map(f: MetaData => Text): List[Text] = f(this)::(next map f)
+
+ /** returns Null or the next MetaData item */
+ def next: MetaData
+
+ /**
+ * Gets value of unqualified (unprefixed) attribute with given key, None if not found
+ *
+ * @param key
+ * @return value in Some(Seq[Node]) if key is found, None otherwise
+ */
+ final def get(key: String): Option[Seq[Node]] = apply(key) match {
+ case null => None
+ case x => Some(x)
+ }
+
+ /** same as get(uri, owner.scope, key) */
+ final def get(uri: String, owner: Node, key: String): Option[Seq[Node]] =
+ get(uri, owner.scope, key)
+
+
+ /** gets value of qualified (prefixed) attribute with given key.
+ * @param uri namespace of key
+ * @param scope a namespace scp (usually of the element owning this attribute list)
+ * @param key to be looked fore
+ * @return value as Some[Seq[Node]] if key is found, None otherwise
+ */
+ final def get(uri: String, scope: NamespaceBinding, key: String): Option[Seq[Node]] =
+ apply(uri, scope, key) match {
+ case null => None
+ case x => Some(x)
+ }
+
+ override def hashCode(): Int
+
+ def toString1(): String = {
+ val sb = new StringBuilder()
+ toString1(sb)
+ sb.toString()
+ }
+
+ //appends string representations of single attribute to StringBuilder
+ def toString1(sb:StringBuilder): Unit
+
+ override def toString(): String = {
+ val sb = new StringBuilder()
+ toString(sb)
+ sb.toString()
+ }
+
+ def toString(sb: StringBuilder): StringBuilder = {
+ sb.append(' ')
+ toString1(sb)
+ next.toString(sb)
+ }
+
+ /**
+ * @param scope ...
+ * @return <code>true</code> iff ...
+ */
+ def wellformed(scope: NamespaceBinding): Boolean
+
+ /**
+ * @param key ...
+ * @return ...
+ */
+ def remove(key:String): MetaData
+
+ /**
+ * @param namespace ...
+ * @param scope ...
+ * @param key ...
+ * @return ...
+ */
+ def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData
+
+ /**
+ * @param namespace ...
+ * @param owner ...
+ * @param key ...
+ * @return ...
+ */
+ final def remove(namespace: String, owner: Node, key: String): MetaData =
+ remove(namespace, owner.scope, key)
+
+}
diff --git a/src/dotnet-library/scala/xml/NamespaceBinding.scala b/src/dotnet-library/scala/xml/NamespaceBinding.scala
new file mode 100644
index 0000000000..c1acb444e5
--- /dev/null
+++ b/src/dotnet-library/scala/xml/NamespaceBinding.scala
@@ -0,0 +1,73 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+import Predef.IllegalArgumentException
+import compat.StringBuilder
+
+/** The class <code>NamespaceBinding</code> represents namespace bindings
+ * and scopes. The binding for the default namespace is treated as a null
+ * prefix. the absent namespace is represented with the null uri. Neither
+ * prefix nor uri may be empty, which is not checked.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+[serializable]
+class NamespaceBinding(val prefix: String,
+ val uri: String,
+ val parent: NamespaceBinding) extends AnyRef {
+
+ private val serialVersionUID = 0 - 2518644165573446725L
+
+ if (null != prefix && 0 == prefix.length())
+ throw new IllegalArgumentException("zero length prefix not allowed")
+
+ def getURI(_prefix: String): String =
+ if (prefix == _prefix) uri else parent.getURI(_prefix)
+
+ /** Returns some prefix that is mapped to the prefix.
+ *
+ * @param _uri
+ * @return
+ */
+ def getPrefix(_uri: String): String =
+ if (_uri == uri) uri else parent.getURI(_uri)
+
+ override def toString(): String = {
+ val sb = new StringBuilder()
+ toString(sb, TopScope)
+ sb.toString()
+ }
+
+ def toString(stop: NamespaceBinding): String = {
+ val sb = new StringBuilder()
+ toString(sb, stop)
+ sb.toString()
+ }
+
+ def toString(sb: StringBuilder, stop: NamespaceBinding): Unit = {
+ if (this ne stop) { // contains?
+ sb.append(" xmlns")
+ if (prefix ne null) {
+ sb.append(':').append(prefix)
+ }
+ sb.append('=')
+ .append('"')
+ .append(uri)
+ .append('"');
+ parent.toString(sb, stop) // copy(ignore)
+ }
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/Node.scala b/src/dotnet-library/scala/xml/Node.scala
new file mode 100644
index 0000000000..fcffd0ce07
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Node.scala
@@ -0,0 +1,193 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/**
+ * This object provides methods ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+object Node {
+
+ /** the constant empty attribute sequence */
+ final def NoAttributes: MetaData = Null
+
+ /** the empty namespace */
+ val EmptyNamespace = ""
+
+}
+
+/**
+ * An abstract class representing XML with nodes of a labelled tree.
+ * This class contains an implementation of a subset of XPath for navigation.
+ *
+ * @author Burak Emir and others
+ * @version 1.1
+ */
+abstract class Node extends NodeSeq {
+
+ /** prefix of this node */
+ def prefix: String = null
+
+ /** label of this node. I.e. "foo" for &lt;foo/&gt;) */
+ def label: String
+
+ /** used internally. Atom/Molecule = -1 PI = -2 Comment = -3 EntityRef = -5
+ */
+ def typeTag$: Int = 0
+
+ /**
+ * method returning the namespace bindings of this node. by default, this is TopScope,
+ * which means there are no namespace bindings except the predefined one for "xml".
+ */
+ def scope: NamespaceBinding = TopScope
+
+ /**
+ * convenience, same as <code>getNamespace(this.prefix)</code>
+ */
+ def namespace = getNamespace(this.prefix)
+
+ /**
+ * Convenience method, same as <code>scope.getURI(pre)</code> but additionally
+ * checks if scope is <code>null</code>.
+ *
+ * @param pre the prefix whose namespace name we would like to obtain
+ * @return the namespace if <code>scope != null</code> and prefix was
+ * found, else <code>null</code>
+ */
+ def getNamespace(pre: String): String = if (scope eq null) null else scope.getURI(pre)
+
+ /**
+ * Convenience method, looks up an unprefixed attribute in attributes of this node.
+ * Same as <code>attributes.getValue(key)</code>
+ *
+ * @param key of queried attribute.
+ * @return value of <code>UnprefixedAttribute</code> with given key
+ * in attributes, if it exists, otherwise <code>null</code>.
+ */
+ final def attribute(key: String): Option[Seq[Node]] = attributes.get(key)
+
+ /**
+ * Convenience method, looks up a prefixed attribute in attributes of this node.
+ * Same as <code>attributes.getValue(uri, this, key)</code>
+ *
+ * @param uri namespace of queried attribute (may not be null).
+ * @param key of queried attribute.
+ * @return value of <code>PrefixedAttribute</code> with given namespace
+ * and given key, otherwise <code>null</code>.
+ */
+ final def attribute(uri: String, key: String): Option[Seq[Node]] = attributes.get(uri, this, key)
+
+ /**
+ * Returns attribute meaning all attributes of this node, prefixed and unprefixed,
+ * in no particular order. In class Node, this defaults to Null (the empty attribute list).
+ *
+ * @return all attributes of this node
+ */
+ def attributes: MetaData = Null
+
+ /**
+ * Returns child axis i.e. all children of this node.
+ *
+ * @return all children of this node
+ */
+ def child: Seq[Node]
+
+ /**
+ * Descendant axis (all descendants of this node, not including node itself)
+ * includes all text nodes, element nodes, comments and processing instructions.
+ */
+ def descendant: List[Node] =
+ child.toList.flatMap { x => x::x.descendant }
+
+ /**
+ * Descendant axis (all descendants of this node, including thisa node)
+ * includes all text nodes, element nodes, comments and processing instructions.
+ */
+ def descendant_or_self: List[Node] = this :: descendant
+
+ /**
+ * Returns true if x is structurally equal to this node. Compares prefix,
+ * label, attributes and children.
+ *
+ * @param x ...
+ * @return <code>true</code> if ..
+ */
+ override def equals(x: Any): Boolean = x match {
+ case g:Group => false
+ case that: Node =>
+ ((that.prefix == this.prefix )
+ &&(that.label == this.label )
+ &&(that.attributes == this.attributes)
+ && that.child.sameElements(this.child)) // sameElements
+ case _ => false
+ }
+
+ /**
+ * Returns a hashcode. A standard implementation of hashcodes is obtained by calling
+ * Utility.hashCode(pre, label, attributes.hashCode(), child);
+ */
+ override def hashCode(): Int
+
+ // implementations of NodeSeq methods
+
+ /**
+ * returns a sequence consisting of only this node
+ */
+ def theSeq: Seq[Node] = this :: Nil
+
+ /**
+ * String representation of this node
+ *
+ * @param stripComment if true, strips comment nodes from result
+ * @return ...
+ */
+ def toString(stripComment: Boolean): String =
+ Utility.toXML(this, stripComment)
+
+ /**
+ * Same as <code>toString(false)</code>.
+ *
+ * @see <code><a href="#toString">toString(Boolean)</a></code>
+ */
+ override def toString(): String = toString(false)
+
+ /**
+ * Appends qualified name of this node to <code>StringBuilder</code>.
+ *
+ * @param sb ...
+ * @return ...
+ */
+ def nameToString(sb: StringBuilder): StringBuilder = {
+ if (null != prefix) {
+ sb.append(prefix)
+ sb.append(':')
+ }
+ sb.append(label);
+ }
+
+ /**
+ * Returns a type symbol (e.g. DTD, XSD), default <code>null</code>.
+ */
+ def xmlType(): TypeSymbol = null
+
+ /**
+ * Returns a text representation of this node. Note that this is not equivalent to
+ * the XPath node-test called text(), it is rather an implementation of the
+ * XPath function string()
+ */
+ override def text: String
+
+}
diff --git a/src/dotnet-library/scala/xml/NodeBuffer.scala b/src/dotnet-library/scala/xml/NodeBuffer.scala
new file mode 100644
index 0000000000..4bc4b61ab1
--- /dev/null
+++ b/src/dotnet-library/scala/xml/NodeBuffer.scala
@@ -0,0 +1,64 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+/**
+ * This class acts as a Buffer for nodes. If it is used as a sequence
+ * of nodes <code>Seq[Node]</code>, it must be ensured that no updates
+ * occur after that point, because <code>scala.xml.Node</code> is assumed
+ * to be immutable.
+ *
+ * Despite this being a sequence, don't use it as key in a hashtable.
+ * Calling the hashcode function will result in a runtime error.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+class NodeBuffer extends scala.collection.mutable.ArrayBuffer[Node] {
+
+ /**
+ * Append given object to this buffer, returns reference on this NodeBuffer
+ * for convenience. Some rules apply: If o is null, it is ignored. If it is
+ * an Iterator or Iterable, its elements will be added. If o is a node, it is
+ * added as it is. If it is anything else, it gets wrapped in an Atom.
+ *
+ *
+ * @param o converts to an xml node and adds to this node buffer
+ * @return this nodebuffer
+ */
+ def &+(o: Any): NodeBuffer = {
+ o match {
+ case null => // ignore null
+
+ case _:Unit =>
+ // ignore
+ case it:Iterator[_] =>
+ while(it.hasNext) {
+ this &+ it.next
+ }
+ case n:Node =>
+ super.+(n)
+ case ns:Iterable[_] =>
+ val it = ns.elements
+ while (it.hasNext) {
+ this &+ it.next
+ //if (it.hasNext)
+ // this &+ " ";
+ }
+ //case s:String => super.+(Text(o.toString()));
+ case d =>
+ super.+(new Atom(d))
+ }
+ this
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/NodeSeq.scala b/src/dotnet-library/scala/xml/NodeSeq.scala
new file mode 100644
index 0000000000..3bed37b5c4
--- /dev/null
+++ b/src/dotnet-library/scala/xml/NodeSeq.scala
@@ -0,0 +1,178 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+/** This object ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+object NodeSeq {
+ final val Empty = new NodeSeq { def theSeq = Nil }
+ def fromSeq(s: Seq[Node]): NodeSeq = new NodeSeq {
+ def theSeq = s
+ }
+ implicit def view(s: Seq[Node]): NodeSeq = fromSeq(s)
+}
+
+/** This class implements a wrapper around <code>Seq[Node]</code> that
+ * adds XPath and comprehension methods.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class NodeSeq extends Seq[Node] {
+ import NodeSeq.view // import view magic for NodeSeq wrappers
+ def theSeq: Seq[Node]
+ def length = theSeq.length
+ def elements = theSeq.elements
+ def apply(i: Int): Node = theSeq.apply(i)
+
+ def apply(f: Node => Boolean): NodeSeq = filter(f)
+
+ /** structural equality */
+ override def equals(x: Any) = x match {
+ case z:Node => (length == 1) && z == apply(0)
+ case z:Seq[_] => sameElements(z)
+ case z:String => text == z
+ case _ => false;
+ }
+
+ /** Projection function. Similar to XPath, use <code>this \ "foo"</code>
+ * to get a list of all elements of this sequence that are labelled with
+ * <code>"foo"</code>. Use <code>\ "_"</code> as a wildcard.
+ * The document order is preserved.
+ *
+ * @param that ...
+ * @return ...
+ */
+ def \(that: String): NodeSeq = that match {
+ case "_" =>
+ var zs: List[Node] = Nil
+ val it = this.elements
+ while (it.hasNext) {
+ val x = it.next
+ val jt = x.child.elements
+ while (jt.hasNext) {
+ val y = jt.next
+ if (y.typeTag$ != -1)
+ zs = y::zs
+ }
+ }
+ NodeSeq.fromSeq(zs.reverse)
+
+ case _ if (that.charAt(0) == '@') && (this.length == 1) =>
+ val k = that.substring(1)
+ val y = this(0)
+ y.attribute(k) match {
+ case Some(x) => Group(x)
+ case _ => NodeSeq.Empty
+ }
+
+ case _ =>
+ var zs: List[Node] = Nil
+ val it = this.elements
+ while (it.hasNext) {
+ val x = it.next
+ val jt = x.child.elements
+ while (jt.hasNext) {
+ val y = jt.next
+ if (y.label == that)
+ zs = y::zs
+ }
+ }
+ NodeSeq.fromSeq(zs.reverse)
+ }
+
+ /** projection function. Similar to XPath, use <code>this \\ 'foo</code>
+ * to get a list of all elements of this sequence that are labelled with
+ * <code>"foo"</code>. Use <code>\\ "_"</code> as a wildcard.
+ * The document order is preserved.
+ *
+ * @param that ...
+ * @return ...
+ */
+ def \\ (that: String): NodeSeq = that match {
+ case "_" =>
+ var zs: List[Node] = Nil
+ val it = this.elements
+ while (it.hasNext) {
+ val x = it.next
+ val jt = x.descendant_or_self.elements
+ while (jt.hasNext) {
+ val y = jt.next
+ if (y.typeTag$ != -1)
+ zs = y::zs
+ }
+ }
+ zs.reverse
+
+ case _ if that.charAt(0) == '@' =>
+ var zs: List[Node] = Nil
+ val it = this.elements
+ while (it.hasNext) {
+ val x = it.next
+ val jt = x.descendant_or_self.elements
+ while (jt.hasNext) {
+ val y = jt.next
+ if (y.typeTag$ != -1) {
+ val kt = (y \ that).elements
+ while (kt.hasNext) {
+ zs = (kt.next)::zs
+ }
+ }
+ }
+ }
+ zs.reverse
+
+ case _ =>
+ var zs: List[Node] = Nil
+ val it = this.elements
+ while (it.hasNext) {
+ val x = it.next
+ val jt = x.descendant_or_self.elements
+ while (jt.hasNext) {
+ val y = jt.next
+ if (y.typeTag$ != -1 && y.label == that)
+ zs = y::zs
+ }
+ }
+ zs.reverse
+ }
+
+ override def toString(): String = theSeq.elements.foldLeft ("") {
+ (s: String, x: Node) => s + x.toString()
+ }
+/*
+ def map(f: Node => NodeSeq): NodeSeq = flatMap(f)
+
+ def flatMap(f: Node => NodeSeq): NodeSeq = {
+ val y = toList flatMap { x => f(x).toList }
+ y
+ }
+
+ override def filter(f: Node => Boolean): NodeSeq = {
+ val x = toList filter f
+ x
+ }
+*/
+
+ def text: String = {
+ val sb = new compat.StringBuilder()
+ val it = elements
+ while (it.hasNext) {
+ sb.append(it.next.text)
+ }
+ sb.toString()
+ }
+}
diff --git a/src/dotnet-library/scala/xml/NodeTraverser.scala b/src/dotnet-library/scala/xml/NodeTraverser.scala
new file mode 100644
index 0000000000..f6fac46bb4
--- /dev/null
+++ b/src/dotnet-library/scala/xml/NodeTraverser.scala
@@ -0,0 +1,34 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+/** This class ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class NodeTraverser extends parsing.MarkupHandler {
+
+ def traverse(n: Node): Unit = n match {
+ case x:ProcInstr => procInstr(0, x.target, x.text)
+ case x:Comment => comment(0, x.text)
+ case x:Text => text(0, x.data)
+ case x:EntityRef => entityRef(0, x.entityName)
+ case _ =>
+ elemStart(0, n.prefix, n.label, n.attributes, n.scope)
+ for (val m <- n.child)
+ traverse(m)
+ elem(0, n.prefix, n.label, n.attributes, n.scope, NodeSeq.fromSeq(n.child))
+ elemEnd(0, n.prefix, n.label)
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/Null.scala b/src/dotnet-library/scala/xml/Null.scala
new file mode 100644
index 0000000000..ef15e0973f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Null.scala
@@ -0,0 +1,84 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import Predef.IllegalArgumentException
+import compat.StringBuilder
+
+case object Null extends MetaData {
+
+ /** appends given MetaData items to this MetaData list */
+ override def append(m: MetaData): MetaData = m
+
+ override def containedIn1(m: MetaData): Boolean = false
+
+ /** returns its argument */
+ def copy(next: MetaData) = next
+
+ override def elements = Iterator.empty
+
+ override def filter(f: MetaData => Boolean): MetaData = this
+
+ /** returns null */
+ def getNamespace(owner: Node) = null
+
+ final override def hasNext = false
+
+ final override def length = 0
+
+ final override def length(i: Int) = i
+
+ def isPrefixed = false
+
+ /** deep equals method */
+ override def equals(that: Any) = that match {
+ case m: MetaData => m.length == 0
+ case _ => false
+ }
+
+ def equals1(that:MetaData) = that.length == 0
+
+ def key = null
+
+ def value = null
+
+ override def map(f: MetaData => Text): List[Text] = Nil
+
+ def next = null
+
+ /** null */
+ def apply(key: String) = {
+ if(!Parsing.isNameStart (key charAt 0))
+ throw new IllegalArgumentException("not a valid attribute name '"+key+"', so can never match !")
+ null
+ }
+
+ /** gets value of qualified (prefixed) attribute with given key */
+ def apply(namespace: String, scope: NamespaceBinding, key: String) = null
+
+ override def hashCode(): Int = 0
+
+ override def toString1(): String = ""
+
+ //appends string representations of single attribute to StringBuilder
+ def toString1(sb:StringBuilder) = {}
+
+ override def toString(): String = ""
+
+ override def toString(sb: StringBuilder): StringBuilder = sb
+
+ override def wellformed(scope: NamespaceBinding) = true
+
+ def remove(key: String) = this
+
+ def remove(namespace: String, scope: NamespaceBinding, key: String) = this
+}
diff --git a/src/dotnet-library/scala/xml/Parsing.scala b/src/dotnet-library/scala/xml/Parsing.scala
new file mode 100644
index 0000000000..17bf4567b4
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Parsing.scala
@@ -0,0 +1,105 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+/** The object <code>Parsing</code> ...
+ *
+ * @author Burak Emir
+ * @version 1.0
+ *
+ * @deprecated use either <code>parsing.TokenTests</code> or
+ * <code>Utilty</code> (helper functions for parsing XML fragments).
+ */
+object Parsing {
+
+ /** <pre>(#x20 | #x9 | #xD | #xA)</pre> */
+ final def isSpace(ch: Char): Boolean = ch match {
+ case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true
+ case _ => false
+ }
+
+ /** <pre>(#x20 | #x9 | #xD | #xA)+</pre> */
+ final def isSpace(cs: Seq[Char]): Boolean = {
+ val it = cs.elements
+ it.hasNext && it.forall { isSpace }
+ }
+
+ /** <pre>NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
+ * | CombiningChar | Extender</pre>
+ *
+ * see [4] and Appendix B of XML 1.0 specification
+ */
+ def isNameChar(ch: Char) = isNameStart(ch) || (ch match {
+ case '.' | '-' | ':' => true
+ case _ => java.lang.Character.getType(ch).asInstanceOf[Byte] match {
+ case java.lang.Character.COMBINING_SPACING_MARK => true // Mc
+ case java.lang.Character.ENCLOSING_MARK => true // Me
+ case java.lang.Character.NON_SPACING_MARK => true // Mn
+ case java.lang.Character.MODIFIER_LETTER => true // Lm
+ case java.lang.Character.DECIMAL_DIGIT_NUMBER => true // Nd
+ case _ => false
+ }
+ });
+
+ /** <pre>NameStart ::= ( Letter | '_' )</pre>
+ * where Letter means in one of the Unicode general
+ * categories { Ll, Lu, Lo, Lt, Nl }
+ *
+ * We do not allow a name to start with ':'.
+ * see [3] and Appendix B of XML 1.0 specification
+ */
+ def isNameStart(ch: Char) =
+ java.lang.Character.getType(ch).asInstanceOf[Byte] match {
+ case java.lang.Character.LOWERCASE_LETTER => true
+ case java.lang.Character.UPPERCASE_LETTER => true
+ case java.lang.Character.OTHER_LETTER => true
+ case java.lang.Character.TITLECASE_LETTER => true
+ case java.lang.Character.LETTER_NUMBER => true
+ case _ => ch == '_'
+ }
+
+ /** <pre>Name ::= ( Letter | '_' ) (NameChar)*</pre>
+ *
+ * see [5] of XML 1.0 specification
+ */
+ def isName(s: String): Boolean =
+ if (s.length() > 0) {
+ val z: Seq[Char] = s
+ val y = z.elements
+ if (isNameStart(y.next)) {
+ while (y.hasNext && isNameChar(y.next)) {}
+ !y.hasNext
+ } else false
+ } else false
+
+ def isPubIDChar(c: Char) = c match {
+ case '\u0020' | '\u000D' | '\u000A' => true
+ case _ if
+ ('0' < c && c < '9')||('a' < c && c < 'z')||('A' < c && c < 'Z') => true
+ case '-' | '\''| '(' | ')' | '+' | ',' | '.' | '/' | ':' | '=' |
+ '?' | ';' | '!' | '*' | '#' | '@' | '$' | '_' | '%' => true
+ case _ => false
+ }
+
+ def checkSysID(s: String): Boolean =
+ s.indexOf('"') == -1 || s.indexOf('\'') == -1
+
+ def checkPubID(s: String): Boolean =
+ if (s.length() > 0) {
+ val z:Seq[Char] = s
+ val y = z.elements
+ while (y.hasNext && isPubIDChar(y.next)) {}
+ !y.hasNext
+ } else true
+
+}
diff --git a/src/dotnet-library/scala/xml/PrefixedAttribute.scala b/src/dotnet-library/scala/xml/PrefixedAttribute.scala
new file mode 100644
index 0000000000..397a68507c
--- /dev/null
+++ b/src/dotnet-library/scala/xml/PrefixedAttribute.scala
@@ -0,0 +1,101 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** prefixed attributes always have a non-null namespace.
+ * @param value the attribute value, which may not be null
+ */
+class PrefixedAttribute(val pre: String,
+ val key: String,
+ val value: Seq[Node],
+ val next: MetaData) extends MetaData {
+
+ if(value eq null)
+ throw new UnsupportedOperationException("value is null")
+
+ /** same as this(key, Utility.parseAttributeValue(value), next) */
+ def this(pre: String, key: String, value: String, next: MetaData) =
+ this(pre, key, Utility.parseAttributeValue(value), next)
+
+ /*
+ // the problem here is the fact that we cannot remove the proper attribute from
+ // next, and thus cannot guarantee that hashcodes are computed properly
+ def this(pre: String, key: String, value: scala.AllRef, next: MetaData) =
+ throw new UnsupportedOperationException("can't construct prefixed nil attributes")
+ */
+
+ /** Returns a copy of this unprefixed attribute with the given
+ * next field.
+ */
+ def copy(next: MetaData) =
+ new PrefixedAttribute(pre, key, value, next)
+
+ def equals1(m: MetaData) =
+ (m.isPrefixed &&
+ (m.asInstanceOf[PrefixedAttribute].pre == pre) &&
+ (m.key == key) && (m.value sameElements value))
+
+ def getNamespace(owner: Node) =
+ owner.getNamespace(pre)
+
+ /** forwards the call to next (because caller looks for unprefixed attribute */
+ def apply(key: String): Seq[Node] = next(key)
+
+ /** gets attribute value of qualified (prefixed) attribute with given key
+ */
+ def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = {
+ if (key == this.key && scope.getURI(pre) == namespace)
+ value
+ else
+ next(namespace, scope, key)
+ }
+
+ /** returns true */
+ final def isPrefixed = true
+
+ /** returns the hashcode.
+ */
+ override def hashCode() =
+ pre.hashCode() * 41 + key.hashCode() * 7 + next.hashCode()
+
+
+ /** appends string representation of only this attribute to stringbuffer */
+ def toString1(sb:StringBuilder): Unit = if(value ne null) {
+ sb.append(pre)
+ sb.append(':')
+ sb.append(key)
+ sb.append('=')
+ val sb2 = new StringBuilder()
+ for (val c <- value) {
+ Utility.toXML(c, TopScope, sb2, true)
+ }
+ Utility.appendQuoted(sb2.toString(), sb)
+ }
+
+ def wellformed(scope: NamespaceBinding): Boolean = {
+ (null == next(scope.getURI(pre), scope, key) &&
+ next.wellformed(scope))
+ }
+
+ def remove(key: String) =
+ copy(next.remove(key))
+
+ def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData =
+ if (key == this.key && scope.getURI(pre) == namespace)
+ next
+ else
+ next.remove(namespace, scope, key)
+
+}
+
diff --git a/src/dotnet-library/scala/xml/PrettyPrinter.scala b/src/dotnet-library/scala/xml/PrettyPrinter.scala
new file mode 100644
index 0000000000..6930cd96c7
--- /dev/null
+++ b/src/dotnet-library/scala/xml/PrettyPrinter.scala
@@ -0,0 +1,306 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import scala.collection.Map
+import compat.StringBuilder
+
+/** Class for pretty printing. After instantiating, you can use the
+ * toPrettyXML methods to convert XML to a formatted string. The class
+ * can be reused to pretty print any number of XML nodes.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ *
+ * @param width the width to fit the output into
+ * @step indentation
+ */
+class PrettyPrinter( width:Int, step:Int ) {
+
+ class BrokenException() extends java.lang.Exception
+
+ class Item
+ case object Break extends Item {
+ override def toString() = "\\"
+ }
+ case class Box(col: Int, s: String) extends Item
+ case class Para(s: String) extends Item
+
+ protected var items: List[Item] = Nil
+
+ protected var cur = 0
+ //protected var pmap:Map[String,String] = _
+
+ protected def reset() = {
+ cur = 0
+ items = Nil
+ }
+
+ /** Try to cut at whitespace.
+ *
+ * @param s ...
+ * @param ind ...
+ * @return ...
+ */
+ protected def cut(s: String, ind: Int): List[Item] = {
+ val tmp = width - cur
+ if (s.length() < tmp)
+ return List(Box(ind, s))
+ val sb = new StringBuilder()
+ var i = s.indexOf(' ')
+ if (i > tmp || i == -1) throw new BrokenException() // cannot break
+
+ var last: List[Int] = Nil
+ while (i < tmp) {
+ last = i::last
+ i = s.indexOf(' ', i)
+ }
+ var res: List[Item] = Nil
+ while (Nil != last) try {
+ val b = Box(ind, s.substring(0, last.head))
+ cur = ind
+ res = b :: Break :: cut(s.substring(last.head, s.length()), ind)
+ // backtrack
+ } catch {
+ case _:BrokenException => last = last.tail
+ }
+ throw new BrokenException()
+ }
+
+ /** Try to make indented box, if possible, else para.
+ *
+ * @param ind ...
+ * @param s ...
+ * @return ...
+ */
+ protected def makeBox(ind: Int, s: String) = {
+ if (cur < ind)
+ cur == ind
+ if (cur + s.length() > width) { // fits in this line
+ items = Box( ind, s ) :: items
+ cur = cur + s.length()
+ } else try {
+ for (val b <- cut(s, ind).elements) // break it up
+ items = b :: items
+ } catch {
+ case _:BrokenException => makePara(ind, s) // give up, para
+ }
+ }
+
+ // dont respect indent in para, but afterwards
+ protected def makePara(ind: Int, s: String) = {
+ items = Break::Para(s)::Break::items
+ cur = ind
+ }
+
+ // respect indent
+ protected def makeBreak() = { // using wrapping here...
+ items = Break :: items
+ cur = 0
+ }
+
+ /**
+ * @param n ...
+ * @return ...
+ */
+ protected def leafTag(n: Node) = {
+ val sb = new StringBuilder("<")
+ n.nameToString(sb)
+ //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb );
+ n.attributes.toString(sb)
+ //Utility.attr2xml( n.scope, n.attributes, pmap, sb );
+ sb.append("/>")
+ sb.toString()
+ }
+
+ protected def startTag(n: Node, pscope: NamespaceBinding): Pair[String, Int] = {
+ val sb = new StringBuilder("<")
+ n.nameToString(sb) //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb );
+ val i = sb.length() + 1
+ n.attributes.toString(sb)
+ n.scope.toString(sb, pscope)
+ sb.append('>')
+ Pair(sb.toString(), i)
+ }
+
+ protected def endTag(n: Node) = {
+ val sb = new StringBuilder("</")
+ n.nameToString(sb) //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb );
+ sb.append('>')
+ sb.toString()
+ }
+
+ protected def childrenAreLeaves(n: Node): Boolean = {
+ val it = n.child.elements
+ while (it.hasNext)
+ it.next match {
+ case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr =>
+ case _:Node =>
+ return false
+ }
+ true
+ }
+
+ protected def fits(test: String) =
+ test.length() < width - cur
+
+ /** @param tail: what we'd like to sqeeze in */
+ protected def traverse(node: Node, pscope: NamespaceBinding, ind: Int): Unit = node match {
+
+ case Text(s) if s.trim() == "" =>
+ ;
+ case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr =>
+ makeBox( ind, node.toString().trim() )
+ case _ =>
+ val test = {
+ val sb = new StringBuilder()
+ Utility.toXML(node, pscope, sb, false)
+ if (node.attribute("http://www.w3.org/XML/1998/namespace", "space") == "preserve")
+ sb.toString()
+ else
+ TextBuffer.fromString(sb.toString()).toText(0)._data
+ }
+ if (childrenAreLeaves(node) && fits(test)) {
+ makeBox(ind, test)
+ } else {
+ val Pair(stg, len2) = startTag(node, pscope)
+ val etg = endTag(node)
+ if (stg.length() < width - cur) { // start tag fits
+ makeBox(ind, stg)
+ makeBreak()
+ traverse(node.child.elements, node.scope, ind + step)
+ makeBox(ind, etg)
+ } else if (len2 < width - cur) {
+ // <start label + attrs + tag + content + end tag
+ makeBox(ind, stg.substring(0, len2))
+ makeBreak() // todo: break the rest in pieces
+ /*{ //@todo
+ val sq:Seq[String] = stg.split(" ");
+ val it = sq.elements;
+ it.next;
+ for( val c <- it ) {
+ makeBox( ind+len2-2, c );
+ makeBreak();
+ }
+ }*/
+ makeBox(ind, stg.substring(len2, stg.length()))
+ makeBreak()
+ traverse(node.child.elements, node.scope, ind + step)
+ makeBox(cur, etg)
+ makeBreak()
+ } else { // give up
+ makeBox(ind, test)
+ makeBreak()
+ }
+ }
+ }
+
+ protected def traverse(it: Iterator[Node], scope: NamespaceBinding, ind: Int ): Unit =
+ for (val c <- it) {
+ traverse(c, scope, ind)
+ makeBreak()
+ }
+
+ /** Appends a formatted string containing well-formed XML with
+ * given namespace to prefix mapping to the given string buffer.
+ *
+ * @param n the node to be serialized
+ * @param pmap the namespace to prefix mapping
+ * @param sb the stringbuffer to append to
+ */
+ def format(n: Node, sb: StringBuilder ): Unit = // entry point
+ format(n, null, sb)
+
+ def format(n: Node, pscope: NamespaceBinding, sb: StringBuilder): Unit = { // entry point
+ var lastwasbreak = false
+ reset()
+ traverse(n, pscope, 0)
+ var cur = 0
+ for (val b <- items.reverse) b match {
+ case Break =>
+ if (!lastwasbreak) sb.append('\n') // on windows: \r\n ?
+ lastwasbreak = true
+ cur = 0
+// while( cur < last ) {
+// sb.append(' ');
+// cur = cur + 1;
+// }
+
+ case Box(i, s) =>
+ lastwasbreak = false
+ while (cur < i) {
+ sb.append(' ')
+ cur = cur + 1
+ }
+ sb.append(s)
+ case Para( s ) =>
+ lastwasbreak = false
+ sb.append(s)
+ }
+ }
+
+ // public convenience methods
+
+ /** returns a formatted string containing well-formed XML with
+ * default namespace prefix mapping
+ *
+ * @param n the node to be serialized
+ * @return ...
+ */
+ def format(n: Node): String = format(n, null) //Utility.defaultPrefixes(n))
+
+ /** Returns a formatted string containing well-formed XML with
+ * given namespace to prefix mapping.
+ *
+ * @param n the node to be serialized
+ * @param pmap the namespace to prefix mapping
+ * @return ...
+ */
+ def format(n: Node, pscope: NamespaceBinding): String = {
+ val sb = new StringBuilder()
+ format(n, pscope, sb)
+ sb.toString()
+ }
+
+ /** Returns a formatted string containing well-formed XML nodes with
+ * default namespace prefix mapping.
+ *
+ * @param nodes ...
+ * @return ...
+ */
+ def formatNodes(nodes: Seq[Node]): String =
+ formatNodes(nodes, null)
+
+ /** Returns a formatted string containing well-formed XML.
+ *
+ * @param nodes the sequence of nodes to be serialized
+ * @param pmap the namespace to prefix mapping
+ */
+ def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding): String = {
+ var sb = new StringBuilder()
+ formatNodes(nodes, pscope, sb)
+ sb.toString()
+ }
+
+ /** Appends a formatted string containing well-formed XML with
+ * the given namespace to prefix mapping to the given stringbuffer.
+ *
+ * @param n the node to be serialized
+ * @param pmap the namespace to prefix mapping
+ * @param sb the string buffer to which to append to
+ */
+ def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding, sb: StringBuilder): Unit =
+ for (val n <- nodes.elements) {
+ sb.append(format(n, pscope))
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/ProcInstr.scala b/src/dotnet-library/scala/xml/ProcInstr.scala
new file mode 100644
index 0000000000..3ff1f9b82c
--- /dev/null
+++ b/src/dotnet-library/scala/xml/ProcInstr.scala
@@ -0,0 +1,68 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml;
+
+
+import compat.StringBuilder
+
+/** an XML node for processing instructions (PI)
+ *
+ * @author Burak Emir
+ * @param target target name of this PI
+ * @param text text contained in this node, may not contain "?>"
+**/
+
+case class ProcInstr(target:String, proctext:String) extends SpecialNode {
+
+ if( !Utility.isName( target ) )
+ throw new IllegalArgumentException(target+" must be an XML Name");
+ else if( text.indexOf("?>" ) != -1 )
+ throw new IllegalArgumentException(proctext+" may not contain \"?>\"");
+
+ final override def typeTag$:Int = -2;
+
+ (target: Seq[Char]) match {
+ case Seq('X'|'x','M'|'m','L'|'l') =>
+ throw new IllegalArgumentException(target+" is reserved");
+ case _ =>
+ }
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ case ProcInstr(x,y) => x.equals(target) && y.equals(proctext);
+ case _ => false
+ }
+
+ /** the constant "#PI" */
+ final def label = "#PI";
+
+ /** hashcode for this PI */
+ override def hashCode() = target.hashCode() * 7 + proctext.hashCode();
+
+
+ override def text = "";
+
+ /** appends &quot;&lt;?&quot; target (&quot; &quot;+text)?+&quot;?&gt;&quot;
+ * to this stringbuffer.
+ */
+ override def toString(sb: StringBuilder) = {
+ sb
+ .append("<?")
+ .append(target);
+ if( proctext.length() > 0 ) {
+ sb
+ .append(' ')
+ .append(proctext);
+ };
+ sb.append("?>");
+ }
+}
diff --git a/src/dotnet-library/scala/xml/SpecialNode.scala b/src/dotnet-library/scala/xml/SpecialNode.scala
new file mode 100644
index 0000000000..9fb23a64a3
--- /dev/null
+++ b/src/dotnet-library/scala/xml/SpecialNode.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** &lt;code&gt;SpecialNode&lt;/code&gt; is a special XML node which
+ * represents either text (PCDATA), a comment, a PI, or an entity ref.
+ * SpecialNodes also play the role of XMLEvents for pull-parsing.
+ * @author Burak Emir
+ */
+abstract class SpecialNode extends Node with pull.XMLEvent {
+
+ /** always empty */
+ final override def attributes = Null
+
+ /** always Node.EmptyNamespace */
+ final override def namespace = null
+
+ /** always empty */
+ final def child = Nil
+
+ /** append string representation to the given stringbuffer */
+ def toString(sb: StringBuilder): StringBuilder
+
+}
diff --git a/src/dotnet-library/scala/xml/Text.scala b/src/dotnet-library/scala/xml/Text.scala
new file mode 100644
index 0000000000..7170239611
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Text.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** The class <code>Text</code> implements an XML node for text (PCDATA).
+ * It is used in both non-bound and bound XML representations.
+ *
+ * @author Burak Emir
+ *
+ * @param text the text contained in this node, may not be null.
+ */
+case class Text(_data: String) extends Atom[String](_data) {
+
+ if (null == data)
+ throw new java.lang.NullPointerException("tried to construct Text with null")
+
+ final override def equals(x: Any) = x match {
+ case s:String => s.equals(data.toString())
+ case s:Text => data == s.data
+ case _ => false
+ }
+
+ /** Returns text, with some characters escaped according to the XML
+ * specification.
+ *
+ * @param sb ...
+ * @return ...
+ */
+ override def toString(sb: StringBuilder) =
+ Utility.escape(data.toString(), sb)
+
+}
diff --git a/src/dotnet-library/scala/xml/TextBuffer.scala b/src/dotnet-library/scala/xml/TextBuffer.scala
new file mode 100644
index 0000000000..7831b38621
--- /dev/null
+++ b/src/dotnet-library/scala/xml/TextBuffer.scala
@@ -0,0 +1,65 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+object TextBuffer {
+ def fromString(str: String): TextBuffer =
+ new TextBuffer().append(str)
+}
+
+/** The class <code>TextBuffer</code> is for creating text nodes without
+ * surplus whitespace. All occurrences of one or more whitespace in strings
+ * appended with the <code>append</code> method will be replaced by a single
+ * space character, and leading and trailing space will be removed completely.
+ */
+class TextBuffer {
+
+ val sb = new compat.StringBuilder()
+ var ws = true
+
+ def appendSpace = if(!ws) { ws = true; sb.append(' ') } else {}
+ def appendChar(c: char) = { ws = false; sb.append( c ) }
+
+ /** Appends this string to the text buffer, trimming whitespaces as needed.
+ *
+ * @param cs ...
+ * @return ...
+ */
+ def append(cs: Seq[Char]): TextBuffer = {
+ for (val c <- cs) {
+ if (Utility.isSpace(c))
+ appendSpace
+ else
+ appendChar(c)
+ }
+ this
+ }
+
+ /** Returns an empty sequence if text is only whitespace.
+ *
+ * @return the text without whitespaces.
+ */
+ def toText: Seq[Text] = {
+ var len = sb.length() /* invariant */
+ if (len == 0) return Nil
+
+ if (Utility.isSpace(sb.charAt(len - 1))) {
+ len = len - 1
+ sb.setLength(len)
+ }
+ if (len == 0) return Nil
+
+ List(Text(sb.toString()))
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/TopScope.scala b/src/dotnet-library/scala/xml/TopScope.scala
new file mode 100644
index 0000000000..e42cdf736d
--- /dev/null
+++ b/src/dotnet-library/scala/xml/TopScope.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+package scala.xml;
+
+import compat.StringBuilder
+
+/** top level namespace scope. only contains the predefined binding
+ * for the &quot;xml&quot; prefix which is bound to
+ * &quot;http://www.w3.org/XML/1998/namespace&quot;
+ */
+case object TopScope extends NamespaceBinding(null, null, null) {
+
+ override def getURI(prefix1: String): String =
+ if(prefix1 == "xml" /*XML.xml*/)
+ "http://www.w3.org/XML/1998/namespace"
+ else
+ null;
+
+ override def getPrefix(uri1: String): String =
+ if(uri1 == "http://www.w3.org/XML/1998/namespace" /*XML.namespace*/)
+ "xml" //XML.xml
+ else
+ null;
+
+ override def toString() = "";
+
+ override def toString(stop: NamespaceBinding) = "";
+
+ override def toString(sb: StringBuilder, ignore: NamespaceBinding) = {};
+
+}
diff --git a/src/dotnet-library/scala/xml/TypeSymbol.scala b/src/dotnet-library/scala/xml/TypeSymbol.scala
new file mode 100644
index 0000000000..4834139f92
--- /dev/null
+++ b/src/dotnet-library/scala/xml/TypeSymbol.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml;
+
+
+abstract class TypeSymbol;
diff --git a/src/dotnet-library/scala/xml/Unparsed.scala b/src/dotnet-library/scala/xml/Unparsed.scala
new file mode 100644
index 0000000000..f4275ceea7
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Unparsed.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: Text.scala 8097 2006-07-11 17:15:02 +0200 (Tue, 11 Jul 2006) emir $
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** an XML node for unparsed content. It will be output verbatim, all bets
+ * are off regarding wellformedness etc.
+ * @author Burak Emir
+ * @param _data content in this node, may not be null.
+ */
+case class Unparsed(_data: String) extends Atom[String](_data) {
+
+ if (null == data)
+ throw new java.lang.NullPointerException("tried to construct Unparsed with null")
+
+ final override def equals(x: Any) = x match {
+ case s:String => s.equals(data)
+ case s:Text => data == s.data
+ case s:Unparsed => data == s.data
+ case _ => false
+ }
+
+ /** returns text, with some characters escaped according to XML spec */
+ override def toString(sb: StringBuilder) = sb append data
+
+}
diff --git a/src/dotnet-library/scala/xml/UnprefixedAttribute.scala b/src/dotnet-library/scala/xml/UnprefixedAttribute.scala
new file mode 100644
index 0000000000..81d02c955f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/UnprefixedAttribute.scala
@@ -0,0 +1,87 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+
+/** unprefixed attributes have the null namespace, and no prefix field
+ *
+ */
+class UnprefixedAttribute(val key: String, val value: Seq[Node], next1: MetaData) extends MetaData {
+
+ val next = if(value ne null) next1 else next1.remove(key)
+
+ /** same as this(key, Utility.parseAttributeValue(value), next) */
+ def this(key: String, value: String, next: MetaData) =
+ this(key, if(value ne null) Text(value) else {val z:NodeSeq=null;z}, next)
+
+ /** returns a copy of this unprefixed attribute with the given next field*/
+ def copy(next: MetaData) =
+ new UnprefixedAttribute(key, value, next)
+
+ def equals1(m:MetaData) =
+ !m.isPrefixed && (m.key == key) && (m.value sameElements value)
+
+ /** returns null */
+ final def getNamespace(owner: Node): String =
+ null
+
+ /**
+ * Gets value of unqualified (unprefixed) attribute with given key, null if not found
+ *
+ * @param key
+ * @return value as Seq[Node] if key is found, null otherwise
+ */
+ def apply(key: String): Seq[Node] =
+ if (key == this.key) value else next(key)
+
+ /**
+ * Forwards the call to next (because caller looks for prefixed attribute).
+ *
+ * @param namespace
+ * @param scope
+ * @param key
+ * @return ..
+ */
+ def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] =
+ next(namespace, scope, key)
+
+ /** returns the hashcode.
+ */
+ override def hashCode() =
+ key.hashCode() * 7 + { if(value ne null) value.hashCode() * 53 else 0 } + next.hashCode()
+
+ /** returns false */
+ final def isPrefixed = false
+
+ /** appends string representation of only this attribute to stringbuffer */
+ def toString1(sb:StringBuilder): Unit = if(value ne null) {
+ sb.append(key)
+ sb.append('=')
+ val sb2 = new StringBuilder()
+ for (val c <- value) {
+ Utility.toXML(c, TopScope, sb2, true)
+ }
+ Utility.appendQuoted(sb2.toString(), sb)
+ }
+
+ def wellformed(scope: NamespaceBinding): Boolean =
+ (null == next(null, scope, key)) && next.wellformed(scope)
+
+ def remove(key: String) =
+ if(this.key == key) next else copy(next.remove(key))
+
+ def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData =
+ next.remove(namespace, scope, key)
+
+}
+
diff --git a/src/dotnet-library/scala/xml/Utility.scala b/src/dotnet-library/scala/xml/Utility.scala
new file mode 100644
index 0000000000..3a83d6be57
--- /dev/null
+++ b/src/dotnet-library/scala/xml/Utility.scala
@@ -0,0 +1,444 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+import compat.StringBuilder
+import collection.mutable.{Set, HashSet}
+
+/**
+ * The <code>Utility</code> object provides utility functions for processing
+ * instances of bound and not bound XML classes, as well as escaping text nodes.
+ *
+ * @author Burak Emir
+ */
+object Utility extends AnyRef with parsing.TokenTests {
+
+ def view(s: String): Text = Text(s)
+
+ /**
+ * Escapes the characters &lt; &gt; &amp; and &quot; from string.
+ *
+ * @param text ...
+ * @return ...
+ */
+ final def escape(text: String): String =
+ escape(text, new StringBuilder()).toString()
+
+ /**
+ * Appends escaped string to <code>s</code>.
+ *
+ * @param text ...
+ * @param s ...
+ * @return ...
+ */
+ final def escape(text: String, s: StringBuilder): StringBuilder = {
+ for (val c <- Iterator.fromString(text)) c match {
+ case '<' => s.append("&lt;")
+ case '>' => s.append("&gt;")
+ case '&' => s.append("&amp;")
+ case '"' => s.append("&quot;")
+ //case '\'' => s.append("&apos;") // is valid xhtml but not html, and IE doesn't know it, says jweb
+ case _ => s.append(c)
+ }
+ s
+ }
+
+ /**
+ * Appends unescaped string to <code>s</code>, amp becomes &amp;
+ * lt becomes &lt; etc..
+ *
+ * @param ref ...
+ * @param s ...
+ * @return <code>null</code> if <code>ref</code> was not a predefined
+ * entity.
+ */
+ final def unescape(ref: String, s: StringBuilder): StringBuilder =
+ ref match {
+ case "lt" => s.append('<')
+ case "gt" => s.append('>')
+ case "amp" => s.append('&')
+ case "quot" => s.append('"')
+ case "apos" => s.append('\'')
+ case _ => null
+ }
+
+ /**
+ * Returns a set of all namespaces used in a sequence of nodes
+ * and all their descendants, including the empty namespaces.
+ *
+ * @param nodes ...
+ * @return ...
+ */
+ def collectNamespaces(nodes: Seq[Node]): Set[String] = {
+ var m = new HashSet[String]()
+ val it = nodes.elements
+ while (it.hasNext)
+ collectNamespaces(it.next, m);
+ m
+ }
+
+ /**
+ * Adds all namespaces in node to set.
+ *
+ * @param n ...
+ * @param set ...
+ */
+ def collectNamespaces(n: Node, set: Set[String]): Unit = {
+ if (n.typeTag$ >= 0) {
+ set += n.namespace
+ for (val a <- n.attributes) a match {
+ case _:PrefixedAttribute =>
+ set += a.getNamespace(n)
+ case _ =>
+ }
+ for (val i <- n.child)
+ collectNamespaces(i, set);
+ }
+ }
+
+ /**
+ * Returs the string representation of an XML node, with comments stripped
+ * the comments.
+ *
+ * @param n the XML node
+ * @return the string representation of node <code>n</code>.
+ *
+ * @see "toXML(Node, Boolean)"
+ */
+ def toXML(n: Node): String = toXML(n, true)
+
+ /**
+ * Return the string representation of a Node. uses namespace mapping from
+ * <code>defaultPrefixes(n)</code>.
+ *
+ * @param n the XML node
+ * @param stripComment ...
+ * @return ...
+ *
+ * @todo define a way to escape literal characters to &amp;xx; references
+ */
+ def toXML(n: Node, stripComment: Boolean): String = {
+ val sb = new StringBuilder()
+ toXML(n, TopScope, sb, stripComment)
+ sb.toString()
+ }
+
+
+ /**
+ * Appends a tree to the given stringbuffer within given namespace scope.
+ *
+ * @param n the node
+ * @param pscope the parent scope
+ * @param sb stringbuffer to append to
+ * @param stripComment if true, strip comments
+ */
+ def toXML(x: Node, pscope: NamespaceBinding, sb: StringBuilder, stripComment: Boolean): Unit = {
+ x match {
+
+ case c: Comment if !stripComment =>
+ c.toString(sb)
+
+ case x: SpecialNode =>
+ x.toString(sb)
+
+ case g: Group =>
+ for (val c <- g.nodes) {
+ toXML(c, x.scope, sb, stripComment)
+ }
+
+ case _ =>
+ // print tag with namespace declarations
+ sb.append('<')
+ x.nameToString(sb)
+ if (x.attributes ne null) {
+ x.attributes.toString(sb)
+ }
+ x.scope.toString(sb, pscope)
+ sb.append('>')
+ sequenceToXML(x.child, pscope, sb, stripComment)
+ sb.append("</")
+ x.nameToString(sb)
+ sb.append('>')
+ }
+ }
+
+ /**
+ * @param children ...
+ * @param pscope ...
+ * @param sb ...
+ * @param stripComment ...
+ */
+ def sequenceToXML(children: Seq[Node], pscope: NamespaceBinding,
+ sb: StringBuilder, stripComment: Boolean): Unit = {
+ if (children.isEmpty)
+ return
+ else if (children forall { y => y.isInstanceOf[Atom[Any]] && !y.isInstanceOf[Text] }) { // add space
+ val it = children.elements
+ val f = it.next
+ toXML(f, f.scope, sb, stripComment)
+ while (it.hasNext) {
+ val x = it.next
+ sb.append(' ')
+ toXML(x, x.scope, sb, stripComment)
+ }
+ } else for (val c <- children) {
+ toXML(c, c.scope, sb, stripComment)
+ }
+ }
+
+ /**
+ * Returns prefix of qualified name if any.
+ *
+ * @param name ...
+ * @return ...
+ */
+ final def prefix(name: String): Option[String] = {
+ val i = name.indexOf(':'.asInstanceOf[Int])
+ if( i != -1 ) Some( name.substring(0, i) ) else None
+ }
+
+ /**
+ * Returns a hashcode for the given constituents of a node
+ *
+ * @param uri
+ * @param label
+ * @param attribHashCode
+ * @param children
+ */
+ def hashCode(pre: String, label: String, attribHashCode: Int, scpeHash: Int, children: Seq[Node]) = {
+ ( if(pre ne null) {41 * pre.hashCode() % 7} else {0})
+ + label.hashCode() * 53
+ + attribHashCode * 7
+ + scpeHash * 31
+ + children.hashCode()
+ }
+
+ /**
+ * Returns a hashcode for the given constituents of a node
+ *
+ * @param uri
+ * @param label
+ * @param attribs
+ * @param children
+ def hashCode(uri: String, label: String, attribs: scala.collection.mutable.HashMap[Pair[String,String],String], scpe: Int, children: Seq[Node]): Int = {
+ 41 * uri.hashCode() % 7 + label.hashCode() + attribs.toList.hashCode() + scpe + children.hashCode()
+ }
+ */
+
+ /**
+ * @param s ...
+ * @return ...
+ */
+ def systemLiteralToString(s: String): String = {
+ val sb = new StringBuilder()
+ systemLiteralToString(sb, s)
+ sb.toString()
+ }
+
+ /**
+ * @param sb ...
+ * @param s ...
+ * @return ...
+ */
+ def systemLiteralToString(sb: StringBuilder, s: String): StringBuilder = {
+ sb.append("SYSTEM ")
+ appendQuoted(s, sb)
+ }
+
+ /**
+ * @param s ...
+ * @return ...
+ */
+ def publicLiteralToString(s: String): String = {
+ val sb = new StringBuilder()
+ systemLiteralToString(sb, s)
+ sb.toString()
+ }
+
+ /**
+ * @param sb ...
+ * @param s ...
+ * @return ...
+ */
+ def publicLiteralToString(sb: StringBuilder, s: String): StringBuilder = {
+ sb.append("PUBLIC \"").append(s).append('"')
+ }
+
+ /**
+ * Appends &quot;s&quot; if string <code>s</code> does not contain &quot;,
+ * &apos;s&apos; otherwise.
+ *
+ * @param s ...
+ * @param sb ...
+ * @return ...
+ */
+ def appendQuoted(s: String, sb: StringBuilder) = {
+ val ch = if (s.indexOf('"'.asInstanceOf[Int]) == -1) '"' else '\'';
+ sb.append(ch).append(s).append(ch)
+ }
+
+ /**
+ * Appends &quot;s&quot; and escapes and &quot; i s with \&quot;
+ *
+ * @param s ...
+ * @param sb ...
+ * @return ...
+ */
+ def appendEscapedQuoted(s: String, sb: StringBuilder) = {
+ sb.append('"')
+ for (val c <- s) c match {
+ case '"' => sb.append('\\'); sb.append('"')
+ case _ => sb.append(c)
+ }
+ sb.append('"')
+ }
+
+ /**
+ * @param s ...
+ * @param index ...
+ * @return ...
+ */
+ def getName(s: String, index: Int): String = {
+ var i = index;
+ val sb = new StringBuilder();
+ if (i < s.length()) {
+ var c = s.charAt(i);
+ if (isNameStart(s.charAt(i)))
+ while (i < s.length() && { c = s.charAt(i); isNameChar(c)}) {
+ sb.append(c)
+ i = i + 1
+ }
+ sb.toString()
+ } else null
+ }
+
+ /**
+ * Returns <code>null</code> if the value is a correct attribute value,
+ * error message if it isn't.
+ *
+ * @param value ...
+ * @return ...
+ */
+ def checkAttributeValue(value: String): String = {
+ var i = 0
+ while (i < value.length()) {
+ value.charAt(i) match {
+ case '<' =>
+ return "< not allowed in attribute value";
+ case '&' =>
+ val n = getName(value, i+1);
+ if (n eq null)
+ return "malformed entity reference in attribute value ["+value+"]";
+ i = i + n.length() + 1
+ if (i >= value.length() || value.charAt(i) != ';')
+ return "malformed entity reference in attribute value ["+value+"]";
+ case _ =>
+ }
+ i = i + 1
+ }
+ null
+ }
+
+ /**
+ * new
+ *
+ * @param value ...
+ * @return ...
+ */
+ def parseAttributeValue(value: String): Seq[Node] = {
+ val zs: Seq[Char] = value
+ val sb = new StringBuilder
+ var rfb: StringBuilder = null
+ val nb = new NodeBuffer()
+ val it = zs.elements
+ while (it.hasNext) {
+ var c = it.next
+ c match {
+ case '&' => // entity! flush buffer into text node
+ it.next match {
+ case '#' =>
+ c = it.next
+ val theChar = parseCharRef ({ ()=> c },{ () => c = it.next },{s => throw new RuntimeException(s)})
+ sb.append(theChar)
+
+ case x =>
+ if (rfb eq null) rfb = new StringBuilder()
+ rfb.append(x)
+ c = it.next
+ while (c != ';') {
+ rfb.append(c)
+ c = it.next
+ }
+ val ref = rfb.toString()
+ rfb.setLength(0)
+ unescape(ref,sb) match {
+ case null =>
+ if (sb.length() > 0) { // flush buffer
+ nb += Text(sb.toString())
+ sb.setLength(0)
+ }
+ nb += EntityRef(sb.toString()) // add entityref
+ case _ =>
+ }
+ }
+ case x =>
+ sb.append(x)
+ }
+ }
+ if (sb.length() > 0) { // flush buffer
+ val x = Text(sb.toString())
+ if (nb.length == 0)
+ return x
+ else
+ nb += x
+ }
+ return nb
+ }
+
+ /**
+ * <pre>
+ * CharRef ::= "&amp;#" '0'..'9' {'0'..'9'} ";"
+ * | "&amp;#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";"
+ * </pre>
+ * <p>
+ * see [66]
+ * <p>
+ *
+ * @param ch ...
+ * @param nextch ...
+ * @param reportSyntaxError ...
+ * @return ...
+ */
+ def parseCharRef(ch: () => Char, nextch: () => Unit, reportSyntaxError:(String) => Unit): String = {
+ val hex = (ch() == 'x') && { nextch(); true }
+ val base = if (hex) 16 else 10
+ var i = 0
+ while (ch() != ';') {
+ ch() match {
+ case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
+ i = i * base + ch().asDigit
+ case 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
+ | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' =>
+ if (! hex)
+ reportSyntaxError("hex char not allowed in decimal char ref\n" +
+ "Did you mean to write &#x ?")
+ else
+ i = i * base + ch().asDigit
+ case _ =>
+ reportSyntaxError("character '" + ch() + "' not allowed in char ref\n")
+ }
+ nextch()
+ }
+ i.asInstanceOf[char].toString()
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/XML.scala b/src/dotnet-library/scala/xml/XML.scala
new file mode 100644
index 0000000000..e9e51ca520
--- /dev/null
+++ b/src/dotnet-library/scala/xml/XML.scala
@@ -0,0 +1,157 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml
+
+
+import Predef._
+import scala.xml.parsing.NoBindingFactoryAdapter
+import org.xml.sax.InputSource
+import java.io.{File, FileDescriptor, FileInputStream, FileOutputStream}
+import java.io.{InputStream, Reader, StringReader, Writer}
+
+/** The object <code>XML</code> provides constants, and functions to load
+ * and save XML elements. Use this when data binding is not desired, i.e.
+ * when XML is handled using <code>Symbol</code> nodes.
+ *
+ * @author Burak Emir
+ * @version 1.0, 25/04/2005
+ */
+object XML {
+
+ val xml = "xml"
+ val xmlns = "xmlns"
+ val namespace = "http://www.w3.org/XML/1998/namespace"
+ val preserve = "preserve"
+ val space = "space"
+ val lang = "lang"
+
+ // functions for generic xml loading, saving
+
+ /** loads XML from given file, using XML parser in JDK. */
+ final def loadFile(file: File): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(
+ new FileInputStream(file)
+ ))
+
+ /** loads XML from given file descriptor, using XML parser in JDK.
+ *
+ * @param fileDesc ...
+ * @return ...
+ */
+ final def loadFile(fileDesc: FileDescriptor): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(
+ new FileInputStream(fileDesc)
+ ))
+
+ /** loads XML from given file, using XML parser in JDK. */
+ final def loadFile(fileName: String): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(
+ new FileInputStream(fileName)
+ ));
+
+ /** loads XML from given InputStream, using XML parser in JDK. */
+ final def load( is:InputStream ): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(is))
+
+ /** loads XML from given Reader, using XML parser in JDK. */
+ final def load(reader: Reader): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(reader))
+
+ /** loads XML from given sysID, using XML parser in JDK. */
+ final def load(sysID: String): Elem =
+ new NoBindingFactoryAdapter().loadXML(new InputSource(sysID))
+
+ /** loads XML from a given input source, using XML parser in JDK.
+ *
+ * @param source ...
+ * @return ...
+ */
+ final def load(source: InputSource): Elem =
+ new NoBindingFactoryAdapter().loadXML(source)
+
+ /** loads XML from a string, using XML parser in JDK. */
+ final def loadString(string: String): Elem =
+ load(new StringReader(string))
+
+ /** Saves XML to filename with encoding ISO-8859-1 without xml-decl without
+ * <code>doctype</code>.
+ *
+ * @param filename ...
+ * @param node ...
+ */
+ final def save(filename: String, node: Node): Unit =
+ save(filename, node, "ISO-8859-1")
+
+ /** saves XML to filename with given encoding, without xml-decl without
+ * <code>doctype</code>.
+ *
+ * @param filename ...
+ * @param node ...
+ * @param enc ...
+ */
+ final def save(filename: String, node: Node, enc: String): Unit =
+ saveFull(filename, node, enc, false, null);
+
+ /** saves a node to a file with given filename using encoding iso-8859-1
+ * optionally with xmldecl and doctype declaration.
+ *
+ * @param filename the filename
+ * @param node the xml node we want to write
+ * @param xmlDecl if true, write xml declaration
+ * @param doctype if not null, write doctype declaration
+ */
+ final def saveFull(filename: String, node: Node, xmlDecl: Boolean, doctype: dtd.DocType): Unit =
+ saveFull(filename, node, "ISO-8859-1", xmlDecl, doctype)
+
+ /** Saves a node to a file with given filename using given encoding
+ * optionally with xmldecl and doctype declaration.
+ *
+ * @param filename the filename
+ * @param node the xml node we want to write
+ * @param enc encoding to use
+ * @param xmlDecl if true, write xml declaration
+ * @param doctype if not null, write doctype declaration
+ */
+
+ final def saveFull(filename: String, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType): Unit = {
+ var fos: FileOutputStream = null
+ var w: Writer = null
+ try {
+ // using NIO classes of JDK 1.4
+ import java.io.{FileOutputStream, Writer}
+ import java.nio.channels.{Channels, FileChannel}
+
+ fos = new FileOutputStream(filename)
+ w = Channels.newWriter(fos.getChannel(), enc)
+ write(w, node, enc, xmlDecl, doctype)
+ } finally {
+ w.close()
+ fos.close()
+ }
+ }
+
+ /** Writes the given node using writer, optionally with xml decl and doctype.
+ * It's the caller's responsibility to close the writer.
+ *
+ * @param w the writer
+ * @param node the xml node we want to write
+ * @param enc the string to be used in <code>xmlDecl</code>
+ * @param xmlDecl if true, write xml declaration
+ * @param doctype if not null, write doctype declaration
+ */
+ final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType): Unit = {
+ /* TODO: optimize by giving writer parameter to toXML*/
+ if (xmlDecl) w.write("<?xml version='1.0' encoding='" + enc + "'?>\n")
+ if (doctype ne null) w.write( doctype.toString() + "\n")
+ w.write(Utility.toXML(node))
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/ContentModel.scala b/src/dotnet-library/scala/xml/dtd/ContentModel.scala
new file mode 100644
index 0000000000..0f7eb6e8cb
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/ContentModel.scala
@@ -0,0 +1,212 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+import compat.StringBuilder;
+import scala.util.regexp.WordExp;
+import scala.util.automata._;
+
+object ContentModel extends WordExp {
+ type _labelT = ElemName;
+ type _regexpT = RegExp;
+
+ object Translator extends WordBerrySethi {
+
+ override val lang: ContentModel.this.type = ContentModel.this;
+ import lang._ ;
+ //val re = Sequ(Star(Letter(IntConst( 3 ))));
+ //val aut = automatonFrom(re, 7)
+ }
+
+
+ case class ElemName(name: String) extends Label {
+ override def toString() = "ElemName(\""+name+"\")";
+ }
+
+ def isMixed(cm: ContentModel) = cm.isInstanceOf[MIXED];
+ def containsText(cm: ContentModel) = (cm == PCDATA) || isMixed(cm);
+
+ def parse(s: String): ContentModel = ContentModelParser.parse( s );
+
+ def getLabels(r: RegExp): scala.collection.Set[String] = {
+ val s = new scala.collection.mutable.HashSet[String]();
+ def traverse1(xs: Seq[RegExp]): Unit = {
+ val it = xs.elements;
+ while( it.hasNext )
+ traverse( it.next );
+ }
+ def traverse(r: RegExp): Unit = {
+ r match {
+ case Letter(ElemName( name )) => s += name;
+ case Star( x @ _ ) => traverse( x ); // bug if x@_*
+ case Sequ( xs @ _* ) => traverse1(xs);
+ case Alt( xs @ _* ) => traverse1(xs);
+ }
+ }
+ traverse( r );
+ return s
+ }
+
+ def toString(r: RegExp):String = {
+ val sb = new StringBuilder();
+ toString(r, sb);
+ sb.toString();
+ }
+
+ /* precond: rs.length >= 1 */
+ private def toString(rs: Seq[RegExp], sb: StringBuilder, sep: Char): Unit = {
+
+ val it = rs.elements;
+ val fst = it.next;
+ toString(fst, sb);
+ for(val z <- it) {
+ sb.append( sep );
+ toString( z, sb );
+ }
+ sb
+ }
+
+ def toString(c: ContentModel, sb: StringBuilder): StringBuilder = c match {
+
+ case ANY =>
+ sb.append("ANY");
+
+ case EMPTY =>
+ sb.append("EMPTY");
+
+ case PCDATA =>
+ sb.append("(#PCDATA)");
+
+ case ELEMENTS( _ ) | MIXED( _ ) =>
+ c.toString(sb)
+
+ }
+
+ def toString(r: RegExp, sb:StringBuilder): StringBuilder = {
+ r match {
+ case Eps =>
+ sb
+
+ case Sequ(rs @ _*) =>
+ sb.append( '(' ); toString(rs, sb, ','); sb.append( ')' );
+
+ case Alt(rs @ _*) =>
+ sb.append( '(' ); toString(rs, sb, '|'); sb.append( ')' );
+
+ case Star(r: RegExp) =>
+ sb.append( '(' ); toString(r, sb); sb.append( ")*" );
+
+ case Letter(ElemName(name)) =>
+ sb.append(name);
+
+ }
+ }
+
+}
+
+sealed abstract class ContentModel {
+ override def toString(): String = {
+ val sb = new StringBuilder();
+ toString(sb);
+ sb.toString();
+ }
+
+ def toString(sb:StringBuilder): StringBuilder;
+ /*
+ def validate(cs: NodeSeq): Boolean = this.match {
+ case ANY => true ;
+ case EMPTY => cs.length == 0;
+ case PCDATA => cs.length == 0
+ || (cs.length == 1 && cs(0).isInstanceOf[Text]);
+ case m@MIXED(r) => m.runDFA(cs);
+ case e@ELEMENTS(r) => e.runDFA(cs);
+ }
+ */
+}
+
+case object PCDATA extends ContentModel {
+ override def toString(sb:StringBuilder): StringBuilder = sb.append("(#PCDATA)");
+}
+case object EMPTY extends ContentModel {
+ override def toString(sb:StringBuilder): StringBuilder = sb.append("EMPTY");
+}
+case object ANY extends ContentModel {
+ override def toString(sb:StringBuilder): StringBuilder = sb.append("ANY");
+}
+abstract class DFAContentModel extends ContentModel {
+ import ContentModel.{ ElemName };
+ def r: ContentModel.RegExp;
+ private var _dfa: DetWordAutom[ContentModel.ElemName] = null;
+
+ def dfa = {
+ if(null == _dfa) {
+ val nfa = ContentModel.Translator.automatonFrom(r, 1);
+ _dfa = new SubsetConstruction(nfa).determinize;
+ }
+ _dfa
+ }
+}
+case class MIXED(r:ContentModel.RegExp) extends DFAContentModel {
+ import ContentModel.{ Alt, Eps, RegExp };
+ /*
+ def getIterator(ns:NodeSeq) = new Iterator[String] {
+ def cond(n:Node) =
+ !n.isInstanceOf[Text] && !n.isInstanceOf[SpecialNode];
+Console.println("ns = "+ns);
+ val jt = ns.elements;
+ def hasNext = jt.hasNext;
+ def next = {
+ var r: Node = jt.next;
+ while(!cond(r) && jt.hasNext) {
+ Console.println("skipping "+r);
+ r = jt.next;
+ }
+ Console.println("MIXED, iterator.next, r = "+r);
+ if(Text("") == r)
+ null
+ else
+ r.label
+ }
+ }
+ */
+ override def toString(sb:StringBuilder): StringBuilder = {
+ sb.append("(#PCDATA|");
+ //r match {
+ // case Alt(Eps, rs@_*) => ContentModel.toString(Alt(rs:_*):RegExp, sb);
+ //}
+ ContentModel.toString(Alt(r.asInstanceOf[Alt].rs.toList.drop(1):_*):RegExp, sb);
+ sb.append(")*");
+ }
+}
+
+case class ELEMENTS(r:ContentModel.RegExp) extends DFAContentModel {
+ /*
+ def getIterator(ns:NodeSeq) = new Iterator[String] {
+ val jt = ns.elements.buffered;
+ def hasNext = jt.hasNext;
+ def next = {
+ var r: Node = jt.next;
+ while(r.isInstanceOf[SpecialNode] && jt.hasNext) {
+ r = jt.head;
+ jt.next;
+ }
+ Console.println("MIXED, iterator.next, r = "+r);
+ if(r.isInstanceOf[Text])
+ throw ValidationException("Text not allowed here!")
+ else
+ r.label
+ }
+ }
+ */
+ override def toString(sb:StringBuilder): StringBuilder =
+ ContentModel.toString(r, sb);
+}
diff --git a/src/dotnet-library/scala/xml/dtd/ContentModelParser.scala b/src/dotnet-library/scala/xml/dtd/ContentModelParser.scala
new file mode 100644
index 0000000000..712c0c24ff
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/ContentModelParser.scala
@@ -0,0 +1,156 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+/** Parser for regexps (content models in DTD element declarations) */
+
+object ContentModelParser extends Scanner { // a bit too permissive concerning #PCDATA
+ import ContentModel._ ;
+
+ /** parses the argument to a regexp */
+ def parse(s:String): ContentModel = { initScanner( s ); contentspec }
+
+ // zzz parser methods zzz
+ def accept(tok: Int) = {
+ if( token != tok ) {
+ if(( tok == STAR )&&( token == END )) // common mistake
+ error("in DTDs, \n"+
+ "mixed content models must be like (#PCDATA|Name|Name|...)*");
+ else
+ error("expected "+token2string(tok)+
+ ", got unexpected token:"+token2string(token));
+ }
+ nextToken
+ }
+
+ // s [ '+' | '*' | '?' ]
+ def maybeSuffix(s: RegExp) = token match {
+ case STAR => nextToken; Star( s )
+ case PLUS => nextToken; Sequ( s, Star( s ))
+ case OPT => nextToken; Alt( Eps, s )
+ case _ => s
+ }
+
+
+ // contentspec ::= EMPTY | ANY | (#PCDATA) | "(#PCDATA|"regexp)
+
+ def contentspec: ContentModel = token match {
+
+ case NAME => value match {
+ case "ANY" => ANY
+ case "EMPTY" => EMPTY
+ case _ => error("expected ANY, EMPTY or '(' instead of " + value );
+ }
+ case LPAREN =>
+
+ nextToken;
+ sOpt;
+ if( token != TOKEN_PCDATA )
+ ELEMENTS(regexp);
+ else {
+ nextToken;
+ token match {
+ case RPAREN =>
+ PCDATA
+ case CHOICE =>
+ val res = MIXED(choiceRest(Eps));
+ sOpt;
+ accept( RPAREN );
+ accept( STAR );
+ res
+ case _ =>
+ error("unexpected token:" + token2string(token) );
+ }
+ }
+
+ case _ =>
+ error("unexpected token:" + token2string(token) );
+ }
+ // sopt ::= S?
+ def sOpt = if( token == S ) nextToken;
+
+ // (' S? mixed ::= '#PCDATA' S? ')'
+ // | '#PCDATA' (S? '|' S? atom)* S? ')*'
+ /*
+ def mixed = {
+ accept( TOKEN_PCDATA );
+ sOpt;
+ if( token == RPAREN )
+ PCDATA_
+ else {
+ val t = choiceRest( PCDATA_ );
+ if( !isMixed( t ) )
+ error("mixed content models must be like (#PCDATA.|.|.|.)*");
+ accept( RPAREN );
+ // lax: (workaround for buggy Java XML parser in JDK1.4.2)
+ if( token == STAR ) accept( STAR );
+ // strict:
+ // accept( STAR );
+ Star( t )
+ }
+ }
+*/
+ // '(' S? regexp ::= cp S? [seqRest|choiceRest] ')' [ '+' | '*' | '?' ]
+ def regexp:RegExp = {
+ //Console.println("regexp, token = "+token2string(token));
+ val p = particle;
+ sOpt;
+ maybeSuffix( token match {
+ case RPAREN => nextToken; p
+ case CHOICE => val q = choiceRest( p );accept( RPAREN ); q
+ case COMMA => val q = seqRest( p ); accept( RPAREN ); q
+ })
+ }
+
+
+ // seqRest ::= (',' S? cp S?)+
+ def seqRest( p:RegExp ) = {
+ var k = List( p );
+ while( token == COMMA ) {
+ nextToken;
+ sOpt;
+ k = particle::k;
+ sOpt;
+ }
+ Sequ( k.reverse:_* )
+ }
+
+ // choiceRest ::= ('|' S? cp S?)+
+ def choiceRest( p:RegExp ) = {
+ var k = List( p );
+ while( token == CHOICE ) {
+ nextToken;
+ sOpt;
+ k = particle::k;
+ sOpt;
+ }
+ Alt( k.reverse:_* )
+ }
+
+ // particle ::= '(' S? regexp
+ // | name [ '+' | '*' | '?' ]
+ def particle = {
+ //Console.println("particle, token="+token2string(token));
+ token match {
+ case LPAREN => nextToken; sOpt; regexp;
+ case NAME => val a = Letter(ElemName(value)); nextToken; maybeSuffix( a )
+ case _ => error("expected '(' or Name, got:"+token2string( token ));
+ }
+ }
+
+ // atom ::= name
+ def atom = token match {
+ case NAME => val a = Letter(ElemName(value)); nextToken; a
+ case _ => error("expected Name, got:"+token2string( token ));
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/DTD.scala b/src/dotnet-library/scala/xml/dtd/DTD.scala
new file mode 100644
index 0000000000..d1907fd5c0
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/DTD.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+import scala.collection.mutable.{ HashMap, Map }
+
+/** a document type declaration */
+abstract class DTD {
+
+ var externalID: ExternalID = null;
+
+ def notations: Seq[NotationDecl] = Nil;
+
+ def unparsedEntities: Seq[EntityDecl] = Nil;
+
+ var elem: Map[String, ElemDecl] = new HashMap[String, ElemDecl]();
+
+ var attr: Map[String, AttListDecl] = new HashMap[String, AttListDecl]();
+
+ var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]();
+
+ var decls: List[Decl] = Nil;
+
+ //def getElemDecl(elem:String): ElemDecl;
+
+ //def getAttribDecl(elem: String, attr: String): AttrDecl;
+
+ override def toString() = {
+ val sb = new compat.StringBuilder();
+ sb.append("DTD [\n");
+ if(null != externalID)
+ sb.append(externalID.toString()).append('\n');
+ for(val d <- decls)
+ sb.append(d.toString()).append('\n');
+ sb.append("]").toString()
+ }
+
+ /*
+ def initializeEntities() = {
+ for(val x <- decls) x match {
+ case y @ ParsedEntityDecl(name, _) => ent.update(name, y);
+ case y @ UnparsedEntityDecl(name, _, _) => ent.update(name, y);
+ case y @ ParameterEntityDecl(name, _) => ent.update(name, y);
+ case _ =>
+ }
+ }
+ */
+
+}
diff --git a/src/dotnet-library/scala/xml/dtd/Decl.scala b/src/dotnet-library/scala/xml/dtd/Decl.scala
new file mode 100644
index 0000000000..3aec3b1c70
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/Decl.scala
@@ -0,0 +1,176 @@
+/* __ *\
+ ** ________ ___ / / ___ Scala API **
+ ** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+ ** __\ \/ /__/ __ |/ /__/ __ | **
+ ** /____/\___/_/ |_/____/_/ | | **
+ ** |/ **
+ \* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+import compat.StringBuilder
+
+abstract class Decl;
+
+abstract class MarkupDecl extends Decl {
+ def toString(sb: StringBuilder): StringBuilder;
+}
+
+/** an element declaration
+ */
+case class ElemDecl(name: String, contentModel: ContentModel) extends MarkupDecl with DtdTypeSymbol {
+
+ //def mixed = ; // to do
+
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb
+ .append("<!ELEMENT ")
+ .append(name)
+ .append(' ');
+
+ ContentModel.toString(contentModel, sb);
+ sb.append('>');
+ }
+
+} // ElemDecl
+
+case class AttListDecl(name: String, attrs:List[AttrDecl]) extends MarkupDecl with DtdTypeSymbol {
+
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb
+ .append("<!ATTLIST ")
+ .append(name)
+ .append('\n')
+ .append(attrs.mkString("","\n",">"));
+ }
+}
+
+/** an attribute declaration. at this point, the tpe is a string. Future
+ * versions might provide a way to access the attribute types more
+ * directly.
+ */
+case class AttrDecl( name:String, tpe:String, default:DefaultDecl ) {
+
+ override def toString(): String =
+ toString(new StringBuilder()).toString();
+
+ def toString(sb: StringBuilder): StringBuilder = {
+ sb.append(" ").append( name ).append(' ').append( tpe ).append(' ');
+ default.toString(sb)
+ }
+
+}
+
+/** an entity declaration */
+abstract class EntityDecl extends MarkupDecl;
+
+/** a parsed general entity declaration */
+case class ParsedEntityDecl( name:String, entdef:EntityDef ) extends EntityDecl {
+
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb.append("<!ENTITY ").append( name ).append(' ');
+ entdef.toString(sb).append('>');
+ }
+}
+
+/** a parameter entity declaration */
+case class ParameterEntityDecl(name: String, entdef: EntityDef) extends EntityDecl {
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb.append("<!ENTITY % ").append( name ).append(' ');
+ entdef.toString(sb).append('>');
+ }
+}
+
+/** an unparsed entity declaration */
+case class UnparsedEntityDecl( name:String, extID:ExternalID, notation:String ) extends EntityDecl {
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb.append("<!ENTITY ").append( name ).append(' ');
+ extID.toString(sb).append(" NDATA ").append(notation).append('>');
+ }
+}
+/** a notation declaration */
+case class NotationDecl( name:String, extID:ExternalID ) extends MarkupDecl {
+ override def toString(sb: StringBuilder): StringBuilder = {
+ sb.append("<!NOTATION ").append( name ).append(' ');
+ extID.toString(sb);
+ }
+}
+
+abstract class EntityDef {
+ def toString(sb: StringBuilder): StringBuilder;
+}
+
+case class IntDef(value:String) extends EntityDef {
+ private def validateValue(): Unit = {
+ var tmp = value;
+ var ix = tmp.indexOf('%');
+ while( ix != -1) {
+ val iz = tmp.indexOf(';', ix);
+ if(iz == -1 && iz == ix + 1)
+ throw new IllegalArgumentException("no % allowed in entity value, except for parameter-entity-references");
+ else {
+ val n = tmp.substring(ix, iz);
+
+ if( !Utility.isName( n ))
+ throw new IllegalArgumentException("interal entity def: \""+n+"\" must be an XML Name");
+
+ tmp = tmp.substring(iz+1, tmp.length());
+ ix = tmp.indexOf('%');
+ }
+ }
+ }
+ validateValue();
+
+ override def toString(sb: StringBuilder): StringBuilder =
+ Utility.appendQuoted(value, sb);
+
+}
+
+case class ExtDef(extID:ExternalID) extends EntityDef {
+ override def toString(sb: StringBuilder): StringBuilder =
+ extID.toString(sb);
+}
+
+
+
+/** a parsed entity reference */
+case class PEReference(ent:String) extends MarkupDecl {
+ if( !Utility.isName( ent ))
+ throw new IllegalArgumentException("ent must be an XML Name");
+
+ override def toString(sb: StringBuilder): StringBuilder =
+ sb.append('%').append(ent).append(';');
+}
+
+
+// default declarations for attributes
+
+abstract class DefaultDecl {
+ override def toString(): String;
+ def toString(sb: StringBuilder): StringBuilder;
+}
+
+case object REQUIRED extends DefaultDecl {
+ override def toString(): String = "#REQUIRED";
+ override def toString(sb:StringBuilder) = sb.append("#REQUIRED");
+}
+
+case object IMPLIED extends DefaultDecl {
+ override def toString(): String = "#IMPLIED";
+ override def toString(sb:StringBuilder) = sb.append("#IMPLIED");
+}
+
+case class DEFAULT(fixed: Boolean, attValue:String) extends DefaultDecl {
+ override def toString(): String =
+ toString(new StringBuilder()).toString();
+
+ override def toString(sb:StringBuilder): StringBuilder = {
+ if(fixed)
+ sb.append("#FIXED ");
+ Utility.appendEscapedQuoted( attValue, sb );
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/DocType.scala b/src/dotnet-library/scala/xml/dtd/DocType.scala
new file mode 100644
index 0000000000..e31f43990f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/DocType.scala
@@ -0,0 +1,47 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+/** an XML node for document type declaration
+ *
+ * @author Burak Emir
+ * @param target name of this DOCTYPE
+ * @param extID None, or Some(external ID of this doctype)
+ * @param intSubset sequence of internal subset declarations
+**/
+
+case class DocType( name:String, extID:ExternalID, intSubset:Seq[dtd.Decl]) {
+
+ if( !Utility.isName( name ) )
+ throw new IllegalArgumentException(name+" must be an XML Name");
+
+ /** hashcode for this processing instruction */
+ final override def hashCode() = name.hashCode() + 7 * extID.hashCode() + 41*intSubset.toList.hashCode();
+
+ /** returns "&lt;!DOCTYPE + name + extID? + ("["+intSubSet+"]")? >" */
+ final override def toString() = {
+ val sb = new compat.StringBuilder().append("<!DOCTYPE ");
+ sb.append( name );
+ sb.append(' ');
+ sb.append(extID.toString());
+ if( intSubset.length > 0 ) {
+ sb.append('[');
+ for( val d <- intSubset ) {
+ sb.append( d.toString() );
+ }
+ sb.append(']');
+ }
+ sb.append('>');
+ sb.toString();
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala b/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala
new file mode 100644
index 0000000000..1933db6c34
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+trait DtdTypeSymbol;
diff --git a/src/dotnet-library/scala/xml/dtd/ElementValidator.scala b/src/dotnet-library/scala/xml/dtd/ElementValidator.scala
new file mode 100644
index 0000000000..645caa66eb
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/ElementValidator.scala
@@ -0,0 +1,179 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+import ContentModel.ElemName ;
+import scala.util.automata._ ;
+
+/** validate children and/or attributes of an element
+ * exceptions are created but not thrown.
+ */
+class ElementValidator() extends Function1[Node,Boolean] {
+
+ var exc: List[ValidationException] = Nil;
+
+ protected var contentModel: ContentModel = _;
+ protected var dfa: DetWordAutom[ElemName] = _;
+ protected var adecls: List[AttrDecl] = _;
+
+ /** set content model, enabling element validation */
+ def setContentModel(cm:ContentModel) = {
+ contentModel = cm; cm match {
+ case ELEMENTS( r ) =>
+ val nfa = ContentModel.Translator.automatonFrom(r, 1);
+ dfa = new SubsetConstruction(nfa).determinize;
+ case _ =>
+ dfa = null;
+ }
+ }
+
+ def getContentModel = contentModel;
+
+ /** set meta data, enabling attribute validation */
+ def setMetaData(adecls: List[AttrDecl]) =
+ this.adecls = adecls;
+
+ def getIterator(nodes: Seq[Node], skipPCDATA: Boolean): Iterator[ElemName] =
+ nodes.toList
+ .filter { x => x match {
+ case y:SpecialNode => y match {
+
+ case a:Atom[_] if (a.data.isInstanceOf[String] &&
+ a.data.asInstanceOf[String].trim.length == 0 ) =>
+ false; // always skip all-whitespace nodes
+
+ case _ =>
+ !skipPCDATA
+
+ }
+ case _ =>
+ x.namespace eq null
+ }}
+ . map { x => ElemName(x.label) }
+ . elements;
+
+ /** check attributes, return true if md corresponds to attribute declarations in adecls.
+ */
+ def check(md: MetaData): Boolean = {
+ //Console.println("checking md = "+md);
+ //Console.println("adecls = "+adecls);
+ //@todo other exceptions
+ import MakeValidationException._;
+ val len: Int = exc.length;
+ var j = 0;
+ var ok = new scala.collection.mutable.BitSet(adecls.length);
+ def find(Key:String): AttrDecl = {
+ var attr: AttrDecl = null;
+ val jt = adecls.elements; while(j < adecls.length) {
+ jt.next match {
+ case a @ AttrDecl(Key, _, _) => attr = a; ok += j; j = adecls.length;
+ case _ => j = j + 1;
+ }
+ }
+ attr
+ }
+ val it = md.elements; while(it.hasNext) {
+ val attr = it.next;
+ //Console.println("attr:"+attr);
+ j = 0;
+ find(attr.key) match {
+
+ case null =>
+ //Console.println("exc");
+ exc = fromUndefinedAttribute( attr.key ) :: exc;
+
+ case AttrDecl(_, tpe, DEFAULT(true, fixedValue)) if(attr.value != fixedValue) =>
+ exc = fromFixedAttribute( attr.key, fixedValue, attr.value.toString()) :: exc;
+
+ case s =>
+ //Console.println("s: "+s);
+
+ }
+ }
+ //Console.println("so far:"+(exc.length == len));
+
+ //val missing = ok.toSet( false ); FIXME: it doesn't seem to be used anywhere
+ j = 0; var kt = adecls.elements; while(kt.hasNext) {
+ kt.next match {
+ case AttrDecl(key, tpe, REQUIRED) if !ok(j) =>
+ exc = fromMissingAttribute( key, tpe ) :: exc;
+ j = j + 1;
+ case _ =>
+ j = j + 1;
+ }
+ }
+ //Console.println("finish:"+(exc.length == len));
+ (exc.length == len) //- true if no new exception
+ }
+
+ /** check children, return true if conform to content model
+ * @pre contentModel != null
+ */
+ def check(nodes: Seq[Node]): Boolean = contentModel match {
+
+ case ANY => true ;
+
+ case EMPTY => !getIterator(nodes, false).hasNext
+
+ case PCDATA => !getIterator(nodes, true).hasNext;
+
+ case MIXED(ContentModel.Alt(branches @ _*)) => //@todo
+ val j = exc.length;
+ def find(Key: String): Boolean = {
+ var res = false;
+ val jt = branches.elements;
+ while(jt.hasNext && !res)
+ jt.next match {
+ case ContentModel.Letter(ElemName(Key)) => res = true;
+ case _ =>
+ }
+ res
+ }
+
+ var it = getIterator(nodes, true); while(it.hasNext) {
+ var label = it.next.name;
+ if(!find(label)) {
+ exc = MakeValidationException.fromUndefinedElement(label) :: exc;
+ }
+ }
+
+ (exc.length == j) //- true if no new exception
+
+ case _:ELEMENTS =>
+ var q = 0;
+ val it = getIterator(nodes, false);
+ //Console.println("it empty from the start? "+(!it.hasNext));
+ while( it.hasNext ) {
+ val e = it.next;
+ dfa.delta(q).get(e) match {
+ case Some(p) => q = p;
+ case _ => throw ValidationException("element "+e+" not allowed here")
+ }
+ //Console.println("q now " + q);
+ }
+ dfa.isFinal(q) //- true if arrived in final state
+ }
+
+ /** applies various validations - accumulates error messages in exc
+ * @todo: fail on first error, ignore other errors (rearranging conditions)
+ */
+ def apply(n: Node): Boolean = {
+ //- ? check children
+ var res = (null == contentModel) || check( n.child );
+
+ //- ? check attributes
+ res = ((null == adecls) || check( n.attributes )) && res;
+
+ res
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/ExternalID.scala b/src/dotnet-library/scala/xml/dtd/ExternalID.scala
new file mode 100644
index 0000000000..514db9c60f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/ExternalID.scala
@@ -0,0 +1,91 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd
+
+
+import compat.StringBuilder
+
+/** an ExternalIDs - either PublicID or SystemID
+ *
+ * @author Burak Emir
+ * @param target target name of this PI
+ * @param text text contained in this node, may not contain "?>"
+**/
+
+abstract class ExternalID {
+
+ /** returns "PUBLIC "+publicLiteral+" SYSTEM "+systemLiteral */
+ override def toString(): String
+
+ /** returns "PUBLIC "+publicLiteral+" SYSTEM "+systemLiteral */
+ def toString(sb: StringBuilder): StringBuilder
+
+ def systemId: String
+
+}
+
+/** a system identifier
+ *
+ * @author Burak Emir
+ * @param systemLiteral the system identifier literal
+**/
+
+case class SystemID( systemId:String ) extends ExternalID with parsing.TokenTests{
+
+ if( !checkSysID( systemId ) )
+ throw new IllegalArgumentException(
+ "can't use both \" and ' in systemLiteral"
+ )
+ /** returns " SYSTEM "+systemLiteral */
+ override def toString() =
+ Utility.systemLiteralToString( systemId )
+
+ override def toString(sb: StringBuilder): StringBuilder =
+ Utility.systemLiteralToString( sb, systemId )
+}
+
+
+/** a public identifier
+ *
+ * @author Burak Emir
+ * @param publicLiteral the public identifier literal
+ * @param systemLiteral (can be null for notation pubIDs) the system identifier literal
+**/
+case class PublicID( publicId:String, systemId:String ) extends ExternalID with parsing.TokenTests{
+
+ if( !checkPubID( publicId ))
+ throw new IllegalArgumentException(
+ "publicId must consist of PubidChars"
+ )
+ if( (systemId ne null) && !checkSysID( systemId ) )
+ throw new IllegalArgumentException(
+ "can't use both \" and ' in systemId"
+ )
+
+ /** the constant "#PI" */
+ def label = "#PI"
+
+ /** always empty */
+ def attribute = Node.NoAttributes
+
+ /** always empty */
+ def child = Nil
+
+ /** appends "PUBLIC "+publicId+" SYSTEM "+systemId to argument */
+ override def toString(sb: StringBuilder): StringBuilder = {
+ Utility.publicLiteralToString( sb, publicId ).append(' ')
+ if(systemId ne null)
+ Utility.systemLiteralToString( sb, systemId )
+ else
+ sb
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/Scanner.scala b/src/dotnet-library/scala/xml/dtd/Scanner.scala
new file mode 100644
index 0000000000..9b30ba5ab6
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/Scanner.scala
@@ -0,0 +1,99 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+/** Scanner for regexps (content models in DTD element declarations)
+ * todo: cleanup
+ */
+class Scanner extends Tokens with parsing.TokenTests {
+
+ // zzz constants zzz
+ final val ENDCH = '\u0000';
+
+ // zzz fields zzz
+ var token:Int = END;
+ var value:String = _;
+
+ private var it:Iterator[Char] = null;
+ private var c:Char = 'z';
+
+
+ /** initializes the scanner on input s */
+ final def initScanner( s:String ) = {
+ //Console.println("[scanner init on \""+s+"\"]");
+ value = "";
+ it = Iterator.fromString( s );
+ token = 1+END;
+ next;
+ nextToken;
+ }
+
+ /** scans the next token */
+ final def nextToken:Unit = {
+ if( token != END ) token = readToken;
+ //Console.println("["+token2string( token )+"]");
+ }
+
+ // zzz scanner methods zzz
+
+ // todo: see XML specification... probably isLetter,isDigit is fine
+ final def isIdentChar = ( ('a' <= c && c <= 'z')
+ || ('A' <= c && c <= 'Z'));
+
+ final def next = if( it.hasNext ) c = it.next else c = ENDCH;
+
+ final def acc( d:char ):Unit =
+ if( c == d ) next; else error("expected '"+d+"' found '"+c+"' !");
+
+ final def accS( ds:Seq[Char] ):Unit = {
+ val jt = ds.elements; while( jt.hasNext ) { acc( jt.next ) }
+ }
+
+ /*
+ final def isSpace = c match {
+ case '\u0020' | '\u0009' | '\u000D' | '\u000A' => true
+ case _ => false;
+ }
+ */
+
+ final def readToken: Int =
+ if(isSpace(c)) {
+ while( isSpace(c) ) {
+ c = it.next;
+ }
+ S
+ } else c match {
+ case '(' => next; LPAREN
+ case ')' => next; RPAREN
+ case ',' => next; COMMA
+ case '*' => next; STAR
+ case '+' => next; PLUS
+ case '?' => next; OPT
+ case '|' => next; CHOICE
+ case '#' => next; accS( "PCDATA" ); TOKEN_PCDATA
+ case ENDCH => END;
+ case _ =>
+ if( isNameStart( c ) ) name; // NAME
+ else {
+ error("unexpected character:"+c); END
+ }
+ }
+
+ final def name = {
+ val sb = new compat.StringBuilder();
+ do { sb.append( c ); next } while ( isNameChar( c ) ) ;
+ value = sb.toString();
+ NAME
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/dtd/Tokens.scala b/src/dotnet-library/scala/xml/dtd/Tokens.scala
new file mode 100644
index 0000000000..43185983a8
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/Tokens.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+class Tokens {
+
+ // Tokens
+
+ final val TOKEN_PCDATA = 0
+ final val NAME = 1
+ final val LPAREN = 3
+ final val RPAREN = 4
+ final val COMMA = 5
+ final val STAR = 6
+ final val PLUS = 7
+ final val OPT = 8
+ final val CHOICE = 9
+ final val END = 10
+ final val S = 13
+
+ final def token2string(i: Int): String = i match {
+ case 0 => "#PCDATA"
+ case 1 => "NAME"
+ case 3 => "("
+ case 4 => ")"
+ case 5 => ","
+ case 6 => "*"
+ case 7 => "+"
+ case 8 => "?"
+ case 9 => "|"
+ case 10 => "END"
+ case 13 => " "
+ }
+}
diff --git a/src/dotnet-library/scala/xml/dtd/ValidationException.scala b/src/dotnet-library/scala/xml/dtd/ValidationException.scala
new file mode 100644
index 0000000000..a37d6f3231
--- /dev/null
+++ b/src/dotnet-library/scala/xml/dtd/ValidationException.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.dtd;
+
+
+case class ValidationException( e:String ) extends Exception( e );
+
+object MakeValidationException {
+ def fromFixedAttribute( k: String, value: String, actual: String ) =
+ ValidationException("value of attribute " + k + " FIXED to \""+value+"\", but document tries \""+actual+"\"");
+
+ def fromNonEmptyElement() = {
+ new ValidationException("element should be *empty*");
+ }
+ def fromUndefinedElement( label:String ) =
+ new ValidationException("element \""+ label +"\" not allowed here");
+
+ def fromUndefinedAttribute( key:String ) =
+ new ValidationException("attribute " + key +" not allowed here" );
+
+ def fromMissingAttribute( allKeys:scala.collection.Set[String] ) = {
+ val sb = new compat.StringBuilder();
+ sb.append("missing value for REQUIRED attribute");
+ if( allKeys.size > 1 ) sb.append('s');
+ val it = allKeys.elements;
+ while (it.hasNext) {
+ sb.append('\'').append(it.next).append('\'')
+ }
+ new ValidationException(sb.toString());
+ }
+
+ def fromMissingAttribute( key: String, tpe: String ) = {
+ new ValidationException("missing value for REQUIRED attribute "+key+" of type "+tpe);
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/factory/Binder.scala b/src/dotnet-library/scala/xml/factory/Binder.scala
new file mode 100644
index 0000000000..d6b6b3d08e
--- /dev/null
+++ b/src/dotnet-library/scala/xml/factory/Binder.scala
@@ -0,0 +1,55 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.factory;
+
+
+import scala.xml.parsing.ValidatingMarkupHandler;
+
+abstract class Binder(val preserveWS: Boolean) extends ValidatingMarkupHandler {
+
+ var result: NodeBuffer = new NodeBuffer();
+
+ def reportSyntaxError(pos:Int, str:String) = {}
+
+ final def procInstr(pos: Int, target: String, txt: String ) =
+ ProcInstr(target, txt);
+
+ final def comment(pos: Int, txt: String ) =
+ Comment( txt );
+
+ final def entityRef(pos: Int, n: String) =
+ EntityRef( n );
+
+ final def text(pos: Int, txt:String) =
+ Text( txt );
+
+ final def traverse(n:Node): Unit = n match {
+ case x:ProcInstr => result &+ procInstr(0, x.target, x.text)
+ case x:Comment => result &+ comment(0, x.text)
+ case x:Text => result &+ text(0, x.data)
+ case x:EntityRef => result &+ entityRef(0, x.entityName)
+ case _ =>
+ elemStart(0, n.prefix, n.label, n.attributes, n.scope);
+ val old = result;
+ result = new NodeBuffer();
+ for(val m <- n.child)
+ traverse(m);
+ result = old &+ elem(0, n.prefix, n.label, n.attributes, n.scope, NodeSeq.fromSeq(result)).toList;
+ elemEnd(0, n.prefix, n.label);
+ }
+
+ final def validate(n:Node): Node = {
+ this.rootLabel = n.label;
+ traverse(n);
+ result(0)
+ }
+}
diff --git a/src/dotnet-library/scala/xml/factory/LoggedNodeFactory.scala b/src/dotnet-library/scala/xml/factory/LoggedNodeFactory.scala
new file mode 100644
index 0000000000..e6d3791bff
--- /dev/null
+++ b/src/dotnet-library/scala/xml/factory/LoggedNodeFactory.scala
@@ -0,0 +1,95 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.factory
+
+
+/** <p>
+ * This class logs what the nodefactory is actually doing.
+ * If you want to see what happens during loading, use it like this:
+ * </p><pre>
+ * <b>object</b> testLogged <b>extends</b> Application {
+ *
+ * <b>val</b> x = <b>new</b> scala.xml.nobinding.NoBindingFactoryAdapter
+ * <b>with</b> scala.xml.LoggedNodeFactory[scala.xml.Elem]()
+ * <b>with</b> scala.util.logging.ConsoleLogger;
+ *
+ * Console.println("Start");
+ *
+ * <b>val</b> doc = x.loadXML(new org.xml.sax.InputSource("http://lamp.epfl.ch/~buraq"));
+ *
+ * Console.println("End");
+ *
+ * Console.println(doc);
+ * }</pre>
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class LoggedNodeFactory[A <: Node]
+extends NodeFactory[A]
+with scala.util.logging.Logged {
+
+ // configuration values;
+ val logNode = true
+ val logText = false
+ val logComment = false
+ val logProcInstr = false
+
+ final val NONE = 0
+ final val CACHE = 1
+ final val FULL = 2
+ /** 0 = no loggging, 1 = cache hits, 2 = detail */
+ val logCompressLevel = 1
+
+ // methods of NodeFactory
+
+ /** logged version of makeNode method */
+ override def makeNode(pre: String, label: String, attrSeq: MetaData,
+ scope: NamespaceBinding, children: Seq[Node]): A = {
+ if (logNode)
+ log("[makeNode for "+label+"]");
+
+ val hash = Utility.hashCode(pre, label, attrSeq.hashCode(), scope.hashCode(), children)
+
+ /*
+ if(logCompressLevel >= FULL) {
+ log("[hashcode total:"+hash);
+ log(" elem name "+uname+" hash "+ ? ));
+ log(" attrs "+attrSeq+" hash "+attrSeq.hashCode());
+ log(" children :"+children+" hash "+children.hashCode());
+ }
+ */
+ if (!cache.get( hash ).isEmpty && (logCompressLevel >= CACHE))
+ log("[cache hit !]");
+
+ super.makeNode(pre, label, attrSeq, scope, children)
+ }
+
+ override def makeText(s: String) = {
+ if (logText)
+ log("[makeText:\""+s+"\"]");
+ super.makeText(s)
+ }
+
+ override def makeComment(s: String): Seq[Comment] = {
+ if (logComment)
+ log("[makeComment:\""+s+"\"]");
+ super.makeComment(s)
+ }
+
+ override def makeProcInstr(t: String, s: String): Seq[ProcInstr] = {
+ if (logProcInstr)
+ log("[makeProcInstr:\""+t+" "+ s+"\"]");
+ super.makeProcInstr(t, s)
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/factory/NodeFactory.scala b/src/dotnet-library/scala/xml/factory/NodeFactory.scala
new file mode 100644
index 0000000000..f17b43b55f
--- /dev/null
+++ b/src/dotnet-library/scala/xml/factory/NodeFactory.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.factory;
+
+
+trait NodeFactory[A <: Node] {
+
+ val ignoreComments = false;
+ val ignoreProcInstr = false;
+
+ /* default behaviour is to use hash-consing */
+ val cache = new collection.mutable.HashMap[Int, List[A]]();
+
+ protected def create(pre: String, name: String, attrs: MetaData, scope: NamespaceBinding, children:Seq[Node]): A;
+
+ protected def construct(hash: Int, old:List[A], pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]): A = {
+ val el = create(pre, name, attrSeq, scope, children);
+ cache.update( hash, el::old );
+ el
+ }
+
+ /** faster equality, because */
+ def eqElements(ch1:Seq[Node], ch2:Seq[Node]): Boolean = {
+ (ch1.length == ch2.length) && {
+ val it1 = ch1.elements;
+ val it2 = ch2.elements;
+ var res = true;
+ while(res && it1.hasNext) {
+ res = it1.next.eq(it2.next);
+ }
+ res
+ }
+ }
+
+ def nodeEquals(n: Node, pre: String, name: String, attrSeq:MetaData, scope: NamespaceBinding, children:Seq[Node]) = (
+ (n.prefix == pre)
+ &&(n.label == name)
+ &&(n.attributes == attrSeq)
+ // scope??
+ &&(eqElements(n.child,children)));
+
+ def makeNode(pre: String, name: String, attrSeq:MetaData, scpe: NamespaceBinding, children:Seq[Node]): A = {
+ //Console.println("NodeFactory::makeNode("+pre+","+name+","+attrSeq+","+scpe+","+children+")");
+ val hash = Utility.hashCode( pre, name, attrSeq.hashCode(), scpe.hashCode(), children ) ;
+ cache.get( hash ) match {
+ case Some(list) => // find structurally equal
+ val it = list.elements;
+ val lookup = it.find { x => nodeEquals(x, pre, name, attrSeq, scpe, children) };
+ lookup match {
+ case Some(x) =>
+ //Console.println("[cache hit !]"+x);
+ x; // return cached elem
+ case _ => construct(hash, list, pre, name, attrSeq, scpe, children);
+ }
+ case _ => construct(hash, Nil, pre, name, attrSeq, scpe, children)
+ }
+ }
+
+ def makeText(s: String) =
+ Text( s );
+
+ def makeComment(s: String): Seq[Comment] =
+ if(ignoreComments) Nil else List(Comment( s ));
+
+ def makeProcInstr(t: String, s: String): Seq[ProcInstr] =
+ if(ignoreProcInstr) Nil else List(ProcInstr(t, s));
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/ConstructingHandler.scala b/src/dotnet-library/scala/xml/parsing/ConstructingHandler.scala
new file mode 100644
index 0000000000..93f8a07c92
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/ConstructingHandler.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing
+
+/** Implementation of MarkupHandler that constructs nodes.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class ConstructingHandler extends MarkupHandler {
+
+ val preserveWS: Boolean
+
+ def elem(pos: int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq =
+ Elem(pre, label, attrs, pscope, nodes:_*)
+
+ def procInstr(pos: Int, target: String, txt: String) =
+ ProcInstr(target, txt)
+
+ def comment(pos: Int, txt: String) =
+ Comment(txt)
+
+ def entityRef(pos: Int, n: String) =
+ EntityRef(n)
+
+ def text(pos: Int, txt:String) =
+ Text(txt)
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/ConstructingParser.scala b/src/dotnet-library/scala/xml/parsing/ConstructingParser.scala
new file mode 100644
index 0000000000..b7c88c79ec
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/ConstructingParser.scala
@@ -0,0 +1,67 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing
+
+import java.io.File
+
+import scala.io.Source
+
+object ConstructingParser {
+
+ def fromFile(inp: File, preserveWS: Boolean) = {
+ val p = new ConstructingParser(Source.fromFile(inp), preserveWS)
+ p.nextch
+ p
+ }
+
+ def fromSource(inp: Source, preserveWS: Boolean) = {
+ val p = new ConstructingParser(inp, preserveWS)
+ p.nextch
+ p
+ }
+}
+
+/** An xml parser. parses XML and invokes callback methods of a MarkupHandler.
+ * Don't forget to call next.ch on a freshly instantiated parser in order to
+ * initialize it. If you get the parser from the object method, initialization
+ * is already done for you.
+ *
+ *<pre>
+object parseFromURL {
+ def main(args:Array[String]): Unit = {
+ val url = args(0);
+ val src = scala.io.Source.fromURL(url);
+ val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false); // fromSource initializes automatically
+ val doc = cpa.document();
+
+ // let's see what it is
+ val ppr = new scala.xml.PrettyPrinter(80,5);
+ val ele = doc.docElem;
+ Console.println("finished parsing");
+ val out = ppr.format(ele);
+ Console.println(out);
+ }
+}
+</pre>
+ */
+class ConstructingParser(inp: Source, presWS:Boolean)
+extends ConstructingHandler
+with ExternalSources
+with MarkupParser {
+
+ // default impl. of Logged
+ override def log(msg: String): Unit = {}
+
+ val preserveWS = presWS
+ val input = inp
+}
+
diff --git a/src/dotnet-library/scala/xml/parsing/DefaultMarkupHandler.scala b/src/dotnet-library/scala/xml/parsing/DefaultMarkupHandler.scala
new file mode 100644
index 0000000000..d9a175218e
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/DefaultMarkupHandler.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+
+/** default implemenation of markup handler always returns NodeSeq.Empty */
+abstract class DefaultMarkupHandler extends MarkupHandler {
+
+ def elem(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding, args: NodeSeq) = NodeSeq.Empty;
+
+ def procInstr(pos: Int, target: String, txt: String) = NodeSeq.Empty;
+
+ def comment(pos: Int, comment: String ): NodeSeq = NodeSeq.Empty;
+
+ def entityRef(pos: Int, n: String) = NodeSeq.Empty;
+
+ def text(pos: Int, txt:String) = NodeSeq.Empty;
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/ExternalSources.scala b/src/dotnet-library/scala/xml/parsing/ExternalSources.scala
new file mode 100644
index 0000000000..90b7f406a4
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/ExternalSources.scala
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+import compat.StringBuilder
+import scala.io.Source;
+import java.net.URL;
+
+trait ExternalSources requires (ExternalSources with MarkupParser with MarkupHandler) {
+
+ private def externalSourceFromURL(url:URL): Source = {
+ import java.io.{BufferedReader, InputStreamReader};
+ val in =
+ new BufferedReader(
+ new InputStreamReader(
+ url.openStream()));
+
+ //@todo: replace this hack with proper Source implementation
+
+ val str = new StringBuilder();
+ var inputLine:String = null;
+
+ //while (inputLine = in.readLine()) != null) {
+ while ({inputLine = in.readLine(); inputLine} ne null) {
+ // Console.println(inputLine); // DEBUG
+ str.append(inputLine);
+ str.append('\n'); // readable output
+ }
+ in.close();
+
+ class MyClass extends Source {
+
+ def newIter = new Iterator[Char] {
+ var i = -1;
+ private val len = str.length()-1;
+ def hasNext = i < len;
+ def next = {
+ i = i + 1;
+ str.charAt(i);
+ }
+ }
+
+ val iter = newIter;
+
+ def reset: Source = new MyClass;
+
+ /*override var*/ descr = url.toExternalForm();
+ }
+
+ return new MyClass;
+ }
+
+ def externalSource(systemId: String): Source = {
+ //Console.println("in external source("+systemId+")");
+ if(systemId.startsWith("http:")) {
+ return externalSourceFromURL(new URL(systemId));
+ }
+
+ var fileStr = input.descr;
+
+ if(input.descr.startsWith("file:")) {
+ fileStr = input.descr.substring(5, input.descr.length());
+ } else
+ fileStr = fileStr.substring(0,
+ fileStr.lastIndexOf(java.io.File.separator)+1);
+ Source.fromFile(fileStr + systemId);
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/FactoryAdapter.scala b/src/dotnet-library/scala/xml/parsing/FactoryAdapter.scala
new file mode 100644
index 0000000000..d1deabb5a2
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/FactoryAdapter.scala
@@ -0,0 +1,336 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing
+
+import java.io.{InputStream, Reader, File, FileDescriptor, FileInputStream}
+import scala.collection.mutable.{HashMap,Stack}
+import compat.StringBuilder
+
+import org.xml.sax.Attributes
+import org.xml.sax.ContentHandler
+
+import org.xml.sax.ErrorHandler
+import org.xml.sax.Locator
+import org.xml.sax.InputSource
+
+import org.xml.sax.SAXException
+import org.xml.sax.SAXNotRecognizedException
+import org.xml.sax.SAXNotSupportedException
+import org.xml.sax.SAXParseException
+import org.xml.sax.helpers.DefaultHandler
+
+import javax.xml.parsers.SAXParserFactory
+import javax.xml.parsers.ParserConfigurationException
+import javax.xml.parsers.SAXParser
+
+
+/** SAX adapter class, for use with Java SAX parser. Keeps track of
+ * namespace bindings, without relying on namespace handling of the
+ * underlying SAX parser.
+ */
+abstract class FactoryAdapter extends DefaultHandler() {
+
+ val buffer = new StringBuilder()
+ val attribStack = new Stack[MetaData]
+ val hStack = new Stack[Node] // [ element ] contains siblings
+ val tagStack = new Stack[String]
+ var scopeStack = new Stack[NamespaceBinding]
+
+ var curTag : String = null
+ var capture: Boolean = false
+
+ // abstract methods
+
+ /** Tests if an XML element contains text.
+ * @return true if element named <code>localName</code> contains text.
+ */
+ def nodeContainsText(localName: String): Boolean // abstract
+
+ /** creates an new non-text(tree) node.
+ * @param elemName
+ * @param attribs
+ * @param chIter
+ * @return a new XML element.
+ */
+ def createNode(pre: String, elemName: String, attribs: MetaData,
+ scope: NamespaceBinding, chIter: List[Node]): Node //abstract
+
+ /** creates a Text node.
+ * @param text
+ * @return a new Text node.
+ */
+ def createText(text: String): Text // abstract
+
+ //
+ // ContentHandler methods
+ //
+
+ val normalizeWhitespace = false
+
+ /** Characters.
+ * @param ch
+ * @param offset
+ * @param length
+ */
+ override def characters(ch: Array[Char], offset: Int, length: Int): Unit = {
+ if (capture) {
+ if (normalizeWhitespace) {
+ // normalizing whitespace is not compliant, but useful */
+ var i: Int = offset
+ var ws = false
+ while (i < offset + length) {
+ if (ch(i).isWhitespace) {
+ if (!ws) {
+ buffer.append(' ')
+ ws = true
+ }
+ } else {
+ buffer.append(ch(i))
+ ws = false
+ }
+ i = i + 1
+ }
+ } else { // compliant:report every character
+ buffer.append(ch, offset, length)
+ }
+ }
+ }
+
+ //var elemCount = 0; //STATISTICS
+
+ /* ContentHandler methods */
+
+ /* Start prefix mapping - use default impl.
+ def startPrefixMapping( prefix:String , uri:String ):Unit = {}
+ */
+
+ /* Start element. */
+ override def startElement(uri: String, _localName: String,
+ qname: String, attributes: Attributes): Unit = {
+ /*elemCount = elemCount + 1; STATISTICS */
+ captureText()
+ //Console.println("FactoryAdapter::startElement("+uri+","+_localName+","+qname+","+attributes+")");
+ tagStack.push(curTag)
+ curTag = qname; //localName ;
+
+ val colon = qname.indexOf(':'.asInstanceOf[Int])
+ val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length())
+
+ //Console.println("FactoryAdapter::startElement - localName ="+localName);
+
+ capture = nodeContainsText(localName)
+
+ hStack.push(null)
+ var m: MetaData = Null
+
+ var scpe = scopeStack.top
+ for (val i <- List.range(0, attributes.getLength())) {
+ //val attrType = attributes.getType(i); // unused for now
+ val qname = attributes.getQName(i)
+ val value = attributes.getValue(i)
+ val colon = qname.indexOf(':'.asInstanceOf[Int])
+ if (-1 != colon) { // prefixed attribute
+ val pre = qname.substring(0, colon)
+ val key = qname.substring(colon+1, qname.length())
+ if ("xmlns" /*XML.xmlns*/ == pre)
+ scpe = value.length() match {
+ case 0 => new NamespaceBinding(key, null, scpe)
+ case _ => new NamespaceBinding(key, value, scpe)
+ }
+ else
+ m = new PrefixedAttribute(pre, key, value, m)
+ } else if ("xmlns" /*XML.xmlns*/ == qname)
+ scpe = value.length() match {
+ case 0 => new NamespaceBinding(null, null, scpe)
+ case _ => new NamespaceBinding(null, value, scpe)
+ }
+ else
+ m = new UnprefixedAttribute(qname, value, m)
+ }
+ scopeStack.push(scpe)
+ attribStack.push(m)
+ {}
+ } // startElement(String,String,String,Attributes)
+
+
+ /** captures text, possibly normalizing whitespace
+ */
+ def captureText(): Unit = {
+ if (capture) {
+ val text = buffer.toString()
+ if (text.length() > 0 && !text.equals(" ")) {
+ hStack.push(createText(text))
+ }
+ }
+ buffer.setLength(0)
+ }
+
+ /** End element.
+ * @param uri
+ * @param localName
+ * @param qname
+ * @throws org.xml.sax.SAXException if ..
+ */
+ override def endElement(uri: String , _localName: String , qname: String): Unit = {
+ captureText()
+
+ val metaData = attribStack.pop
+
+ // reverse order to get it right
+ var v: List[Node] = Nil
+ var child: Node = hStack.pop
+ while (child ne null) {
+ v = child::v
+ child = hStack.pop
+ }
+
+ val colon = qname.indexOf(':'.asInstanceOf[Int])
+ val localName =
+ if (-1 == colon) qname
+ else qname.substring(colon+1, qname.length())
+
+ val scp = scopeStack.pop
+ // create element
+ val pre = if (-1 == colon) null else qname.substring(0, colon)
+ rootElem = createNode(pre, localName, metaData, scp, v)
+
+ hStack.push(rootElem)
+
+ // set
+ curTag = tagStack.pop
+
+ capture =
+ if (curTag ne null) nodeContainsText(curTag) // root level
+ else false
+ } // endElement(String,String,String)
+
+ //
+ // ErrorHandler methods
+ //
+
+ /** Warning.*/
+ override def warning(ex: SAXParseException): Unit = {
+ // ignore warning, crimson warns even for entity resolution!
+ //printError("Warning", ex);
+ }
+
+ /** Error. */
+ override def error(ex: SAXParseException): Unit =
+ printError("Error", ex)
+
+ /** Fatal error.*/
+ override def fatalError(ex: SAXParseException): Unit =
+ printError("Fatal Error", ex)
+
+ //
+ // Protected methods
+ //
+
+ /** Prints the error message */
+ protected def printError(errtype: String, ex: SAXParseException): Unit =
+ Console.withOut(Console.err) {
+ Console.print("[")
+ Console.print(errtype)
+ Console.print("] ")
+
+ var systemId = ex.getSystemId()
+ if (systemId ne null) {
+ val index = systemId.lastIndexOf('/'.asInstanceOf[Int])
+ if (index != -1)
+ systemId = systemId.substring(index + 1)
+ //Console.print(systemId)
+ }
+
+ Console.print(':')
+ Console.print(ex.getLineNumber())
+ Console.print(':')
+ Console.print(ex.getColumnNumber())
+ Console.print(": ")
+ Console.print(ex.getMessage())
+ Console.println
+ Console.flush
+ }
+
+ var rootElem: Node = null:Node
+
+ //FactoryAdapter
+ // MAIN
+ //
+
+ /** load XML document
+ * @param source
+ * @return a new XML document object
+ */
+ def loadXML(source: InputSource): Node = {
+ // create parser
+ val parser: SAXParser = try {
+ val f = SAXParserFactory.newInstance()
+ f.setNamespaceAware(false)
+ f.newSAXParser()
+ } catch {
+ case e: Exception =>
+ Console.err.println("error: Unable to instantiate parser")
+ exit(1)
+ }
+
+ // parse file
+ //try {
+ //Console.err.println("[parsing \"" + source + "\"]");
+ scopeStack.push(TopScope)
+ parser.parse(source, this)
+ scopeStack.pop
+ /*
+ } catch {
+ case ( e:SAXParseException ) => {
+ // ignore
+ }
+ case ( e:Exception ) => {
+ Console.err.println("error: Parse error occurred - " + e.getMessage());
+ if (e.isInstanceOf[ SAXException ]) {
+ (e.asInstanceOf[ SAXException ])
+ .getException()
+ .printStackTrace( System.err );
+ } else {
+ e.printStackTrace(System.err);
+ }
+ }
+ } // catch
+*/
+ //Console.err.println("[FactoryAdapter: total #elements = "+elemCount+"]");
+ rootElem
+ } // loadXML
+
+ /** loads XML from given file */
+ def loadFile(file: File): Node =
+ loadXML(new InputSource(new FileInputStream(file)))
+
+ /** loads XML from given file descriptor */
+ def loadFile(fileDesc: FileDescriptor): Node =
+ loadXML(new InputSource(new FileInputStream(fileDesc)))
+
+ /** loads XML from given file */
+ def loadFile(fileName: String): Node =
+ loadXML(new InputSource(new FileInputStream(fileName)))
+
+ /** loads XML from given InputStream */
+ def load(is: InputStream): Node =
+ loadXML(new InputSource(is))
+
+ /** loads XML from given Reader */
+ def load(reader: Reader): Node =
+ loadXML(new InputSource(reader))
+
+ /** loads XML from given sysID */
+ def load(sysID: String): Node =
+ loadXML(new InputSource(sysID))
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/FatalError.scala b/src/dotnet-library/scala/xml/parsing/FatalError.scala
new file mode 100644
index 0000000000..2768becb8b
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/FatalError.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+
+case class FatalError(msg:String) extends java.lang.RuntimeException(msg);
diff --git a/src/dotnet-library/scala/xml/parsing/MarkupHandler.scala b/src/dotnet-library/scala/xml/parsing/MarkupHandler.scala
new file mode 100644
index 0000000000..5d7577d752
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/MarkupHandler.scala
@@ -0,0 +1,161 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing
+
+import scala.collection.mutable.{HashMap, Map}
+import scala.io.Source
+import scala.xml.dtd._
+import scala.util.logging.Logged
+
+/** class that handles markup - provides callback methods to MarkupParser.
+ * the default is nonvalidating behaviour
+ *
+ * @author Burak Emir
+ * @version 1.0
+ *
+ * @todo can we ignore more entity declarations (i.e. those with extIDs)?
+ * @todo expanding entity references
+ */
+abstract class MarkupHandler extends AnyRef with Logged {
+
+ // impl. of Logged
+ //def log(msg:String) = {}
+
+ /** returns true is this markup handler is validing */
+ val isValidating: Boolean = false
+
+ var decls: List[Decl] = Nil
+
+ var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]()
+
+ def lookupElemDecl(Label: String): ElemDecl = {
+ def lookup(xs:List[Decl]): ElemDecl = xs match {
+ case (z @ ElemDecl(Label, _)) :: zs => return z
+ case _::zs => lookup(zs)
+ case _ => return null
+ }
+ lookup(decls)
+ }
+
+ def replacementText(entityName: String): Source = ent.get(entityName) match {
+ case Some(ParsedEntityDecl(_, IntDef(value))) =>
+ Source.fromString(value)
+ case Some(ParameterEntityDecl(_, IntDef(value))) =>
+ Source.fromString(" "+value+" ")
+ case Some(_) =>
+ Source.fromString("<!-- "+entityName+"; -->")
+ case None =>
+ Source.fromString("<!-- unknown entity "+entityName+"; -->")
+ }
+
+ //def checkChildren(pos:int, pre: String, label:String,ns:NodeSeq): Unit = {}
+
+ def endDTD(n:String): Unit = {}
+
+ /** callback method invoked by MarkupParser after start-tag of element.
+ *
+ * @param pos the position in the sourcefile
+ * @param pre the prefix
+ * @param label the local name
+ * @param attrs the attributes (metadata)
+ */
+ def elemStart(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding): Unit = {}
+
+ /** callback method invoked by MarkupParser after end-tag of element.
+ *
+ * @param pos the position in the source file
+ * @param pre the prefix
+ * @param label the local name
+ * @param attrs the attributes (metadata)
+ */
+ def elemEnd(pos: int, pre: String, label: String): Unit = {}
+
+ /** callback method invoked by MarkupParser after parsing an elementm,
+ * between the elemStart and elemEnd callbacks
+ *
+ * @param pos the position in the source file
+ * @param pre the prefix
+ * @param label the local name
+ * @param attrs the attributes (metadata)
+ * @param args the children of this element
+ * @return ...
+ */
+ def elem(pos: int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, args: NodeSeq): NodeSeq
+
+ /** callback method invoked by MarkupParser after parsing PI.
+ *
+ * @param pos the position in the source file
+ * @param target ...
+ * @param txt ...
+ * @return ...
+ */
+ def procInstr(pos: Int, target: String, txt: String): NodeSeq
+
+ /** callback method invoked by MarkupParser after parsing comment.
+ *
+ * @param pos the position in the source file
+ * @param comment ...
+ * @return ...
+ */
+ def comment(pos: Int, comment: String): NodeSeq
+
+ /** callback method invoked by MarkupParser after parsing entity ref.
+ * @todo expanding entity references
+ */
+ def entityRef(pos: Int, n: String): NodeSeq
+
+ /** callback method invoked by MarkupParser after parsing text.
+ */
+ def text(pos: Int, txt: String): NodeSeq
+
+ // DTD handler methods
+
+ def elemDecl(n: String, cmstr: String): Unit = {}
+
+ def attListDecl(name: String, attList: List[AttrDecl]): Unit = {}
+
+ def parameterEntityDecl(name: String, edef: EntityDef): Unit = {
+ //log("parameterEntityDecl("+name+","+edef+")");
+ edef match {
+ case _:ExtDef if !isValidating =>
+ ; // ignore (cf REC-xml 4.4.1)
+ case _ =>
+ val y = ParameterEntityDecl(name, edef)
+ decls = y :: decls
+ ent.update(name, y)
+ //log("ent.get(..) = "+ent.get(name))
+ }
+ }
+
+ def parsedEntityDecl(name: String, edef: EntityDef): Unit = edef match {
+ case _:ExtDef if !isValidating =>
+ ; // ignore (cf REC-xml 4.8 and 4.4.1)
+ case _ =>
+ val y = ParsedEntityDecl(name, edef)
+ decls = y :: decls
+ ent.update(name, y)
+ }
+
+ def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit =
+ {}
+
+ def notationDecl(notat: String, extID: ExternalID): Unit =
+ {}
+
+ def peReference(name: String): Unit =
+ decls = PEReference( name ) :: decls
+
+ /** report a syntax error */
+ def reportSyntaxError(pos: Int, str: String): Unit
+
+}
+
diff --git a/src/dotnet-library/scala/xml/parsing/MarkupParser.scala b/src/dotnet-library/scala/xml/parsing/MarkupParser.scala
new file mode 100644
index 0000000000..e1813fdac5
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/MarkupParser.scala
@@ -0,0 +1,1213 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing
+
+import compat.StringBuilder
+import scala.io.Source
+import scala.xml.dtd._
+
+/**
+ * An XML parser.
+ *
+ * Parses XML 1.0, invokes callback methods of a MarkupHandler
+ * and returns whatever the markup handler returns. Use
+ * <code>ConstructingParser</code> if you just want to parse XML to
+ * construct instances of <code>scala.xml.Node</code>.
+ *
+ * While XML elements are returned, DTD declarations - if handled - are
+ * collected using side-effects.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+trait MarkupParser requires (MarkupParser with MarkupHandler) extends AnyRef with TokenTests {
+
+ val input: Source
+
+ /** if true, does not remove surplus whitespace */
+ val preserveWS: Boolean
+
+ def externalSource(systemLiteral: String): Source
+
+ //
+ // variables, values
+ //
+
+ var curInput: Source = input
+
+ /** the handler of the markup, returns this */
+ private val handle: MarkupHandler = this
+
+ /** stack of inputs */
+ var inpStack: List[Source] = Nil
+
+ /** holds the position in the source file */
+ var pos: Int = _
+
+
+ /* used when reading external subset */
+ var extIndex = -1
+
+ /** holds temporary values of pos */
+ var tmppos: Int = _
+
+ /** holds the next character */
+ var ch: Char = _
+
+ /** character buffer, for names */
+ protected val cbuf = new StringBuilder()
+
+ var dtd: DTD = null
+
+ protected var doc: Document = null
+
+ var eof: Boolean = false
+
+ //
+ // methods
+ //
+
+ /** &lt;? prolog ::= xml S ... ?&gt;
+ */
+ def xmlProcInstr(): MetaData = {
+ xToken("xml")
+ xSpace
+ val Pair(md,scp) = xAttributes(TopScope)
+ if (scp != TopScope)
+ reportSyntaxError("no xmlns definitions here, please.");
+ xToken('?')
+ xToken('>')
+ md
+ }
+
+ /** &lt;? prolog ::= xml S
+ * // this is a bit more lenient than necessary...
+ */
+ def prolog(): Tuple3[Option[String], Option[String], Option[Boolean]] = {
+
+ //Console.println("(DEBUG) prolog")
+ var n = 0
+ var info_ver: Option[String] = None
+ var info_enc: Option[String] = None
+ var info_stdl: Option[Boolean] = None
+
+ var m = xmlProcInstr()
+
+ xSpace
+
+ m("version") match {
+ case null => ;
+ case Text("1.0") => info_ver = Some("1.0"); n = n + 1
+ case _ => reportSyntaxError("cannot deal with versions != 1.0")
+ }
+
+ m("encoding") match {
+ case null => ;
+ case Text(enc) =>
+ if (!isValidIANAEncoding(enc.toString()))
+ reportSyntaxError("\"" + enc + "\" is not a valid encoding")
+ else {
+ info_enc = Some(enc.toString())
+ n = n + 1
+ }
+ }
+ m("standalone") match {
+ case null => ;
+ case Text("yes") => info_stdl = Some(true); n = n + 1
+ case Text("no") => info_stdl = Some(false); n = n + 1
+ case _ => reportSyntaxError("either 'yes' or 'no' expected")
+ }
+
+ if (m.length - n != 0) {
+ reportSyntaxError("VersionInfo EncodingDecl? SDDecl? or '?>' expected!");
+ }
+ //Console.println("[MarkupParser::prolog] finished parsing prolog!");
+ Tuple3(info_ver,info_enc,info_stdl)
+ }
+
+ /** prolog, but without standalone */
+ def textDecl(): Tuple2[Option[String],Option[String]] = {
+
+ var info_ver: Option[String] = None
+ var info_enc: Option[String] = None
+
+ var m = xmlProcInstr()
+ var n = 0
+
+ m("version") match {
+ case null => ;
+ case Text("1.0") => info_ver = Some("1.0"); n = n + 1
+ case _ => reportSyntaxError("cannot deal with versions != 1.0")
+ }
+
+ m("encoding") match {
+ case null => ;
+ case Text(enc) =>
+ if (!isValidIANAEncoding(enc.toString()))
+ reportSyntaxError("\"" + enc + "\" is not a valid encoding")
+ else {
+ info_enc = Some(enc.toString())
+ n = n + 1
+ }
+ }
+
+ if (m.length - n != 0) {
+ reportSyntaxError("VersionInfo EncodingDecl? or '?>' expected!");
+ }
+ //Console.println("[MarkupParser::textDecl] finished parsing textdecl");
+ Tuple2(info_ver, info_enc);
+ }
+
+ /**
+ *[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
+ *[23] XMLDecl ::= '&lt;?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+ *[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
+ *[25] Eq ::= S? '=' S?
+ *[26] VersionNum ::= '1.0'
+ *[27] Misc ::= Comment | PI | S
+ */
+
+ def document(): Document = {
+
+ //Console.println("(DEBUG) document")
+ doc = new Document()
+
+ this.dtd = null
+ var info_prolog: Tuple3[Option[String], Option[String], Option[Boolean]] = Tuple3(None, None, None);
+ if ('<' != ch) {
+ reportSyntaxError("< expected")
+ return null
+ }
+
+ nextch // is prolog ?
+ var children: NodeSeq = null
+ if ('?' == ch) {
+ //Console.println("[MarkupParser::document] starts with xml declaration");
+ nextch;
+ info_prolog = prolog()
+ doc.version = info_prolog._1
+ doc.encoding = info_prolog._2
+ doc.standAlone = info_prolog._3
+
+ children = content(TopScope) // DTD handled as side effect
+ } else {
+ //Console.println("[MarkupParser::document] does not start with xml declaration");
+ //
+
+ val ts = new NodeBuffer();
+ content1(TopScope, ts); // DTD handled as side effect
+ ts &+ content(TopScope);
+ children = NodeSeq.fromSeq(ts);
+ }
+ //Console.println("[MarkupParser::document] children now: "+children.toList);
+ var elemCount = 0;
+ var theNode: Node = null;
+ for (val c <- children) c match {
+ case _:ProcInstr => ;
+ case _:Comment => ;
+ case _:EntityRef => // todo: fix entities, shouldn't be "special"
+ reportSyntaxError("no entity references alllowed here");
+ case s:SpecialNode =>
+ if(s.toString().trim().length() > 0) //non-empty text nodes not allowed
+ elemCount = elemCount + 2;
+ case m:Node =>
+ elemCount = elemCount + 1;
+ theNode = m;
+ }
+ if (1 != elemCount) {
+ reportSyntaxError("document must contain exactly one element")
+ Console.println(children.toList)
+ }
+
+ doc.children = children
+ doc.docElem = theNode
+ doc
+ }
+
+ /** append Unicode character to name buffer*/
+ protected def putChar(c: Char) = cbuf.append(c)
+
+ //var xEmbeddedBlock = false;
+
+ /** this method assign the next character to ch and advances in input */
+ def nextch: Unit = {
+ if (curInput.hasNext) {
+ ch = curInput.next
+ pos = curInput.pos
+ } else {
+ val ilen = inpStack.length;
+ //Console.println(" ilen = "+ilen+ " extIndex = "+extIndex);
+ if ((ilen != extIndex) && (ilen > 0)) {
+ /** for external source, inpStack == Nil ! need notify of eof! */
+ pop()
+ } else {
+ eof = true
+ ch = 0.asInstanceOf[Char]
+ }
+ }
+ }
+
+ //final val enableEmbeddedExpressions: Boolean = false;
+
+ /** munch expected XML token, report syntax error for unexpected
+ */
+ def xToken(that: Char): Unit = {
+ if (ch == that)
+ nextch
+ else {
+ reportSyntaxError("'" + that + "' expected instead of '" + ch + "'")
+ error("FATAL")
+ }
+ }
+
+ def xToken(that: Seq[Char]): Unit = {
+ val it = that.elements;
+ while (it.hasNext)
+ xToken(it.next);
+ }
+
+ /** parse attribute and create namespace scope, metadata
+ * [41] Attributes ::= { S Name Eq AttValue }
+ */
+ def xAttributes(pscope:NamespaceBinding): Pair[MetaData,NamespaceBinding] = {
+ var scope: NamespaceBinding = pscope
+ var aMap: MetaData = Null
+ while (isNameStart(ch)) {
+ val pos = this.pos
+
+ val qname = xName
+ val _ = xEQ
+ val value = xAttributeValue()
+
+ Utility.prefix(qname) match {
+ case Some("xmlns") =>
+ val prefix = qname.substring(6 /*xmlns:*/ , qname.length());
+ scope = new NamespaceBinding(prefix, value, scope);
+
+ case Some(prefix) =>
+ val key = qname.substring(prefix.length()+1, qname.length());
+ aMap = new PrefixedAttribute(prefix, key, value, aMap);
+
+ case _ =>
+ if( qname == "xmlns" )
+ scope = new NamespaceBinding(null, value, scope);
+ else
+ aMap = new UnprefixedAttribute(qname, value, aMap);
+ }
+
+ if ((ch != '/') && (ch != '>') && ('?' != ch))
+ xSpace;
+ }
+
+ if(!aMap.wellformed(scope))
+ reportSyntaxError( "double attribute");
+
+ Pair(aMap,scope)
+ }
+
+ /** attribute value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def xAttributeValue(): String = {
+ val endch = ch
+ nextch
+ while (ch != endch) {
+ if ('<' == ch)
+ reportSyntaxError( "'<' not allowed in attrib value" );
+ putChar(ch)
+ nextch
+ }
+ nextch
+ val str = cbuf.toString()
+ cbuf.setLength(0)
+
+ // well-formedness constraint
+ normalizeAttributeValue(str)
+ }
+
+ /** entity value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def xEntityValue(): String = {
+ val endch = ch
+ nextch
+ while (ch != endch) {
+ putChar(ch)
+ nextch
+ }
+ nextch
+ val str = cbuf.toString()
+ cbuf.setLength(0)
+ str
+ }
+
+
+ /** parse a start or empty tag.
+ * [40] STag ::= '&lt;' Name { S Attribute } [S]
+ * [44] EmptyElemTag ::= '&lt;' Name { S Attribute } [S]
+ */
+ protected def xTag(pscope:NamespaceBinding): Tuple3[String, MetaData, NamespaceBinding] = {
+ val qname = xName
+
+ xSpaceOpt
+ val Pair(aMap: MetaData, scope: NamespaceBinding) = {
+ if (isNameStart(ch))
+ xAttributes(pscope)
+ else
+ Pair(Null, pscope)
+ }
+ Triple(qname, aMap, scope)
+ }
+
+ /** [42] '&lt;' xmlEndTag ::= '&lt;' '/' Name S? '&gt;'
+ */
+ def xEndTag(n: String) = {
+ xToken('/')
+ val m = xName
+ if (n != m)
+ reportSyntaxError("expected closing tag of " + n/* +", not "+m*/);
+ xSpaceOpt
+ xToken('>')
+ }
+
+ /** '&lt;! CharData ::= [CDATA[ ( {char} - {char}"]]&gt;"{char} ) ']]&gt;'
+ *
+ * see [15]
+ */
+ def xCharData: NodeSeq = {
+ xToken("[CDATA[")
+ val pos1 = pos
+ val sb: StringBuilder = new StringBuilder()
+ while (true) {
+ if (ch==']' &&
+ { sb.append(ch); nextch; ch == ']' } &&
+ { sb.append(ch); nextch; ch == '>' } ) {
+ sb.setLength(sb.length() - 2);
+ nextch;
+ return handle.text( pos1, sb.toString() );
+ } else sb.append( ch );
+ nextch;
+ }
+ throw FatalError("this cannot happen");
+ };
+
+ /** CharRef ::= "&amp;#" '0'..'9' {'0'..'9'} ";"
+ * | "&amp;#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";"
+ *
+ * see [66]
+ */
+ def xCharRef(ch: () => Char, nextch: () => Unit): String = {
+ Utility.parseCharRef(ch, nextch, &reportSyntaxError)
+ /*
+ val hex = (ch() == 'x') && { nextch(); true };
+ val base = if (hex) 16 else 10;
+ var i = 0;
+ while (ch() != ';') {
+ ch() match {
+ case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
+ i = i * base + Character.digit( ch(), base );
+ case 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
+ | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' =>
+ if (! hex)
+ reportSyntaxError("hex char not allowed in decimal char ref\n"
+ +"Did you mean to write &#x ?");
+ else
+ i = i * base + Character.digit(ch(), base);
+ case _ =>
+ reportSyntaxError("character '" + ch() + " not allowed in char ref\n");
+ }
+ nextch();
+ }
+ new String(Array(i.asInstanceOf[char]))
+ */
+ }
+
+
+ /** Comment ::= '&lt;!--' ((Char - '-') | ('-' (Char - '-')))* '--&gt;'
+ *
+ * see [15]
+ */
+ def xComment: NodeSeq = {
+ val sb: StringBuilder = new StringBuilder();
+ xToken('-');
+ xToken('-');
+ while (true) {
+ if (ch == '-' && { sb.append(ch); nextch; ch == '-' }) {
+ sb.setLength(sb.length() - 1);
+ nextch;
+ xToken('>');
+ return handle.comment(pos, sb.toString());
+ } else sb.append(ch);
+ nextch;
+ }
+ throw FatalError("this cannot happen");
+ };
+
+ /* todo: move this into the NodeBuilder class */
+ def appendText(pos: Int, ts: NodeBuffer, txt: String): Unit = {
+ if (preserveWS)
+ ts &+ handle.text(pos, txt);
+ else
+ for (val t <- TextBuffer.fromString(txt).toText) {
+ ts &+ handle.text(pos, t.text);
+ }
+ }
+
+ /** '&lt;' content1 ::= ... */
+ def content1(pscope: NamespaceBinding, ts: NodeBuffer): Unit =
+ ch match {
+ case '!' =>
+ nextch
+ if ('[' == ch) // CDATA
+ ts &+ xCharData
+ else if ('D' == ch) // doctypedecl, parse DTD // @todo REMOVE HACK
+ parseDTD()
+ else // comment
+ ts &+ xComment
+ case '?' => // PI
+ nextch
+ ts &+ xProcInstr
+ case _ =>
+ ts &+ element1(pscope) // child
+ }
+
+ /** content1 ::= '&lt;' content1 | '&amp;' charref ... */
+ def content(pscope: NamespaceBinding): NodeSeq = {
+ var ts = new NodeBuffer
+ var exit = eof
+ while (! exit) {
+ //Console.println("in content, ch = '"+ch+"' line="+scala.io.Position.line(pos));
+ /* if( xEmbeddedBlock ) {
+ ts.append( xEmbeddedExpr );
+ } else {*/
+ tmppos = pos;
+ exit = eof;
+ if(!eof)
+ ch match {
+ case '<' => // another tag
+ //Console.println("before ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos);
+ nextch;
+ //Console.println("after ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos);
+
+ if('/' ==ch)
+ exit = true; // end tag
+ else
+ content1(pscope, ts)
+ //case '{' =>
+/* if( xCheckEmbeddedBlock ) {
+ ts.appendAll(xEmbeddedExpr);
+ } else {*/
+ // val str = new StringBuilder("{");
+ // str.append(xText);
+ // appendText(tmppos, ts, str.toString());
+ /*}*/
+ // postcond: xEmbeddedBlock == false!
+ case '&' => // EntityRef or CharRef
+ nextch;
+ ch match {
+ case '#' => // CharacterRef
+ nextch;
+ val theChar = handle.text( tmppos,
+ xCharRef ({ ()=> ch },{ () => nextch }) );
+ xToken(';');
+ ts &+ theChar ;
+ case _ => // EntityRef
+ val n = xName
+ xToken(';')
+ n match {
+ case "lt" => ts &+ '<'
+ case "gt" => ts &+ '>'
+ case "amp" => ts &+ '&'
+ case "quote" => ts &+ '"'
+ case _ =>
+ /*
+ ts + handle.entityRef( tmppos, n ) ;
+ */
+ push(n)
+ }
+ }
+ case _ => // text content
+ //Console.println("text content?? pos = "+pos);
+ appendText(tmppos, ts, xText);
+ // here xEmbeddedBlock might be true
+ }
+ /*}*/
+ }
+ val list = ts.toList
+ // 2do: optimize seq repr.
+ new NodeSeq {
+ val theSeq = list
+ }
+ } // content(NamespaceBinding)
+
+ /** externalID ::= SYSTEM S syslit
+ * PUBLIC S pubid S syslit
+ */
+
+ def externalID(): ExternalID = ch match {
+ case 'S' =>
+ nextch
+ xToken("YSTEM")
+ xSpace
+ val sysID = systemLiteral()
+ new SystemID(sysID)
+ case 'P' =>
+ nextch; xToken("UBLIC")
+ xSpace
+ val pubID = pubidLiteral()
+ xSpace
+ val sysID = systemLiteral()
+ new PublicID(pubID, sysID)
+ }
+
+
+ /** parses document type declaration and assigns it to instance variable
+ * dtd.
+ *
+ * &lt;! parseDTD ::= DOCTYPE name ... >
+ */
+ def parseDTD(): Unit = { // dirty but fast
+ //Console.println("(DEBUG) parseDTD");
+ var extID: ExternalID = null
+ if (this.dtd ne null)
+ reportSyntaxError("unexpected character (DOCTYPE already defined");
+ xToken("DOCTYPE")
+ xSpace
+ val n = xName
+ xSpace
+ //external ID
+ if ('S' == ch || 'P' == ch) {
+ extID = externalID()
+ xSpaceOpt
+ }
+
+ /* parse external subset of DTD
+ */
+
+ if ((null != extID) && isValidating) {
+
+ pushExternal(extID.systemId)
+ //val extSubsetSrc = externalSource( extID.systemId );
+
+ extIndex = inpStack.length
+ /*
+ .indexOf(':') != -1) { // assume URI
+ Source.fromFile(new java.net.URI(extID.systemLiteral));
+ } else {
+ Source.fromFile(extID.systemLiteral);
+ }
+ */
+ //Console.println("I'll print it now");
+ //val old = curInput;
+ //tmppos = curInput.pos;
+ //val oldch = ch;
+ //curInput = extSubsetSrc;
+ //pos = 0;
+ //nextch;
+
+ extSubset()
+
+ pop()
+
+ extIndex = -1
+
+ //curInput = old;
+ //pos = curInput.pos;
+ //ch = curInput.ch;
+ //eof = false;
+ //while(extSubsetSrc.hasNext)
+ //Console.print(extSubsetSrc.next);
+
+ //Console.println("returned from external, current ch = "+ch )
+ }
+
+ if ('[' == ch) { // internal subset
+ nextch
+ /* TODO */
+ //Console.println("hello");
+ intSubset()
+ //while(']' != ch)
+ // nextch;
+ // TODO: do the DTD parsing?? ?!?!?!?!!
+ xToken(']')
+ xSpaceOpt
+ }
+ xToken('>')
+ this.dtd = new DTD {
+ /*override var*/ externalID = extID
+ /*override val */decls = handle.decls.reverse
+ }
+ //this.dtd.initializeEntities();
+ if (doc ne null)
+ doc.dtd = this.dtd
+
+ handle.endDTD(n)
+ }
+
+ def element(pscope: NamespaceBinding): NodeSeq = {
+ xToken('<')
+ element1(pscope)
+ }
+
+ /** '&lt;' element ::= xmlTag1 '&gt;' { xmlExpr | '{' simpleExpr '}' } ETag
+ * | xmlTag1 '/' '&gt;'
+ */
+ def element1(pscope: NamespaceBinding): NodeSeq = {
+ val pos = this.pos
+ val Tuple3(qname, aMap, scope) = xTag(pscope)
+ val Tuple2(pre, local) = Utility.prefix(qname) match {
+ case Some(p) => Pair(p,qname.substring(p.length()+1, qname.length()))
+ case _ => Pair(null,qname)
+ }
+ val ts = {
+ if (ch == '/') { // empty element
+ xToken('/')
+ xToken('>')
+ handle.elemStart(pos, pre, local, aMap, scope)
+ NodeSeq.Empty
+ }
+ else { // element with content
+ xToken('>')
+ handle.elemStart(pos, pre, local, aMap, scope)
+ val tmp = content(scope)
+ xEndTag(qname)
+ tmp
+ }
+ }
+ val res = handle.elem(pos, pre, local, aMap, scope, ts)
+ handle.elemEnd(pos, pre, local)
+ res
+ }
+
+ //def xEmbeddedExpr: MarkupType;
+
+ /** Name ::= (Letter | '_' | ':') (NameChar)*
+ *
+ * see [5] of XML 1.0 specification
+ */
+ def xName: String = {
+ if (isNameStart(ch)) {
+ while (isNameChar(ch)) {
+ putChar(ch)
+ nextch
+ }
+ val n = cbuf.toString().intern()
+ cbuf.setLength(0)
+ n
+ } else {
+ reportSyntaxError("name expected")
+ new String()
+ }
+ }
+
+ /** scan [S] '=' [S]*/
+ def xEQ = { xSpaceOpt; xToken('='); xSpaceOpt }
+
+ /** skip optional space S? */
+ def xSpaceOpt = while (isSpace(ch) && !eof) { nextch; }
+
+ /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
+ def xSpace =
+ if (isSpace(ch)) { nextch; xSpaceOpt }
+ else reportSyntaxError("whitespace expected")
+
+ /** '&lt;?' ProcInstr ::= Name [S ({Char} - ({Char}'&gt;?' {Char})]'?&gt;'
+ *
+ * see [15]
+ */
+ def xProcInstr: NodeSeq = {
+ val sb:StringBuilder = new StringBuilder()
+ val n = xName
+ if (isSpace(ch)) {
+ xSpace
+ while (true) {
+ if (ch == '?' && { sb.append( ch ); nextch; ch == '>' }) {
+ sb.setLength(sb.length() - 1);
+ nextch;
+ return handle.procInstr(tmppos, n.toString(), sb.toString());
+ } else
+ sb.append(ch);
+ nextch
+ }
+ };
+ xToken('?')
+ xToken('>')
+ handle.procInstr(tmppos, n.toString(), sb.toString())
+ }
+
+ /** parse character data.
+ * precondition: xEmbeddedBlock == false (we are not in a scala block)
+ */
+ def xText: String = {
+ //if( xEmbeddedBlock ) throw FatalError("internal error: encountered embedded block"); // assert
+
+ /*if( xCheckEmbeddedBlock )
+ return ""
+ else {*/
+ //Console.println("in xText! ch = '"+ch+"'");
+ var exit = false;
+ while (! exit) {
+ //Console.println("LOOP in xText! ch = '"+ch+"' + pos="+pos);
+ putChar(ch);
+ val opos = pos;
+ nextch;
+
+ //Console.println("STILL LOOP in xText! ch = '"+ch+"' + pos="+pos+" opos="+opos);
+
+
+ exit = eof || /*{ nextch; xCheckEmbeddedBlock }||*/( ch == '<' ) || ( ch == '&' );
+ }
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+ str
+ /*}*/
+ }
+
+ /** attribute value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def systemLiteral(): String = {
+ val endch = ch
+ if (ch != '\'' && ch != '"')
+ reportSyntaxError("quote ' or \" expected");
+ nextch
+ while (ch != endch) {
+ putChar(ch)
+ nextch
+ }
+ nextch
+ val str = cbuf.toString()
+ cbuf.setLength(0)
+ str
+ }
+
+
+ /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" */
+ def pubidLiteral(): String = {
+ val endch = ch
+ if (ch!='\'' && ch != '"')
+ reportSyntaxError("quote ' or \" expected");
+ nextch
+ while (ch != endch) {
+ putChar(ch)
+ //Console.println("hello '"+ch+"'"+isPubIDChar(ch));
+ if (!isPubIDChar(ch))
+ reportSyntaxError("char '"+ch+"' is not allowed in public id");
+ nextch
+ }
+ nextch
+ val str = cbuf.toString()
+ cbuf.setLength(0)
+ str
+ }
+
+ //
+ // dtd parsing
+ //
+
+ def extSubset(): Unit = {
+ var textdecl:Tuple2[Option[String],Option[String]] = null;
+ if (ch=='<') {
+ nextch
+ if (ch=='?') {
+ nextch
+ textdecl = textDecl()
+ } else
+ markupDecl1()
+ }
+ while (!eof)
+ markupDecl()
+ }
+
+ def markupDecl1() = {
+ def doInclude() = {
+ xToken('['); while(']' != ch) markupDecl(); nextch // ']'
+ }
+ def doIgnore() = {
+ xToken('['); while(']' != ch) nextch; nextch; // ']'
+ }
+ if ('?' == ch) {
+ nextch
+ xProcInstr // simply ignore processing instructions!
+ } else {
+ xToken('!')
+ ch match {
+ case '-' =>
+ xComment // ignore comments
+
+ case 'E' =>
+ nextch
+ if ('L' == ch) {
+ nextch
+ elementDecl()
+ } else
+ entityDecl()
+
+ case 'A' =>
+ nextch
+ attrDecl()
+
+ case 'N' =>
+ nextch
+ notationDecl()
+
+ case '[' if inpStack.length >= extIndex =>
+ nextch
+ xSpaceOpt
+ ch match {
+ case '%' =>
+ nextch
+ val ent = xName
+ xToken(';')
+ xSpaceOpt
+ /*
+ Console.println("hello, pushing!");
+ {
+ val test = replacementText(ent);
+ while(test.hasNext)
+ Console.print(test.next);
+ } */
+ push(ent)
+ xSpaceOpt
+ //Console.println("hello, getting name");
+ val stmt = xName
+ //Console.println("hello, got name");
+ xSpaceOpt
+ //Console.println("how can we be eof = "+eof);
+
+ // eof = true because not external?!
+ //if(!eof)
+ // error("expected only INCLUDE or IGNORE");
+
+ //pop();
+
+ //Console.println("hello, popped");
+ stmt match {
+ // parameter entity
+ case "INCLUDE" =>
+ doInclude()
+ case "IGNORE" =>
+ doIgnore()
+ }
+ case 'I' =>
+ nextch
+ ch match {
+ case 'G' =>
+ nextch
+ xToken("NORE")
+ xSpaceOpt
+ doIgnore()
+ case 'N' =>
+ nextch
+ xToken("NCLUDE")
+ doInclude()
+ }
+ }
+ xToken(']')
+ xToken('>')
+
+ case _ =>
+ curInput.reportError(pos, "unexpected character '"+ch+"', expected some markupdecl")
+ while (ch!='>')
+ nextch
+ }
+ }
+ }
+
+ def markupDecl(): Unit = ch match {
+ case '%' => // parameter entity reference
+ nextch
+ val ent = xName
+ xToken(';')
+ if (!isValidating)
+ handle.peReference(ent) // n-v: just create PE-reference
+ else
+ push(ent) // v: parse replacementText
+
+ //peReference
+ case '<' =>
+ nextch
+ markupDecl1()
+ case _ if isSpace(ch) =>
+ xSpace
+ case _ =>
+ reportSyntaxError("markupdecl: unexpected character '"+ch+"' #" + ch.asInstanceOf[Int])
+ nextch
+ }
+
+ /** "rec-xml/#ExtSubset" pe references may not occur within markup
+ declarations
+ */
+ def intSubset(): Unit = {
+ //Console.println("(DEBUG) intSubset()")
+ xSpace
+ while (']' != ch)
+ markupDecl()
+ }
+
+ /** &lt;! element := ELEMENT
+ */
+ def elementDecl(): Unit = {
+ xToken("EMENT")
+ xSpace
+ val n = xName
+ xSpace
+ while ('>' != ch) {
+ //Console.println("["+ch+"]")
+ putChar(ch)
+ nextch
+ }
+ //Console.println("END["+ch+"]")
+ nextch
+ val cmstr = cbuf.toString()
+ cbuf.setLength(0)
+ handle.elemDecl(n, cmstr)
+ }
+
+ /** &lt;! attlist := ATTLIST
+ */
+ def attrDecl() = {
+ xToken("TTLIST")
+ xSpace
+ val n = xName
+ xSpace
+ var attList: List[AttrDecl] = Nil
+ // later: find the elemDecl for n
+ while ('>' != ch) {
+ val aname = xName
+ //Console.println("attribute name: "+aname);
+ var defdecl: DefaultDecl = null
+ xSpace
+ // could be enumeration (foo,bar) parse this later :-/
+ while ('"' != ch && '\'' != ch && '#' != ch && '<' != ch) {
+ if (!isSpace(ch))
+ cbuf.append(ch);
+ nextch;
+ }
+ val atpe = cbuf.toString()
+ cbuf.setLength(0)
+ //Console.println("attr type: "+atpe);
+ ch match {
+ case '\'' | '"' =>
+ val defValue = xAttributeValue() // default value
+ defdecl = DEFAULT(false, defValue)
+
+ case '#' =>
+ nextch
+ xName match {
+ case "FIXED" =>
+ xSpace
+ val defValue = xAttributeValue() // default value
+ defdecl = DEFAULT(true, defValue)
+ case "IMPLIED" =>
+ defdecl = IMPLIED
+ case "REQUIRED" =>
+ defdecl = REQUIRED
+ }
+ case _ =>
+ }
+ xSpaceOpt
+
+ attList = AttrDecl(aname, atpe, defdecl) :: attList
+ cbuf.setLength(0)
+ }
+ nextch
+ handle.attListDecl(n, attList.reverse)
+ }
+
+ /** &lt;! element := ELEMENT
+ */
+ def entityDecl() = {
+ //Console.println("entityDecl()")
+ var isParameterEntity = false
+ var entdef: EntityDef = null
+ xToken("NTITY")
+ xSpace
+ if ('%' == ch) {
+ nextch
+ isParameterEntity = true
+ xSpace
+ }
+ val n = xName
+ xSpace
+ ch match {
+ case 'S' | 'P' => //sy
+ val extID = externalID()
+ if (isParameterEntity) {
+ xSpaceOpt
+ xToken('>')
+ handle.parameterEntityDecl(n, ExtDef(extID))
+ } else { // notation?
+ xSpace
+ if ('>' != ch) {
+ xToken("NDATA")
+ xSpace
+ val notat = xName
+ xSpaceOpt
+ xToken('>')
+ handle.unparsedEntityDecl(n, extID, notat)
+ } else {
+ nextch
+ handle.parsedEntityDecl(n, ExtDef(extID))
+ }
+ }
+
+ case '"' | '\'' =>
+ val av = xEntityValue()
+ xSpaceOpt
+ xToken('>')
+ if (isParameterEntity)
+ handle.parameterEntityDecl(n, IntDef(av))
+ else
+ handle.parsedEntityDecl(n, IntDef(av))
+ }
+ {}
+ } // entityDecl
+
+ /** 'N' notationDecl ::= "OTATION"
+ */
+ def notationDecl(): Unit = {
+ xToken("OTATION")
+ xSpace
+ val notat = xName
+ xSpace
+ val extID = if (ch == 'S') {
+ externalID();
+ }
+ else if (ch == 'P') {
+ /** PublicID (without system, only used in NOTATION) */
+ nextch
+ xToken("UBLIC")
+ xSpace
+ val pubID = pubidLiteral()
+ xSpaceOpt
+ val sysID = if (ch != '>')
+ systemLiteral()
+ else
+ null;
+ new PublicID(pubID, sysID);
+ } else {
+ reportSyntaxError("PUBLIC or SYSTEM expected");
+ error("died parsing notationdecl")
+ }
+ xSpaceOpt
+ xToken('>')
+ handle.notationDecl(notat, extID)
+ }
+
+ /**
+ * report a syntax error
+ */
+ def reportSyntaxError(pos: int, str: String): Unit = {
+ curInput.reportError(pos, str)
+ //error("MarkupParser::synerr") // DEBUG
+ }
+
+ def reportSyntaxError(str: String): Unit = reportSyntaxError(pos, str)
+
+ /**
+ * report a syntax error
+ */
+ def reportValidationError(pos: int, str: String): Unit =
+ curInput.reportError(pos, str)
+
+ def push(entityName:String) = {
+ //Console.println("BEFORE PUSHING "+ch)
+ //Console.println("BEFORE PUSHING "+pos)
+ //Console.print("[PUSHING "+entityName+"]")
+ if (!eof)
+ inpStack = curInput :: inpStack
+
+ curInput = replacementText(entityName)
+ nextch
+ }
+
+ /*
+ def push(src:Source) = {
+ curInput = src
+ nextch
+ }
+ */
+
+ def pushExternal(systemId:String) = {
+ //Console.print("BEFORE PUSH, curInput = $"+curInput.descr)
+ //Console.println(" stack = "+inpStack.map { x => "$"+x.descr })
+
+ //Console.print("[PUSHING EXTERNAL "+systemId+"]")
+ if (!eof)
+ inpStack = curInput :: inpStack
+
+ curInput = externalSource(systemId)
+
+ //Console.print("AFTER PUSH, curInput = $"+curInput.descr)
+ //Console.println(" stack = "+inpStack.map { x => "$"+x.descr })
+
+ nextch
+ }
+
+ def pop() = {
+ curInput = inpStack.head
+ inpStack = inpStack.tail
+ ch = curInput.ch
+ pos = curInput.pos
+ eof = false // must be false, because of places where entity refs occur
+ //Console.println("\n AFTER POP, curInput = $"+curInput.descr);
+ //Console.println(inpStack.map { x => x.descr });
+ }
+
+ /** for the moment, replace only character references
+ * see spec 3.3.3
+ * precond: cbuf empty
+ */
+ def normalizeAttributeValue(attval: String) = {
+ val s: Seq[Char] = attval
+ val it = s.elements
+ while(it.hasNext) {
+ it.next match {
+ case ' '|'\t'|'\n'|'\r' =>
+ cbuf.append(' ');
+ case '&' => it.next match {
+ case '#' =>
+ var c = it.next
+ val s = xCharRef ({ () => c }, { () => c = it.next })
+ cbuf.append(s)
+ case nchar =>
+ val nbuf = new StringBuilder()
+ var d = nchar
+ do {
+ nbuf.append(d)
+ d = it.next
+ } while(d != ';');
+ nbuf.toString() match {
+ case "lt" => cbuf.append('<')
+ case "gt" => cbuf.append('>')
+ case "amp" => cbuf.append('&')
+ case "quote" => cbuf.append('"')
+ case name =>
+ //don't handle entityrefs for now
+ cbuf.append('&')
+ cbuf.append(name)
+ cbuf.append(';')
+ }
+ }
+ case c => cbuf.append(c)
+ }
+ }
+ val name = cbuf.toString()
+ cbuf.setLength(0)
+ name
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/NoBindingFactoryAdapter.scala b/src/dotnet-library/scala/xml/parsing/NoBindingFactoryAdapter.scala
new file mode 100644
index 0000000000..b3b17d6909
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/NoBindingFactoryAdapter.scala
@@ -0,0 +1,57 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+
+import scala.xml.factory.NodeFactory;
+import org.xml.sax.InputSource;
+
+/** nobinding adaptor providing callbacks to parser to create elements.
+* implements hash-consing
+*/
+class NoBindingFactoryAdapter extends FactoryAdapter with NodeFactory[Elem] {
+
+ // -- FactoryAdapter methods
+
+ /** returns true. Every XML node may contain text that the application needs
+ **/
+ def nodeContainsText( label:java.lang.String ): Boolean = true;
+
+
+ // methods for NodeFactory[Elem]
+
+ /** constructs an instance of scala.xml.Elem */
+ protected def create(pre: String, label: String, attrs: MetaData, scpe: NamespaceBinding, children:Seq[Node]): Elem = {
+ Elem( pre, label, attrs, scpe, children:_* );
+ }
+
+ // -- methods for FactoryAdapter
+
+ /** creates a node. never creates the same node twice, using hash-consing
+ */
+ def createNode(pre:String, label: String, attrs: MetaData, scpe: NamespaceBinding, children: List[Node] ): Elem = {
+ //Console.println("NoBindingFactoryAdapter::createNode("+pre+","+label+","+attrs+","+scpe+","+children+")");
+ Elem( pre, label, attrs, scpe, children:_* );
+ //makeNode(pre, label, attrs, scpe, children);
+ }
+
+ /** creates a text node
+ */
+ def createText( text:String ) =
+ Text( text );
+
+ /** loads an XML document, returning a Symbol node.
+ */
+ override def loadXML( source:InputSource ):Elem =
+ super.loadXML( source ).asInstanceOf[ Elem ];
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/TokenTests.scala b/src/dotnet-library/scala/xml/parsing/TokenTests.scala
new file mode 100644
index 0000000000..d56b9bb7d7
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/TokenTests.scala
@@ -0,0 +1,146 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+
+/**
+ * Helper functions for parsing XML fragments
+ */
+trait TokenTests {
+
+ /** (#x20 | #x9 | #xD | #xA) */
+ final def isSpace( ch:Char ): Boolean = ch match {
+ case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true
+ case _ => false;
+ }
+
+ /** (#x20 | #x9 | #xD | #xA)+ */
+ final def isSpace(cs: Seq[Char]): Boolean = {
+ val it = cs.elements;
+ it.hasNext && it.forall { isSpace };
+ }
+
+ /** NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
+ * | CombiningChar | Extender
+ *
+ * see [4] and Appendix B of XML 1.0 specification
+ */
+ def isNameChar(ch: Char) = isNameStart(ch) || (ch match {
+ case '.' | '-' | ':' => true;
+ case _ => java.lang.Character.getType( ch ).asInstanceOf[Byte] match {
+ case java.lang.Character.COMBINING_SPACING_MARK => true; // Mc
+ case java.lang.Character.ENCLOSING_MARK => true; // Me
+ case java.lang.Character.NON_SPACING_MARK => true; // Mn
+ case java.lang.Character.MODIFIER_LETTER => true; // Lm
+ case java.lang.Character.DECIMAL_DIGIT_NUMBER => true; // Nd
+ case _ => false;
+ }
+ });
+
+ /** NameStart ::= ( Letter | '_' )
+ * where Letter means in one of the Unicode general
+ * categories { Ll, Lu, Lo, Lt, Nl }
+ *
+ * We do not allow a name to start with ':'.
+ * see [3] and Appendix B of XML 1.0 specification
+ */
+ def isNameStart(ch: Char) =
+ java.lang.Character.getType(ch).asInstanceOf[Byte] match {
+ case java.lang.Character.LOWERCASE_LETTER => true;
+ case java.lang.Character.UPPERCASE_LETTER => true;
+ case java.lang.Character.OTHER_LETTER => true;
+ case java.lang.Character.TITLECASE_LETTER => true;
+ case java.lang.Character.LETTER_NUMBER => true;
+ case _ => ch match {
+ case '_' => true
+ case _ => false;
+ }
+ }
+
+ /** Name ::= ( Letter | '_' ) (NameChar)*
+ *
+ * see [5] of XML 1.0 specification
+ */
+ def isName(s: String): Boolean = {
+ if( s.length() > 0 ) {
+ val y = s.elements;
+ if (isNameStart(y.next)) {
+ while (y.hasNext && isNameChar(y.next)) {};
+ !y.hasNext
+ } else false;
+ } else false;
+ }
+
+ def isPubIDChar(ch: Char): Boolean = {
+ //Console.println("char: '" + ch + "'");
+ ch match {
+ case '\u0020' | '\u000D' | '\u000A' => true;
+ case _ if
+ (('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'z') ||
+ ('A' <= ch && ch <= 'Z')) => true;
+ case '-' | '\''| '(' | ')' | '+' | ',' | '.' |
+ '/' | ':' | '=' | '?' | ';' | '!' | '*' |
+ '#' | '@' | '$' | '_' | '%' => true
+ case _ =>
+ //Console.println("false: '" + ch + "'");
+ false;
+ }
+ }
+
+ /**
+ * Returns true if the encoding name is a valid IANA encoding.
+ * This method does not verify that there is a decoder available
+ * for this encoding, only that the characters are valid for an
+ * IANA encoding name.
+ *
+ * @param ianaEncoding The IANA encoding name.
+ */
+ def isValidIANAEncoding(ianaEncoding: Seq[Char]): Boolean = {
+ val it = ianaEncoding.elements;
+ if (!it.hasNext)
+ return false;
+
+ var c = it.next;
+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+ while (it.hasNext) {
+ c = it.next;
+ if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
+ (c < '0' || c > '9') && c != '.' && c != '_' &&
+ c != '-') {
+ return false;
+ }
+ }
+ return true;
+ } else
+ return false;
+ } // isValidIANAEncoding(String): Boolean
+
+ def checkSysID( s:String ): Boolean = {
+ s.indexOf('"'.asInstanceOf[Int]) == -1 || s.indexOf('\''.asInstanceOf[Int]) == -1
+ }
+
+ def checkPubID(s: String): Boolean = {
+ //Console.println("checkPubID of \""+s+"\"");
+ if (s.length() > 0) {
+ val y = s.elements;
+ var c = ' ';
+ while (y.hasNext && isPubIDChar(c)) {
+ //Console.println(c);
+ c = y.next
+ };
+ !y.hasNext
+ }
+ else
+ true
+ }
+
+}
diff --git a/src/dotnet-library/scala/xml/parsing/ValidatingMarkupHandler.scala b/src/dotnet-library/scala/xml/parsing/ValidatingMarkupHandler.scala
new file mode 100644
index 0000000000..a233cc527c
--- /dev/null
+++ b/src/dotnet-library/scala/xml/parsing/ValidatingMarkupHandler.scala
@@ -0,0 +1,116 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.parsing;
+
+
+import scala.xml.dtd._ ;
+import scala.util.logging.Logged ;
+
+abstract class ValidatingMarkupHandler extends MarkupHandler with Logged {
+
+ var rootLabel:String = _;
+ var qStack: List[Int] = Nil;
+ var qCurrent: Int = -1;
+
+ var declStack: List[ElemDecl] = Nil;
+ var declCurrent: ElemDecl = null;
+
+ final override val isValidating = true;
+
+ override def log(msg:String) = {};
+
+ /*
+ override def checkChildren(pos: Int, pre: String, label:String,ns:NodeSeq): Unit = {
+ Console.println("checkChildren()");
+ val decl = lookupElemDecl(label);
+ // @todo: nice error message
+ val res = decl.contentModel.validate(ns);
+ Console.println("res = "+res);
+ if(!res)
+ //error("invalid!");
+ }
+ */
+
+ override def endDTD(n:String) = {
+ rootLabel = n;
+ }
+ override def elemStart(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding): Unit = {
+
+ def advanceDFA(dm:DFAContentModel) = {
+ val trans = dm.dfa.delta(qCurrent);
+ log("advanceDFA(dm): "+dm);
+ log("advanceDFA(trans): "+trans);
+ trans.get(ContentModel.ElemName(label)) match {
+ case Some(qNew) => qCurrent = qNew
+ case _ => reportValidationError(pos, "DTD says, wrong element, expected one of "+trans.keys.toString());
+ }
+ }
+ // advance in current automaton
+ log("[qCurrent = "+qCurrent+" visiting "+label+"]");
+
+ if(qCurrent == -1) { // root
+ log(" checking root");
+ if(label != rootLabel)
+ reportValidationError(pos, "this element should be "+rootLabel);
+ } else {
+ log(" checking node");
+ declCurrent.contentModel match {
+ case ANY =>
+
+ case EMPTY =>
+ reportValidationError(pos, "DTD says, no elems, no text allowed here");
+ case PCDATA =>
+ reportValidationError(pos, "DTD says, no elements allowed here");
+
+ case m@MIXED(r) => advanceDFA(m);
+ case e@ELEMENTS(r) => advanceDFA(e);
+ }
+ }
+ // push state, decl
+ qStack = qCurrent :: qStack;
+ declStack = declCurrent :: declStack;
+
+ declCurrent = lookupElemDecl(label);
+ qCurrent = 0;
+ log(" done now");
+ }
+
+ override def elemEnd(pos: int, pre: String, label: String): Unit = {
+ log(" elemEnd");
+ qCurrent = qStack.head;
+ qStack = qStack.tail;
+ declCurrent = declStack.head;
+ declStack = declStack.tail;
+ log(" qCurrent now"+qCurrent);
+ log(" declCurrent now"+declCurrent);
+ }
+
+ final override def elemDecl(name: String, cmstr: String): Unit =
+ decls = ElemDecl( name, ContentModel.parse(cmstr)) :: decls;
+
+ final override def attListDecl(name: String, attList: List[AttrDecl]): Unit =
+ decls = AttListDecl( name, attList) :: decls;
+
+ final override def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit = {
+ decls = UnparsedEntityDecl( name, extID, notat) :: decls;
+ }
+
+ final override def notationDecl(notat: String, extID: ExternalID): Unit =
+ decls = NotationDecl( notat, extID) :: decls;
+
+ final override def peReference(name: String): Unit =
+ decls = PEReference( name ) :: decls;
+
+ /** report a syntax error */
+ def reportValidationError(pos: Int, str: String): Unit;
+
+}
diff --git a/src/dotnet-library/scala/xml/path/Expression.scala b/src/dotnet-library/scala/xml/path/Expression.scala
new file mode 100644
index 0000000000..c9da0bc338
--- /dev/null
+++ b/src/dotnet-library/scala/xml/path/Expression.scala
@@ -0,0 +1,66 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.path;
+
+
+object Expression {
+
+ final def testFromString(x: String): Test = {
+ x.charAt(0) match {
+ case '*' if( x.length() == 1 ) => WildcardTest;
+ case _ => NameTest(x);
+ }
+ }
+
+ case class FExp(e:Expr, c:Cond) {
+ def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo
+ }
+
+ abstract class GenExp ;
+ case class Attrib(test: NameTest, e: Expr) extends GenExp;
+
+ abstract class Expr extends GenExp {
+ def \ (x: String) =
+ if( x=="*")
+ Child(WildcardTest, this)
+ else
+ Child(NameTest(x), this);
+
+ def \\ (x: String) =
+ if( x=="*")
+ DescOrSelf(WildcardTest, this)
+ else
+ DescOrSelf(NameTest(x), this);
+
+ def apply(c: Cond) = FExp(this, c);
+
+ def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo
+ }
+
+ case object Root extends Expr;
+
+ case class Child(test: Test, e: Expr) extends Expr;
+ case class DescOrSelf(test: Test, e: Expr) extends Expr;
+
+
+ abstract class Test;
+
+ case object WildcardTest extends Test; // "x \ * "
+ case class NameTest(label: String) extends Test; // "x \ bar"
+
+
+ abstract class Cond;
+
+ case class Exists(p: GenExp) extends Cond ; // "p [ p ]"
+ case class Equals(p: Expr, c:String) extends Cond ; // "p [ @p == bla ]"
+
+}
diff --git a/src/dotnet-library/scala/xml/pull/XMLEvent.scala b/src/dotnet-library/scala/xml/pull/XMLEvent.scala
new file mode 100644
index 0000000000..50e657489d
--- /dev/null
+++ b/src/dotnet-library/scala/xml/pull/XMLEvent.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.pull
+
+/** represents an XMLEvent for pull parsing
+ */
+trait XMLEvent {
+}
+
+case class ElemStart(pre: String, label: String, attrs: MetaData, scope:NamespaceBinding) extends XMLEvent
+
+case class ElemEnd(pre: String, label: String) extends XMLEvent
diff --git a/src/dotnet-library/scala/xml/pull/XMLEventReader.scala b/src/dotnet-library/scala/xml/pull/XMLEventReader.scala
new file mode 100644
index 0000000000..130d7afe19
--- /dev/null
+++ b/src/dotnet-library/scala/xml/pull/XMLEventReader.scala
@@ -0,0 +1,131 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.pull
+
+
+import java.lang.{Runnable, Thread}
+
+import scala.io.Source
+import scala.xml.parsing.{MarkupParser, MarkupHandler,ExternalSources}
+
+/** a pull parser that offers to view an XML document as a series of events.
+ * Please note that this API might change. Here's how to use this class
+ *
+<pre>
+import scala.xml._
+import scala.xml.pull._
+import scala.io.Source
+
+object reader {
+ val src = Source.fromString("<hello><world/></hello>")
+ val er = new XMLEventReader().initialize(src)
+
+ def main(args:Array[String]): unit = {
+ Console.println(er.next)
+ Console.println(er.next)
+ }
+}
+</pre>
+ */
+class XMLEventReader extends Iterator[XMLEvent] {
+
+ var src:Source = null
+ def getSource = this.src
+ def initialize(src:Source): this.type = {
+ this.src = src
+ this.parserThread = new Thread(new Parser())
+ this.parserThread.start()
+ this
+ }
+
+ // -- this part of the class is for communication with the thread
+ var xmlEvent: XMLEvent = null
+ var continue: Boolean = true
+
+ def myresume = synchronized {
+ while(continue) {
+ wait()
+ }
+ continue = true;
+ notifyAll
+ }
+ def getAndClearEvent: XMLEvent = synchronized {
+ while(xmlEvent eq null) {
+ wait()
+ }
+ val r = xmlEvent
+ xmlEvent = null
+ r
+ }
+ def setEvent(e:XMLEvent) = {
+ xmlEvent = e;
+ }
+
+ def doNotify() = synchronized {
+ XMLEventReader.this.continue = false;
+ notifyAll()
+ while(!XMLEventReader.this.continue) wait();
+ NodeSeq.Empty
+ }
+
+ // iterator methods
+
+ def next: XMLEvent = {
+ myresume;
+ val r = getAndClearEvent
+ r
+ }
+
+ def hasNext = true
+
+ var parserThread: Thread = null
+
+ class Parser extends MarkupHandler with MarkupParser with ExternalSources with Runnable {
+
+ val preserveWS = true
+ val input = XMLEventReader.this.getSource
+
+ override def elemStart(pos:int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding):Unit = {
+ setEvent(ElemStart(pre,label,attrs,scope)); doNotify
+ }
+
+ override def elemEnd(pos: int, pre: String, label: String): Unit = {
+ setEvent(ElemEnd(pre,label)); doNotify
+ }
+
+ final def elem(pos: int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq =
+ NodeSeq.Empty
+
+ def procInstr(pos: Int, target: String, txt: String ) = {
+ setEvent(ElemStart(null,"comm",null,null)); doNotify
+ }
+
+ def comment(pos: Int, txt: String ) = {
+ setEvent(ElemStart(null,"comm",null,null)); doNotify
+ }
+
+ def entityRef(pos: Int, n: String) = {
+ setEvent(ElemStart(null,"eref",null,null)); doNotify
+ }
+
+ def text(pos: Int, txt:String) = {
+ setEvent(ElemStart(null,"tex",null,null)); doNotify
+ }
+
+ override def run(): unit = {
+ curInput = input
+ this.nextch
+ doNotify()
+ this.document()
+ }
+ }
+}
diff --git a/src/dotnet-library/scala/xml/transform/BasicTransformer.scala b/src/dotnet-library/scala/xml/transform/BasicTransformer.scala
new file mode 100644
index 0000000000..8364e498d4
--- /dev/null
+++ b/src/dotnet-library/scala/xml/transform/BasicTransformer.scala
@@ -0,0 +1,146 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.transform
+
+
+/** A class for XML transformations.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class BasicTransformer extends Function1[Node,Node] {
+
+ protected case class NeedsCopy(result: Seq[Node]) extends java.lang.Throwable
+
+ /** Returns a new node buffer with the first <code>pos</code> elements
+ * from <code>ns</code>.
+ */
+ protected def buffer(pos: Int, ns :Seq[Node]): NodeBuffer = {
+ val nb = new NodeBuffer()
+ var jt = ns.elements
+ var j = 0; while (j < pos-1) {
+ nb.append(jt.next)
+ j = j + 1
+ }
+ nb
+ }
+
+ /** turns a nodebuffer into a sequence, so hashcode works */
+ protected def freeze(nb: NodeBuffer): Seq[Node] = {
+ val arr = new Array[Node](nb.length)
+ var i = 0
+ val it = nb.elements; while (it.hasNext) {
+ arr(i) = it.next
+ i = i + 1
+ }
+ val seq: Seq[Node] = arr
+ seq
+ }
+
+ protected def single(ns: Seq[Node]) =
+ 1 == ns.length
+
+ /**
+ * @param n ...
+ * @param ns ...
+ * @return ...
+ */
+ protected def unchanged(n: Node, ns: Seq[Node]) =
+ single(ns) && (ns.elements.next.eq(n))
+
+ /** Call transform(Node) for each node in ns, append results
+ * to NodeBuffer.
+ */
+ def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = {
+ while (it.hasNext)
+ nb ++ transform(it.next);
+ freeze(nb)
+ }
+
+ /** Call transform(Node) to each node in ns, yield ns if nothing changes,
+ * otherwise a new sequence of concatenated results.
+ */
+ def transform(ns: Seq[Node]): Seq[Node] = {
+ var i = 0
+ val it = ns.elements
+ try {
+ while (it.hasNext) {
+ val n = it.next
+ val n2 = transform(n)
+ if (!unchanged(n, n2)) {
+ throw NeedsCopy(n2)
+ }
+ i = i + 1
+ }
+ ns
+ } catch {
+ case NeedsCopy(n2) =>
+ val nb = buffer(i, ns)
+ nb ++ n2
+ transform(it, nb)
+ }
+ }
+
+ def transform(n: Node): Seq[Node] = {
+ if (n.typeTag$ < 0)
+ n
+ else {
+ val ch = n.child
+ val nch = transform(ch)
+ if (ch.eq(nch))
+ n
+ else
+ Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*)
+ }
+ }
+
+ def apply(n: Node): Node = {
+ val seq = transform(n)
+ if (!single(seq))
+ throw new UnsupportedOperationException("transform must return single node for root");
+ else seq.elements.next
+ }
+}
+
+/*
+class IdentityTransformer extends BasicTransformer {
+ override def transform(n: Node): Seq[Node] = n.match {
+ case <world/> => <xml-world/>
+ case _ => super.transform(n);
+ }
+}
+
+object Foo with Application {
+
+ val tr = new IdentityTransformer;
+ val n = tr( <hello><world/></hello> );
+ Console.println(n);
+
+ val tr2 = new RewriteRule {
+ final override val name = "A rule";
+ override def transform(n: Node) = n.match {
+ case <a/> => <b/><c/>
+ case _ => n
+ }
+ }
+ val tr3 = new RewriteRule {
+ final override val name = "E rule";
+ override def transform(n: Node) = n.match {
+ case <e/> => <f><f/></f>
+ case _ => n
+ }
+ }
+ val tr4 = new RuleTransformer(tr2, tr3);
+ val m = tr4( <hello><a/><e/></hello> );
+ Console.println(m);
+}
+*/
diff --git a/src/dotnet-library/scala/xml/transform/RewriteRule.scala b/src/dotnet-library/scala/xml/transform/RewriteRule.scala
new file mode 100644
index 0000000000..8100e6eae9
--- /dev/null
+++ b/src/dotnet-library/scala/xml/transform/RewriteRule.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml.transform
+
+/** a RewriteRule, when applied to a term, yields either
+ * the resulting of rewriting or the term itself it the rule
+ * is not applied.
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+abstract class RewriteRule extends BasicTransformer {
+ /** a name for this rewrite rule */
+ val name = this.toString()
+ override def transform(ns: Seq[Node]): Seq[Node] = super.transform(ns)
+ override def transform(n: Node): Seq[Node] = n
+}
+
diff --git a/src/dotnet-library/scala/xml/transform/RuleTransformer.scala b/src/dotnet-library/scala/xml/transform/RuleTransformer.scala
new file mode 100644
index 0000000000..f8d2ecc413
--- /dev/null
+++ b/src/dotnet-library/scala/xml/transform/RuleTransformer.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.xml.transform;
+
+
+class RuleTransformer(rules:RewriteRule*) extends BasicTransformer {
+ override def transform(n:Node): Seq[Node] = {
+ var m: Seq[Node] = super.transform(n);
+ val it = rules.elements; while(it.hasNext) {
+ val rule = it.next;
+ val m2 = rule.transform(m);
+ //if(!m2.eq(m)) Console.println("applied rule \""+rule.name+"\"");
+ m = m2;
+ }
+ m
+ }
+}