From e3b42865333ed502b3e454c98eefbfc705e33d82 Mon Sep 17 00:00:00 2001 From: mihaylov Date: Wed, 7 Feb 2007 09:06:25 +0000 Subject: Created src/dotnet-library from r9912 of src/li... Created src/dotnet-library from r9912 of src/library --- src/dotnet-library/scala/All$.scala | 25 + src/dotnet-library/scala/AllRef$.scala | 25 + src/dotnet-library/scala/Application.scala | 58 + src/dotnet-library/scala/Array.scala | 278 +++++ src/dotnet-library/scala/Attribute.scala | 23 + src/dotnet-library/scala/BigInt.scala | 363 ++++++ src/dotnet-library/scala/BufferedIterator.scala | 29 + src/dotnet-library/scala/ByNameFunction.scala | 27 + src/dotnet-library/scala/Cell.scala | 22 + src/dotnet-library/scala/ClassfileAttribute.scala | 21 + src/dotnet-library/scala/Console.scala | 334 ++++++ src/dotnet-library/scala/CountedIterator.scala | 26 + src/dotnet-library/scala/Enumeration.scala | 138 +++ src/dotnet-library/scala/Function.scala | 144 +++ src/dotnet-library/scala/Function0.scala | 42 + src/dotnet-library/scala/Function1.scala | 50 + src/dotnet-library/scala/Function2.scala | 42 + src/dotnet-library/scala/Function3.scala | 26 + src/dotnet-library/scala/Function4.scala | 26 + src/dotnet-library/scala/Function5.scala | 26 + src/dotnet-library/scala/Function6.scala | 26 + src/dotnet-library/scala/Function7.scala | 26 + src/dotnet-library/scala/Function8.scala | 26 + src/dotnet-library/scala/Function9.scala | 21 + src/dotnet-library/scala/Iterable.scala | 378 ++++++ src/dotnet-library/scala/IterableProxy.scala | 54 + src/dotnet-library/scala/Iterator.scala | 647 +++++++++++ src/dotnet-library/scala/List.scala | 1159 +++++++++++++++++++ src/dotnet-library/scala/MatchError.scala | 51 + src/dotnet-library/scala/Math.scala | 140 +++ src/dotnet-library/scala/NotDefinedError.scala | 17 + src/dotnet-library/scala/Option.scala | 132 +++ src/dotnet-library/scala/Ordered.scala | 36 + src/dotnet-library/scala/PartialFunction.scala | 45 + src/dotnet-library/scala/PartiallyOrdered.scala | 50 + src/dotnet-library/scala/Predef.scala | 285 +++++ src/dotnet-library/scala/Product.scala | 42 + src/dotnet-library/scala/Product1.scala | 50 + src/dotnet-library/scala/Product10.scala | 86 ++ src/dotnet-library/scala/Product11.scala | 90 ++ src/dotnet-library/scala/Product12.scala | 94 ++ src/dotnet-library/scala/Product13.scala | 98 ++ src/dotnet-library/scala/Product14.scala | 102 ++ src/dotnet-library/scala/Product15.scala | 106 ++ src/dotnet-library/scala/Product16.scala | 110 ++ src/dotnet-library/scala/Product17.scala | 114 ++ src/dotnet-library/scala/Product18.scala | 118 ++ src/dotnet-library/scala/Product19.scala | 122 ++ src/dotnet-library/scala/Product2.scala | 54 + src/dotnet-library/scala/Product20.scala | 126 ++ src/dotnet-library/scala/Product21.scala | 130 +++ src/dotnet-library/scala/Product22.scala | 134 +++ src/dotnet-library/scala/Product3.scala | 58 + src/dotnet-library/scala/Product4.scala | 62 + src/dotnet-library/scala/Product5.scala | 66 ++ src/dotnet-library/scala/Product6.scala | 70 ++ src/dotnet-library/scala/Product7.scala | 74 ++ src/dotnet-library/scala/Product8.scala | 78 ++ src/dotnet-library/scala/Product9.scala | 82 ++ src/dotnet-library/scala/Proxy.scala | 28 + src/dotnet-library/scala/Responder.scala | 90 ++ src/dotnet-library/scala/ScalaObject.scala | 23 + src/dotnet-library/scala/Seq.scala | 274 +++++ src/dotnet-library/scala/SeqProxy.scala | 44 + src/dotnet-library/scala/SerialVersionUID.scala | 19 + src/dotnet-library/scala/StaticAttribute.scala | 21 + src/dotnet-library/scala/Stream.scala | 457 ++++++++ src/dotnet-library/scala/Symbol.scala | 57 + src/dotnet-library/scala/Tuple1.scala | 25 + src/dotnet-library/scala/Tuple10.scala | 25 + src/dotnet-library/scala/Tuple11.scala | 25 + src/dotnet-library/scala/Tuple12.scala | 25 + src/dotnet-library/scala/Tuple13.scala | 25 + src/dotnet-library/scala/Tuple14.scala | 25 + src/dotnet-library/scala/Tuple15.scala | 25 + src/dotnet-library/scala/Tuple16.scala | 25 + src/dotnet-library/scala/Tuple17.scala | 25 + src/dotnet-library/scala/Tuple18.scala | 25 + src/dotnet-library/scala/Tuple19.scala | 25 + src/dotnet-library/scala/Tuple2.scala | 25 + src/dotnet-library/scala/Tuple20.scala | 25 + src/dotnet-library/scala/Tuple21.scala | 25 + src/dotnet-library/scala/Tuple22.scala | 25 + src/dotnet-library/scala/Tuple3.scala | 25 + src/dotnet-library/scala/Tuple4.scala | 25 + src/dotnet-library/scala/Tuple5.scala | 25 + src/dotnet-library/scala/Tuple6.scala | 25 + src/dotnet-library/scala/Tuple7.scala | 25 + src/dotnet-library/scala/Tuple8.scala | 25 + src/dotnet-library/scala/Tuple9.scala | 25 + src/dotnet-library/scala/cloneable.scala | 18 + src/dotnet-library/scala/collection/BitSet.scala | 140 +++ src/dotnet-library/scala/collection/Map.scala | 158 +++ src/dotnet-library/scala/collection/MapProxy.scala | 37 + src/dotnet-library/scala/collection/Set.scala | 103 ++ src/dotnet-library/scala/collection/SetProxy.scala | 30 + .../scala/collection/immutable/BitSet.scala | 51 + .../scala/collection/immutable/EmptyMap.scala | 37 + .../scala/collection/immutable/EmptySet.scala | 36 + .../scala/collection/immutable/HashMap.scala | 154 +++ .../scala/collection/immutable/HashSet.scala | 118 ++ .../scala/collection/immutable/ListMap.scala | 160 +++ .../scala/collection/immutable/ListSet.scala | 138 +++ .../scala/collection/immutable/Map.scala | 238 ++++ .../scala/collection/immutable/Map1.scala | 40 + .../scala/collection/immutable/Map2.scala | 46 + .../scala/collection/immutable/Map3.scala | 49 + .../scala/collection/immutable/Map4.scala | 52 + .../scala/collection/immutable/Queue.scala | 161 +++ .../scala/collection/immutable/RedBlack.scala | 98 ++ .../scala/collection/immutable/Set.scala | 169 +++ .../scala/collection/immutable/Set1.scala | 42 + .../scala/collection/immutable/Set2.scala | 43 + .../scala/collection/immutable/Set3.scala | 44 + .../scala/collection/immutable/Set4.scala | 45 + .../scala/collection/immutable/Stack.scala | 134 +++ .../scala/collection/immutable/Tree.scala | 406 +++++++ .../scala/collection/immutable/TreeMap.scala | 112 ++ .../collection/immutable/TreeMap.scala.disabled | 101 ++ .../scala/collection/immutable/TreeSet.scala | 84 ++ .../collection/immutable/UnbalancedTreeMap.scala | 143 +++ .../scala/collection/jcl/ArrayList.scala | 20 + .../scala/collection/jcl/Buffer.scala | 159 +++ .../scala/collection/jcl/BufferIterator.scala | 32 + .../scala/collection/jcl/BufferWrapper.scala | 51 + .../scala/collection/jcl/Collection.scala | 84 ++ .../scala/collection/jcl/CollectionWrapper.scala | 41 + .../scala/collection/jcl/HashMap.scala | 19 + .../scala/collection/jcl/HashSet.scala | 20 + .../scala/collection/jcl/IdentityHashMap.scala | 22 + .../scala/collection/jcl/IterableWrapper.scala | 39 + .../scala/collection/jcl/LinkedHashMap.scala | 20 + .../scala/collection/jcl/LinkedHashSet.scala | 20 + .../scala/collection/jcl/LinkedList.scala | 29 + src/dotnet-library/scala/collection/jcl/Map.scala | 97 ++ .../scala/collection/jcl/MapWrapper.scala | 66 ++ .../scala/collection/jcl/MutableIterable.scala | 80 ++ .../scala/collection/jcl/MutableIterator.scala | 100 ++ .../scala/collection/jcl/MutableSeq.scala | 82 ++ .../scala/collection/jcl/Ranged.scala | 62 + .../scala/collection/jcl/SeqIterator.scala | 58 + src/dotnet-library/scala/collection/jcl/Set.scala | 51 + .../scala/collection/jcl/SetWrapper.scala | 21 + .../scala/collection/jcl/Sorted.scala | 46 + .../scala/collection/jcl/SortedMap.scala | 90 ++ .../scala/collection/jcl/SortedMapWrapper.scala | 39 + .../scala/collection/jcl/SortedSet.scala | 75 ++ .../scala/collection/jcl/SortedSetWrapper.scala | 38 + .../scala/collection/jcl/Tests.scala | 77 ++ .../scala/collection/jcl/TreeMap.scala | 19 + .../scala/collection/jcl/TreeSet.scala | 20 + .../scala/collection/jcl/WeakHashMap.scala | 29 + .../scala/collection/mutable/ArrayBuffer.scala | 178 +++ .../scala/collection/mutable/BitSet.scala | 100 ++ .../scala/collection/mutable/Buffer.scala | 245 ++++ .../scala/collection/mutable/BufferProxy.scala | 154 +++ .../scala/collection/mutable/DefaultEntry.scala | 18 + .../scala/collection/mutable/DefaultMapModel.scala | 45 + .../collection/mutable/DoubleLinkedList.scala | 53 + .../scala/collection/mutable/FlatHashTable.scala | 148 +++ .../scala/collection/mutable/HashMap.scala | 40 + .../scala/collection/mutable/HashSet.scala | 43 + .../scala/collection/mutable/HashTable.scala | 168 +++ .../scala/collection/mutable/History.scala | 48 + .../collection/mutable/ImmutableMapAdaptor.scala | 65 ++ .../collection/mutable/ImmutableSetAdaptor.scala | 49 + .../scala/collection/mutable/JavaMapAdaptor.scala | 68 ++ .../scala/collection/mutable/JavaSetAdaptor.scala | 46 + .../scala/collection/mutable/LinkedHashSet.scala | 52 + .../scala/collection/mutable/LinkedList.scala | 33 + .../scala/collection/mutable/ListBuffer.scala | 283 +++++ .../scala/collection/mutable/Location.scala | 29 + .../scala/collection/mutable/Map.scala | 240 ++++ .../scala/collection/mutable/MapProxy.scala | 56 + .../scala/collection/mutable/Message.scala | 82 ++ .../scala/collection/mutable/MultiMap.scala | 43 + .../scala/collection/mutable/MutableList.scala | 80 ++ .../collection/mutable/ObservableBuffer.scala | 82 ++ .../scala/collection/mutable/ObservableMap.scala | 58 + .../scala/collection/mutable/ObservableSet.scala | 45 + .../scala/collection/mutable/PriorityQueue.scala | 193 ++++ .../collection/mutable/PriorityQueueProxy.scala | 100 ++ .../scala/collection/mutable/Publisher.scala | 48 + .../scala/collection/mutable/Queue.scala | 196 ++++ .../scala/collection/mutable/QueueProxy.scala | 101 ++ .../scala/collection/mutable/ResizableArray.scala | 85 ++ .../collection/mutable/RevertableHistory.scala | 33 + .../scala/collection/mutable/Scriptable.scala | 26 + .../scala/collection/mutable/Set.scala | 211 ++++ .../scala/collection/mutable/SetProxy.scala | 58 + .../collection/mutable/SingleLinkedList.scala | 63 + .../scala/collection/mutable/Stack.scala | 133 +++ .../scala/collection/mutable/StackProxy.scala | 111 ++ .../scala/collection/mutable/Subscriber.scala | 25 + .../collection/mutable/SynchronizedBuffer.scala | 191 +++ .../scala/collection/mutable/SynchronizedMap.scala | 157 +++ .../mutable/SynchronizedPriorityQueue.scala | 99 ++ .../collection/mutable/SynchronizedQueue.scala | 95 ++ .../scala/collection/mutable/SynchronizedSet.scala | 110 ++ .../collection/mutable/SynchronizedStack.scala | 111 ++ .../scala/collection/mutable/Undoable.scala | 26 + src/dotnet-library/scala/compat/Math.scala | 51 + src/dotnet-library/scala/compat/Platform.scala | 37 + .../scala/compat/StringBuilder.scala | 59 + src/dotnet-library/scala/concurrent/Actor.scala | 48 + src/dotnet-library/scala/concurrent/Channel.scala | 46 + src/dotnet-library/scala/concurrent/Lock.scala | 31 + src/dotnet-library/scala/concurrent/MailBox.scala | 176 +++ .../scala/concurrent/NameServer.scala | 46 + src/dotnet-library/scala/concurrent/Pid.scala | 48 + src/dotnet-library/scala/concurrent/Process.scala | 93 ++ .../scala/concurrent/SyncChannel.scala | 44 + src/dotnet-library/scala/concurrent/SyncVar.scala | 43 + src/dotnet-library/scala/concurrent/TIMEOUT.scala | 21 + src/dotnet-library/scala/concurrent/jolib.scala | 80 ++ src/dotnet-library/scala/concurrent/ops.scala | 78 ++ src/dotnet-library/scala/concurrent/pilib.scala | 205 ++++ src/dotnet-library/scala/deprecated.scala | 18 + src/dotnet-library/scala/io/BytePickle.scala | 318 +++++ src/dotnet-library/scala/io/Position.scala | 108 ++ src/dotnet-library/scala/io/Source.scala | 371 ++++++ src/dotnet-library/scala/io/UTF8Codec.scala | 83 ++ src/dotnet-library/scala/mobile/Code.scala | 234 ++++ src/dotnet-library/scala/mobile/Location.scala | 100 ++ .../scala/reflect/BeanProperty.scala | 34 + src/dotnet-library/scala/reflect/Code.scala | 22 + src/dotnet-library/scala/reflect/Print.scala | 98 ++ src/dotnet-library/scala/reflect/Symbol.scala | 62 + src/dotnet-library/scala/reflect/Tree.scala | 35 + src/dotnet-library/scala/reflect/Type.scala | 48 + src/dotnet-library/scala/reflect/TypedCode.scala | 15 + src/dotnet-library/scala/remote.scala | 20 + src/dotnet-library/scala/runtime/BooleanRef.java | 18 + .../scala/runtime/BoxedAnyArray.scala | 255 ++++ src/dotnet-library/scala/runtime/BoxedArray.scala | 125 ++ src/dotnet-library/scala/runtime/BoxedBoolean.java | 44 + .../scala/runtime/BoxedBooleanArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedByte.java | 57 + .../scala/runtime/BoxedByteArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedChar.java | 58 + .../scala/runtime/BoxedCharArray.scala | 61 + src/dotnet-library/scala/runtime/BoxedDouble.java | 49 + .../scala/runtime/BoxedDoubleArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedFloat.java | 48 + .../scala/runtime/BoxedFloatArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedInt.java | 57 + .../scala/runtime/BoxedIntArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedLong.java | 49 + .../scala/runtime/BoxedLongArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedNumber.java | 23 + .../scala/runtime/BoxedObjectArray.scala | 65 ++ src/dotnet-library/scala/runtime/BoxedShort.java | 58 + .../scala/runtime/BoxedShortArray.scala | 60 + src/dotnet-library/scala/runtime/BoxedUnit.java | 34 + src/dotnet-library/scala/runtime/ByteRef.java | 19 + src/dotnet-library/scala/runtime/CharRef.java | 19 + src/dotnet-library/scala/runtime/DoubleRef.java | 19 + .../scala/runtime/ExceptionHandling.java | 26 + src/dotnet-library/scala/runtime/FloatRef.java | 19 + src/dotnet-library/scala/runtime/IntRef.java | 19 + src/dotnet-library/scala/runtime/LongRef.java | 19 + .../scala/runtime/NonLocalReturnException.scala | 15 + src/dotnet-library/scala/runtime/Nothing$.scala | 21 + src/dotnet-library/scala/runtime/Null$.scala | 21 + src/dotnet-library/scala/runtime/ObjectRef.java | 19 + src/dotnet-library/scala/runtime/RichBoolean.scala | 23 + src/dotnet-library/scala/runtime/RichByte.scala | 23 + src/dotnet-library/scala/runtime/RichChar.scala | 50 + src/dotnet-library/scala/runtime/RichDouble.scala | 33 + .../scala/runtime/RichException.scala | 28 + src/dotnet-library/scala/runtime/RichFloat.scala | 33 + src/dotnet-library/scala/runtime/RichInt.scala | 28 + src/dotnet-library/scala/runtime/RichLong.scala | 27 + src/dotnet-library/scala/runtime/RichShort.scala | 23 + src/dotnet-library/scala/runtime/RichString.scala | 145 +++ .../scala/runtime/ScalaRunTime.scala | 148 +++ src/dotnet-library/scala/runtime/ShortRef.java | 18 + src/dotnet-library/scala/runtime/StringAdd.scala | 14 + src/dotnet-library/scala/serializable.scala | 18 + src/dotnet-library/scala/testing/Benchmark.scala | 87 ++ src/dotnet-library/scala/testing/SUnit.scala | 195 ++++ src/dotnet-library/scala/testing/UnitTest.scala | 85 ++ src/dotnet-library/scala/text/Document.scala | 123 ++ src/dotnet-library/scala/throws.scala | 30 + src/dotnet-library/scala/transient.scala | 15 + src/dotnet-library/scala/util/Fluid.scala | 78 ++ src/dotnet-library/scala/util/Sorting.scala | 519 +++++++++ .../scala/util/automata/BaseBerrySethi.scala | 198 ++++ .../scala/util/automata/DetWordAutom.scala | 84 ++ .../scala/util/automata/Inclusion.scala | 72 ++ .../scala/util/automata/NondetWordAutom.scala | 113 ++ .../scala/util/automata/SubsetConstruction.scala | 178 +++ .../scala/util/automata/WordBerrySethi.scala | 297 +++++ .../scala/util/grammar/HedgeRHS.scala | 23 + .../scala/util/grammar/TreeRHS.scala | 20 + .../scala/util/logging/ConsoleLogger.scala | 28 + src/dotnet-library/scala/util/logging/Logged.scala | 40 + .../util/parsing/CharInputStreamIterator.scala | 46 + .../scala/util/parsing/Parsers.scala | 85 ++ .../scala/util/parsing/SimpleTokenizer.scala | 65 ++ src/dotnet-library/scala/util/regexp/Base.scala | 76 ++ .../scala/util/regexp/PointedHedgeExp.scala | 37 + .../scala/util/regexp/SyntaxError.scala | 20 + src/dotnet-library/scala/util/regexp/WordExp.scala | 56 + src/dotnet-library/scala/volatile.scala | 15 + src/dotnet-library/scala/xml/Atom.scala | 55 + src/dotnet-library/scala/xml/Comment.scala | 47 + src/dotnet-library/scala/xml/Document.scala | 89 ++ src/dotnet-library/scala/xml/Elem.scala | 70 ++ src/dotnet-library/scala/xml/EntityRef.scala | 58 + src/dotnet-library/scala/xml/Group.scala | 74 ++ .../scala/xml/MalformedAttributeException.scala | 15 + src/dotnet-library/scala/xml/MetaData.scala | 215 ++++ .../scala/xml/NamespaceBinding.scala | 73 ++ src/dotnet-library/scala/xml/Node.scala | 193 ++++ src/dotnet-library/scala/xml/NodeBuffer.scala | 64 ++ src/dotnet-library/scala/xml/NodeSeq.scala | 178 +++ src/dotnet-library/scala/xml/NodeTraverser.scala | 34 + src/dotnet-library/scala/xml/Null.scala | 84 ++ src/dotnet-library/scala/xml/Parsing.scala | 105 ++ .../scala/xml/PrefixedAttribute.scala | 101 ++ src/dotnet-library/scala/xml/PrettyPrinter.scala | 306 +++++ src/dotnet-library/scala/xml/ProcInstr.scala | 68 ++ src/dotnet-library/scala/xml/SpecialNode.scala | 35 + src/dotnet-library/scala/xml/Text.scala | 43 + src/dotnet-library/scala/xml/TextBuffer.scala | 65 ++ src/dotnet-library/scala/xml/TopScope.scala | 38 + src/dotnet-library/scala/xml/TypeSymbol.scala | 15 + src/dotnet-library/scala/xml/Unparsed.scala | 36 + .../scala/xml/UnprefixedAttribute.scala | 87 ++ src/dotnet-library/scala/xml/Utility.scala | 444 +++++++ src/dotnet-library/scala/xml/XML.scala | 157 +++ .../scala/xml/dtd/ContentModel.scala | 212 ++++ .../scala/xml/dtd/ContentModelParser.scala | 156 +++ src/dotnet-library/scala/xml/dtd/DTD.scala | 58 + src/dotnet-library/scala/xml/dtd/Decl.scala | 176 +++ src/dotnet-library/scala/xml/dtd/DocType.scala | 47 + .../scala/xml/dtd/DtdTypeSymbol.scala | 15 + .../scala/xml/dtd/ElementValidator.scala | 179 +++ src/dotnet-library/scala/xml/dtd/ExternalID.scala | 91 ++ src/dotnet-library/scala/xml/dtd/Scanner.scala | 99 ++ src/dotnet-library/scala/xml/dtd/Tokens.scala | 44 + .../scala/xml/dtd/ValidationException.scala | 45 + src/dotnet-library/scala/xml/factory/Binder.scala | 55 + .../scala/xml/factory/LoggedNodeFactory.scala | 95 ++ .../scala/xml/factory/NodeFactory.scala | 77 ++ .../scala/xml/parsing/ConstructingHandler.scala | 38 + .../scala/xml/parsing/ConstructingParser.scala | 67 ++ .../scala/xml/parsing/DefaultMarkupHandler.scala | 28 + .../scala/xml/parsing/ExternalSources.scala | 78 ++ .../scala/xml/parsing/FactoryAdapter.scala | 336 ++++++ .../scala/xml/parsing/FatalError.scala | 15 + .../scala/xml/parsing/MarkupHandler.scala | 161 +++ .../scala/xml/parsing/MarkupParser.scala | 1213 ++++++++++++++++++++ .../xml/parsing/NoBindingFactoryAdapter.scala | 57 + .../scala/xml/parsing/TokenTests.scala | 146 +++ .../xml/parsing/ValidatingMarkupHandler.scala | 116 ++ src/dotnet-library/scala/xml/path/Expression.scala | 66 ++ src/dotnet-library/scala/xml/pull/XMLEvent.scala | 21 + .../scala/xml/pull/XMLEventReader.scala | 131 +++ .../scala/xml/transform/BasicTransformer.scala | 146 +++ .../scala/xml/transform/RewriteRule.scala | 26 + .../scala/xml/transform/RuleTransformer.scala | 26 + 363 files changed, 32237 insertions(+) create mode 100644 src/dotnet-library/scala/All$.scala create mode 100644 src/dotnet-library/scala/AllRef$.scala create mode 100644 src/dotnet-library/scala/Application.scala create mode 100644 src/dotnet-library/scala/Array.scala create mode 100644 src/dotnet-library/scala/Attribute.scala create mode 100644 src/dotnet-library/scala/BigInt.scala create mode 100644 src/dotnet-library/scala/BufferedIterator.scala create mode 100755 src/dotnet-library/scala/ByNameFunction.scala create mode 100644 src/dotnet-library/scala/Cell.scala create mode 100644 src/dotnet-library/scala/ClassfileAttribute.scala create mode 100644 src/dotnet-library/scala/Console.scala create mode 100644 src/dotnet-library/scala/CountedIterator.scala create mode 100644 src/dotnet-library/scala/Enumeration.scala create mode 100644 src/dotnet-library/scala/Function.scala create mode 100644 src/dotnet-library/scala/Function0.scala create mode 100644 src/dotnet-library/scala/Function1.scala create mode 100644 src/dotnet-library/scala/Function2.scala create mode 100644 src/dotnet-library/scala/Function3.scala create mode 100644 src/dotnet-library/scala/Function4.scala create mode 100644 src/dotnet-library/scala/Function5.scala create mode 100644 src/dotnet-library/scala/Function6.scala create mode 100644 src/dotnet-library/scala/Function7.scala create mode 100644 src/dotnet-library/scala/Function8.scala create mode 100644 src/dotnet-library/scala/Function9.scala create mode 100644 src/dotnet-library/scala/Iterable.scala create mode 100644 src/dotnet-library/scala/IterableProxy.scala create mode 100644 src/dotnet-library/scala/Iterator.scala create mode 100644 src/dotnet-library/scala/List.scala create mode 100644 src/dotnet-library/scala/MatchError.scala create mode 100644 src/dotnet-library/scala/Math.scala create mode 100644 src/dotnet-library/scala/NotDefinedError.scala create mode 100644 src/dotnet-library/scala/Option.scala create mode 100644 src/dotnet-library/scala/Ordered.scala create mode 100644 src/dotnet-library/scala/PartialFunction.scala create mode 100644 src/dotnet-library/scala/PartiallyOrdered.scala create mode 100644 src/dotnet-library/scala/Predef.scala create mode 100644 src/dotnet-library/scala/Product.scala create mode 100644 src/dotnet-library/scala/Product1.scala create mode 100644 src/dotnet-library/scala/Product10.scala create mode 100644 src/dotnet-library/scala/Product11.scala create mode 100644 src/dotnet-library/scala/Product12.scala create mode 100644 src/dotnet-library/scala/Product13.scala create mode 100644 src/dotnet-library/scala/Product14.scala create mode 100644 src/dotnet-library/scala/Product15.scala create mode 100644 src/dotnet-library/scala/Product16.scala create mode 100644 src/dotnet-library/scala/Product17.scala create mode 100644 src/dotnet-library/scala/Product18.scala create mode 100644 src/dotnet-library/scala/Product19.scala create mode 100644 src/dotnet-library/scala/Product2.scala create mode 100644 src/dotnet-library/scala/Product20.scala create mode 100644 src/dotnet-library/scala/Product21.scala create mode 100644 src/dotnet-library/scala/Product22.scala create mode 100644 src/dotnet-library/scala/Product3.scala create mode 100644 src/dotnet-library/scala/Product4.scala create mode 100644 src/dotnet-library/scala/Product5.scala create mode 100644 src/dotnet-library/scala/Product6.scala create mode 100644 src/dotnet-library/scala/Product7.scala create mode 100644 src/dotnet-library/scala/Product8.scala create mode 100644 src/dotnet-library/scala/Product9.scala create mode 100644 src/dotnet-library/scala/Proxy.scala create mode 100644 src/dotnet-library/scala/Responder.scala create mode 100644 src/dotnet-library/scala/ScalaObject.scala create mode 100644 src/dotnet-library/scala/Seq.scala create mode 100644 src/dotnet-library/scala/SeqProxy.scala create mode 100644 src/dotnet-library/scala/SerialVersionUID.scala create mode 100644 src/dotnet-library/scala/StaticAttribute.scala create mode 100644 src/dotnet-library/scala/Stream.scala create mode 100644 src/dotnet-library/scala/Symbol.scala create mode 100644 src/dotnet-library/scala/Tuple1.scala create mode 100644 src/dotnet-library/scala/Tuple10.scala create mode 100644 src/dotnet-library/scala/Tuple11.scala create mode 100644 src/dotnet-library/scala/Tuple12.scala create mode 100644 src/dotnet-library/scala/Tuple13.scala create mode 100644 src/dotnet-library/scala/Tuple14.scala create mode 100644 src/dotnet-library/scala/Tuple15.scala create mode 100644 src/dotnet-library/scala/Tuple16.scala create mode 100644 src/dotnet-library/scala/Tuple17.scala create mode 100644 src/dotnet-library/scala/Tuple18.scala create mode 100644 src/dotnet-library/scala/Tuple19.scala create mode 100644 src/dotnet-library/scala/Tuple2.scala create mode 100644 src/dotnet-library/scala/Tuple20.scala create mode 100644 src/dotnet-library/scala/Tuple21.scala create mode 100644 src/dotnet-library/scala/Tuple22.scala create mode 100644 src/dotnet-library/scala/Tuple3.scala create mode 100644 src/dotnet-library/scala/Tuple4.scala create mode 100644 src/dotnet-library/scala/Tuple5.scala create mode 100644 src/dotnet-library/scala/Tuple6.scala create mode 100644 src/dotnet-library/scala/Tuple7.scala create mode 100644 src/dotnet-library/scala/Tuple8.scala create mode 100644 src/dotnet-library/scala/Tuple9.scala create mode 100644 src/dotnet-library/scala/cloneable.scala create mode 100644 src/dotnet-library/scala/collection/BitSet.scala create mode 100644 src/dotnet-library/scala/collection/Map.scala create mode 100644 src/dotnet-library/scala/collection/MapProxy.scala create mode 100644 src/dotnet-library/scala/collection/Set.scala create mode 100644 src/dotnet-library/scala/collection/SetProxy.scala create mode 100644 src/dotnet-library/scala/collection/immutable/BitSet.scala create mode 100755 src/dotnet-library/scala/collection/immutable/EmptyMap.scala create mode 100755 src/dotnet-library/scala/collection/immutable/EmptySet.scala create mode 100755 src/dotnet-library/scala/collection/immutable/HashMap.scala create mode 100755 src/dotnet-library/scala/collection/immutable/HashSet.scala create mode 100644 src/dotnet-library/scala/collection/immutable/ListMap.scala create mode 100644 src/dotnet-library/scala/collection/immutable/ListSet.scala create mode 100644 src/dotnet-library/scala/collection/immutable/Map.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Map1.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Map2.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Map3.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Map4.scala create mode 100644 src/dotnet-library/scala/collection/immutable/Queue.scala create mode 100755 src/dotnet-library/scala/collection/immutable/RedBlack.scala create mode 100644 src/dotnet-library/scala/collection/immutable/Set.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Set1.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Set2.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Set3.scala create mode 100755 src/dotnet-library/scala/collection/immutable/Set4.scala create mode 100644 src/dotnet-library/scala/collection/immutable/Stack.scala create mode 100644 src/dotnet-library/scala/collection/immutable/Tree.scala create mode 100644 src/dotnet-library/scala/collection/immutable/TreeMap.scala create mode 100755 src/dotnet-library/scala/collection/immutable/TreeMap.scala.disabled create mode 100644 src/dotnet-library/scala/collection/immutable/TreeSet.scala create mode 100755 src/dotnet-library/scala/collection/immutable/UnbalancedTreeMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/ArrayList.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Buffer.scala create mode 100644 src/dotnet-library/scala/collection/jcl/BufferIterator.scala create mode 100644 src/dotnet-library/scala/collection/jcl/BufferWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Collection.scala create mode 100644 src/dotnet-library/scala/collection/jcl/CollectionWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/HashMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/HashSet.scala create mode 100644 src/dotnet-library/scala/collection/jcl/IdentityHashMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/IterableWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/LinkedHashMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/LinkedHashSet.scala create mode 100644 src/dotnet-library/scala/collection/jcl/LinkedList.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Map.scala create mode 100644 src/dotnet-library/scala/collection/jcl/MapWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/MutableIterable.scala create mode 100644 src/dotnet-library/scala/collection/jcl/MutableIterator.scala create mode 100644 src/dotnet-library/scala/collection/jcl/MutableSeq.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Ranged.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SeqIterator.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Set.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SetWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Sorted.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SortedMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SortedMapWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SortedSet.scala create mode 100644 src/dotnet-library/scala/collection/jcl/SortedSetWrapper.scala create mode 100644 src/dotnet-library/scala/collection/jcl/Tests.scala create mode 100644 src/dotnet-library/scala/collection/jcl/TreeMap.scala create mode 100644 src/dotnet-library/scala/collection/jcl/TreeSet.scala create mode 100644 src/dotnet-library/scala/collection/jcl/WeakHashMap.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ArrayBuffer.scala create mode 100644 src/dotnet-library/scala/collection/mutable/BitSet.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Buffer.scala create mode 100644 src/dotnet-library/scala/collection/mutable/BufferProxy.scala create mode 100755 src/dotnet-library/scala/collection/mutable/DefaultEntry.scala create mode 100644 src/dotnet-library/scala/collection/mutable/DefaultMapModel.scala create mode 100644 src/dotnet-library/scala/collection/mutable/DoubleLinkedList.scala create mode 100755 src/dotnet-library/scala/collection/mutable/FlatHashTable.scala create mode 100644 src/dotnet-library/scala/collection/mutable/HashMap.scala create mode 100644 src/dotnet-library/scala/collection/mutable/HashSet.scala create mode 100644 src/dotnet-library/scala/collection/mutable/HashTable.scala create mode 100644 src/dotnet-library/scala/collection/mutable/History.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ImmutableMapAdaptor.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ImmutableSetAdaptor.scala create mode 100644 src/dotnet-library/scala/collection/mutable/JavaMapAdaptor.scala create mode 100644 src/dotnet-library/scala/collection/mutable/JavaSetAdaptor.scala create mode 100644 src/dotnet-library/scala/collection/mutable/LinkedHashSet.scala create mode 100644 src/dotnet-library/scala/collection/mutable/LinkedList.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ListBuffer.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Location.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Map.scala create mode 100644 src/dotnet-library/scala/collection/mutable/MapProxy.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Message.scala create mode 100644 src/dotnet-library/scala/collection/mutable/MultiMap.scala create mode 100644 src/dotnet-library/scala/collection/mutable/MutableList.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ObservableBuffer.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ObservableMap.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ObservableSet.scala create mode 100644 src/dotnet-library/scala/collection/mutable/PriorityQueue.scala create mode 100644 src/dotnet-library/scala/collection/mutable/PriorityQueueProxy.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Publisher.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Queue.scala create mode 100644 src/dotnet-library/scala/collection/mutable/QueueProxy.scala create mode 100644 src/dotnet-library/scala/collection/mutable/ResizableArray.scala create mode 100644 src/dotnet-library/scala/collection/mutable/RevertableHistory.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Scriptable.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Set.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SetProxy.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SingleLinkedList.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Stack.scala create mode 100644 src/dotnet-library/scala/collection/mutable/StackProxy.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Subscriber.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedBuffer.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedMap.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedPriorityQueue.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedQueue.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedSet.scala create mode 100644 src/dotnet-library/scala/collection/mutable/SynchronizedStack.scala create mode 100644 src/dotnet-library/scala/collection/mutable/Undoable.scala create mode 100644 src/dotnet-library/scala/compat/Math.scala create mode 100644 src/dotnet-library/scala/compat/Platform.scala create mode 100644 src/dotnet-library/scala/compat/StringBuilder.scala create mode 100644 src/dotnet-library/scala/concurrent/Actor.scala create mode 100644 src/dotnet-library/scala/concurrent/Channel.scala create mode 100644 src/dotnet-library/scala/concurrent/Lock.scala create mode 100644 src/dotnet-library/scala/concurrent/MailBox.scala create mode 100644 src/dotnet-library/scala/concurrent/NameServer.scala create mode 100644 src/dotnet-library/scala/concurrent/Pid.scala create mode 100644 src/dotnet-library/scala/concurrent/Process.scala create mode 100644 src/dotnet-library/scala/concurrent/SyncChannel.scala create mode 100644 src/dotnet-library/scala/concurrent/SyncVar.scala create mode 100644 src/dotnet-library/scala/concurrent/TIMEOUT.scala create mode 100644 src/dotnet-library/scala/concurrent/jolib.scala create mode 100644 src/dotnet-library/scala/concurrent/ops.scala create mode 100644 src/dotnet-library/scala/concurrent/pilib.scala create mode 100755 src/dotnet-library/scala/deprecated.scala create mode 100644 src/dotnet-library/scala/io/BytePickle.scala create mode 100644 src/dotnet-library/scala/io/Position.scala create mode 100644 src/dotnet-library/scala/io/Source.scala create mode 100644 src/dotnet-library/scala/io/UTF8Codec.scala create mode 100644 src/dotnet-library/scala/mobile/Code.scala create mode 100644 src/dotnet-library/scala/mobile/Location.scala create mode 100644 src/dotnet-library/scala/reflect/BeanProperty.scala create mode 100644 src/dotnet-library/scala/reflect/Code.scala create mode 100644 src/dotnet-library/scala/reflect/Print.scala create mode 100644 src/dotnet-library/scala/reflect/Symbol.scala create mode 100644 src/dotnet-library/scala/reflect/Tree.scala create mode 100644 src/dotnet-library/scala/reflect/Type.scala create mode 100644 src/dotnet-library/scala/reflect/TypedCode.scala create mode 100644 src/dotnet-library/scala/remote.scala create mode 100644 src/dotnet-library/scala/runtime/BooleanRef.java create mode 100644 src/dotnet-library/scala/runtime/BoxedAnyArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedBoolean.java create mode 100644 src/dotnet-library/scala/runtime/BoxedBooleanArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedByte.java create mode 100644 src/dotnet-library/scala/runtime/BoxedByteArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedChar.java create mode 100644 src/dotnet-library/scala/runtime/BoxedCharArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedDouble.java create mode 100644 src/dotnet-library/scala/runtime/BoxedDoubleArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedFloat.java create mode 100644 src/dotnet-library/scala/runtime/BoxedFloatArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedInt.java create mode 100644 src/dotnet-library/scala/runtime/BoxedIntArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedLong.java create mode 100644 src/dotnet-library/scala/runtime/BoxedLongArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedNumber.java create mode 100644 src/dotnet-library/scala/runtime/BoxedObjectArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedShort.java create mode 100644 src/dotnet-library/scala/runtime/BoxedShortArray.scala create mode 100644 src/dotnet-library/scala/runtime/BoxedUnit.java create mode 100644 src/dotnet-library/scala/runtime/ByteRef.java create mode 100644 src/dotnet-library/scala/runtime/CharRef.java create mode 100644 src/dotnet-library/scala/runtime/DoubleRef.java create mode 100644 src/dotnet-library/scala/runtime/ExceptionHandling.java create mode 100644 src/dotnet-library/scala/runtime/FloatRef.java create mode 100644 src/dotnet-library/scala/runtime/IntRef.java create mode 100644 src/dotnet-library/scala/runtime/LongRef.java create mode 100644 src/dotnet-library/scala/runtime/NonLocalReturnException.scala create mode 100644 src/dotnet-library/scala/runtime/Nothing$.scala create mode 100644 src/dotnet-library/scala/runtime/Null$.scala create mode 100644 src/dotnet-library/scala/runtime/ObjectRef.java create mode 100644 src/dotnet-library/scala/runtime/RichBoolean.scala create mode 100644 src/dotnet-library/scala/runtime/RichByte.scala create mode 100644 src/dotnet-library/scala/runtime/RichChar.scala create mode 100644 src/dotnet-library/scala/runtime/RichDouble.scala create mode 100644 src/dotnet-library/scala/runtime/RichException.scala create mode 100644 src/dotnet-library/scala/runtime/RichFloat.scala create mode 100644 src/dotnet-library/scala/runtime/RichInt.scala create mode 100644 src/dotnet-library/scala/runtime/RichLong.scala create mode 100644 src/dotnet-library/scala/runtime/RichShort.scala create mode 100644 src/dotnet-library/scala/runtime/RichString.scala create mode 100644 src/dotnet-library/scala/runtime/ScalaRunTime.scala create mode 100644 src/dotnet-library/scala/runtime/ShortRef.java create mode 100644 src/dotnet-library/scala/runtime/StringAdd.scala create mode 100644 src/dotnet-library/scala/serializable.scala create mode 100644 src/dotnet-library/scala/testing/Benchmark.scala create mode 100644 src/dotnet-library/scala/testing/SUnit.scala create mode 100644 src/dotnet-library/scala/testing/UnitTest.scala create mode 100644 src/dotnet-library/scala/text/Document.scala create mode 100644 src/dotnet-library/scala/throws.scala create mode 100644 src/dotnet-library/scala/transient.scala create mode 100644 src/dotnet-library/scala/util/Fluid.scala create mode 100644 src/dotnet-library/scala/util/Sorting.scala create mode 100644 src/dotnet-library/scala/util/automata/BaseBerrySethi.scala create mode 100644 src/dotnet-library/scala/util/automata/DetWordAutom.scala create mode 100644 src/dotnet-library/scala/util/automata/Inclusion.scala create mode 100644 src/dotnet-library/scala/util/automata/NondetWordAutom.scala create mode 100644 src/dotnet-library/scala/util/automata/SubsetConstruction.scala create mode 100644 src/dotnet-library/scala/util/automata/WordBerrySethi.scala create mode 100644 src/dotnet-library/scala/util/grammar/HedgeRHS.scala create mode 100644 src/dotnet-library/scala/util/grammar/TreeRHS.scala create mode 100644 src/dotnet-library/scala/util/logging/ConsoleLogger.scala create mode 100644 src/dotnet-library/scala/util/logging/Logged.scala create mode 100644 src/dotnet-library/scala/util/parsing/CharInputStreamIterator.scala create mode 100644 src/dotnet-library/scala/util/parsing/Parsers.scala create mode 100644 src/dotnet-library/scala/util/parsing/SimpleTokenizer.scala create mode 100644 src/dotnet-library/scala/util/regexp/Base.scala create mode 100644 src/dotnet-library/scala/util/regexp/PointedHedgeExp.scala create mode 100644 src/dotnet-library/scala/util/regexp/SyntaxError.scala create mode 100644 src/dotnet-library/scala/util/regexp/WordExp.scala create mode 100644 src/dotnet-library/scala/volatile.scala create mode 100644 src/dotnet-library/scala/xml/Atom.scala create mode 100644 src/dotnet-library/scala/xml/Comment.scala create mode 100644 src/dotnet-library/scala/xml/Document.scala create mode 100644 src/dotnet-library/scala/xml/Elem.scala create mode 100644 src/dotnet-library/scala/xml/EntityRef.scala create mode 100644 src/dotnet-library/scala/xml/Group.scala create mode 100644 src/dotnet-library/scala/xml/MalformedAttributeException.scala create mode 100644 src/dotnet-library/scala/xml/MetaData.scala create mode 100644 src/dotnet-library/scala/xml/NamespaceBinding.scala create mode 100644 src/dotnet-library/scala/xml/Node.scala create mode 100644 src/dotnet-library/scala/xml/NodeBuffer.scala create mode 100644 src/dotnet-library/scala/xml/NodeSeq.scala create mode 100644 src/dotnet-library/scala/xml/NodeTraverser.scala create mode 100644 src/dotnet-library/scala/xml/Null.scala create mode 100644 src/dotnet-library/scala/xml/Parsing.scala create mode 100644 src/dotnet-library/scala/xml/PrefixedAttribute.scala create mode 100644 src/dotnet-library/scala/xml/PrettyPrinter.scala create mode 100644 src/dotnet-library/scala/xml/ProcInstr.scala create mode 100644 src/dotnet-library/scala/xml/SpecialNode.scala create mode 100644 src/dotnet-library/scala/xml/Text.scala create mode 100644 src/dotnet-library/scala/xml/TextBuffer.scala create mode 100644 src/dotnet-library/scala/xml/TopScope.scala create mode 100644 src/dotnet-library/scala/xml/TypeSymbol.scala create mode 100644 src/dotnet-library/scala/xml/Unparsed.scala create mode 100644 src/dotnet-library/scala/xml/UnprefixedAttribute.scala create mode 100644 src/dotnet-library/scala/xml/Utility.scala create mode 100644 src/dotnet-library/scala/xml/XML.scala create mode 100644 src/dotnet-library/scala/xml/dtd/ContentModel.scala create mode 100644 src/dotnet-library/scala/xml/dtd/ContentModelParser.scala create mode 100644 src/dotnet-library/scala/xml/dtd/DTD.scala create mode 100644 src/dotnet-library/scala/xml/dtd/Decl.scala create mode 100644 src/dotnet-library/scala/xml/dtd/DocType.scala create mode 100644 src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala create mode 100644 src/dotnet-library/scala/xml/dtd/ElementValidator.scala create mode 100644 src/dotnet-library/scala/xml/dtd/ExternalID.scala create mode 100644 src/dotnet-library/scala/xml/dtd/Scanner.scala create mode 100644 src/dotnet-library/scala/xml/dtd/Tokens.scala create mode 100644 src/dotnet-library/scala/xml/dtd/ValidationException.scala create mode 100644 src/dotnet-library/scala/xml/factory/Binder.scala create mode 100644 src/dotnet-library/scala/xml/factory/LoggedNodeFactory.scala create mode 100644 src/dotnet-library/scala/xml/factory/NodeFactory.scala create mode 100644 src/dotnet-library/scala/xml/parsing/ConstructingHandler.scala create mode 100644 src/dotnet-library/scala/xml/parsing/ConstructingParser.scala create mode 100644 src/dotnet-library/scala/xml/parsing/DefaultMarkupHandler.scala create mode 100644 src/dotnet-library/scala/xml/parsing/ExternalSources.scala create mode 100644 src/dotnet-library/scala/xml/parsing/FactoryAdapter.scala create mode 100644 src/dotnet-library/scala/xml/parsing/FatalError.scala create mode 100644 src/dotnet-library/scala/xml/parsing/MarkupHandler.scala create mode 100644 src/dotnet-library/scala/xml/parsing/MarkupParser.scala create mode 100644 src/dotnet-library/scala/xml/parsing/NoBindingFactoryAdapter.scala create mode 100644 src/dotnet-library/scala/xml/parsing/TokenTests.scala create mode 100644 src/dotnet-library/scala/xml/parsing/ValidatingMarkupHandler.scala create mode 100644 src/dotnet-library/scala/xml/path/Expression.scala create mode 100644 src/dotnet-library/scala/xml/pull/XMLEvent.scala create mode 100644 src/dotnet-library/scala/xml/pull/XMLEventReader.scala create mode 100644 src/dotnet-library/scala/xml/transform/BasicTransformer.scala create mode 100644 src/dotnet-library/scala/xml/transform/RewriteRule.scala create mode 100644 src/dotnet-library/scala/xml/transform/RuleTransformer.scala (limited to 'src') 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 scala.All. If such type appears in method + * signatures, it is erased to this one. + * + * @deprecated To be removed at some time in the future. Kept only for + * backward compatibility. Newly compiled code will refer to + * scala.runtime.Nothing$ + */ + +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 scala.AllRef. If such type appears in method + * signatures, it is erased to this one. + * + * @deprecated To be removed at some time in the future. Kept only for + * backward compatibility. Newly compiled code will refer to + * scala.runtime.Null$ + */ + +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 Application class can be used to quickly turn objects + * into executable programs. Here is an example: + *
+ *  object Main extends Application {
+ *    Console.println("Hello World!")
+ *  }
+ *  
+ * Here, object Main inherits the main method + * of Application. The body of the Main 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 Application by setting the global scala.time property. + * Here is an example for benchmarking object Main: + *
+ *  java -Dscala.time Main
+ *  
+ * + * @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 + * System.arraycopy(src, srcPos, dest, destPos, length), + * 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 0; xs.apply(0) is the first + * element of array xs. + * Note the indexing syntax xs(i) is a shorthand for xs.apply(i). + * @param i the index + * @throws ArrayIndexOutOfBoundsException if i < 0 or + * length <= i + */ + def apply(i: Int): A = throw new Error() + + /** Update the element at given index. + * Indices start a 0; xs.apply(0) is the first + * element of array xs. + * Note the indexing syntax xs(i) = x is a shorthand + * for xs.update(i, x). + * @param i the index + * @param x the value to be written at index i + * @throws ArrayIndexOutOfBoundsException if i < 0 or + * length <= i + */ + 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 len elements + * starting at index from + * @param from The index of the first element of the slice + * @param end The index of the element following the slice + * @throws IndexOutOfBoundsException if from < 0 + * or length < from + len + */ + 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 p. The order of the elements is preserved. + * + * @param p the predicate used to filter the array. + * @return the elements of this array satisfying p. + */ + override def filter(p: A => Boolean): Array[A] = throw new Error() + + /** Returns the array resulting from applying the given function f to each + * element of this array. + * + * @param f function to apply to each element. + * @return [f(a0), ..., f(an)] if this array is [a0, ..., an]. + */ + override def map[B](f: A => B): Array[B] = throw new Error() + + /** Applies the given function f to each element of + * this array, then concatenates the results. + * + * @param f the function to apply on each element. + * @return f(a0) ::: ... ::: f(an) if + * this array is [a0, ..., an]. + */ + override def flatMap[B](f: A => Iterable[B]): Array[B] = throw new Error() + + /** Returns an array formed from this array and the specified array + * that 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 Array({a0,b0}, ..., + * {amin(m,n),bmin(m,n)}) when + * Array(a0, ..., am) + * zip Array(b0, ..., bn) 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 Array({a0,0}, {a1,1},...) + * where ai 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 + +/**

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 StaticAttribute or/and ClassfileAttribute. + *

+ * + * @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 BigInt whose value is equal to that of the + * specified integer value. + * + * @param i the specified integer value + * @return the constructed BigInt + */ + 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 BigInt whose value is equal to that of the + * specified long value. + * + * @param l the specified long value + * @return the constructed BigInt + */ + 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 radix 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 int to BigInt. + */ + 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 Ordered. + */ + 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 (this raised to the power of exp). + */ + def pow (exp: Int): BigInt = new BigInt(this.bigInteger.pow(exp)) + + /** Returns a BigInt whose value is + * (this raised to the power of exp modulo m). + */ + 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 this modulo m). + */ + 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 byte. + * 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 short. + * 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 char. + * 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 int. + * 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 long. + * 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 float. + * if this BigInt has too great a magnitude to represent as a float, + * it will be converted to Float.NEGATIVE_INFINITY or + * Float.POSITIVE_INFINITY as appropriate. + */ + def floatValue = this.bigInteger.floatValue + + /** Converts this BigInt to a double. + * if this BigInt has too great a magnitude to represent as a float, + * it will be converted to Float.NEGATIVE_INFINITY or + * Float.POSITIVE_INFINITY 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 PartialFunction[A, B] is a + * unary function where the domain does not include all values of type + * A. The function isDefinedAt 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() = "" +} + 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 Cell is a generic wrapper which completely + * hides the functionality of the wrapped object. The wrapped + * object is accessible via the elem 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 + +/**

A base class for classfile attributes. These are stored as + * Java annotations in classfiles. + *

+ * + * @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 Console object implements functionality for + * printing Scala values on the terminal. There are also functions + * for reading specific values. Console 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) + + /**

+ * Format and print out some text (in a fashion similar to printf in C or + * printf in Java 6). + *

+ *

+ * The format of the text to print is specified by the parameter + * text. The arguments that are inserted into specific + * locations in text are provided with parameter + * args. See class java.text.MessageFormat + * for a full specification of the format syntax. + *

+ * + * @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 Console.printf. + */ + 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 java.text.MessageFormat 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 readf, 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 readf, 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 readf, 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} + +/** + *

The class Enumeration provides the same functionality as the + * enum construct found in C-like languages like C++ or Java. + * Here is an example:

+ *
+ * object Main extends Application {
+ *
+ *   object WeekDays extends Enumeration  {
+ *     val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ *   }
+ *
+ *   def isWorkingDay(d: WeekDays.Value) =
+ *     ! (d == WeekDays.Sat || d == WeekDays.Sun)
+ *
+ *   WeekDays filter (isWorkingDay) foreach { d => Console.println(d) }
+ * }
+ * 
+ * + * @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 f1, ..., + * fn, return the function f1 + * andThen ... andThen fn. + * + * @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 + + +/**

+ * Function with 0 parameters. + *

+ *

+ In the following example the definition of + * currentSeconds is a shorthand for the anonymous class + * definition anonfun0: + *

+ *
+ *  object Main extends Application {
+ *
+ *    val currentSeconds = () => System.currentTimeMillis() / 1000L
+ *
+ *    val anonfun0 = new Function0[Long] {
+ *      def apply(): Long = System.currentTimeMillis() / 1000L
+ *    }
+ *
+ *    Console.println(currentSeconds())
+ *    Console.println(anonfun0())
+ *  }
+ */ +trait Function0[+R] extends AnyRef { + def apply(): R + override def toString() = "" + +} 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 + + +/**

+ * Function with 1 parameters. + *

+ *

+ In the following example the definition of + * succ is a shorthand for the anonymous class definition + * anonfun1: + *

+ *
+ *  object Main extends Application {
+ *
+ *    val succ = (x: Int) => x + 1
+ *
+ *    val anonfun1 = new Function1[Int, Int] {
+ *      def apply(x: Int): Int = x + 1
+ *    }
+ *
+ *    Console.println(succ(0))
+ *    Console.println(anonfun1(0))
+ *  }
+ */ +trait Function1[-T1, +R] extends AnyRef { + def apply(v1:T1): R + override def toString() = "" + + /** (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 + + +/**

+ * Function with 2 parameters. + *

+ *

+ In the following example the definition of + * max is a shorthand for the anonymous class definition + * anonfun2: + *

+ *
+ *  object Main extends Application {
+ *
+ *    val max = (x: Int, y: Int) => if (x < y) y else x
+ *
+ *    val anonfun2 = new Function2[Int, Int, Int] {
+ *      def apply(x: Int, y: Int): Int = if (x < y) y else x
+ *    }
+ *
+ *    Console.println(max(0, 1))
+ *    Console.println(anonfun2(0, 1))
+ *  }
+ */ +trait Function2[-T1, -T2, +R] extends AnyRef { + def apply(v1:T1, v2:T2): R + override def toString() = "" + +} 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 + + +/**

+ * Function with 3 parameters. + *

+ * + */ +trait Function3[-T1, -T2, -T3, +R] extends AnyRef { + def apply(v1:T1, v2:T2, v3:T3): R + override def toString() = "" + +} 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 + + +/**

+ * Function with 4 parameters. + *

+ * + */ +trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { + def apply(v1:T1, v2:T2, v3:T3, v4:T4): R + override def toString() = "" + +} 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 + + +/**

+ * Function with 5 parameters. + *

+ * + */ +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() = "" + +} 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 + + +/**

+ * Function with 6 parameters. + *

+ * + */ +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() = "" + +} 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 + + +/**

+ * Function with 7 parameters. + *

+ * + */ +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() = "" + +} 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 + + +/**

+ * Function with 8 parameters. + *

+ * + */ +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() = "" + +} 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() = "" +} 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()") + 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()") + 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 + * elements 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 ++ 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 + * f to each element of this iterable. + * + * @param f function to apply to each element. + * @return f(a0), ..., f(an) + * if this iterable is a0, ..., an. + */ + 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 f to each element of + * this iterable, then concatenates the results. + * + * @param f the function to apply on each element. + * @return f(a0) ::: ... ::: f(an) if + * this iterable is a0, ..., an. + */ + 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 p. The order of the elements is preserved. + * + * @param p the predicate used to filter the list. + * @return the elements of this list satisfying p. + */ + 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 p. + * + * @param p the test predicate. + * @return the longest prefix of this iterable whose elements satisfy + * the predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return the longest suffix of the iterable whose first element + * does not satisfy the predicate p. + */ + def dropWhile(p: A => Boolean): Iterable[A] = + new ArrayBuffer[A] ++ elements.dropWhile(p) + + /** Returns an iterable consisting only over the first n + * elements of this iterable, or else the whole iterable, if it has less + * than n 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 n first elements + * If this iterable has less than n 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 f 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 p 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 p to all elements of this + * iterable object and return true, iff there is at least one + * element for which p 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 p, + * or None 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 p, + * 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 f, from left to right, and starting with + * the value z. + * + * @return f(... (f(f(z, a0), a1) ...), + * an) if the list is + * [a0, a1, ..., an]. + */ + 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 f, from right to left, and starting with + * the value z. + * + * @return f(a0, f(a1, f(..., f(an, z)...))) + * if the list is [a0, a1, ..., an]. + */ + def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op) + + /** Similar to foldLeft but can be used as + * an operator with the order of list and zero arguments reversed. + * That is, z /: xs is the same as xs foldLeft z + */ + def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) + + /** An alias for foldRight. + * That is, xs :\ z is the same as xs foldRight z + */ + def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op) + + /** Combines the elements of this iterable object together using the binary + * operator op, from left to right + * @param op The operator to apply + * @return op(... op(a0,a1), ..., an) + if the iterable object has elements + * a0, a1, ..., an. + * @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 op, from right to left + * @param op The operator to apply + * + * @return a0 op (... op (an-1 op an)...) + * if the iterable object has elements a0, a1, ..., + * an. + * + * @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 start and is finished by the string + * end. Inside, the string representations of elements (w.r.t. + * the method toString()) are separated by the string + * sep. + *

+ * Ex:
+ * List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)" + * + * @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 toString()) + * are separated by the string sep. + * + * @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 Iterator 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 xs. + */ + 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 str + */ + 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 Product<n>. + */ + 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 fromProduct instead. + */ + [deprecated] def fromCaseClass(n: Product) = fromProduct(n) + + /** Create an iterator with elements + * en+1 = en + 1 + * where e0 = lo + * and ei < end. + * + * @param lo the start value of the iterator + * @param end the end value of the iterator + * @return the iterator with values in range [lo;end). + */ + def range(lo: Int, end: Int): Iterator[Int] = + range(lo, end, 1) + + /** Create an iterator with elements + * en+1 = en + step + * where e0 = lo + * and ei < end. + * + * @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 [lo;end). + */ + 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 + * en+1 = step(en) + * where e0 = lo + * and ei < end. + * + * @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 [lo;end). + */ + 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 + * en+1 = en + 1 + * where e0 = lo. + * + * @param lo the start value of the iterator + * @return the iterator starting at value lo. + */ + def from(lo: Int): Iterator[Int] = + from(lo, 1) + + /** Create an iterator with elements + * en+1 = en + step + * where e0 = lo. + * + * @param lo the start value of the iterator + * @param step the increment value of the iterator + * @return the iterator starting at value lo. + */ + 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 + * en+1 = step(en) + * where e0 = lo. + * + * @param lo the start value of the iterator + * @param step the increment function of the iterator + * @return the iterator starting at value lo. + */ + 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 hasNext method for checking + * if there is a next element available, and a next 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 n + * 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 n 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 f. + */ + 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 that. + * @deprecated use ++ + */ + 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 that. + */ + 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 f to each element of + * this iterator, then concatenates the results. + * + * @param f the function to apply on each element. + * @return an iterator over f(a0), ... , + * f(an) if this iterator yields the + * elements a0, ..., an. + */ + 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 p. The order of the elements + * is preserved. + * + * @param p the predicate used to filter the iterator. + * @return the elements of this iterator satisfying p. + */ + 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 p. + * The order of the elements is preserved. + * + * @param p the predicate used to filter the iterator. + * @return the longest prefix of this iterator satisfying p. + */ + def takeWhile(p: A => Boolean): Iterator[A] = predicatedIterator(p, false) + + /** Skips longest sequence of elements of this iterator which satisfy given + * predicate p, 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 + * that 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 {a0,b0}, + * {a1,b1}, ... where + * ai are the elements from this iterator + * and bi are the elements from iterator + * that. + */ + 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 {a0,0}, + * {a1,1}... where ai + * 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 f 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 p 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 = { + var res = true + while (res && hasNext) { res = p(next) } + res + } + + /** Apply a predicate p to all elements of this + * iterable object and return true, iff there is at least one + * element for which p yields true. + * + * @param p the predicate + * @return true iff the predicate yields true + * 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 elem is a member of this iterator. + * + * @param elem element whose membership has to be tested. + * @return true iff there is an element of this iterator which + * is equal (w.r.t. ==) to elem. + */ + 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 + * p, or None 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 op, from left to right, and starting with + * the value z. + * + * @return op(... (op(op(z,a0),a1) ...), + * an) if the iterator yields elements + * a0, a1, ..., an. + */ + 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 op, from right to left, and starting with + * the value z. + * + * @return a0 op (... op (an op z)...) + * if the iterator yields elements a0, a1, ..., + * an. + */ + 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 foldLeft but can be used as + * an operator with the order of iterator and zero arguments reversed. + * That is, z /: xs is the same as xs foldLeft z. + * + * @param z the left argument of the first application of op + * (evaluation occurs from left to right). + * @param op the applied operator. + * @return the result value + * @see foldLeft. + */ + def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) + + /** An alias for foldRight. + * That is, xs :\ z is the same as xs foldRight z. + * + * @param z the right argument of the first application of op + * (evaluation occurs from right to left). + * @param op the applied operator. + * @return the result value. + * @see foldRight. + */ + def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op) + + /** Combines the elements of this iterator together using the binary + * operator op, from left to right + * @param op The operator to apply + * @return op(... op(a0,a1), ..., an) + if the iterator yields elements + * a0, a1, ..., an. + * @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 op, from right to left + * @param op The operator to apply + * + * @return a0 op (... op (an-1 op an)...) + * if the iterator yields elements a0, a1, ..., + * an. + + * @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 xs with the elements of + * this sequence starting at position start. + * + * @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 start and is finished by the string + * end. Inside, the string representations of elements (w.r.t. + * the method toString()) are separated by the string + * sep. + *

+ * Ex:
+ * List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)" + * + * @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 toString()) + * are separated by the string sep. + * + * @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 n, + * returns the nth element of the resulting list, where + * n is in interval [0;n). + * @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 it.next + */ + 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 arr + * 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 arr + * 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 xs unchanged if function + * f 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 f + * to corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return [f(a0,b0), ..., f(an,bn)] if the lists are + * [a0, ..., ak], [b0, ..., bl] and + * n = min(k,l) + */ + 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 f to + * corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return [f(a0,b0,c0), ..., f(an,bn,cn)] if the lists are + * [a0, ..., ak], [b0, ..., bl], [c0, ..., cm] and + * n = min(k,l,m) + */ + 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 p holds + * for all corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return n == 0 || (p(a0,b0) && + * ... && p(an,bn))] + * if the lists are [a0, ..., ak]; + * [b0, ..., bl] + * and m = min(k,l) + */ + 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 p holds + * for some corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return n != 0 && (p(a0,b0) || ... || p(an,bn))] if the lists are + * [a0, ..., ak], [b0, ..., bl] and + * m = min(k,l) + */ + 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 + * a. This class comes with two implementing case + * classes scala.Nil and scala.:: that + * implement the abstract members isEmpty, + * head and tail. + * + * @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 true, 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] + + /**

+ * Add an element x at the beginning of this list. + * Example: + *

+ *
+   *    1 :: List(2, 3) = List(2, 3).::(1) = List(1, 2, 3)
+ * + * @param x the element to append. + * @return the list with x appended at the beginning. + */ + def ::[b >: a] (x: b): List[b] = + new scala.::(x, this) + + /**

+ * Returns a list resulting from the concatenation of the given + * list prefix and this list. Example: + *

+ *
+   *    List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)
+ * + * @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 reverse + * on the prefix followed by a call to :::, 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 List.range(0, xs.length). + * + * @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 n first elements of this list, or else the whole + * list, if it has less than n elements. + * + * @param n the number of elements to take. + * @return the n 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 n first elements. + * If this list has less than n elements, the empty list is returned. + * + * @param n the number of elements to drop. + * @return the list without its n first elements. + */ + override def drop(n: Int): List[a] = + if (n == 0 || isEmpty) this + else (tail drop (n-1)) + + /** Returns the rightmost n elements from this list. + * + * @param n the number of elements to take + * @return the suffix of length n 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 n elements. + * + * @param n the number of elements to take + * @return the suffix of length n 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 n + * 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 p. + * + * @param p the test predicate. + * @return the longest prefix of this list whose elements satisfy + * the predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return the longest suffix of the list whose first element + * does not satisfy the predicate p. + */ + 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 p, 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 span but with the predicate inverted. + */ + def break(p: a => Boolean): {List[a], List[a]} = span { x => !p(x) } + + /** Returns the n-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 n 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 f to each + * element of this list. + * + * @param f function to apply to each element. + * @return [f(a0), ..., f(an)] if this list is [a0, ..., an]. + */ + 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 map + * followed by a call to reverse, 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 f 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 p. The order of the elements is preserved. + * + * @param p the predicate used to filter the list. + * @return the elements of this list satisfying p. + */ + 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 + * p. This is like filter with the + * predicate inversed. + * + * @param p the predicate to use to test elements + * @return the list without all elements which satisfy p + */ + 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 + * p 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} + } + + /**

+ * Sort the list according to the comparison function + * <(e1: a, e2: a) => Boolean, + * which should be true iff e1 is smaller than + * e2. Example: + *

+ *
+   *    List("Steve", "Tom", "John", "Bob")
+   *      .sort((e1, e2) => (e1 compareTo e2) < 0) =
+   *    List("Bob", "John", "Steve", "Tom")
+ *

+ * Note: The current implementation is inefficent for + * already sorted lists. + *

+ * + * @param lt the comparison function + * @return a list sorted according to the comparison function + * <(e1: a, e2: a) => Boolean. + */ + 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 p. + */ + 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 p is satisfied by all elements + * in this list. + * + * @param p the test predicate. + * @return true iff all elements of this list satisfy the + * predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return true iff there exists an element in this list that + * satisfies the predicate p. + */ + 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 p, + * or None 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 f, from left to right, and starting with + * the value z. + * + * @return f(... (f(f(z, a0), a1) ...), + * an) if the list is + * [a0, a1, ..., an]. + */ + 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 f, from right to left, and starting with + * the value z. + * + * @return f(a0, f(a1, f(..., f(an, z)...))) + * if the list is [a0, a1, ..., an]. + */ + 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 op, from left to right + * @param op The operator to apply + * @return op(... op(a0,a1), ..., an) + if the list has elements + * a0, a1, ..., an. + * @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 op, from right to left + * @param op The operator to apply + * + * @return a0 op (... op (an-1 op an)...) + * if the list has elements a0, a1, ..., + * an. + * + * @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 f to each element of + * this list, then concatenates the results. + * + * @param f the function to apply on each element. + * @return f(a0) ::: ... ::: f(an) if + * this list is [a0, ..., an]. + */ + 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 + * that 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 List({a0,b0}, ..., + * {amin(m,n),bmin(m,n)}) when + * List(a0, ..., am) + * zip List(b0, ..., bn) 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 List({a0,0}, {a1,1}...) + * where ai 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 + * that by associating each element of the former with + * the element at the same position in the latter. + * + * @param that list that may have a different length + * as the self list. + * @param thisElem element thisElem is used to fill up the + * resulting list if the self list is shorter than + * that + * @param thatElem element thatElem is used to fill up the + * resulting list if that is shorter than + * the self list + * @return List({a0,b0}, ..., + * {an,bn}, {elem,bn+1}, + * ..., {elem,bm}) + * when [a0, ..., an] zip + * [b0, ..., bm] is + * invoked where m > n. + */ + 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 + * that. + * + * @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 that. + */ + 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 + * that. + * + * @param that the list of elements to remove from this list. + * @return this list without the elements of the given list + * that. + */ + 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 + * that. + * + * @param that the list to intersect. + * @return the list of elements contained both in this list and + * in the given list that. + */ + def intersect[b >: a](that: List[b]): List[b] = filter(x => that contains x) + + /** Removes redundant elements from the list. Uses the method == + * 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 Math contains methods for performing basic numeric + * operations such as the elementary exponential, logarithm, square root, and + * trigonometric functions. + */ +object Math { + + /** The double value that is closer than any other to + * e, the base of the natural logarithms. + */ + val E = java.lang.Math.E + + /** The double value that is closer than any other to + * pi, the ratio of the circumference of a circle to its + * diameter. + */ + val Pi = java.lang.Math.PI + + /** Returns a double value with a positive sign, greater than + * or equal to 0.0 and less than 1.0. + */ + 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 x 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 x in degrees. + */ + def toDegrees(x: Double): Double = java.lang.Math.toDegrees(x) + + /** Returns Euler's number e raised to the power of a + * double value. + * + * @param x the exponent to raise e to. + * @return the value ea, where e + * 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 double value that is closest in value to the + * argument and is equal to a mathematical integer. + * + * @param x a double 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 (x, y) to polar + * (r, theta). + * + * @param x the ordinate coordinate + * @param y the abscissa coordinate + * @return the theta component of the point (r, theta) + * in polar coordinates that corresponds to the point + * (x, y) 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 xy. + */ + def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y) + + /** Returns the closest long to the argument. + * + * @param x a floating-point value to be rounded to a long. + * @return the value of the argument rounded to the nearest + * long 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 Option + * are either instances of case class Some or it is case + * object None. + * + * @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 None value, false otherwise. + */ + def isEmpty: Boolean + + /** True if the option is a Some(...) 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. Some(f(this.get)). + * 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 p + * yields false on its value, return None. + * 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 f 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 Some[A] represents existing values of type + * A. + * + * @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 this with operand that. + * returns x where + * x < 0 iff this < that + * x == 0 iff this == that + * x > 0 iff this > that + */ + 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 PartialFunction[A, B] is a + * unary function where the domain does not include all values of type + * A. The function isDefinedAt 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 x 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 this with operand that. + * Returns None if operands are not comparable. + * If operands are comparable, returns Some(x) where + * x < 0 iff this < that + * x == 0 iff this == that + * x > 0 iff this > that + */ + 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 Predef 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 Product 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 A(x_1,...,x_k)), returns x_(i+1) + * for 0 <= i < k + * + * @param n the position of the n-th element + * @throws IndexOutOfBoundsException + * @return ... + */ + def element(n: Int): Any + + /** return k for a product A(x_1,...,x_k)) + */ + 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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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<=n<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 Any to another object self. + * 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 + * a. + * + * @param x ... + * @return ... + */ + def constant[a](x: a) = new Responder[a] { + def respond(k: a => unit) = k(x) + } + + /** Executes x and returns true, 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 Seq[A] represents finite sequences of elements + * of type A. + * + * @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 ++ 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 x? + * + * @param x .. + * @return true, iff x 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 + * f to each element of this sequence. + * + * @param f function to apply to each element. + * @return f(a0), ..., f(an) if this + * sequence is a0, ..., an. + */ + 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 f to each element of + * this sequence, then concatenates the results. + * + * @param f the function to apply on each element. + * @return f(a0) ::: ... ::: f(an) if + * this sequence is a0, ..., an. + */ + 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 p. The order of the elements is preserved. + * + * @param p the predicate used to filter the list. + * @return the elements of this list satisfying p. + */ + override def filter(p: A => Boolean): Seq[A] = super.filter(p).asInstanceOf[Seq[A]] + + /** Returns a sequence consisting only over the first n + * elements of this sequence, or else the whole sequence, if it has less + * than n 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 n first elements + * If this sequence has less than n 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 p. + * + * @param p the test predicate. + * @return the longest prefix of this sequence whose elements satisfy + * the predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return the longest suffix of the sequence whose first element + * does not satisfy the predicate p. + */ + 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 elem is a member of this + * sequence. + * + * @param elem element whose membership has to be tested. + * @return true iff there is an element of this sequence + * which is equal (w.r.t. ==) to elem. + */ + def contains(elem: Any): Boolean = exists (.==(elem)) + + /** Returns a subsequence starting from index from + * consisting of len 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 from + * consisting of len elements. + * + * @deprecated use slice instead + */ + [deprecated] def subseq(from: Int, end: Int): Seq[A] = slice(from, end - from) + + /** Converts this sequence to a fresh Array with length elements. + */ + def toArray[B >: A]: Array[B] = { + val result = new Array[B](length) + copyToArray(result, 0) + result + } + + /** Fills the given array xs with the elements of + * this sequence starting at position start. + * + * @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 toString 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 + +/**

A base class for static attributes. These are available + * to the Scala typechecker, even across different compilation units. + *

+ * + * @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 Stream 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 + * vn+1 = vn + 1 + * where v0 = start + * and vi < end. + * + * @param start the start value of the stream + * @param end the end value of the stream + * @return the stream starting at value start. + */ + def range(start: Int, end: Int): Stream[Int] = + range(start, end, 1) + + /** + * Create a stream with element values + * vn+1 = vn + step + * where v0 = start + * and vi < end. + * + * @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 start. + */ + 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 + * vn+1 = step(vn) + * where v0 = start + * and vi < end. + * + * @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 start. + */ + 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 start + * and incrementing by step step + * + * @param start the start value of the stream + * @param step the increment value of the stream + * @return the stream starting at value start. + */ + def from(start: Int, step: Int): Stream[Int] = + cons(start, from(start+step, step)) + + /** + * Create an infinite stream starting at start + * and incrementing by 1. + * + * @param start the start value of the stream + * @return the stream starting at value start. + */ + def from(start: Int): Stream[Int] = from(start, 1) +} + +/** + *

The class Stream implements lazy lists where elements + * are only evaluated when they are needed. Here is an example:

+ *
+ * object Main extends Application {
+ *
+ *   def from(n: Int): Stream[Int] =
+ *     Stream.cons(n, from(n + 1))
+ *
+ *   def sieve(s: Stream[Int]): Stream[Int] =
+ *     Stream.cons(s.head, sieve(s.tail filter { x => x % s.head != 0 }))
+ *
+ *   def primes = sieve(from(2))
+ *
+ *   primes take 10 print
+ * }
+ * 
+ * + * @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 n-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 n in this stream. + * @throws Predef.NoSuchElementException if the stream is too short. + */ + def apply(n: Int) = drop(n).head + + /** Returns the n first elements of this stream, or else the whole + * stream, if it has less than n elements. + * + * @param n the number of elements to take. + * @return the n 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 n first elements. + * If the stream has less than n elements, the empty stream is returned. + * + * @param n the number of elements to drop. + * @return the stream without its n 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 p. + * + * @param p the test predicate. + * @return the longest prefix of this stream whose elements satisfy + * the predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return the longest suffix of the stream whose first element + * does not satisfy the predicate p. + */ + 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 f to each + * element of this stream. + * + * @param f function to apply to each element. + * @return [f(a0), ..., f(an)] if this stream is [a0, ..., an]. + */ + 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 f 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 p. The order of the elements is preserved. + * + * @param p the predicate used to filter the stream. + * @return the elements of this stream satisfying p. + */ + 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 p is satisfied by all elements + * in this stream. + * + * @param p the test predicate. + * @return true iff all elements of this stream satisfy the + * predicate p. + */ + 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 p. + * + * @param p the test predicate. + * @return true iff there exists an element in this stream that + * satisfies the predicate p. + */ + 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 f, from left to right, and starting with + * the value z. + * + * @return f(... (f(f(z, a0), a1) ...), + * an) if the stream is + * [a0, a1, ..., an]. + */ + 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 f, from rigth to left, and starting with + * the value z. + * + * @return f(a0, f(a1, f(..., f(an, z)...))) + * if the stream is [a0, a1, ..., an]. + */ + 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 f to each element of + * this stream, then concatenates the results. + * + * @param f the function to apply on each element. + * @return f(a0) ::: ... ::: f(an) if + * this stream is [a0, ..., an]. + */ + 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 xs with the elements of + * this stream starting at position start. + * + * @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 + * that 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 Stream({a0,b0}, ..., + * {amin(m,n),bmin(m,n))} when + * Stream(a0, ..., am) + * zip Stream(b0, ..., bn) 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 Stream({a0,0}, {a0,1},...) + * where ai 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 sep + * @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] + +/**

+ * Instances of Symbol can be created easily with + * Scala's built-in quote mechanism. + *

+ *

+ * For instance, the Scala + * term 'mysym will invoke the constructor of the + * Symbol class in the following way: + * new Symbol("mysym"). + *

+ * + * @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 + } + + /**

+ * Makes this symbol into a unique reference. + *

+ *

+ * If two interened symbols are equal (i.e. they have the same name) + * then they must be identical (wrt reference equality). + *

+ * + * @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 + + +/**

+ * The class BitSet provides the interface for a space-efficient + * implementation of dense integer sets represented as bits in array of + * integers. Bit indices are between 0..(capacity-1) inclusive. + *

+ * + * @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 true if bit i 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 true, 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 that. + * Uses accelerated (32 x faster) check if the other set is a BitSet + * + * @param other another set. + * @return true, 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 Int cells needed to store + * n bits. + */ + protected final def memsize(n: Int): Int = offset(n + 31) + + /** + * @param n ... + * @return the number of bits represented by n 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._ + + +/**

+ * This class defines the interface of collections that unambiguously map + * keys to values (i.e. a key is mapped to at least one value). + *

+ *

+ * Class Map may only be used for accessing elements from map + * implementations. Two different extensions of class Map in + * the package + * scala.collection.mutable + * and + * scala.collection.immutable 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. + *

+ * + * @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 key 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 true 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 true 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 true 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 true 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 equals + */ + 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 scala.collection.Map. + * 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 + + +/**

+ * This class defines the interface of collections that do not contain + * duplicate elements. + *

+ *

+ * Class Set may only be used for accessing elements + * from set implementations. Two different extensions + * of class Set in the package + * + * scala.collection.mutable and + * + * scala.collection.immutable 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. + *

+ * + * @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 elem. + * + * @param elem the element to check for membership. + * @return true iff elem is contained in + * this set. + */ + def contains(elem: A): Boolean + + /** This method allows sets to be interpreted as predicates. + * It returns true, iff this set contains element + * elem. + * + * @param elem the element to check for membership. + * @return true iff elem is contained in + * this set. + */ + def apply(elem: A): Boolean = contains(elem) + + /** Checks if this set is empty. + * + * @return true iff there is no element in the set. + */ + def isEmpty: Boolean = size == 0 + + /** Checks if this set is a subset of set that. + * + * @param that another set. + * @return true 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 true 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 scala.collection.Set. + * 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 BitSet provides an immutable bitset view on an + * int array. Instances can conveniently be created from instances of + * Bit indices are between 0..(capacity-1) inclusive. + * + * @param size size represents the number of relevant bits + * @param capacity ... + * @param ba ba array of ints of length + * n>>>5 + * @param copy copy if yes, then ba 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 empty 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 ListMap represent + * empty maps; they can be either created by calling the constructor + * directly, or by applying the function ListMap.empty. + * + * @author Matthias Zenger + * @author Martin Oderskty + * @version 2.0, 01/01/2007 + */ +[serializable] +class ListMap[A, +B] extends Map[A, B] { + + /** Returns a new ListMap instance mapping keys of the + * same type to values of type C. + */ + 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 key 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 key + * to value. If the map contains already a + * mapping for key, 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 key. + * 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 key 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 key + * to value. If the map contains already a + * mapping for key, 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 key. + * 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 empty 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 ListSet represent + * empty sets; they can be either created by calling the constructor + * directly, or by applying the function ListSet.empty. + * + * @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 elem. + * + * @param elem the element to check for membership. + * @return true, iff elem 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) + + /** - 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 elem. + * + * @param elem the element to check for membership. + * @return true, iff elem 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) + + /** - 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._ + +/**

+ * This class extends the Map interface of collections + * that unambiguously map keys to values (i.e. a key is mapped to at + * least one value). + *

+ *

+ * This class defines the interface for functional map implementations + * relying on immutable data structures. + *

+ *

+ * Concrete map implementations have to provide functionality for + * the abstract methods in + * scala.collection.Map as well as for + * factory, update, and -. + *

+ * + * @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 C. + */ + def empty[C]: Map[A, C] + + /** This method allows one to create a new map with an + * additional mapping from key + * to value. If the map contains already a + * mapping for key, it will be overridden by this + * function. + * + * @param key ... + * @param value ... + * @return the created map + * @deprecated use +({A, B}) 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 key + * it is returned unchanged. Otherwise, return a new map + * without a binding for key + */ + 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 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 - (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 f. + * + * @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 + * p returns false. + * + * @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 + } + + /**

+ * This method defines syntactic sugar for adding a + * mapping. It is typically used in the following way: + *

+ *
+   *    map + key -> value
+   *  
+ * @deprecated use +({A, B}) instead + */ + [deprecated] def +(key: A): MapTo = new MapTo(key) + + /** incl can be used to add many mappings at the same time + * to the map. The method assumes that a mapping is represented + * by a Pair object who's first component denotes the + * key, and who's second component refers to the value. + * + * @param mappings ... + * @return ... + * @deprecated use + instead + */ + [deprecated] def incl[B1 >: B](mappings: {A, B1}*): Map[A, B1] = incl(mappings) + + /** incl 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 Pair objects who's first component + * denotes the key, and who's second component refers to the value. + * + * @deprecated use ++ 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 - 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 keys object. + * + * @param keys ... + * @return the updated map + * @deprecated use -- 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 toString. + * + * @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 +({A, B}) 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() +} + +/** Queue 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 n-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 n 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 Iterable 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 + * scala.collection.Set as well as for + and + * -. + * + * Note that abstract immutable.Set's are not covariant in their type + * parameter. This is because some subclasses cannot support the + * + 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 elems 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) + + /** incl 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 that 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 elems 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 + * elems 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) + + /** excl 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 that 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 that. + * It removes all the elements that are not present in that. + * + * @param that the set to intersect with + */ + def intersect(that: collection.Set[A]): Set[A] = filter(that.contains) + + /** This method is an alias for intersect. + * It computes an intersection with set that. + * It removes all the elements that are not present in that. + * + * @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 f to each + * element of this set. + * + * @param f function to apply to each element. + * @return a set containing f(a0), ..., f(an) + * if this set contains a0, ..., an. + */ + override def map[B](f: A => B): Set[B] = + foldLeft(empty[B])((set: Set[B], elem: A) => set + f(elem)) + + /** Applies the given function f 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 f(a0), ..., f(an) + * if this set contains a0, ..., an. + */ + override def flatMap[B](f: A => Iterable[B]): Set[B] = + foldLeft(empty[B])((set: Set[B], elem: A) => set incl f(elem)) + + /** Method filter removes all elements from the set for + * which the predicate p yields the value false. + * + * @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 Stack represent + * empty stacks; they can be either created by calling the constructor + * directly, or by applying the function Stack.Empty. + * + * @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 + +/**

+ * General Balanced Trees - highly efficient functional dictionaries. + *

+ *

+ * 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 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. + *

+ *

+ * The tree consists of entries conatining a key with an order. + *

+ *

+ * When instanciating the tree an order for the keys has to be + * supplied. + *

+ * + * @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.
+   *  class C[T](...) extends Tree[A,B](...) {
+   *    type This = C[T];
+   *  
+ */ + 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]() + + /**

+ * This abstract method should be defined by a concrete implementation + * C[T] as something like: + *

+ *
+   *    override def New(sz: Int, t: aNode): This {
+   *      new C[T](order) {
+   *        override def size = sz
+   *        override protected def tree: aNode = t
+   *    }
+   *  
+ *

+ * The concrete implementation should also override the def of This + * override type This = C[T]; + *

+ */ + 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 not 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 not 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 key 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] +} + +/** + * ITree is an internal class used by + * Tree. + */ +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 +} + +/** + * INode is an internal class used by + * Tree. + */ +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 +} + +/** + * GBTree is an internal class used by + * Tree. + * + * @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 empty 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 not 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 not 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 key 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 not 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 not 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 key 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 empty 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 not 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 elem. + * + * @param elem the element to check for membership. + * @return true, iff elem 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 not 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 not 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 key 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 that into this buffer just before + * the element at index idx. + * + * @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 + * f. + * + * @param f + * @return true 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 false 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. + * None if there is no lower bound. + * @param until The upper-bound (exclusive) of the ranged projection. + * None 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 None 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. + * None if there is no lower bound. + * @param until The upper-bound (exclusive) of the ranged projection. + * None 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; + +/**

+ * A wrapper around a Java sorted set. + *

+ *

+ * The comparator of the sorted set matches the comparator of this set. + *

+ * + * @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; + +/**

+ * A map that is backed by a Java weak hash map, whose keys are maintained + * as weak references. + *

+ *

+ * Because keys are weak references, the garbage collector can collect + * them if they are not referred to elsewhere. + *

+ *

+ * Useful for implementing caches. + *

+ * + * @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 Buffer 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 elements 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 i 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 elements 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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert a new element at index n. + * + * @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 n 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 n with the new element + * newelem. + * + * @param n the index of the element to replace. + * @param newelem the new element. + * @throws Predef.IndexOutOfBoundsException if n 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 n 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 ArrayBuffer 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 BitSet 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 n 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 i-th bit to true. + * No restriction on i + */ + 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 i-th bit. + * + * @param i the i-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 elements 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 elements 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 elements 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 elements 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 elements 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 elements 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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert the new elements at index n. + * + * @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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert a new element at index n. + * + * @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 n with the new element + * newelem. + * + * @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 n 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 n 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 scala.collection.mutable.Buffer. + * 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 elements 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 elements 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 elements 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 elements 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 elements 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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert the new elements at index n. + * + * @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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert a new element at index n. + * + * @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 n with the new element + * newelem. + * + * @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 Buffer 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 Map + * class in terms of three functions: findEntry, + * addEntry, and entries. + * + * @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 A refers to the element type + * of the list, type variable This 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 HashTable[A] implements a hashtable + * that maps keys of type A to values of the fully abstract + * member type Entry. Classes that make use of HashTable + * have to provide an implementation for Entry + * + * There are mainly two parameters that affect the performance of a hashtable: + * the initial size and the load factor. The size + * refers to the number of buckets in the hashtable, and the load + * factor 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 HashTable. + * + * @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 + + +/** History[A, B] objects may subscribe to events of + * type A published by an object of type B. + * The history subscriber object records all published events + * up to maximum number of maxHistory 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 empty has + * to be redefined if the immutable map on which this mutable map is + * originally based is not empty. empty 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 empty has + * to be redefined if the immutable set on which this mutable set is + * originally based is not empty. empty 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 java.util.Map 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 java.util.Set. + * + * @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 (elem) + * and the tail (next) 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 ListBuffer .. + * + * @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 this -= x; this + * + * @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 n with the new element + * newelem. + * + * @param n the index of the element to replace. + * @param x the new element. + * @throws Predef.IndexOutOfBoundsException if n 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 n. Opposed to method + * update, this method will not replace an element with a new + * one. Instead, it will insert a new element at index n. + * + * @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 n 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 n. + * @pre an element exists at position n + * @throws Predef.IndexOutOfBoundsException if n 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()) + } + + /**

+ * Returns an iterator over all elements of this list. + *

+ *
+ * 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 + * toList.elements. + *
+ * + * @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 ListBuffer with the same elements. + */ + override def clone(): Buffer[A] = (new ListBuffer[A]) ++ this + + /** 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: 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 Location describes locations in messages implemented + * by class Message. + * + * @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 + * scala.collection.Map as well as for update, + * and -=. + * + * @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 key + * to value to the map. If the map already contains a + * mapping for key, 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 key 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 keys 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 keys 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 f. + * + * @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 + * p returns true. + * + * @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: + *
+   *  map += key -> value;
+   *  
+ * @deprecated use +={key, value} + */ + [deprecated] def +=(key: A): MapTo = new MapTo(key) + + /** incl can be used to add many mappings at the same time + * to the map. The method assumes that a mapping is represented + * by a Pair object who's first component denotes the + * key, and who's second component refers to the value. + * + * @param mappings + * @deprecated use += + */ + [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 -= + */ + [deprecated] def excl(keys: A*): Unit = this --= keys.elements + + /** This method removes all the mappings for which the predicate + * p returns false. + * + * @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 + + +/**

+ * This is a simple wrapper class for scala.collection.mutable.Map. + *

+ *

+ * It is most useful for assembling customized map abstractions + * dynamically using object composition and forwarding. + *

+ * + * @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 Message represents messages that are issued by observable + * collection classes whenever a data structure is changed. Class Message + * has several subclasses for the various kinds of events: Update + * Remove, Include, Reset, and + * Script. + * + * @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 A + * to Set[B] objects into multi maps which map A to + * B 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 Buffer, + * Stack, and Queue. + * + * @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 nth 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 nth element of this list or None + * 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 scala.List 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 Buffer class into which this abstract + * class is mixed in. Class ObservableBuffer publishes + * events of the type Message. + * + * @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 Map class into which this abstract + * class is mixed in. Class ObservableMap publishes + * events of the type Message. + * + * @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 Set class into which this abstract + * class is mixed in. Class ObservableSet publishes + * events of the type Message. + * + * @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 + * Ordered[T] 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 Iterable 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 + * Ordered[T] 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 Iterable 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 + + +/** Publisher[A,This] objects publish events of type A + * 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 Publisher is typically used + * as a mixin. The type variable This 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} + +/** Queue 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 Iterable 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 + + +/** Queue 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 n. + * + * @return the element at index n. + */ + 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 Iterable 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 xs with the elements of + * this sequence starting at position start. + * + * @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 History object which supports + * an undo operation. Type variable A refers to the type + * of the published events, B denotes the publisher type. + * Type B is typically a subtype of Publisher. + * + * @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 Scriptable 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 + * + * scala.collection.Set as well as for +=, + * -= and clear. + * + * @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 elem + * from this set depending on the value of parameter included. + * Typically, one would use the following syntax: + *
set(elem) = true
+ * + */ + 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 that 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 + * elems 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 elems 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 + * elems to the set. + * @param elems the iterator containing the elements to be added + */ + def ++ (elems: Iterator[A]): Set[A] = { this ++= elems; this } + + /** incl can be used to add many elements to the set + * at the same time. + * @deprecated use ++= 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 elems from the set. + */ + def --=(elems: Iterable[A]): Unit = --=(elems.elements) + + /** Remove all the elements provided by an iterator + * elems 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 elems 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 + * elems 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 } + + /** excl removes many elements from the set. + */ + [deprecated] def excl(elems: A*): Unit = --=(elems.elements) + + /** This method computes an intersection with set that. + * It removes all the elements that are not present in that. + * + * @param that the set to intersect with. + */ + def intersect(that: Set[A]): Unit = retain(that.contains) + + /** Method filter removes all elements from the set for + * which the predicate p yields the value false. + * @deprecated use retain instead + */ + [deprecated] override def filter(p: A => Boolean): Set[A] = { + toList.foreach { + elem => if (!p(elem)) -=(elem) + } + this + } + + /** Method retain removes all elements from the set for + * which the predicate p yields the value false. + */ + 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 Predef.UnsupportedOperationException + * 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 scala.collection.mutable.Set. + * 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 A refers to the element type of the + * list, type variable This 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 Iterable 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 n. + * + * @return the element at index n. + */ + 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 Iterable 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 + + +/** Subscriber[A, B] objects may subscribe to events of + * type A published by an object of type B. + * B is typically a subtype of Publisher. + * + * @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 Buffer + * 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 elements 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 elements 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 elements 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 elements 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 elements 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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert the new elements at index n. + * + * @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 n. Opposed to method + * update, this method will not replace an element with a + * one. Instead, it will insert a new element at index n. + * + * @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 n with the new element + * newelem. + * + * @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 ArrayBuffer 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 Map + * 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 + * Ordered[T] 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 Iterable 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 Queue[T] 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 Iterable 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 Set + * 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 Stack[T] 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 Iterable 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 Undoable class provide an operation + * undo 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 Actor ... + * + * @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 + * f 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 + * f 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 Pid 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 SyncChannel ... + * + * @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 SyncVar ... + * + * @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 + * receiveWithin 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 ops ... + * + * @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 + + +/**

+ * Library for using Pi-calculus concurrent primitives in Scala. As an + * example, the definition of a two-place buffer using the pilib + * library looks like: + *

+ * def Buffer[a](put: Chan[a], get: Chan[a]): unit = {
+ *   def B0: unit = choice ( put * { x => B1(x) } );
+ *   def B1(x: a): unit = choice ( get(x) * B0, put * { y => B2(x, y) } )
+ *   def B2(x: a, y: a): unit = choice ( get(x) * B1(y) )
+ *   B0
+ * }
+ * 
+ * + * @see PiLib: A Hosted Language for Pi-Calculus Style Concurrency + * @author Vincent Cremet, Martin Odersky + * @version 1.0 + */ +object pilib { + + /////////////////////////// SPAWN ////////////////////////////// + + /** + * Run several processes in parallel using the following syntax: + * spawn < p_1 | ... | p_n > + */ + 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 http://research.microsoft.com/~akenn/fun/. + * + * @author Philipp Haller (philipp.haller<at>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 + +/**

+ * The object Position provides convenience methods to encode + * line and column number in one single integer. The encode line (column) + * numbers range from 0 to LINE_MASK + * (COLUMN_MASK), where 0 indicates that the line (column) is + * the undefined and 1 represents the first line (column). Line (Column) + * numbers greater than LINE_MASK + * (COLUMN_MASK) are replaced by LINE_MASK + * (COLUMN_MASK). Furthermore, if the encoded line number is + * LINE_MASK, the column number is always set to 0. + *

+ *

+ * The following properties hold: + *

+ *
    + *
  • + * the undefined position is 0: encode(0,0) == 0 + *
  • + *
  • + * encodings are non-negative : encode(line,column) >= 0 + *
  • + *
  • + * position order is preserved: + * (line1 < line2) || (line1 == line2 && column1 < column2) + *
    implies
    + * encode(line1,column1) <= encode(line2,column2) + *
  • + *
+ * + * @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 Source instance from the given array of bytes, + * with empty description. + * + * @param bytes ... + * @return the created Source 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 Source instance from a single character. + * + * @param c ... + * @return the create Source 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 Source implements an iterable representation + * of source files. Calling method reset 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 true 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 out. + * + * @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 java.lang.System.out. + * + * @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 provides apply methods + * with different arities (actually up to 9 parameters) to invoke + * a function simply by specifying its name and argument types.

+ * + * Example:

+ *    val url = new URL("http://scala-lang.org/classes/examples.jar");
+ *    val obj = new Location(url) create "examples.sort";
+ *    val ar = Array(6, 2, 8, 5, 1);
+ *    obj[Array[Int], Unit]("println")(ar);
+ *    obj[Array[Int], Unit]("sort")(ar);
+ *    obj[Array[Int], Unit]("println")(ar);
+ * + * @see Location + * + * @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 Location provides a create + * method to instantiate objects from a network location by + * specifying the URL address of the jar/class file.

+ * + * 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.

+ * + * Example:

+ *    val url = new URL("http://scala-lang.org/classes/examples.jar");
+ *    val obj = new Location(url) create "examples.sort";
+ * + * @see Code + * + * @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 className + * at this location. + * + * @param classname the name of the class + * @return the code description corresponding to + * className. + */ + 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 Location 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.

+ * + * Example:

+ *    val obj = Location.create("xcode.Math");
+ *    val x = obj[Int, Int]("square")(5);
+ * + * @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 +
+  [BeanProperty]
+  var status = ""
+
+

adds the following methods to the generated code

+
+  def setStatus(s:String): Unit = { this.status = s }
+  def getStatus: String         = { this.status }
+
+ * +

+ However, you cannot call setStatus from Scala, you should + use the normal Scala access and assignment. +

+ */ +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 = "" + 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] */ +/** tpe[args1, ..., argsn] */ +case class AppliedType(tpe: Type, args: List[Type]) extends Type + +/** [a <: lo >: hi] */ +case class TypeBounds(lo: Type, hi: Type) extends Type + +/** (formals1 ... formalsn) restpe */ +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 $tag in trait + * scala.ScalaObject. + */ +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 new Array[T](length) where T + * 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 + +/** + *

A class representing Array[T]

+ */ +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 xs with the elements of + * this sequence starting at position start. + * + * @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 scala.Nothing. 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 scala.Null. 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 index. + */ + 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 + + /**

+ * Strip trailing line end character from this string if it has one. + * A line end character is one of + *

+ *
    + *
  • LF - line feed (0x0A hex)
  • + *
  • FF - form feed (0x0C hex)
  • + *
+ *

+ * If a line feed character LF is preceded by a carriage return CR + * (0x0D hex), the CR character is also stripped (Windows convention). + *

+ */ + 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 + } + } + + /**

+ * Return all lines in this string in an iterator, including trailing + * line end characters. + *

+ *

+ * 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 + *

+ *
    + *
  • LF - line feed (0x0A hex)
  • + *
  • FF - form feed (0x0C hex)
  • + *
+ */ + 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 .stripLineEnd to all lines + * returned by linesWithSeparators. + */ + 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) + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by marginChar from the line. + *
+ */ + 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 + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by | from the line. + *
+ */ + 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 ScalaRunTime 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 + +/** Benchmark can be used to quickly turn an existing + * class into a benchmark. Here is a short example: + * + *
+ *  object sort1 extends Sorter with Benchmark {
+ *    def run = sort(List.range(1, 1000))
+ *  }
+ *  
+ *

+ * The run method has to be defined by the user, who will perform + * the timed operation there. + * Run the benchmark as follows: + *

+ *
+ *  > scala sort1 5 times.log
+ *  
+ *

+ * This will run the benchmark 5 times and log the execution times in + * a file called times.log + *

+ */ +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 ") + Console.println(" or: scala benchmarks.program ") + } + } +} + 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 + +/** + *

+ * Unit testing methods in the spirit of + * JUnit framework. + *

+ *

+ * Use these classes like this: + *

+ *
+ * import scala.testing.SUnit
+ * import SUnit._
+ *
+ * class MyTest(n: String) extends TestCase(n) {
+ *
+ *   override def runTest() = n match {
+ *     case "myTest1" => assertTrue(true)
+ *     case "myTest2" => assertTrue("hello", false)
+ *   }
+ * }
+ *
+ * val r = new TestResult()
+ * suite.run(r)
+ * for (val tf <- r.failures()) {
+ *   Console.println(tf.toString())
+ * }
+ * 
+ */ +object SUnit { + + /** a Test can be run with its result being collected */ + trait Test { + def run(r: TestResult): Unit + } + + /** The class TestCase 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 TestFailure 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 TestSuite 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 AssertFailed with given message msg. + */ + 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. + *

+ * Example: + *

+ *
+ * class Reader(fname: String) {
+ *   private val in =
+ *     new BufferedReader(new FileReader(fname))
+ *   [throws(classOf[IOException])]
+ *   def read() = in.read()
+ * }
+ * + * @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 dynamic scope, but where + * access to the fluid itself is resolved through static + * binding to a variable referencing the fluid. + * + * The current value can be retrieved with the + * value method. New values can be + * pushed using the withValue method. + * Values pushed via withValue only + * stay valid while the withValue's + * second argument, a parameterless closure, + * executes. When the second argument finishes, + * the fluid reverts to the previous value. + * + * Usage of withValue looks like this: + *
+  * someFluid.withValue(newValue) {
+  *   // ... code called in here that calls value ...
+  *   // ... will be given back the newValue ...
+  * }
+  * 
+ * + * 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 + +/**

+ * 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 Ordered. Some sorts that + * operate directly on a subset of value types are also provided. These + * implementations are derived from those in the Sun JDK. + *

+ *

+ * Note that stability doesn't matter for value types, so use the quickSort + * variants for those. stableSort is intended to be used with + * objects when the prior ordering should be preserved, where possible. + *

+ * + * @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 K given an ordering function + * f. f should return true 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 true 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* + 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* + 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* + 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* + 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 + } + } + } +} + +/**

+ * A RichSorting object is generally created implicitly through + * the use of the sort function on an arbitrary sequence, where + * the items are ordered. + *

+ */ +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 first(r) where the word regexp r. + * + * @param r the regular expression + * @return the computed set first(r) + */ + 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 last(r) where the word regexp r. + * + * @param r the regular expression + * @return the computed set last(r) + */ + 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 ConsoleLogger is mixed into a concrete class who + * has class Logged among its base classes. + * + * @author Burak Emir + * @version 1.0 + */ +trait ConsoleLogger { + + /** logs argument to Console using Console.println + * + * @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 + +/**

+ * Mixing in the class Logged indicates that a class provides + * support for logging. For instance, the developer of a library writes + *

+ *
+ *    class MyClass with Logged { /* do stuff, call log */ }
+ *  
+ *

+ * The user of the library instantiates: + *

+ *
+ *    val x = new MyClass() with ConsoleLogger
+ *  
+ *

+ * and the logging will be sent to the Console object. + *

+ */ +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 _regexpT <: RegExp (from class Base) + * and a type member _labelT <: Label. + * Here is a little example: + *
+ *  import scala.util.regexp._
+ *  import scala.util.automata._
+ *  object MyLang extends WordExp {
+ *    type _regexpT = RegExp
+ *    type _labelT = MyChar
+ *
+ *    case class MyChar(c:Char) extends Label
+ *  }
+ *  import MyLang._
+ *  // (a* | b)*
+ *  val rex = Star(Alt(Star(Letter(MyChar('a'))),Letter(MyChar('b'))))
+ *  object MyBerriSethi extends WordBerrySethi {
+ *    override val lang = MyLang
+ *  }
+ *  val nfa = MyBerriSethi.automatonFrom(Sequ(rex), 1)
+ *  
+ * + * @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 Atom 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 null. + */ +[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 Comment 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 "#REM" */ + def label = "#REM" + + /** hashcode for this Comment */ + override def hashCode() = commentText.hashCode() + + override def text = "" + + /** Appends "" to this string buffer. + */ + override def toString(sb: StringBuilder) = + sb.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 XMLEvent 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 (None) 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 (None) + * 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 Elem extends the Node 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 text(n) for each child + * n. + */ + 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 EntityRef 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 "& entityName;" to this string buffer. + * + * @param sb the string buffer. + * @return the modified string buffer sb. + */ + 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 + +/**

+ * Attribute information item, and linked list of attribute information items. + * These are triples consisting of prefix,key,value. To obtain + * the namespace, getNamespace must be called with the parent. + * If next is null, this is the last attribute in the MetaData list. + *

+ *

+ * Either an UnprefixedAttribute or a PrefixedAttribute + *

+ * + * @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 apply(namespace, owner.scope, key). + * + * @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 true 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 true 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 NamespaceBinding 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 <foo/>) */ + 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 getNamespace(this.prefix) + */ + def namespace = getNamespace(this.prefix) + + /** + * Convenience method, same as scope.getURI(pre) but additionally + * checks if scope is null. + * + * @param pre the prefix whose namespace name we would like to obtain + * @return the namespace if scope != null and prefix was + * found, else null + */ + 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 attributes.getValue(key) + * + * @param key of queried attribute. + * @return value of UnprefixedAttribute with given key + * in attributes, if it exists, otherwise null. + */ + 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 attributes.getValue(uri, this, key) + * + * @param uri namespace of queried attribute (may not be null). + * @param key of queried attribute. + * @return value of PrefixedAttribute with given namespace + * and given key, otherwise null. + */ + 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 true 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 toString(false). + * + * @see toString(Boolean) + */ + override def toString(): String = toString(false) + + /** + * Appends qualified name of this node to StringBuilder. + * + * @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 null. + */ + 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 Seq[Node], it must be ensured that no updates + * occur after that point, because scala.xml.Node 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 Seq[Node] 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 this \ "foo" + * to get a list of all elements of this sequence that are labelled with + * "foo". Use \ "_" 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 this \\ 'foo + * to get a list of all elements of this sequence that are labelled with + * "foo". Use \\ "_" 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 Parsing ... + * + * @author Burak Emir + * @version 1.0 + * + * @deprecated use either parsing.TokenTests or + * Utilty (helper functions for parsing XML fragments). + */ +object Parsing { + + /**
(#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 == '_' + } + + /**
Name ::= ( Letter | '_' ) (NameChar)*
+ * + * 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("') + 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) { + // + 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 "<?" target (" "+text)?+"?>" + * to this stringbuffer. + */ + override def toString(sb: StringBuilder) = { + sb + .append(" 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 + +/** <code>SpecialNode</code> 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 Text 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 TextBuffer is for creating text nodes without + * surplus whitespace. All occurrences of one or more whitespace in strings + * appended with the append 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 "xml" prefix which is bound to + * "http://www.w3.org/XML/1998/namespace" + */ +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 Utility 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 < > & and " from string. + * + * @param text ... + * @return ... + */ + final def escape(text: String): String = + escape(text, new StringBuilder()).toString() + + /** + * Appends escaped string to s. + * + * @param text ... + * @param s ... + * @return ... + */ + final def escape(text: String, s: StringBuilder): StringBuilder = { + for (val c <- Iterator.fromString(text)) c match { + case '<' => s.append("<") + case '>' => s.append(">") + case '&' => s.append("&") + case '"' => s.append(""") + //case '\'' => s.append("'") // is valid xhtml but not html, and IE doesn't know it, says jweb + case _ => s.append(c) + } + s + } + + /** + * Appends unescaped string to s, amp becomes & + * lt becomes < etc.. + * + * @param ref ... + * @param s ... + * @return null if ref 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 n. + * + * @see "toXML(Node, Boolean)" + */ + def toXML(n: Node): String = toXML(n, true) + + /** + * Return the string representation of a Node. uses namespace mapping from + * defaultPrefixes(n). + * + * @param n the XML node + * @param stripComment ... + * @return ... + * + * @todo define a way to escape literal characters to &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("') + } + } + + /** + * @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 "s" if string s does not contain ", + * 's' 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 "s" and escapes and " i s with \" + * + * @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 null 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 + } + + /** + *
+   *   CharRef ::= "&#" '0'..'9' {'0'..'9'} ";"
+   *             | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";"
+   * 
+ *

+ * see [66] + *

+ * + * @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 XML 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 Symbol 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 + * doctype. + * + * @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 + * doctype. + * + * @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 xmlDecl + * @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("\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("'); + } + +} // ElemDecl + +case class AttListDecl(name: String, attrs:List[AttrDecl]) extends MarkupDecl with DtdTypeSymbol { + + override def toString(sb: StringBuilder): StringBuilder = { + sb + .append("")); + } +} + +/** 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("'); + } +} + +/** a parameter entity declaration */ +case class ParameterEntityDecl(name: String, entdef: EntityDef) extends EntityDecl { + override def toString(sb: StringBuilder): StringBuilder = { + 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("'); + } +} +/** a notation declaration */ +case class NotationDecl( name:String, extID:ExternalID ) extends MarkupDecl { + override def toString(sb: StringBuilder): StringBuilder = { + sb.append("" */ + final override def toString() = { + val sb = new compat.StringBuilder().append(" 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 + + +/**

+ * This class logs what the nodefactory is actually doing. + * If you want to see what happens during loading, use it like this: + *

+ *  object testLogged extends Application {
+ *
+ *    val x = new scala.xml.nobinding.NoBindingFactoryAdapter
+ *          with scala.xml.LoggedNodeFactory[scala.xml.Elem]()
+ *          with scala.util.logging.ConsoleLogger;
+ *
+ *    Console.println("Start");
+ *
+ *    val doc = x.loadXML(new org.xml.sax.InputSource("http://lamp.epfl.ch/~buraq"));
+ *
+ *    Console.println("End");
+ *
+ *    Console.println(doc);
+ *  }
+ * + * @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. + * + *
+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);
+  }
+}
+
+ */ +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 localName 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("") + case None => + Source.fromString("") + } + + //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 + * ConstructingParser if you just want to parse XML to + * construct instances of scala.xml.Node. + * + * 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 + // + + /** <? prolog ::= xml S ... ?> + */ + def xmlProcInstr(): MetaData = { + xToken("xml") + xSpace + val Pair(md,scp) = xAttributes(TopScope) + if (scp != TopScope) + reportSyntaxError("no xmlns definitions here, please."); + xToken('?') + xToken('>') + md + } + + /** <? 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 ::= '<?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 <. + * 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 <. + * 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 ::= '<' Name { S Attribute } [S] + * [44] EmptyElemTag ::= '<' 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] '<' xmlEndTag ::= '<' '/' Name S? '>' + */ + def xEndTag(n: String) = { + xToken('/') + val m = xName + if (n != m) + reportSyntaxError("expected closing tag of " + n/* +", not "+m*/); + xSpaceOpt + xToken('>') + } + + /** '<! CharData ::= [CDATA[ ( {char} - {char}"]]>"{char} ) ']]>' + * + * 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 ::= "&#" '0'..'9' {'0'..'9'} ";" + * | "&#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 ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' + * + * 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); + } + } + + /** '<' 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 ::= '<' content1 | '&' 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. + * + * <! 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) + } + + /** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag + * | xmlTag1 '/' '>' + */ + 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") + + /** '<?' ProcInstr ::= Name [S ({Char} - ({Char}'>?' {Char})]'?>' + * + * 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 <. + * 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() + } + + /** <! 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) + } + + /** <! 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) + } + + /** <! 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 + * +
+import scala.xml._
+import scala.xml.pull._
+import scala.io.Source
+
+object reader {
+  val src = Source.fromString("")
+  val er = new XMLEventReader().initialize(src)
+
+  def main(args:Array[String]): unit = {
+    Console.println(er.next)
+    Console.println(er.next)
+  }
+}
+
+ */ +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 pos elements + * from ns. + */ + 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 => + case _ => super.transform(n); + } +} + +object Foo with Application { + + val tr = new IdentityTransformer; + val n = tr( ); + Console.println(n); + + val tr2 = new RewriteRule { + final override val name = "A rule"; + override def transform(n: Node) = n.match { + case => + case _ => n + } + } + val tr3 = new RewriteRule { + final override val name = "E rule"; + override def transform(n: Node) = n.match { + case => + case _ => n + } + } + val tr4 = new RuleTransformer(tr2, tr3); + val m = tr4( ); + 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 + } +} -- cgit v1.2.3