summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/All$.java10
-rw-r--r--src/library/scala/AllRef$.java9
-rw-r--r--src/library/scala/AnyVal.cs18
-rw-r--r--src/library/scala/AnyVal.java14
-rw-r--r--src/library/scala/Application.scala51
-rw-r--r--src/library/scala/Array.scala18
-rw-r--r--src/library/scala/Attribute.scala14
-rw-r--r--src/library/scala/Boolean.cs61
-rw-r--r--src/library/scala/Boolean.java53
-rw-r--r--src/library/scala/BufferedIterator.scala26
-rw-r--r--src/library/scala/Byte.cs132
-rw-r--r--src/library/scala/Byte.java189
-rw-r--r--src/library/scala/CaseClass.scala33
-rw-r--r--src/library/scala/Cell.scala20
-rw-r--r--src/library/scala/Char.cs128
-rw-r--r--src/library/scala/Char.java187
-rw-r--r--src/library/scala/Console.scala253
-rw-r--r--src/library/scala/Double.cs66
-rw-r--r--src/library/scala/Double.java78
-rw-r--r--src/library/scala/Enumeration.scala140
-rw-r--r--src/library/scala/Float.cs81
-rw-r--r--src/library/scala/Float.java93
-rw-r--r--src/library/scala/Function0.scala13
-rw-r--r--src/library/scala/Function1.scala13
-rw-r--r--src/library/scala/Function2.scala13
-rw-r--r--src/library/scala/Function3.scala13
-rw-r--r--src/library/scala/Function4.scala13
-rw-r--r--src/library/scala/Function5.scala13
-rw-r--r--src/library/scala/Function6.scala13
-rw-r--r--src/library/scala/Function7.scala13
-rw-r--r--src/library/scala/Function8.scala13
-rw-r--r--src/library/scala/Function9.scala13
-rw-r--r--src/library/scala/Int.cs127
-rw-r--r--src/library/scala/Int.java184
-rw-r--r--src/library/scala/Iterable.scala157
-rw-r--r--src/library/scala/IterableProxy.scala97
-rw-r--r--src/library/scala/Iterator.scala429
-rw-r--r--src/library/scala/List.scala919
-rw-r--r--src/library/scala/Long.cs108
-rw-r--r--src/library/scala/Long.java181
-rw-r--r--src/library/scala/MatchError.scala40
-rw-r--r--src/library/scala/None.scala18
-rw-r--r--src/library/scala/Option.scala70
-rw-r--r--src/library/scala/Ordered.scala35
-rw-r--r--src/library/scala/PartialFunction.scala29
-rw-r--r--src/library/scala/PartiallyOrdered.scala49
-rw-r--r--src/library/scala/Predef.scala359
-rw-r--r--src/library/scala/Proxy.scala26
-rw-r--r--src/library/scala/Ref.cs31
-rw-r--r--src/library/scala/Ref.java27
-rw-r--r--src/library/scala/ScalaObject.scala20
-rw-r--r--src/library/scala/Seq.scala194
-rw-r--r--src/library/scala/SeqProxy.scala91
-rw-r--r--src/library/scala/SerialVersionUID.scala12
-rw-r--r--src/library/scala/Short.cs129
-rw-r--r--src/library/scala/Short.java186
-rw-r--r--src/library/scala/Some.scala19
-rw-r--r--src/library/scala/Stream.scala243
-rw-r--r--src/library/scala/Symbol.scala30
-rw-r--r--src/library/scala/Tuple1.scala13
-rw-r--r--src/library/scala/Tuple2.scala13
-rw-r--r--src/library/scala/Tuple3.scala13
-rw-r--r--src/library/scala/Tuple4.scala13
-rw-r--r--src/library/scala/Tuple5.scala13
-rw-r--r--src/library/scala/Tuple6.scala13
-rw-r--r--src/library/scala/Tuple7.scala13
-rw-r--r--src/library/scala/Tuple8.scala13
-rw-r--r--src/library/scala/Tuple9.scala13
-rw-r--r--src/library/scala/Unit.cs45
-rw-r--r--src/library/scala/Unit.java37
-rw-r--r--src/library/scala/_trait_.scala18
-rw-r--r--src/library/scala/cloneable.scala12
-rw-r--r--src/library/scala/collection/BitSet.scala82
-rw-r--r--src/library/scala/collection/Map.scala180
-rw-r--r--src/library/scala/collection/MapProxy.scala43
-rw-r--r--src/library/scala/collection/Set.scala89
-rw-r--r--src/library/scala/collection/SetProxy.scala37
-rw-r--r--src/library/scala/collection/immutable/BitSet.scala117
-rw-r--r--src/library/scala/collection/immutable/ListMap.scala150
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala118
-rw-r--r--src/library/scala/collection/immutable/Map.scala144
-rw-r--r--src/library/scala/collection/immutable/Queue.scala173
-rw-r--r--src/library/scala/collection/immutable/Set.scala81
-rw-r--r--src/library/scala/collection/immutable/Stack.scala139
-rw-r--r--src/library/scala/collection/immutable/Tree.scala374
-rw-r--r--src/library/scala/collection/immutable/TreeMap.scala107
-rw-r--r--src/library/scala/collection/immutable/TreeSet.scala69
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala148
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala87
-rw-r--r--src/library/scala/collection/mutable/Buffer.scala214
-rw-r--r--src/library/scala/collection/mutable/BufferProxy.scala147
-rw-r--r--src/library/scala/collection/mutable/DefaultMapModel.scala52
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedList.scala49
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala36
-rw-r--r--src/library/scala/collection/mutable/HashSet.scala49
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala148
-rw-r--r--src/library/scala/collection/mutable/History.scala42
-rw-r--r--src/library/scala/collection/mutable/ImmutableMapAdaptor.scala64
-rw-r--r--src/library/scala/collection/mutable/ImmutableSetAdaptor.scala50
-rw-r--r--src/library/scala/collection/mutable/JavaMapAdaptor.scala66
-rw-r--r--src/library/scala/collection/mutable/JavaSetAdaptor.scala44
-rw-r--r--src/library/scala/collection/mutable/LinkedList.scala34
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala143
-rw-r--r--src/library/scala/collection/mutable/Location.scala27
-rw-r--r--src/library/scala/collection/mutable/Map.scala169
-rw-r--r--src/library/scala/collection/mutable/MapProxy.scala53
-rw-r--r--src/library/scala/collection/mutable/Message.scala77
-rw-r--r--src/library/scala/collection/mutable/MultiMap.scala38
-rw-r--r--src/library/scala/collection/mutable/MutableList.scala77
-rw-r--r--src/library/scala/collection/mutable/ObservableBuffer.scala74
-rw-r--r--src/library/scala/collection/mutable/ObservableMap.scala48
-rw-r--r--src/library/scala/collection/mutable/ObservableSet.scala39
-rw-r--r--src/library/scala/collection/mutable/PriorityQueue.scala180
-rw-r--r--src/library/scala/collection/mutable/PriorityQueueProxy.scala94
-rw-r--r--src/library/scala/collection/mutable/Publisher.scala45
-rw-r--r--src/library/scala/collection/mutable/Queue.scala194
-rw-r--r--src/library/scala/collection/mutable/QueueProxy.scala97
-rw-r--r--src/library/scala/collection/mutable/ResizableArray.scala64
-rw-r--r--src/library/scala/collection/mutable/RevertableHistory.scala31
-rw-r--r--src/library/scala/collection/mutable/Scriptable.scala24
-rw-r--r--src/library/scala/collection/mutable/Set.scala111
-rw-r--r--src/library/scala/collection/mutable/SetProxy.scala51
-rw-r--r--src/library/scala/collection/mutable/SingleLinkedList.scala63
-rw-r--r--src/library/scala/collection/mutable/Stack.scala132
-rw-r--r--src/library/scala/collection/mutable/StackProxy.scala108
-rw-r--r--src/library/scala/collection/mutable/Subscriber.scala22
-rw-r--r--src/library/scala/collection/mutable/SynchronizedBuffer.scala189
-rw-r--r--src/library/scala/collection/mutable/SynchronizedMap.scala116
-rw-r--r--src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala97
-rw-r--r--src/library/scala/collection/mutable/SynchronizedQueue.scala93
-rw-r--r--src/library/scala/collection/mutable/SynchronizedSet.scala104
-rw-r--r--src/library/scala/collection/mutable/SynchronizedStack.scala109
-rw-r--r--src/library/scala/collection/mutable/Undoable.scala24
-rw-r--r--src/library/scala/concurrent/Actor.scala29
-rw-r--r--src/library/scala/concurrent/Channel.scala37
-rw-r--r--src/library/scala/concurrent/Lock.scala22
-rw-r--r--src/library/scala/concurrent/MailBox.scala170
-rw-r--r--src/library/scala/concurrent/NameServer.scala35
-rw-r--r--src/library/scala/concurrent/Process.scala78
-rw-r--r--src/library/scala/concurrent/SyncChannel.scala38
-rw-r--r--src/library/scala/concurrent/SyncVar.scala37
-rw-r--r--src/library/scala/concurrent/TIMEOUT.scala12
-rw-r--r--src/library/scala/concurrent/jolib.scala75
-rw-r--r--src/library/scala/concurrent/ops.scala52
-rw-r--r--src/library/scala/concurrent/pilib.scala189
-rw-r--r--src/library/scala/dbc/DataType.scala66
-rw-r--r--src/library/scala/dbc/Database.scala186
-rw-r--r--src/library/scala/dbc/Syntax.scala44
-rw-r--r--src/library/scala/dbc/Utilities.scala25
-rw-r--r--src/library/scala/dbc/Value.scala24
-rw-r--r--src/library/scala/dbc/Vendor.scala38
-rw-r--r--src/library/scala/dbc/datatype/ApproximateNumeric.scala53
-rw-r--r--src/library/scala/dbc/datatype/Boolean.scala27
-rw-r--r--src/library/scala/dbc/datatype/Character.scala36
-rw-r--r--src/library/scala/dbc/datatype/CharacterLargeObject.scala27
-rw-r--r--src/library/scala/dbc/datatype/CharacterString.scala20
-rw-r--r--src/library/scala/dbc/datatype/CharacterVarying.scala37
-rw-r--r--src/library/scala/dbc/datatype/ExactNumeric.scala61
-rw-r--r--src/library/scala/dbc/datatype/Factory.scala246
-rw-r--r--src/library/scala/dbc/datatype/Numeric.scala28
-rw-r--r--src/library/scala/dbc/datatype/String.scala20
-rw-r--r--src/library/scala/dbc/datatype/Unknown.scala30
-rw-r--r--src/library/scala/dbc/exception/IncompatibleSchema.scala15
-rw-r--r--src/library/scala/dbc/exception/UnsupportedFeature.scala12
-rw-r--r--src/library/scala/dbc/result/Field.scala60
-rw-r--r--src/library/scala/dbc/result/FieldMetadata.scala32
-rw-r--r--src/library/scala/dbc/result/Relation.scala68
-rw-r--r--src/library/scala/dbc/result/Status.scala24
-rw-r--r--src/library/scala/dbc/result/Tuple.scala38
-rw-r--r--src/library/scala/dbc/statement/AccessMode.scala22
-rw-r--r--src/library/scala/dbc/statement/DerivedColumn.scala32
-rw-r--r--src/library/scala/dbc/statement/Expression.scala25
-rw-r--r--src/library/scala/dbc/statement/Insert.scala32
-rw-r--r--src/library/scala/dbc/statement/InsertionData.scala37
-rw-r--r--src/library/scala/dbc/statement/IsolationLevel.scala28
-rw-r--r--src/library/scala/dbc/statement/JoinType.scala45
-rw-r--r--src/library/scala/dbc/statement/Jointure.scala43
-rw-r--r--src/library/scala/dbc/statement/Relation.scala51
-rw-r--r--src/library/scala/dbc/statement/Select.scala91
-rw-r--r--src/library/scala/dbc/statement/SetClause.scala18
-rw-r--r--src/library/scala/dbc/statement/SetQuantifier.scala30
-rw-r--r--src/library/scala/dbc/statement/Statement.scala14
-rw-r--r--src/library/scala/dbc/statement/Status.scala26
-rw-r--r--src/library/scala/dbc/statement/Table.scala36
-rw-r--r--src/library/scala/dbc/statement/Transaction.scala51
-rw-r--r--src/library/scala/dbc/statement/Update.scala43
-rw-r--r--src/library/scala/dbc/statement/expression/Aggregate.scala30
-rw-r--r--src/library/scala/dbc/statement/expression/BinaryOperator.scala28
-rw-r--r--src/library/scala/dbc/statement/expression/Constant.scala18
-rw-r--r--src/library/scala/dbc/statement/expression/Default.scala17
-rw-r--r--src/library/scala/dbc/statement/expression/Field.scala35
-rw-r--r--src/library/scala/dbc/statement/expression/FunctionCall.scala28
-rw-r--r--src/library/scala/dbc/statement/expression/Select.scala23
-rw-r--r--src/library/scala/dbc/statement/expression/SetFunction.scala35
-rw-r--r--src/library/scala/dbc/statement/expression/TypeCast.scala27
-rw-r--r--src/library/scala/dbc/statement/expression/UnaryOperator.scala28
-rw-r--r--src/library/scala/dbc/syntax/DataTypeUtil.scala94
-rw-r--r--src/library/scala/dbc/syntax/Database.scala29
-rw-r--r--src/library/scala/dbc/syntax/Statement.scala270
-rw-r--r--src/library/scala/dbc/syntax/StatementExpression.scala217
-rw-r--r--src/library/scala/dbc/value/ApproximateNumeric.scala24
-rw-r--r--src/library/scala/dbc/value/Boolean.scala23
-rw-r--r--src/library/scala/dbc/value/Character.scala31
-rw-r--r--src/library/scala/dbc/value/CharacterLargeObject.scala31
-rw-r--r--src/library/scala/dbc/value/CharacterVarying.scala31
-rw-r--r--src/library/scala/dbc/value/Conversion.scala153
-rw-r--r--src/library/scala/dbc/value/ExactNumeric.scala31
-rw-r--r--src/library/scala/dbc/value/Factory.scala91
-rw-r--r--src/library/scala/dbc/value/Unknown.scala23
-rw-r--r--src/library/scala/dbc/vendor/PostgreSQL.scala23
-rw-r--r--src/library/scala/io/Position.scala92
-rw-r--r--src/library/scala/io/Source.scala252
-rw-r--r--src/library/scala/mobile/Code.scala234
-rw-r--r--src/library/scala/mobile/Location.scala96
-rw-r--r--src/library/scala/reflect/Code.scala21
-rw-r--r--src/library/scala/reflect/Print.scala113
-rw-r--r--src/library/scala/reflect/Symbol.scala51
-rw-r--r--src/library/scala/reflect/Type.scala44
-rw-r--r--src/library/scala/reflect/TypedCode.scala13
-rw-r--r--src/library/scala/remote.scala12
-rw-r--r--src/library/scala/runtime/AtomicReference.java54
-rw-r--r--src/library/scala/runtime/BooleanRef.java16
-rw-r--r--src/library/scala/runtime/BoxedAnyArray.scala154
-rw-r--r--src/library/scala/runtime/BoxedArray.scala45
-rw-r--r--src/library/scala/runtime/BoxedBoolean.java49
-rw-r--r--src/library/scala/runtime/BoxedBooleanArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedByte.java58
-rw-r--r--src/library/scala/runtime/BoxedByteArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedChar.java59
-rw-r--r--src/library/scala/runtime/BoxedCharArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedDouble.java50
-rw-r--r--src/library/scala/runtime/BoxedDoubleArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedFloat.java49
-rw-r--r--src/library/scala/runtime/BoxedFloatArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedInt.java59
-rw-r--r--src/library/scala/runtime/BoxedIntArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedLong.java50
-rw-r--r--src/library/scala/runtime/BoxedLongArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedNumber.java21
-rw-r--r--src/library/scala/runtime/BoxedObjectArray.scala29
-rw-r--r--src/library/scala/runtime/BoxedShort.java59
-rw-r--r--src/library/scala/runtime/BoxedShortArray.scala33
-rw-r--r--src/library/scala/runtime/BoxedUnit.java37
-rw-r--r--src/library/scala/runtime/ByteRef.java16
-rw-r--r--src/library/scala/runtime/CharRef.java16
-rw-r--r--src/library/scala/runtime/DoubleRef.java16
-rw-r--r--src/library/scala/runtime/ExceptionHandling.cs33
-rw-r--r--src/library/scala/runtime/ExceptionHandling.java24
-rw-r--r--src/library/scala/runtime/FNV_Hash.java51
-rw-r--r--src/library/scala/runtime/FloatRef.java16
-rw-r--r--src/library/scala/runtime/IOMap.java171
-rw-r--r--src/library/scala/runtime/IntRef.java16
-rw-r--r--src/library/scala/runtime/InterpreterSupport.java108
-rw-r--r--src/library/scala/runtime/LongRef.java16
-rw-r--r--src/library/scala/runtime/MetaAttribute.cs34
-rw-r--r--src/library/scala/runtime/ObjectRef.java16
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala90
-rw-r--r--src/library/scala/runtime/ShortRef.java16
-rw-r--r--src/library/scala/runtime/SymtabAttribute.cs40
-rw-r--r--src/library/scala/runtime/compat/Math.scala36
-rw-r--r--src/library/scala/runtime/compat/Platform.scala35
-rw-r--r--src/library/scala/runtime/compat/StringBuilder.scala26
-rw-r--r--src/library/scala/runtime/matching/Address.scala30
-rw-r--r--src/library/scala/runtime/matching/NonTerm.scala52
-rw-r--r--src/library/scala/runtime/matching/PatternTests.scala5
-rw-r--r--src/library/scala/runtime/matching/Rule.scala102
-rw-r--r--src/library/scala/runtime/matching/TestAlphabet.scala9
-rw-r--r--src/library/scala/serializable.scala12
-rw-r--r--src/library/scala/testing/Benchmark.scala74
-rw-r--r--src/library/scala/testing/SUnit.scala188
-rw-r--r--src/library/scala/testing/UnitTest.scala58
-rw-r--r--src/library/scala/text/Document.scala119
-rw-r--r--src/library/scala/transient.scala12
-rw-r--r--src/library/scala/util/automata/BaseBerrySethi.scala180
-rw-r--r--src/library/scala/util/automata/DetWordAutom.scala56
-rw-r--r--src/library/scala/util/automata/Inclusion.scala54
-rw-r--r--src/library/scala/util/automata/NondetWordAutom.scala101
-rw-r--r--src/library/scala/util/automata/SubsetConstruction.scala143
-rw-r--r--src/library/scala/util/automata/WordBerrySethi.scala275
-rw-r--r--src/library/scala/util/grammar/HedgeRHS.scala12
-rw-r--r--src/library/scala/util/grammar/TreeRHS.scala9
-rw-r--r--src/library/scala/util/logging/ConsoleLogger.scala12
-rw-r--r--src/library/scala/util/logging/Logged.scala23
-rw-r--r--src/library/scala/util/parsing/CharInputStreamIterator.scala35
-rw-r--r--src/library/scala/util/parsing/Parsers.scala68
-rw-r--r--src/library/scala/util/parsing/SimpleTokenizer.scala46
-rw-r--r--src/library/scala/util/regexp/Base.scala63
-rw-r--r--src/library/scala/util/regexp/PointedHedgeExp.scala25
-rw-r--r--src/library/scala/util/regexp/SyntaxError.scala6
-rw-r--r--src/library/scala/util/regexp/WordExp.scala24
-rw-r--r--src/library/scala/volatile.scala12
-rw-r--r--src/library/scala/xml/Atom.scala41
-rw-r--r--src/library/scala/xml/Comment.scala45
-rw-r--r--src/library/scala/xml/Document.scala84
-rw-r--r--src/library/scala/xml/Elem.scala74
-rw-r--r--src/library/scala/xml/EntityRef.scala40
-rw-r--r--src/library/scala/xml/MalformedAttributeException.scala3
-rw-r--r--src/library/scala/xml/MetaData.scala159
-rw-r--r--src/library/scala/xml/Molecule.scala39
-rw-r--r--src/library/scala/xml/NamespaceBinding.scala70
-rw-r--r--src/library/scala/xml/Node.scala145
-rw-r--r--src/library/scala/xml/NodeBuffer.scala55
-rw-r--r--src/library/scala/xml/NodeSeq.scala104
-rw-r--r--src/library/scala/xml/NodeTraverser.scala30
-rw-r--r--src/library/scala/xml/Null.scala75
-rw-r--r--src/library/scala/xml/Parsing.scala102
-rw-r--r--src/library/scala/xml/PrefixedAttribute.scala87
-rw-r--r--src/library/scala/xml/PrettyPrinter.scala274
-rw-r--r--src/library/scala/xml/ProcInstr.scala63
-rw-r--r--src/library/scala/xml/SpecialNode.scala31
-rw-r--r--src/library/scala/xml/Text.scala32
-rw-r--r--src/library/scala/xml/TextBuffer.scala55
-rw-r--r--src/library/scala/xml/TopScope.scala28
-rw-r--r--src/library/scala/xml/TypeSymbol.scala11
-rw-r--r--src/library/scala/xml/UnprefixedAttribute.scala70
-rw-r--r--src/library/scala/xml/Utility.scala244
-rw-r--r--src/library/scala/xml/XML.scala75
-rw-r--r--src/library/scala/xml/dtd/ContentModel.scala200
-rw-r--r--src/library/scala/xml/dtd/ContentModelParser.scala144
-rw-r--r--src/library/scala/xml/dtd/DTD.scala48
-rw-r--r--src/library/scala/xml/dtd/Decl.scala182
-rw-r--r--src/library/scala/xml/dtd/DocType.scala44
-rw-r--r--src/library/scala/xml/dtd/DtdTypeSymbol.scala1
-rw-r--r--src/library/scala/xml/dtd/ElementValidator.scala166
-rw-r--r--src/library/scala/xml/dtd/ExternalID.scala94
-rw-r--r--src/library/scala/xml/dtd/Scanner.scala87
-rw-r--r--src/library/scala/xml/dtd/Tokens.scala32
-rw-r--r--src/library/scala/xml/dtd/ValidationException.scala33
-rw-r--r--src/library/scala/xml/factory/Binder.scala43
-rw-r--r--src/library/scala/xml/factory/LoggedNodeFactory.scala78
-rw-r--r--src/library/scala/xml/factory/NodeFactory.scala77
-rw-r--r--src/library/scala/xml/parsing/ConstructingHandler.scala24
-rw-r--r--src/library/scala/xml/parsing/ConstructingParser.scala61
-rw-r--r--src/library/scala/xml/parsing/DefaultMarkupHandler.scala16
-rw-r--r--src/library/scala/xml/parsing/ExternalSources.scala76
-rw-r--r--src/library/scala/xml/parsing/FactoryAdapter.scala344
-rw-r--r--src/library/scala/xml/parsing/FatalError.scala3
-rw-r--r--src/library/scala/xml/parsing/MarkupHandler.scala148
-rw-r--r--src/library/scala/xml/parsing/MarkupParser.scala1223
-rw-r--r--src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala53
-rw-r--r--src/library/scala/xml/parsing/TokenTests.scala145
-rw-r--r--src/library/scala/xml/parsing/ValidatingMarkupHandler.scala104
-rw-r--r--src/library/scala/xml/path/Expression.scala54
-rw-r--r--src/library/scala/xml/transform/BasicTransformer.scala124
-rw-r--r--src/library/scala/xml/transform/RewriteRule.scala13
-rw-r--r--src/library/scala/xml/transform/RuleTransformer.scala14
-rw-r--r--src/library/scala/xml/xsd/ContentModel.scala39
-rw-r--r--src/library/scala/xml/xsd/Decl.scala26
-rw-r--r--src/library/scala/xml/xsd/XsTypeSymbol.scala38
349 files changed, 25956 insertions, 0 deletions
diff --git a/src/library/scala/All$.java b/src/library/scala/All$.java
new file mode 100644
index 0000000000..e220b26ac7
--- /dev/null
+++ b/src/library/scala/All$.java
@@ -0,0 +1,10 @@
+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.
+ */
+
+public class All$ {}
+
diff --git a/src/library/scala/AllRef$.java b/src/library/scala/AllRef$.java
new file mode 100644
index 0000000000..e8c7e77aa9
--- /dev/null
+++ b/src/library/scala/AllRef$.java
@@ -0,0 +1,9 @@
+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.
+ */
+
+public class AllRef$ {}
diff --git a/src/library/scala/AnyVal.cs b/src/library/scala/AnyVal.cs
new file mode 100644
index 0000000000..13cf2f3e2c
--- /dev/null
+++ b/src/library/scala/AnyVal.cs
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:AnyVal.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.Any;")]
+ public abstract class AnyVal {}
+}
diff --git a/src/library/scala/AnyVal.java b/src/library/scala/AnyVal.java
new file mode 100644
index 0000000000..a7a96d0a6d
--- /dev/null
+++ b/src/library/scala/AnyVal.java
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.Any; */
+public abstract class AnyVal {}
diff --git a/src/library/scala/Application.scala b/src/library/scala/Application.scala
new file mode 100644
index 0000000000..b536c8a31d
--- /dev/null
+++ b/src/library/scala/Application.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Application.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** The <code>Application</code> class can be used to quickly turn objects
+ * into executable programs. Here is an example:
+ * <pre>
+ * object Main with Application {
+ * Console.println("Hello World!");
+ * }
+ * </pre>
+ * Here, object <code>Main</code> inherits the <code>main</code> method
+ * of <code>Application</code>. The body of the <code>Main</code> object
+ * defines the main program. This technique does not work if the main
+ * program depends on command-line arguments (which are not accessible
+ * with the technique presented here).
+ *
+ * It is possible to time the execution of objects that inherit from
+ * class <code>Application</code> by setting the global scala.time property.
+ * Here is an example for benchmarking object <code>Main</code>:
+ * <pre>
+ * java -Dscala.time Main
+ * </pre>
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/09/03
+ */
+
+[_trait_] class Application {
+
+ /** The time when execution of this program started.
+ */
+ val executionStart: Long = java.lang.System.currentTimeMillis();
+
+ /** The default main method.
+ */
+ def main(args: Array[String]) = {
+ if (java.lang.System.getProperty("scala.time") != null)
+ java.lang.System.out.println("[total " +
+ (java.lang.System.currentTimeMillis()
+ - executionStart) + "ms]");
+ }
+}
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala
new file mode 100644
index 0000000000..b1f15e1b6d
--- /dev/null
+++ b/src/library/scala/Array.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+final class Array[A](_length: Int) extends Cloneable with java.io.Serializable with Seq[A] {
+ def length: Int = throw new Error();
+ def apply(i: Int): A = throw new Error();
+ def update(i: Int, x: A): Unit = throw new Error();
+ def elements: Iterator[A] = throw new Error();
+}
diff --git a/src/library/scala/Attribute.scala b/src/library/scala/Attribute.scala
new file mode 100644
index 0000000000..ad0df6b2f3
--- /dev/null
+++ b/src/library/scala/Attribute.scala
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Attribute.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+/** A base class for attributes
+*/
+class Attribute {}
diff --git a/src/library/scala/Boolean.cs b/src/library/scala/Boolean.cs
new file mode 100644
index 0000000000..73e72935ed
--- /dev/null
+++ b/src/library/scala/Boolean.cs
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Boolean.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Boolean : AnyVal
+ {
+
+ public readonly bool value;
+
+ public Boolean(bool value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return other is Boolean && value == ((Boolean)other).value;
+ }
+ public override int GetHashCode()
+ {
+ return value ? 1231 : 1237;
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Boolean;")]
+ public bool __bang ( ) { return !value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (bool that) { return value == that; }
+ public bool __bang__eq (bool that) { return value != that; }
+ public bool __bar__bar (bool that) { return value || that; }
+ public bool __amp__amp (bool that) { return value && that; }
+ public bool __bar (bool that) { return value | that; }
+ public bool __amp (bool that) { return value & that; }
+ public bool __up (bool that) { return value ^ that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Boolean.java b/src/library/scala/Boolean.java
new file mode 100644
index 0000000000..960595f5a5
--- /dev/null
+++ b/src/library/scala/Boolean.java
@@ -0,0 +1,53 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Boolean extends AnyVal implements java.io.Serializable {
+
+ public final boolean value;
+
+ public Boolean(boolean value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Boolean && value == ((Boolean)other).value;
+ }
+ public int hashCode() {
+ int bits = value ? 1231 : 1237;
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Boolean; */
+ public boolean $bang ( ) { return !value ; }
+
+
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (boolean that) { return value == that; }
+ public boolean $bang$eq (boolean that) { return value != that; }
+ public boolean $bar$bar (boolean that) { return value || that; }
+ public boolean $amp$amp (boolean that) { return value && that; }
+ public boolean $bar (boolean that) { return value | that; }
+ public boolean $amp (boolean that) { return value & that; }
+ public boolean $up (boolean that) { return value ^ that; }
+
+}
diff --git a/src/library/scala/BufferedIterator.scala b/src/library/scala/BufferedIterator.scala
new file mode 100644
index 0000000000..6ee72ee785
--- /dev/null
+++ b/src/library/scala/BufferedIterator.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:BufferedIterator.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+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;
+}
diff --git a/src/library/scala/Byte.cs b/src/library/scala/Byte.cs
new file mode 100644
index 0000000000..a8faa7080e
--- /dev/null
+++ b/src/library/scala/Byte.cs
@@ -0,0 +1,132 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Byte.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Byte : AnyVal {
+
+ public readonly sbyte value;
+
+ public Byte(sbyte value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Byte) && (value == ((Byte)other).value);
+ }
+ public override int GetHashCode()
+ {
+ return value;
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Int;")]
+ public int __plus ( ) { return +value ; }
+ [Meta("method []scala.Int;")]
+ public int __minus ( ) { return -value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce ( ) { return value ; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ [Meta("method []scala.Float;")]
+ public float coerce (float dummy) { return value ; }
+ [Meta("method []scala.Int;")]
+ public int __tilde ( ) { return ~value ; }
+
+ public int __less__less (int that) { return value << that; }
+ public int __less__less (long that) { return value << (int)that; }
+ public int __greater__greater(int that) { return value >> that; }
+ public int __greater__greater(long that) { return value >> (int)that; }
+ public int __greater__greater__greater(int that) { return (int)((uint)value >>that); }
+ public int __greater__greater__greater(long that) { return (int)((uint)value >>(int)that); }
+
+ public bool __eq__eq (long that) { return value == that; }
+ public bool __bang__eq (long that) { return value != that; }
+ public bool __less (long that) { return value < that; }
+ public bool __greater (long that) { return value > that; }
+ public bool __less__eq (long that) { return value <= that; }
+ public bool __greater__eq(long that) { return value >= that; }
+ public long __plus (long that) { return value + that; }
+ public long __minus (long that) { return value - that; }
+ public long __times (long that) { return value * that; }
+ public long __div (long that) { return value / that; }
+ public long __percent (long that) { return value % that; }
+ public long __bar (long that) { return value | that; }
+ public long __amp (long that) { return value & that; }
+ public long __up (long that) { return value ^ that; }
+
+ [Meta("method []scala.Long;")]
+ public long coerce (long dummy) { return value ; }
+
+ public bool __eq__eq (int that) { return value == that; }
+ public bool __bang__eq (int that) { return value != that; }
+ public bool __less (int that) { return value < that; }
+ public bool __greater (int that) { return value > that; }
+ public bool __less__eq (int that) { return value <= that; }
+ public bool __greater__eq(int that) { return value >= that; }
+ public int __plus (int that) { return value + that; }
+ public int __minus (int that) { return value - that; }
+ public int __times (int that) { return value * that; }
+ public int __div (int that) { return value / that; }
+ public int __percent (int that) { return value % that; }
+ public int __bar (int that) { return value | that; }
+ public int __amp (int that) { return value & that; }
+ public int __up (int that) { return value ^ that; }
+
+ [Meta("method []scala.Int;")]
+ public int coerce (int dummy) { return value ; }
+
+ [Meta("method []scala.Short;")]
+ public short coerce (short dummy) { return value ; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Byte.java b/src/library/scala/Byte.java
new file mode 100644
index 0000000000..2a841225dc
--- /dev/null
+++ b/src/library/scala/Byte.java
@@ -0,0 +1,189 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Byte extends AnyVal implements java.io.Serializable {
+
+ public final byte value;
+
+ public Byte (byte value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Byte && value == ((Byte )other).value;
+ }
+ public int hashCode() {
+ int bits = value;
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Int ; */
+ public int $plus ( ) { return +value ; }
+ /** @meta method []scala.Int ; */
+ public int $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+ /** @meta method []scala.Float ; */
+ public float coerce ( ) { return value ; }
+ /** @meta method []scala.Int ; */
+ public int $tilde ( ) { return ~value ; }
+
+ public int $less$less (int that) { return value << that; }
+ public int $less$less (long that) { return value << that; }
+ public int $greater$greater(int that) { return value >> that; }
+ public int $greater$greater(long that) { return value >> that; }
+ public int $greater$greater$greater(int that) { return value >>>that; }
+ public int $greater$greater$greater(long that) { return value >>>that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public long $plus (long that) { return value + that; }
+ public long $minus (long that) { return value - that; }
+ public long $times (long that) { return value * that; }
+ public long $div (long that) { return value / that; }
+ public long $percent (long that) { return value % that; }
+ public long $bar (long that) { return value | that; }
+ public long $amp (long that) { return value & that; }
+ public long $up (long that) { return value ^ that; }
+
+ /** @meta method []scala.Long ; */
+ public long coerce ( ) { return value ; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public int $plus (int that) { return value + that; }
+ public int $minus (int that) { return value - that; }
+ public int $times (int that) { return value * that; }
+ public int $div (int that) { return value / that; }
+ public int $percent (int that) { return value % that; }
+ public int $bar (int that) { return value | that; }
+ public int $amp (int that) { return value & that; }
+ public int $up (int that) { return value ^ that; }
+
+ /** @meta method []scala.Int ; */
+ public int coerce ( ) { return value ; }
+
+ /** @meta method []scala.Short ; */
+ public short coerce ( ) { return value ; }
+
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public int $plus (char that) { return value + that; }
+ public int $minus (char that) { return value - that; }
+ public int $times (char that) { return value * that; }
+ public int $div (char that) { return value / that; }
+ public int $percent (char that) { return value % that; }
+ public int $bar (char that) { return value | that; }
+ public int $amp (char that) { return value & that; }
+ public int $up (char that) { return value ^ that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public int $plus (short that) { return value + that; }
+ public int $minus (short that) { return value - that; }
+ public int $times (short that) { return value * that; }
+ public int $div (short that) { return value / that; }
+ public int $percent (short that) { return value % that; }
+ public int $bar (short that) { return value | that; }
+ public int $amp (short that) { return value & that; }
+ public int $up (short that) { return value ^ that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public int $plus (byte that) { return value + that; }
+ public int $minus (byte that) { return value - that; }
+ public int $times (byte that) { return value * that; }
+ public int $div (byte that) { return value / that; }
+ public int $percent (byte that) { return value % that; }
+ public int $bar (byte that) { return value | that; }
+ public int $amp (byte that) { return value & that; }
+ public int $up (byte that) { return value ^ that; }
+}
diff --git a/src/library/scala/CaseClass.scala b/src/library/scala/CaseClass.scala
new file mode 100644
index 0000000000..07b766ede9
--- /dev/null
+++ b/src/library/scala/CaseClass.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:CaseClass.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+/** defines an access function for instances of case classes
+ *
+ * @author Burak Emir
+ */
+trait CaseClass extends AnyRef {
+
+ /** for a case class A(x_0,...,x_(k-1)), returns x_i for 0 &lt;= i &lt; k,
+ ** null otherwise
+ */
+ def caseElement(n: Int): Any ;
+
+ /** need also, for reflection
+ def setCaseElement(n: Int, v: Any): unit
+ */
+
+ /** for a case class A(x_0,...,x_(k-1)), returns k
+ */
+ def caseArity: Int ;
+
+ def caseName: String = ""; // for now
+
+}
diff --git a/src/library/scala/Cell.scala b/src/library/scala/Cell.scala
new file mode 100644
index 0000000000..77ee7015c2
--- /dev/null
+++ b/src/library/scala/Cell.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Cell.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** A <code>Cell</code> is a generic wrapper which completely
+ * hides the functionality of the wrapped object. The wrapped
+ * object is accessible via the <code>elem</code> accessor method.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 08/08/2003
+ */
+case class Cell[+T](elem: T);
diff --git a/src/library/scala/Char.cs b/src/library/scala/Char.cs
new file mode 100644
index 0000000000..3afde58dfd
--- /dev/null
+++ b/src/library/scala/Char.cs
@@ -0,0 +1,128 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Char.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ public abstract class Char : AnyVal {
+
+ public readonly char value;
+
+ public Char(char value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return other is Char && value == ((Char)other).value;
+ }
+ public override int GetHashCode()
+ {
+ return value;
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Int;")]
+ public int __plus ( ) { return +value ; }
+ [Meta("method []scala.Int;")]
+ public int __minus ( ) { return -value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce ( ) { return value ; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ [Meta("method []scala.Float;")]
+ public float coerce (float dummy) { return value; }
+ [Meta("method []scala.Int;")]
+ public int __tilde ( ) { return ~value; }
+
+ public int __less__less (int that) { return value << that; }
+ public int __less__less (long that) { return value << (int)that; }
+ public int __greater__greater(int that) { return value >> that; }
+ public int __greater__greater(long that) { return value >> (int)that; }
+ public int __greater__greater__greater(int that) { return (int)((uint)value >>that); }
+ public int __greater__greater__greater(long that) { return (int)((uint)value >>(int)that); }
+
+ public bool __eq__eq (long that) { return value == that; }
+ public bool __bang__eq (long that) { return value != that; }
+ public bool __less (long that) { return value < that; }
+ public bool __greater (long that) { return value > that; }
+ public bool __less__eq (long that) { return value <= that; }
+ public bool __greater__eq(long that) { return value >= that; }
+ public long __plus (long that) { return value + that; }
+ public long __minus (long that) { return value - that; }
+ public long __times (long that) { return value * that; }
+ public long __div (long that) { return value / that; }
+ public long __percent (long that) { return value % that; }
+ public long __bar (long that) { return value | that; }
+ public long __amp (long that) { return value & that; }
+ public long __up (long that) { return value ^ that; }
+
+ [Meta("method []scala.Long;")]
+ public long coerce (long dummy) { return value ; }
+
+ public bool __eq__eq (int that) { return value == that; }
+ public bool __bang__eq (int that) { return value != that; }
+ public bool __less (int that) { return value < that; }
+ public bool __greater (int that) { return value > that; }
+ public bool __less__eq (int that) { return value <= that; }
+ public bool __greater__eq(int that) { return value >= that; }
+ public int __plus (int that) { return value + that; }
+ public int __minus (int that) { return value - that; }
+ public int __times (int that) { return value * that; }
+ public int __div (int that) { return value / that; }
+ public int __percent (int that) { return value % that; }
+ public int __bar (int that) { return value | that; }
+ public int __amp (int that) { return value & that; }
+ public int __up (int that) { return value ^ that; }
+
+ [Meta("method []scala.Int;")]
+ public int coerce (int dummy) { return value ; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Char.java b/src/library/scala/Char.java
new file mode 100644
index 0000000000..a875e717df
--- /dev/null
+++ b/src/library/scala/Char.java
@@ -0,0 +1,187 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Char extends AnyVal implements java.io.Serializable {
+
+ public final char value;
+
+ public Char (char value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Char && value == ((Char )other).value;
+ }
+ public int hashCode() {
+ int bits = value;
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Int ; */
+ public int $plus ( ) { return +value ; }
+ /** @meta method []scala.Int ; */
+ public int $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+ /** @meta method []scala.Float ; */
+ public float coerce ( ) { return value ; }
+ /** @meta method []scala.Int ; */
+ public int $tilde ( ) { return ~value ; }
+
+ public int $less$less (int that) { return value << that; }
+ public int $less$less (long that) { return value << that; }
+ public int $greater$greater(int that) { return value >> that; }
+ public int $greater$greater(long that) { return value >> that; }
+ public int $greater$greater$greater(int that) { return value >>>that; }
+ public int $greater$greater$greater(long that) { return value >>>that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public long $plus (long that) { return value + that; }
+ public long $minus (long that) { return value - that; }
+ public long $times (long that) { return value * that; }
+ public long $div (long that) { return value / that; }
+ public long $percent (long that) { return value % that; }
+ public long $bar (long that) { return value | that; }
+ public long $amp (long that) { return value & that; }
+ public long $up (long that) { return value ^ that; }
+
+ /** @meta method []scala.Long ; */
+ public long coerce ( ) { return value ; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public int $plus (int that) { return value + that; }
+ public int $minus (int that) { return value - that; }
+ public int $times (int that) { return value * that; }
+ public int $div (int that) { return value / that; }
+ public int $percent (int that) { return value % that; }
+ public int $bar (int that) { return value | that; }
+ public int $amp (int that) { return value & that; }
+ public int $up (int that) { return value ^ that; }
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public int $plus (char that) { return value + that; }
+ public int $minus (char that) { return value - that; }
+ public int $times (char that) { return value * that; }
+ public int $div (char that) { return value / that; }
+ public int $percent (char that) { return value % that; }
+ public int $bar (char that) { return value | that; }
+ public int $amp (char that) { return value & that; }
+ public int $up (char that) { return value ^ that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public int $plus (short that) { return value + that; }
+ public int $minus (short that) { return value - that; }
+ public int $times (short that) { return value * that; }
+ public int $div (short that) { return value / that; }
+ public int $percent (short that) { return value % that; }
+ public int $bar (short that) { return value | that; }
+ public int $amp (short that) { return value & that; }
+ public int $up (short that) { return value ^ that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public int $plus (byte that) { return value + that; }
+ public int $minus (byte that) { return value - that; }
+ public int $times (byte that) { return value * that; }
+ public int $div (byte that) { return value / that; }
+ public int $percent (byte that) { return value % that; }
+ public int $bar (byte that) { return value | that; }
+ public int $amp (byte that) { return value & that; }
+ public int $up (byte that) { return value ^ that; }
+
+
+ /** @meta method []scala.Int ; */
+ public int coerce ( ) { return value ; }
+
+}
diff --git a/src/library/scala/Console.scala b/src/library/scala/Console.scala
new file mode 100644
index 0000000000..f7175d1e19
--- /dev/null
+++ b/src/library/scala/Console.scala
@@ -0,0 +1,253 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Console.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+import Predef._;
+
+/** The <code>Console</code> object implements functionality for
+ * printing Scala values on the terminal. There are also functions
+ * for reading specific values. <code>Console</code> also defines
+ * constants for marking up text on ANSI terminals.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/09/2003
+ */
+object Console {
+ import java.io._;
+ import java.text._;
+
+ // 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 var out: PrintStream = java.lang.System.out;
+ private var in: BufferedReader =
+ new BufferedReader(new InputStreamReader(java.lang.System.in));
+
+ /** Set the default output stream.
+ *
+ * @param out the new output stream.
+ */
+ def setOut(out: PrintStream): Unit = {
+ this.out = out;
+ }
+
+ /** Set the default input stream.
+ *
+ * @param in the new input stream.
+ */
+ def setIn(in: InputStream): Unit = {
+ this.in = new BufferedReader(new InputStreamReader(in));
+ }
+
+ /** Set the default input stream.
+ *
+ * @param reader specifies the new input stream.
+ */
+ def setIn(reader: Reader): Unit = {
+ this.in = new BufferedReader(reader);
+ }
+
+ /** Print an object on the terminal.
+ *
+ * @param obj the object to print.
+ */
+ def print(obj: Any): Unit = {
+ if (obj == null)
+ out.print("null");
+ else
+ out.print(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).
+ * The format of the text to print is specified by the parameter
+ * <code>text</code>. The arguments that are inserted into specific
+ * locations in <code>text</code> are provided with parameter
+ * <code>args</code>. See class <code>java.text.MessageFormat</code>
+ * 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.
+ */
+ def printf(text: String)(args: Any*): Unit = {
+ // todo: Uncurry
+ if (text == null)
+ out.print("null");
+ else
+ out.print(MessageFormat.format(text, textParams(args)));
+ }
+
+ /** Read a full line from the terminal.
+ *
+ * @return the string read from the terminal.
+ */
+ def readLine: String = in.readLine();
+
+ /** Read a boolean value from the terminal.
+ *
+ * @return the boolean value read from the terminal.
+ */
+ def readBoolean: Boolean = in.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 = java.lang.Byte.decode(in.readLine()).byteValue();
+
+ /** Read a short value from the terminal.
+ */
+ def readShort: Short = java.lang.Short.decode(in.readLine()).shortValue();
+
+ /** Read a char value from the terminal.
+ */
+ def readChar: Char = in.readLine().charAt(0);
+
+ /** Read an int value from the terminal.
+ */
+ def readInt: Int = java.lang.Integer.decode(in.readLine()).intValue();
+
+ /** Read a float value from the terminal.
+ */
+ def readFloat: Float =
+ scala.runtime.compat.Platform.parseFloat(in.readLine());
+
+ /** Read a double value from the terminal.
+ */
+ def readDouble: Double =
+ scala.runtime.compat.Platform.parseDouble(in.readLine());
+
+ /** Read in some structured input, specified by a format specifier.
+ * See class <code>java.text.MessageFormat</code> for details of
+ * the format specification.
+ *
+ * @param format the format of the input.
+ * @return a list of all extracted values.
+ */
+ def readf(format: String): List[Any] =
+ textComponents(new MessageFormat(format).parse(in.readLine()));
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first value extracted from the input according to the format
+ * specification.
+ */
+ def readf1(format: String): Any = readf(format).head;
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first two values extracted from the input according to the format
+ * specification.
+ */
+ def readf2(format: String): Pair[Any, Any] = {
+ val res = readf(format);
+ Pair(res.head, res.tail.head)
+ }
+
+ /** Read in some structured input, specified by a format specifier.
+ * Opposed to <code>readf</code>, this function only returns the
+ * first three values extracted from the input according to the format
+ * specification.
+ */
+ def readf3(format: String): Triple[Any, Any, Any] = {
+ val res = readf(format);
+ Triple(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/library/scala/Double.cs b/src/library/scala/Double.cs
new file mode 100644
index 0000000000..30b9293c47
--- /dev/null
+++ b/src/library/scala/Double.cs
@@ -0,0 +1,66 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Double.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Double : AnyVal {
+
+ public readonly double value;
+
+ public Double (double value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return other is Double && value == ((Double )other).value;
+ }
+ public override int GetHashCode()
+ {
+ return value.GetHashCode();
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Double;")]
+ public double __plus (object dummy) { return +value; }
+ [Meta("method []scala.Double;")]
+ public double __minus ( ) { return -value; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Double.java b/src/library/scala/Double.java
new file mode 100644
index 0000000000..77f44fd10e
--- /dev/null
+++ b/src/library/scala/Double.java
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Double extends AnyVal implements java.io.Serializable {
+
+ public final double value;
+
+ public Double (double value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Double && value == ((Double )other).value;
+ }
+ public int hashCode() {
+ long bits = java.lang.Double.doubleToLongBits(value);
+ return (int)(bits ^ (bits >>> 32));
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Double ; */
+ public double $plus ( ) { return +value ; }
+ /** @meta method []scala.Double ; */
+ public double $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+}
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
new file mode 100644
index 0000000000..885d51a180
--- /dev/null
+++ b/src/library/scala/Enumeration.scala
@@ -0,0 +1,140 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Enumeration.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+import scala.collection.mutable._;
+import Predef._;
+
+/**
+ * <p>The class <code>Enumeration</code> provides the same functionality as the
+ * <code>enum</code> construct found in C-like languages like C++ or Java.
+ * Here is an example:</p>
+ * <pre>
+ * <b>object</b> Main <b>with</b> Application {
+ *
+ * <b>object</b> WeekDays <b>extends</b> Enumeration {
+ * <b>val</b> Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
+ * }
+ *
+ * <b>def</b> isWorkingDay(d: WeekDays.Value) =
+ * ! (d == WeekDays.Sat || d == WeekDays.Sun);
+ *
+ * WeekDays filter (isWorkingDay) foreach { d =&gt; System.out.println(d) }
+ * }
+ * </pre>
+ *
+ * @param initial the initial integer value associated with the first element
+ * @param names the sequence of element names of the enumeration
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/02/04
+ */
+abstract class Enumeration(initial: Int, names: String*) {
+
+ def this() = this(0, null);
+
+ def this(names: String*) = this(0, names: _*);
+
+ def name = {
+ val cname = scala.runtime.compat.Platform.getClassName(this);
+ 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 == 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);
+
+ trait Value extends Ordered[Value] {
+ def id: Int;
+ override def compareTo[S >: Value <% Ordered[S]](that: S): Int = that match {
+ case that1: Value => id - that1.id
+ case _ => -(that compareTo this)
+ }
+ }
+
+ 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 == null)
+ Enumeration.this.name + "(" + i + ")";
+ else
+ name;
+ }
+}
diff --git a/src/library/scala/Float.cs b/src/library/scala/Float.cs
new file mode 100644
index 0000000000..5a3a162de9
--- /dev/null
+++ b/src/library/scala/Float.cs
@@ -0,0 +1,81 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Float.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Float : AnyVal {
+
+ public readonly float value;
+
+ public Float(float value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Float) && (value == ((Float)other).value);
+ }
+ public override int GetHashCode()
+ {
+ return value.GetHashCode();
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq(object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Float;")]
+ public float __plus ( ) { return +value ; }
+ [Meta("method []scala.Float;")]
+ public float __minus ( ) { return -value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce ( ) { return value; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Float.java b/src/library/scala/Float.java
new file mode 100644
index 0000000000..a4a35f575e
--- /dev/null
+++ b/src/library/scala/Float.java
@@ -0,0 +1,93 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Float extends AnyVal implements java.io.Serializable {
+
+ public final float value;
+
+ public Float (float value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Float && value == ((Float )other).value;
+ }
+ public int hashCode() {
+ int bits = java.lang.Float.floatToIntBits(value);
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Float ; */
+ public float $plus ( ) { return +value ; }
+ /** @meta method []scala.Float ; */
+ public float $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+}
diff --git a/src/library/scala/Function0.scala b/src/library/scala/Function0.scala
new file mode 100644
index 0000000000..f689152741
--- /dev/null
+++ b/src/library/scala/Function0.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function0[+R] extends AnyRef {
+ def apply(): R;
+}
diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala
new file mode 100644
index 0000000000..cfb5897a2c
--- /dev/null
+++ b/src/library/scala/Function1.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function1[-T0, +R] extends AnyRef {
+ def apply(v0: T0): R;
+}
diff --git a/src/library/scala/Function2.scala b/src/library/scala/Function2.scala
new file mode 100644
index 0000000000..fd5eedc497
--- /dev/null
+++ b/src/library/scala/Function2.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function2[-T0, -T1, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1): R;
+}
diff --git a/src/library/scala/Function3.scala b/src/library/scala/Function3.scala
new file mode 100644
index 0000000000..9212945a4e
--- /dev/null
+++ b/src/library/scala/Function3.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function3[-T0, -T1, -T2, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2): R;
+}
diff --git a/src/library/scala/Function4.scala b/src/library/scala/Function4.scala
new file mode 100644
index 0000000000..4731986c30
--- /dev/null
+++ b/src/library/scala/Function4.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function4[-T0, -T1, -T2, -T3, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3): R;
+}
diff --git a/src/library/scala/Function5.scala b/src/library/scala/Function5.scala
new file mode 100644
index 0000000000..17abc7eb7f
--- /dev/null
+++ b/src/library/scala/Function5.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function5[-T0, -T1, -T2, -T3, -T4, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3, v4: T4): R;
+}
diff --git a/src/library/scala/Function6.scala b/src/library/scala/Function6.scala
new file mode 100644
index 0000000000..02f6c94af2
--- /dev/null
+++ b/src/library/scala/Function6.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function6[-T0, -T1, -T2, -T3, -T4, -T5, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3, v4: T4, v5: T5): R;
+}
diff --git a/src/library/scala/Function7.scala b/src/library/scala/Function7.scala
new file mode 100644
index 0000000000..e97dc787ec
--- /dev/null
+++ b/src/library/scala/Function7.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function7[-T0, -T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6): R;
+}
diff --git a/src/library/scala/Function8.scala b/src/library/scala/Function8.scala
new file mode 100644
index 0000000000..f905cae58d
--- /dev/null
+++ b/src/library/scala/Function8.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+trait Function8[-T0, -T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef {
+ def apply(v0: T0, v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7): R;
+}
diff --git a/src/library/scala/Function9.scala b/src/library/scala/Function9.scala
new file mode 100644
index 0000000000..8ae0a5d658
--- /dev/null
+++ b/src/library/scala/Function9.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+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;
+}
diff --git a/src/library/scala/Int.cs b/src/library/scala/Int.cs
new file mode 100644
index 0000000000..1c909df500
--- /dev/null
+++ b/src/library/scala/Int.cs
@@ -0,0 +1,127 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Int.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Int : AnyVal {
+
+ public readonly int value;
+
+ public Int(int value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Int) && (value == ((Int)other).value);
+ }
+ public override int GetHashCode()
+ {
+ return value;
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Int;")]
+ public int __plus ( ) { return +value ; }
+
+ [Meta("method []scala.Int;")]
+ public int __minus ( ) { return -value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce (double dummy) { return value; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ [Meta("method []scala.Float;")]
+ public float coerce (float dummy) { return value; }
+ [Meta("method []scala.Int;")]
+ public int __tilde ( ) { return ~value; }
+
+ public int __less__less (int that) { return value << that; }
+ public int __less__less (long that) { return value << (int)that; }
+ public int __greater__greater(int that) { return value >> that; }
+ public int __greater__greater(long that) { return value >> (int)that; }
+ public int __greater__greater__greater(int that) { return (int)((uint)value >>that); }
+ public int __greater__greater__greater(long that) { return (int)((uint)value >>(int)that); }
+
+ public bool __eq__eq (long that) { return value == that; }
+ public bool __bang__eq (long that) { return value != that; }
+ public bool __less (long that) { return value < that; }
+ public bool __greater (long that) { return value > that; }
+ public bool __less__eq (long that) { return value <= that; }
+ public bool __greater__eq(long that) { return value >= that; }
+ public long __plus (long that) { return value + that; }
+ public long __minus (long that) { return value - that; }
+ public long __times (long that) { return value * that; }
+ public long __div (long that) { return value / that; }
+ public long __percent (long that) { return value % that; }
+ public long __bar (long that) { return value | that; }
+ public long __amp (long that) { return value & that; }
+ public long __up (long that) { return value ^ that; }
+
+ [Meta("method []scala.Long;")]
+ public long coerce (object dummy) { return value ; }
+
+ public bool __eq__eq (int that) { return value == that; }
+ public bool __bang__eq (int that) { return value != that; }
+ public bool __less (int that) { return value < that; }
+ public bool __greater (int that) { return value > that; }
+ public bool __less__eq (int that) { return value <= that; }
+ public bool __greater__eq(int that) { return value >= that; }
+ public int __plus (int that) { return value + that; }
+ public int __minus (int that) { return value - that; }
+ public int __times (int that) { return value * that; }
+ public int __div (int that) { return value / that; }
+ public int __percent (int that) { return value % that; }
+ public int __bar (int that) { return value | that; }
+ public int __amp (int that) { return value & that; }
+ public int __up (int that) { return value ^ that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Int.java b/src/library/scala/Int.java
new file mode 100644
index 0000000000..5c5d95a63e
--- /dev/null
+++ b/src/library/scala/Int.java
@@ -0,0 +1,184 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Int extends AnyVal implements java.io.Serializable {
+
+ public final int value;
+
+ public Int (int value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Int && value == ((Int )other).value;
+ }
+ public int hashCode() {
+ int bits = value;
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Int ; */
+ public int $plus ( ) { return +value ; }
+
+ /** @meta method []scala.Int ; */
+ public int $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+ /** @meta method []scala.Float ; */
+ public float coerce ( ) { return value ; }
+ /** @meta method []scala.Int ; */
+ public int $tilde ( ) { return ~value ; }
+
+ public int $less$less (int that) { return value << that; }
+ public int $less$less (long that) { return value << that; }
+ public int $greater$greater(int that) { return value >> that; }
+ public int $greater$greater(long that) { return value >> that; }
+ public int $greater$greater$greater(int that) { return value >>>that; }
+ public int $greater$greater$greater(long that) { return value >>>that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public long $plus (long that) { return value + that; }
+ public long $minus (long that) { return value - that; }
+ public long $times (long that) { return value * that; }
+ public long $div (long that) { return value / that; }
+ public long $percent (long that) { return value % that; }
+ public long $bar (long that) { return value | that; }
+ public long $amp (long that) { return value & that; }
+ public long $up (long that) { return value ^ that; }
+
+ /** @meta method []scala.Long ; */
+ public long coerce ( ) { return value ; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public int $plus (int that) { return value + that; }
+ public int $minus (int that) { return value - that; }
+ public int $times (int that) { return value * that; }
+ public int $div (int that) { return value / that; }
+ public int $percent (int that) { return value % that; }
+ public int $bar (int that) { return value | that; }
+ public int $amp (int that) { return value & that; }
+ public int $up (int that) { return value ^ that; }
+
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public int $plus (char that) { return value + that; }
+ public int $minus (char that) { return value - that; }
+ public int $times (char that) { return value * that; }
+ public int $div (char that) { return value / that; }
+ public int $percent (char that) { return value % that; }
+ public int $bar (char that) { return value | that; }
+ public int $amp (char that) { return value & that; }
+ public int $up (char that) { return value ^ that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public int $plus (short that) { return value + that; }
+ public int $minus (short that) { return value - that; }
+ public int $times (short that) { return value * that; }
+ public int $div (short that) { return value / that; }
+ public int $percent (short that) { return value % that; }
+ public int $bar (short that) { return value | that; }
+ public int $amp (short that) { return value & that; }
+ public int $up (short that) { return value ^ that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public int $plus (byte that) { return value + that; }
+ public int $minus (byte that) { return value - that; }
+ public int $times (byte that) { return value * that; }
+ public int $div (byte that) { return value / that; }
+ public int $percent (byte that) { return value % that; }
+ public int $bar (byte that) { return value | that; }
+ public int $amp (byte that) { return value & that; }
+ public int $up (byte that) { return value ^ that; }
+}
diff --git a/src/library/scala/Iterable.scala b/src/library/scala/Iterable.scala
new file mode 100644
index 0000000000..89103802fd
--- /dev/null
+++ b/src/library/scala/Iterable.scala
@@ -0,0 +1,157 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Iterable.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+import Predef._;
+
+object Iterable {
+ def view[A <% Ordered[A]](x: Iterable[A]): Ordered[Iterable[A]] = new Ordered[Iterable[A]] {
+ def compareTo[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 compareTo ys.next;
+ }
+ if (xs.hasNext) 1
+ else if (ys.hasNext) -1
+ else res;
+ case _ =>
+ -(that compareTo 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) error("min(<empty>)");
+ var min = xs.next;
+ while (xs.hasNext) {
+ val x = xs.next;
+ if (x < min) min = x;
+ }
+ min
+ }
+
+ /** The maximum element of a non-empty sequence of ordered elements */
+ def max[A <% Ordered[A]](seq: Iterable[A]): A = {
+ val xs = seq.elements;
+ if (!xs.hasNext) error("max(<empty>)");
+ var max = xs.next;
+ while (xs.hasNext) {
+ val x = xs.next;
+ if (max < x) max = x;
+ }
+ max
+ }
+}
+
+/** Collection classes supporting this trait provide a method
+ * <code>elements</code> which returns an iterator over all the
+ * elements contained in the collection.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+trait Iterable[+A] {
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A];
+
+ /** Concatenates two iterable objects
+ *
+ * @return the new iterable object
+ * @author buraq
+ */
+ def concat[B >: A](that:Iterable[B]): Iterable[B] = new Iterable[B] {
+ def elements: Iterator[B] = Iterable.this.elements.append(that.elements);
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ def foreach(f: A => Unit): Unit = elements.foreach(f);
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff the predicate yields
+ * true for all elements.
+ *
+ * @param p the predicate
+ * @returns true, iff the predicate yields true for all elements.
+ */
+ def forall(p: A => Boolean): Boolean = elements.forall(p);
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields true.
+ *
+ * @param p the predicate
+ * @returns true, iff the predicate yields true for at least one element.
+ */
+ def exists(p: A => Boolean): Boolean = elements.exists(p);
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = elements.find(p);
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ * @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
+ * is <code>List(a0, a1, ..., an)</code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = elements.foldLeft(z)(op);
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from rigth to left, and starting with
+ * the value <code>z</code>.
+ * @return <code>a0 op (... op (an op z)...)</code> if the list
+ * is <code>[a0, a1, ..., an]</code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = elements.foldRight(z)(op);
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ */
+ def /:[B](z: B)(f: (B, A) => B): B = foldLeft(z)(f);
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ */
+ def :\[B](z: B)(f: (A, B) => B): B = foldRight(z)(f);
+
+ /** 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
+ }
+}
diff --git a/src/library/scala/IterableProxy.scala b/src/library/scala/IterableProxy.scala
new file mode 100644
index 0000000000..52ebe8806f
--- /dev/null
+++ b/src/library/scala/IterableProxy.scala
@@ -0,0 +1,97 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:IterableProxy.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** This class implements a proxy for iterable objects. It forwards
+ * all calls to a different iterable object.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 26/04/2004
+ */
+trait IterableProxy[+A] extends Iterable[A] with Proxy {
+
+ def self: Iterable[A];
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A] = self.elements;
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ override def foreach(f: A => Unit): Unit = self.foreach(f);
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff the predicate yields
+ * true for all elements.
+ *
+ * @param p the predicate
+ * @returns true, iff the predicate yields true for all elements.
+ */
+ override def forall(p: A => Boolean): Boolean = self.forall(p);
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields true.
+ *
+ * @param p the predicate
+ * @returns true, iff the predicate yields true for at least one element.
+ */
+ override def exists(p: A => Boolean): Boolean = self.exists(p);
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ override def find(p: A => Boolean): Option[A] = self.find(p);
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ * @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
+ * is <code>List(a0, a1, ..., an)</code>.
+ */
+ override def foldLeft[B](z: B)(op: (B, A) => B): B = self.foldLeft(z)(op);
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from rigth to left, and starting with
+ * the value <code>z</code>.
+ * @return <code>a0 op (... op (an op z)...)</code> if the list
+ * is <code>[a0, a1, ..., an]</code>.
+ */
+ override def foldRight[B](z: B)(op: (A, B) => B): B = self.foldRight(z)(op);
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ */
+ override def /:[B](z: B)(f: (B, A) => B): B = self./:(z)(f);
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ */
+ override def :\[B](z: B)(f: (A, B) => B): B = self.:\(z)(f);
+
+ /** 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.
+ */
+ override def sameElements[B >: A](that: Iterable[B]): Boolean = self.sameElements(that);
+}
diff --git a/src/library/scala/Iterator.scala b/src/library/scala/Iterator.scala
new file mode 100644
index 0000000000..1664eb2ffe
--- /dev/null
+++ b/src/library/scala/Iterator.scala
@@ -0,0 +1,429 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Iterator.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+package scala;
+
+import Predef._;
+
+/** The <code>Iterator</code> object provides various functions for
+ * creating specialized iterators.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.1, 04/02/2004
+ */
+object Iterator {
+
+ def empty[a] = new Iterator[a] {
+ def hasNext: Boolean = false;
+ def next: a = Predef.error("next on empty iterator");
+ }
+
+ 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 Predef.error("next on empty iterator");
+ }
+
+ def fromValues[a](xs: a*) = xs.elements;
+
+ def fromArray[a](xs: Array[a]) = new Iterator[a] {
+ private var i = 0;
+ def hasNext: Boolean = i < xs.length;
+ def next: a =
+ if (i < xs.length) { val x = xs(i) ; i = i + 1 ; x }
+ else Predef.error("next on empty iterator");
+ }
+
+ def fromString(str: String): Iterator[Char] = new Iterator[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 fromCaseClass(n:CaseClass): Iterator[Any] = new Iterator[Any] {
+ private var c:Int = 0;
+ private val cmax = n.caseArity;
+ def hasNext = c < cmax;
+ def next = { val a = n caseElement c; c = c + 1; a }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @return the iterator with values in range [lo;end).
+ */
+ def range(lo: Int, end: Int): Iterator[Int] =
+ range(lo, end, 1);
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment value of the iterator (must be positive or negative)
+ * @return the iterator with values in range [lo;end).
+ */
+ def range(lo: Int, end: Int, step: Int): Iterator[Int] = {
+ assert(step != 0);
+ new Iterator[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 Predef.error("next on empty iterator");
+ def head: Int =
+ if (hasNext) i else Predef.error("head on empty iterator");
+ }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = lo</code>
+ * and <code>e<sub>i</sub> &lt; end</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param end the end value of the iterator
+ * @param step the increment function of the iterator
+ * @return the iterator with values in range [lo;end).
+ */
+ def range(lo: Int, end: Int, step: Int => Int): Iterator[Int] = new Iterator[Int] {
+ private var i = lo;
+ def hasNext: Boolean = i < end;
+ def next: Int =
+ if (i < end) { val j = i; i = step(i); j } else Predef.error("next on empty iterator");
+ def head: Int =
+ if (i < end) i else Predef.error("head on empty iterator");
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + 1</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int): Iterator[Int] =
+ from(lo, 1);
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = e<sub>n</sub> + step</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param step the increment value of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int, step: Int) = new Iterator[Int] {
+ private var i = lo;
+ def hasNext: Boolean = true;
+ def next: Int = { val j = i; i = i + step; j }
+ }
+
+ /** Create an iterator with elements
+ * <code>e<sub>n+1</sub> = step(e<sub>n</sub>)</code>
+ * where <code>e<sub>0</sub> = lo</code>.
+ *
+ * @param lo the start value of the iterator
+ * @param step the increment function of the iterator
+ * @return the iterator starting at value <code>lo</code>.
+ */
+ def from(lo: Int, step: Int => Int) = new Iterator[Int] {
+ private var i = lo;
+ def hasNext: Boolean = true;
+ def next: Int = { val j = i; i = step(i); j }
+ }
+
+}
+
+/** Iterators are data structures that allow to iterate over a sequence
+ * of elements. They have a <code>hasNext</code> method for checking
+ * if there is a next element available, and a <code>next</code> method
+ * which returns the next element and discards it from the iterator.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.2, 15/03/2004
+ */
+trait Iterator[+A] {
+
+ /** Does this iterator provide another element?
+ */
+ def hasNext: Boolean;
+
+ /** Returns the next element.
+ */
+ def next: A;
+
+ /** Returns a new iterator that iterates only over the first <code>n</code>
+ * elements.
+ */
+ 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 Predef.error("next on empty iterator");
+ }
+
+ /** Removes the first <code>n</code> elements from this iterator.
+ */
+ def drop(n: Int): Iterator[A] =
+ if (n > 0) { next; drop(n - 1) } else this;
+
+ /** Returns a new iterator that maps all elements of this iterator
+ * to new elements using function <code>f</code>.
+ */
+ def map[B](f: A => B): Iterator[B] = new Iterator[B] {
+ def hasNext = Iterator.this.hasNext;
+ def next = f(Iterator.this.next)
+ }
+
+ /** Returns a new iterator that first yields the elements of this
+ * iterator followed by the elements provided by iterator <code>that</code>.
+ */
+ 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;
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this iterator, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return an iterator over <code>f(a0), ... , f(an)</code> if this iterator
+ * yields the elements <code>a0, ..., an</code>.
+ */
+ def flatMap[B](f: A => Iterator[B]): Iterator[B] = new Iterator[B] {
+ private var cur: Iterator[B] = Iterator.empty;
+ def hasNext: Boolean =
+ if (cur.hasNext) true
+ else if (Iterator.this.hasNext) {
+ cur = f(Iterator.this.next);
+ hasNext
+ } else false;
+ def next: B =
+ if (cur.hasNext) cur.next
+ else if (Iterator.this.hasNext) {
+ cur = f(Iterator.this.next);
+ next
+ } else Predef.error("next on empty iterator");
+ }
+
+ /** Returns an iterator over all the elements of this iterator that
+ * satisfy the predicate <code>p</code>. The order of the elements
+ * is preserved.
+ *
+ * @param p the redicate used to filter the iterator.
+ * @return the elements of this iterator satisfying <code>p</code>.
+ */
+ def filter(p: A => Boolean): Iterator[A] = new BufferedIterator[A] {
+ private val source = Iterator.this.buffered;
+ private def skip: Unit =
+ while (source.hasNext && !p(source.head)) { source.next; () }
+ def hasNext: Boolean = { skip; source.hasNext }
+ def next: A = { skip; source.next }
+ def head: A = { skip; source.head; }
+ }
+
+ /** Return an iterator formed from this iterator and the specified iterator
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param <code>that</code> must have the same number of elements as this
+ * iterator.
+ * @return an iterator yielding <code>(a0,b0), ..., (an,bn)</code> where
+ * <code>ai</code> are the elements from this iterator and
+ * <code>bi</code> are the elements from iterator <code>that</code>.
+ */
+ def zip[B](that: Iterator[B]) = new Iterator[Pair[A, B]] {
+ def hasNext = Iterator.this.hasNext && that.hasNext;
+ def next = Pair(Iterator.this.next, that.next);
+ }
+
+ /** Apply a function <code>f</code> to all elements of this
+ * iterable object.
+ *
+ * @param f a function that is applied to every element.
+ */
+ def foreach(f: A => Unit): Unit = while (hasNext) { f(next) };
+
+ /** Apply a predicate <code>p</code> to all elements of this
+ * iterable object and return true, iff the predicate yields
+ * true for all elements.
+ *
+ * @param p the predicate
+ * @returns 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 <code>p</code> to all elements of this
+ * iterable object and return true, iff there is at least one
+ * element for which <code>p</code> yields true.
+ *
+ * @param p the predicate
+ * @returns 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 <code>elem</code> is a member of this list.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return True iff there is an element of this list which is
+ * equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): Boolean = exists { x => x == elem };
+
+ /** Find and return the first element of the iterable object satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the iterable object satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ def find(p: A => Boolean): Option[A] = {
+ var res: Option[A] = None;
+ while (res.isEmpty && hasNext) {
+ val e = next;
+ if (p(e)) res = Some(e);
+ }
+ res
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ * @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
+ * is <code>List(a0, a1, ..., an)</code>.
+ */
+ def foldLeft[B](z: B)(op: (B, A) => B): B = {
+ var acc = z;
+ while (hasNext) { acc = op(acc, next) }
+ acc
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from rigth to left, and starting with
+ * the value <code>z</code>.
+ * @return <code>a0 op (... op (an op z)...)</code> if the list
+ * is <code>[a0, a1, ..., an]</code>.
+ */
+ def foldRight[B](z: B)(op: (A, B) => B): B = {
+ def fold(z: B): B =
+ if (hasNext) op(next, fold(z)) else z;
+ fold(z)
+ }
+
+ /** Similar to <code>foldLeft</code> but can be used as
+ * an operator with the order of list and zero arguments reversed.
+ * That is, <code>z /: xs</code> is the same as <code>xs foldLeft z</code>
+ */
+ def /:[B](z: B)(f: (B, A) => B): B = foldLeft(z)(f);
+
+ /** An alias for <code>foldRight</code>.
+ * That is, <code>xs :\ z</code> is the same as <code>xs foldRight z</code>
+ */
+ def :\[B](z: B)(f: (A, B) => B): B = foldRight(z)(f);
+
+ /** 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;
+ override def buffered: BufferedIterator[A] = this;
+ }
+
+ /** Creates two new iterators that both iterate over the same elements
+ * than this iterator (in the same order).
+ */
+ def duplicate: Pair[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;
+ Pair(ahead, new Partner)
+ }
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @return the given array <code>xs</code> filled with this list.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int): Array[B] = {
+ var i = start;
+ while (hasNext) {
+ xs(i) = next;
+ i = i + 1;
+ }
+ xs
+ }
+
+ /** Transform this iterator into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this iterator.
+ */
+ def toList: List[A] = {
+ var res: List[A] = Nil;
+ while (hasNext) {
+ res = next :: res;
+ }
+ res.reverse
+ }
+
+}
diff --git a/src/library/scala/List.scala b/src/library/scala/List.scala
new file mode 100644
index 0000000000..4da2611640
--- /dev/null
+++ b/src/library/scala/List.scala
@@ -0,0 +1,919 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:List.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+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] =
+ // TODO: remove the type test once nsc becomes standard
+ if (xs.isInstanceOf$erased[List[A]])
+ xs.asInstanceOf$erased[List[A]];
+ else
+ fromArray(xs.asInstanceOf$erased[Array[A]]);
+
+ /** 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] =
+ if (from >= end) Nil
+ else from :: range(from + step, end, step);
+
+ /** 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] =
+ if (from >= end) Nil
+ else from :: range(step(from), end, step);
+
+ /** 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] =
+ if (n == 0) Nil
+ else elem :: make(n - 1, elem);
+
+ /** 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 [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] = {
+ def loop(i: int): List[a] =
+ if (i == n) Nil
+ else maker(i) :: loop(i + 1);
+ loop(0)
+ }
+
+ /** Concatenate all the elements of a given list of lists.
+ * @param l the list of lists that are to be concatenated
+ * @return the concatenation of all the lists
+ */
+ def flatten[a](l: List[List[a]]): List[a] = l match {
+ case Nil => Nil
+ case head :: tail => head ::: flatten(tail)
+ }
+
+ /** Transforms a list of pair into a pair of lists.
+ *
+ * @param l the list of pairs to unzip
+ * @return a pair of lists: the first list in the pair contains the list
+ */
+ def unzip[a,b](l: List[Pair[a,b]]): Pair[List[a], List[b]] = l match {
+ case Nil => new Pair(Nil, Nil)
+ case Pair(f, s) :: tail =>
+ val Pair(fs, ss) = unzip(tail);
+ Pair(f :: fs, s :: ss)
+ }
+
+ /** Converts an iterator to a list
+ *
+ * @param it the iterator to convert
+ * @return a list that contains the elements returned by successive
+ * calls to <code>it.next</code>
+ */
+ def fromIterator[a](it: Iterator[a]): List[a] =
+ if (it.hasNext) it.next :: fromIterator(it);
+ else Nil;
+
+ /** Converts an array into a list.
+ *
+ * @param arr the array to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[a](arr: Array[a]): List[a] = fromArray(arr, 0, arr.length);
+
+ /** Converts a range of an array into a list.
+ *
+ * @param arr the array to convert
+ * @param start the first index to consider
+ * @param len the lenght of the range to convert
+ * @return a list that contains the same elements than <code>arr</code>
+ * in the same order
+ */
+ def fromArray[a](arr: Array[a], start: Int, len: Int): List[a] = {
+ var res: List[a] = Nil;
+ var i = start + len;
+ while (i > start) {
+ i = i - 1;
+ res = arr(i) :: res;
+ }
+ res
+ }
+
+ /** Parses a string which contains substrings separated by a
+ *
+ * separator character and returns a list of all substrings.
+ * @param str the string to parse
+ * @param separator the separator character
+ * @return the list of substrings
+ */
+ def fromString(str: String, separator: Char): List[String] = {
+ var words: List[String] = List();
+ var pos = str.length();
+ while (pos > 0) {
+ val pos1 = str.lastIndexOf(separator, pos - 1);
+ if (pos1 + 1 < pos)
+ words = str.substring(pos1 + 1, pos) :: words;
+ pos = pos1
+ }
+ words
+ }
+/*
+ var res: List[String] = Nil;
+ var start = 0;
+ var end = str.indexOf(separator);
+ while (end >= 0) {
+ if (end > start)
+ res = str.substring(start, end) :: res;
+ end = end + 1;
+ start = end;
+ end = str.indexOf(separator, end);
+ }
+ res.reverse
+ }
+*/
+ /** 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] = {
+ var res: List[Char] = Nil;
+ var i = str.length();
+ while (i > 0) {
+ i = i - 1;
+ res = str.charAt(i) :: res;
+ }
+ res
+ }
+
+ /** 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 StringBuffer();
+ var ys = xs;
+ while (!ys.isEmpty) {
+ sb.append(ys.head);
+ ys = ys.tail;
+ }
+ sb.toString()
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code> to
+ * corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0), ..., f(an,bn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>n = min(k,l)</code>
+ */
+ def map2[a,b,c](xs: List[a], ys: List[b])(f: (a, b) => c): List[c] =
+ if (xs.isEmpty || ys.isEmpty) Nil
+ else f(xs.head, ys.head) :: map2(xs.tail, ys.tail)(f);
+
+ /** Like xs map f, but returns xs unchanged if function `f' maps all elements to themselves
+ */
+ def mapConserve[a <: AnyRef](xs: List[a])(f: a => a): List[a] = {
+ if (xs.isEmpty) xs
+ else {
+ val head = xs.head;
+ val head1 = f(head);
+ val tail = xs.tail;
+ val tail1 = mapConserve(tail)(f);
+ if ((head1 eq head) && (tail1 eq tail)) xs else head1 :: tail1
+ }
+ }
+
+ /** Returns the list resulting from applying the given function <code>f</code> to
+ * corresponding elements of the argument lists.
+ *
+ * @param f function to apply to each pair of elements.
+ * @return <code>[f(a0,b0,c0), ..., f(an,bn,cn)]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code>, <code>[c0, ..., cm]</code> and
+ * <code>n = min(k,l,m)</code>
+ */
+ def map3[a,b,c, d](xs: List[a], ys: List[b], zs: List[c])(f: (a, b, c) => d): List[d] =
+ if (xs.isEmpty || ys.isEmpty || zs.isEmpty) Nil
+ else f(xs.head, ys.head, zs.head) :: map3(xs.tail, ys.tail, zs.tail)(f);
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for all corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n == 0 || (p(a0,b0) &amp;&amp; ... &amp;&amp; p(an,bn))]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = min(k,l)</code>
+ */
+ def forall2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean =
+ if (xs.isEmpty || ys.isEmpty) true
+ else f(xs.head, ys.head) && forall2(xs.tail, ys.tail)(f);
+
+ /** Tests whether the given predicate <code>p</code> holds
+ * for some corresponding elements of the argument lists.
+ *
+ * @param p function to apply to each pair of elements.
+ * @return <code>n != 0 &amp;&amp; (p(a0,b0) || ... || p(an,bn))]</code> if the lists are
+ * <code>[a0, ..., ak]</code>, <code>[b0, ..., bl]</code> and
+ * <code>m = min(k,l)</code>
+ */
+ def exists2[a,b](xs: List[a], ys: List[b])(f: (a, b) => boolean): boolean =
+ if (xs.isEmpty || ys.isEmpty) false
+ else f(xs.head, ys.head) || exists2(xs.tail, ys.tail)(f);
+
+ /** 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 compareTo [b >: List[a] <% Ordered[b]](y: b): int = y match {
+ case y1: List[a] => compareLists(x, y1);
+ case _ => -(y compareTo 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 compareTo ys.head;
+ if (s != 0) s
+ else compareLists(xs.tail, ys.tail)
+ }
+ }
+ }
+ def view[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = list2ordered(x);
+}
+
+/** A trait representing an ordered collection of elements of type
+ * <code>a</code>. This class comes with two implementing case
+ * classes <code>scala.Nil</code> and <code>scala.::</code> that
+ * implement the abstract members <code>isEmpty</code>,
+ * <code>head</code> and <code>tail</code>.
+ *
+ * @author Martin Odersky and others
+ * @version 1.0, 16/07/2003
+ */
+sealed abstract class List[+a] extends Seq[a] {
+
+ /** Returns true if the list does not contain any elements.
+ * @return true, iff the list is empty.
+ */
+ def isEmpty: Boolean;
+
+ /** Returns this first element of the list.
+ * @return the first element of this list.
+ * @throws <code>java.lang.RuntimeException</code> if the list is empty.
+ */
+ def head: a;
+
+ /** Returns this list without its first element.
+ * @return this list without its first element.
+ * @throws <code>java.lang.RuntimeException</code> if the list is empty.
+ */
+ def tail: List[a];
+
+ /** Add an element <code>x</code> at the beginning of this list.
+ * <p/>
+ * Ex:<br/>
+ * <code>1 :: [2, 3] = [2, 3].::(1) = [1, 2, 3]</code>.
+ * @param x the element to append.
+ * @return the list with <code>x</code> appended at the beginning.
+ */
+ def ::[b >: a](x: b): List[b] =
+ new scala.::(x, this);
+
+ /** Returns a list resulting from the concatenation of the given
+ * list <code>prefix</code> and this list.
+ * <p/>
+ * Ex:<br/>
+ * <code>[1, 2] ::: [3, 4] = [3, 4].:::([1, 2]) = [1, 2, 3, 4]</code>.
+ * @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] = prefix match {
+ case Nil => this
+ case head :: tail => head :: (tail ::: this);
+ }
+
+ /** Reverse the given prefix and append the current list to that.
+ * This function is equivalent to an application of <code>reverse</code>
+ * on the prefix followed by a call to <code>:::</code>, but more
+ * efficient (and tail recursive).
+ * @param prefix the prefix to reverse and then prepend
+ * @return the concatenation of the reversed prefix and the current list.
+ */
+ def reverse_:::[b >: a](prefix: List[b]): List[b] = prefix match {
+ case Nil => this
+ case head :: tail => tail.reverse_:::(head :: this)//todo: remove type annotation
+ }
+
+ /** Returns the number of elements in the list.
+ *
+ * @return the number of elements in the list.
+ */
+ def length: Int = {
+ var xs = this;
+ var len = 0;
+ while (!xs.isEmpty) {
+ len = len + 1;
+ xs = xs.tail
+ }
+ len
+ }
+
+ /** Creates a list with all indices in the list. This is
+ * equivalent to a call to <code>List.range(0, xs.length)</code>.
+ *
+ * @return a list of all indices in the list.
+ */
+ def indices: List[Int] = {
+ def loop(i: Int, xs: List[a]): List[Int] = xs match {
+ case Nil => Nil
+ case _ :: ys => i :: loop(i + 1, ys)
+ }
+ loop(0, this)
+ }
+
+ /** Returns the elements in the list as an iterator
+ *
+ * @return an iterator on the list elements.
+ */
+ def elements: Iterator[a] = new Iterator[a] {
+ var current = List.this;
+ def hasNext: Boolean = !current.isEmpty;
+ def next: a =
+ if (!hasNext)
+ error("next on empty Iterator")
+ else {
+ val result = current.head; current = current.tail; result
+ }
+ }
+
+ /** Transform this sequence into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this sequence.
+ */
+ override def toList: List[a] = this;
+
+ /** Returns the list without its last element.
+ *
+ * @return the list without its last element.
+ * @throws <code>java.lang.RuntimeException</code> if the list is empty.
+ */
+ def init: List[a] = this match {
+ case Nil => error("Nil.init")
+ case _ :: Nil => Nil
+ case head :: tail => head :: tail.init
+ }
+
+ /** Returns the last element of this list.
+ *
+ * @return the last element of the list.
+ * @throws <code>java.lang.RuntimeException</code> if the list is empty.
+ */
+ def last: a = this match {
+ case Nil => error("Nil.last")
+ case last :: Nil => last
+ case _ :: tail => tail.last
+ }
+
+ /** Returns the <code>n</code> first elements of this list.
+ *
+ * @param n the number of elements to take.
+ * @return the <code>n</code> first elements of this list.
+ */
+ override def take(n: Int): List[a] =
+ if (n == 0 || isEmpty) Nil
+ else head :: (tail take (n-1));
+
+ /** Returns the list without its <code>n</code> first elements.
+ *
+ * @param n the number of elements to drop.
+ * @return the list without its <code>n</code> first elements.
+ */
+ override def drop(n: Int): List[a] =
+ if (n == 0 || isEmpty) this
+ else (tail drop (n-1));
+
+ /** Returns the rightmost <code>n</code> elements from this list.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ * @throws <code>java.lang.RuntimeException</code> if the list is too short.
+ */
+ def takeRight(n: Int): List[a] = {
+ def loop(lead: List[a], lag: List[a]): List[a] = lead match {
+ case Nil => lag
+ case _ :: tail => loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Returns the list wihout its rightmost <code>n</code> elements.
+ *
+ * @param n the number of elements to take
+ * @return the suffix of length <code>n</code> of the list
+ * @throws <code>java.lang.RuntimeException</code> if the list is too short.
+ */
+ def dropRight(n: Int): List[a] = {
+ def loop(lead: List[a], lag: List[a]): List[a] = lead match {
+ case Nil => Nil
+ case _ :: tail => lag.head :: loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ /** Split the list at a given point and return the two parts thus
+ * created.
+ *
+ * @param n the position at which to split
+ * @return a pair of lists composed of the first <code>n</code>
+ * elements, and the other elements.
+ */
+ def splitAt(n: Int): Pair[List[a], List[a]] =
+ if (n == 0) Pair(Nil, this)
+ else {
+ val Pair(tail1, tail2) = tail splitAt (n-1);
+ Pair(head :: tail1, tail2)
+ }
+
+ /** Returns the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest prefix of this list whose elements satisfy
+ * the predicate <code>p</code>.
+ */
+ def takeWhile(p: a => Boolean): List[a] =
+ if (isEmpty || !p(head)) Nil
+ else head :: (tail takeWhile p);
+
+ /** Returns the longest suffix of this list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return the longest suffix of the list whose first element
+ * does not satisfy the predicate <code>p</code>.
+ */
+ def dropWhile(p: a => Boolean): List[a] =
+ if (isEmpty || !p(head)) this
+ else tail dropWhile p;
+
+ /** Returns the longest prefix of the list whose elements all satisfy
+ * the given predicate, and the rest of the list.
+ *
+ * @param p the test predicate
+ * @return a pair consisting of the longest prefix of the list whose
+ * elements all satisfy <code>p</code>, and the rest of the list.
+ */
+ def span(p: a => Boolean): Pair[List[a], List[a]] = this match {
+ case Nil => Pair(Nil, Nil)
+ case head :: tail =>
+ if (p(head)) {
+ val Pair(tail1, tail2) = tail span p;
+ Pair(head :: tail1, tail2)
+ } else
+ Pair(Nil, this)
+ }
+
+ /** Like <code>span</code> but with the predicate inverted.
+ */
+ def break(p: a => Boolean): Pair[List[a], List[a]] = span { x => !p(x) }
+
+ /** Returns the <code>n</code>-th element of this list. The first element
+ * (head of the list) is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this list.
+ * @throws <code>java.lang.RuntimeException</code> if the list is too short.
+ */
+ def apply(n: Int): a = drop(n).head;
+
+ /** Returns the list resulting from applying the given function <code>f</code> to each
+ * element of this list.
+ *
+ * @param f function to apply to each element.
+ * @return <code>[f(a0), ..., f(an)]</code> if this list is <code>[a0, ..., an]</code>.
+ */
+ def map[b](f: a => b): List[b] = this match {
+ case Nil => Nil
+ case head :: tail => f(head) :: (tail map f)
+ }
+
+ /** Apply a function to all the elements of the list, and return the
+ * reversed list of results. This is equivalent to a call to <code>map</code>
+ * followed by a call to <code>reverse</code>, but more efficient.
+ *
+ * @param f the function to apply to each elements.
+ * @return the reversed list of results.
+ */
+ def reverseMap[b](f: a => b): List[b] = {
+ def loop(l: List[a], res: List[b]): List[b] = l match {
+ case Nil => res
+ case head :: tail => loop(tail, f(head) :: res)
+ }
+ loop(this, Nil)
+ }
+
+ /** Apply the given function <code>f</code> to each element of this list
+ * (while respecting the order of the elements).
+ *
+ * @param f the treatment to apply to each element.
+ */
+ override def foreach(f: a => Unit): Unit = {
+ def loop(xs: List[a]): Unit = xs match {
+ case Nil => ()
+ case head :: tail => f(head); loop(tail)
+ }
+ loop(this)
+ }
+
+ /** Returns all the elements of this list that satisfy the
+ * predicate <code>p</code>. The order of the elements is preserved.
+ *
+ * @param p the redicate used to filter the list.
+ * @return the elements of this list satisfying <code>p</code>.
+ */
+ def filter(p: a => Boolean): List[a] = this match {
+ case Nil => this
+ case head :: tail =>
+ if (p(head)) {
+ val tail1 = tail filter p;
+ if (tail eq tail1) this else head :: tail1
+ } else tail filter p
+ }
+
+ /** Removes all elements of the list which satisfy the predicate
+ * <code>p</code>. This is like <code>filter</code> with the
+ * predicate inversed.
+ *
+ * @param p the predicate to use to test elements
+ * @return the list without all elements which satisfy <code>p</code>
+ */
+ def remove(p: a => Boolean): List[a] = this match {
+ case Nil => this
+ case head :: tail =>
+ if (p(head)) tail remove p else head :: (tail remove p)
+ }
+
+ /** Partition the list in two sub-lists according to a predicate.
+ *
+ * @param p the predicate on which to partition
+ * @return a pair of lists: the list of all elements which satisfy
+ * <code>p</code> and the list of all elements which do not. The
+ * relative order of the elements in the sub-lists is the same as in
+ * the original list.
+ */
+ def partition(p: a => Boolean): Pair[List[a], List[a]] = this match {
+ case Nil => Pair(Nil, Nil)
+ case head :: tail =>
+ val Pair(taily, tailn) = tail partition p;
+ if (p(head)) Pair(head :: taily, tailn)
+ else Pair(taily, head :: tailn)
+ }
+
+ /** Sort the list according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>,
+ * which should be true iff e1 is smaller than e2.
+ * Note: The current implementation is inefficent for
+ * already sorted lists.
+ *
+ * @param lt the comparison function
+ * @return a list sorted according to the comparison function
+ * <code>&lt;(e1: a, e2: a) =&gt; Boolean</code>.
+ */
+ def sort(lt : (a,a) => Boolean): List[a] = {
+ def sort_1(smaller: List[a], acc: List[a]): List[a] =
+ smaller match {
+ case Nil =>
+ acc
+ case List(x) =>
+ x::acc
+ case List(x, y) =>
+ if (lt(x, y)) x::(y::acc) else y::x::acc
+ case List(x, y, z) =>
+ 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 Pair(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) =>
+ this
+ case List(x, y) =>
+ if (lt(x, y)) this else y::x::Nil
+ case List(x, y, z) =>
+ 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 Pair(small,large) = tail.partition((e2) => lt(e2, y));
+ sort_1(x::small, y::sort_1(z::large, Nil));
+ }
+ }
+ }
+
+
+ /** Count the number of elements in the list which satisfy a predicate.
+ *
+ * @param p the predicate for which to count
+ * @return the number of elements satisfying the predicate <code>p</code>.
+ */
+ def count(p: a => Boolean): Int = this match {
+ case Nil => 0
+ case head :: tail => if (p(head)) 1 + (tail count p) else (tail count p)
+ }
+
+ /** Tests if the predicate <code>p</code> is satisfied by all elements
+ * in this list.
+ *
+ * @param p the test predicate.
+ * @return True iff all elements of this list satisfy the predicate <code>p</code>.
+ */
+ override def forall(p: a => Boolean): Boolean =
+ isEmpty || (p(head) && (tail forall p));
+
+ /** Tests the existence in this list of an element that satisfies the predicate
+ * <code>p</code>.
+ *
+ * @param p the test predicate.
+ * @return true iff there exists an element in this list that satisfies
+ * the predicate <code>p</code>.
+ */
+ override def exists(p: a => Boolean): Boolean =
+ !isEmpty && (p(head) || (tail exists p));
+
+ /** Tests if the given value <code>elem</code> is a member of this
+ * iterable object.
+ *
+ * @param elem element whose membership has to be tested.
+ * @return True iff there is an element of this list which is
+ * equal (w.r.t. <code>==</code>) to <code>elem</code>.
+ */
+ def contains(elem: Any): boolean = exists { x => x == elem }
+
+ /** Find and return the first element of the list satisfying a
+ * predicate, if any.
+ *
+ * @param p the predicate
+ * @return the first element in the list satisfying <code>p</code>,
+ * or <code>None</code> if none exists.
+ */
+ override def find(p: a => Boolean): Option[a] = this match {
+ case Nil => None
+ case head :: tail => if (p(head)) Some(head) else tail find p
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from left to right, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>op(... (op(op(z,a0),a1) ...), an)</code> if the list
+ * is <code>[a0, a1, ..., an]</code>.
+ */
+ override def foldLeft[b](z: b)(f: (b, a) => b): b = this match {
+ case Nil => z
+ case x :: xs => xs.foldLeft[b](f(z, x))(f)
+ }
+
+ /** Combines the elements of this list together using the binary
+ * operator <code>op</code>, from rigth to left, and starting with
+ * the value <code>z</code>.
+ *
+ * @return <code>a0 op (... op (an op z)...)</code> if the list
+ * is <code>[a0, a1, ..., an]</code>.
+ */
+ override def foldRight[b](z: b)(f: (a, b) => b): b = this match {
+ case Nil => z
+ case x :: xs => f(x, xs.foldRight(z)(f))
+ }
+
+ def reduceLeft[b >: a](f: (b, b) => b): b = this match {
+ case Nil => error("Nil.reduceLeft")
+ case x :: xs => ((xs: List[b]) foldLeft (x: b))(f)
+ }
+
+ def reduceRight[b >: a](f: (b, b) => b): b = this match {
+ case Nil => error("Nil.reduceRight")
+ case x :: Nil => x: b
+ case x :: xs => f(x, xs reduceRight f)
+ }
+
+ /** Applies the given function <code>f</code> to each element of
+ * this list, then concatenates the results.
+ *
+ * @param f the function to apply on each element.
+ * @return <code>f(a0) ::: ... ::: f(an)</code> if this list is
+ * <code>[a0, ..., an]</code>.
+ */
+ def flatMap[b](f: a => List[b]): List[b] = this match {
+ case Nil => Nil
+ case head :: tail => f(head) ::: (tail flatMap f)
+ }
+
+ /** Reverses the elements of this list.
+ * <p/>
+ * Ex: <br/>
+ * <code>[1, 2, 3] reverse = [3, 2, 1]</code>.
+ *
+ * @return the elements of this list in reverse order.
+ */
+ def reverse: List[a] =
+ foldLeft(Nil : List[a])((xs, x) => x :: xs);
+
+ /** Returns a string representation of this list. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * <p/>
+ * Ex: <br/>
+ * <code>List(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ *
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this list.
+ */
+ def mkString(start: String, sep: String, end: String): String = this match {
+ case Nil => start + end
+ case last :: Nil => start + last + end
+ case fst :: tail => start + fst + sep + tail.mkString("", sep, end)
+ }
+
+ override def toString() = mkString("List(", ",", ")");
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param <code>that</code> must have the same length as the self list.
+ * @return <code>[(a0,b0), ..., (an,bn)]</code> when
+ * <code>[a0, ..., an] zip [b0, ..., bn]</code> is invoked.
+ */
+ def zip[b](that: List[b]): List[Pair[a,b]] =
+ if (this.isEmpty || that.isEmpty) Nil
+ else Pair(this.head, that.head) :: this.tail.zip(that.tail);
+
+ /** Returns a list formed from this list and the specified list
+ * <code>that</code> by associating each element of the former with
+ * the element at the same position in the latter.
+ *
+ * @param <code>that</code> may have a different length as the self list.
+ * @param <code>thisElem</code> is used to fill up the resulting list if
+ * the self list is shorter than <code>that</code>
+ * @param <code>thatElem</code> is used to fill up the resulting list if
+ * <code>that</code> is shorter than the self list
+ * @return <code>[(a0,b0), ..., (an,bn), (elem,bn+1), ..., (elem,bm)]</code>
+ * when <code>[a0, ..., an] zip [b0, ..., bm]</code> is invoked where
+ * <code>m &gt; n</code>.
+ */
+ def zipAll[c >: a, b](that: List[b], thisElem: c, thatElem: b): List[Pair[c,b]] =
+ if (this.isEmpty && that.isEmpty)
+ Nil
+ else if (this.isEmpty)
+ List.make(that.length, thisElem) zip that
+ else if (that.isEmpty)
+ this zip List.make(this.length, thatElem)
+ else
+ Pair(this.head, that.head) :: this.tail.zipAll(that.tail, thisElem, thatElem);
+
+ /** Computes the union of this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to add to the list.
+ * @return a list without doubles containing the elements of this
+ * list and those of the given list <code>that</code>.
+ */
+ def union[b >: a](that: List[b]): List[b] = this match {
+ case Nil => that
+ case head :: tail =>
+ if (that contains head) tail union that
+ else head :: (tail union that)
+ }
+
+ /** Computes the difference between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list of elements to remove from this list.
+ * @return this list without the elements of the given list <code>that</code>.
+ */
+ def diff[b >: a](that: List[b]): List[b] = this match {
+ case Nil => Nil
+ case head :: tail =>
+ if (that contains head) tail diff that
+ else head :: (tail diff that)
+ }
+
+ /** Computes the intersection between this list and the given list
+ * <code>that</code>.
+ *
+ * @param that the list to intersect.
+ * @return the list of elements contained both in this list and
+ * in the given list <code>that</code>.
+ */
+ def intersect[b >: a](that: List[b]): List[b] = filter(x => that contains x);
+
+ /** Removes redundant elements from the list. Uses the method <code>==</code>
+ * to decide if two elements are identical.
+ *
+ * @return the list without doubles.
+ */
+ def removeDuplicates: List[a] = this match {
+ case Nil => this
+ case head :: tail =>
+ if (tail contains head) tail.removeDuplicates
+ else head :: tail.removeDuplicates
+ }
+}
+
+/** The empty list.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 15/07/2003
+ */
+[SerialVersionUID(0 - 8256821097970055419L)]
+case object Nil extends List[All] {
+ def isEmpty = true;
+ def head: All = error("head of empty list");
+ def tail: List[All] = error("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, tl: List[b]) extends List[b] {
+ def isEmpty: boolean = false;
+ def head: b = hd;
+ def tail: List[b] = tl;
+}
+
diff --git a/src/library/scala/Long.cs b/src/library/scala/Long.cs
new file mode 100644
index 0000000000..cf147b04b3
--- /dev/null
+++ b/src/library/scala/Long.cs
@@ -0,0 +1,108 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Long.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Long : AnyVal {
+
+ public readonly long value;
+
+ public Long (long value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Long) && value == ((Long)other).value;
+ }
+ public override int GetHashCode()
+ {
+ return value.GetHashCode();
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Long;")]
+ public long __plus ( ) { return +value ; }
+ [Meta("method []scala.Long;")]
+ public long __minus ( ) { return -value ; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce ( ) { return value ; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ [Meta("method []scala.Float;")]
+ public float coerce (object dummy) { return value ; }
+ [Meta("method []scala.Long;")]
+ public long __tilde ( ) { return ~value ; }
+
+ public long __less__less (int that) { return value << that; }
+ public long __less__less (long that) { return value << (int)that; }
+ public long __greater__greater(int that) { return value >> that; }
+ public long __greater__greater(long that) { return value >> (int)that; }
+ public long __greater__greater__greater(int that) { return (int)((ulong)value >>that); }
+ public long __greater__greater__greater(long that) { return (int)((ulong)value >>(int)that); }
+
+ public bool __eq__eq (long that) { return value == that; }
+ public bool __bang__eq (long that) { return value != that; }
+ public bool __less (long that) { return value < that; }
+ public bool __greater (long that) { return value > that; }
+ public bool __less__eq (long that) { return value <= that; }
+ public bool __greater__eq(long that) { return value >= that; }
+ public long __plus (long that) { return value + that; }
+ public long __minus (long that) { return value - that; }
+ public long __times (long that) { return value * that; }
+ public long __div (long that) { return value / that; }
+ public long __percent (long that) { return value % that; }
+ public long __bar (long that) { return value | that; }
+ public long __amp (long that) { return value & that; }
+ public long __up (long that) { return value ^ that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Long.java b/src/library/scala/Long.java
new file mode 100644
index 0000000000..bcaf38eb36
--- /dev/null
+++ b/src/library/scala/Long.java
@@ -0,0 +1,181 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Long extends AnyVal implements java.io.Serializable {
+
+ public final long value;
+
+ public Long (long value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Long && value == ((Long )other).value;
+ }
+ public int hashCode() {
+ long bits = value;
+ return (int)(bits ^ (bits >>> 32));
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Long ; */
+ public long $plus ( ) { return +value ; }
+ /** @meta method []scala.Long ; */
+ public long $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+ /** @meta method []scala.Float ; */
+ public float coerce ( ) { return value ; }
+ /** @meta method []scala.Long ; */
+ public long $tilde ( ) { return ~value ; }
+
+ public long $less$less (int that) { return value << that; }
+ public long $less$less (long that) { return value << that; }
+ public long $greater$greater(int that) { return value >> that; }
+ public long $greater$greater(long that) { return value >> that; }
+ public long $greater$greater$greater(int that) { return value >>>that; }
+ public long $greater$greater$greater(long that) { return value >>>that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public long $plus (long that) { return value + that; }
+ public long $minus (long that) { return value - that; }
+ public long $times (long that) { return value * that; }
+ public long $div (long that) { return value / that; }
+ public long $percent (long that) { return value % that; }
+ public long $bar (long that) { return value | that; }
+ public long $amp (long that) { return value & that; }
+ public long $up (long that) { return value ^ that; }
+/*
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public long $plus (int that) { return value + that; }
+ public long $minus (int that) { return value - that; }
+ public long $times (int that) { return value * that; }
+ public long $div (int that) { return value / that; }
+ public long $percent (int that) { return value % that; }
+ public long $bar (int that) { return value | that; }
+ public long $amp (int that) { return value & that; }
+ public long $up (int that) { return value ^ that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public long $plus (short that) { return value + that; }
+ public long $minus (short that) { return value - that; }
+ public long $times (short that) { return value * that; }
+ public long $div (short that) { return value / that; }
+ public long $percent (short that) { return value % that; }
+ public long $bar (short that) { return value | that; }
+ public long $amp (short that) { return value & that; }
+ public long $up (short that) { return value ^ that; }
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public long $plus (char that) { return value + that; }
+ public long $minus (char that) { return value - that; }
+ public long $times (char that) { return value * that; }
+ public long $div (char that) { return value / that; }
+ public long $percent (char that) { return value % that; }
+ public long $bar (char that) { return value | that; }
+ public long $amp (char that) { return value & that; }
+ public long $up (char that) { return value ^ that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public long $plus (byte that) { return value + that; }
+ public long $minus (byte that) { return value - that; }
+ public long $times (byte that) { return value * that; }
+ public long $div (byte that) { return value / that; }
+ public long $percent (byte that) { return value % that; }
+ public long $bar (byte that) { return value | that; }
+ public long $amp (byte that) { return value & that; }
+ public long $up (byte that) { return value ^ that; }
+*/
+}
diff --git a/src/library/scala/MatchError.scala b/src/library/scala/MatchError.scala
new file mode 100644
index 0000000000..4979df8717
--- /dev/null
+++ b/src/library/scala/MatchError.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** **
+** $Id$
+\* */
+package scala;
+
+
+/** 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 {
+
+ // todo: change pattern matcher so that dummy type parameter T can be removed.
+ def fail[T](source: String, line: Int): All = throw new MatchError(source, line);
+
+ def report(source: String, line: Int, obj: Any) =
+ try {
+ throw new MatchError(source, line, obj.toString())
+ } 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);
+}
diff --git a/src/library/scala/None.scala b/src/library/scala/None.scala
new file mode 100644
index 0000000000..337426b1ee
--- /dev/null
+++ b/src/library/scala/None.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:None.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** This case object represents non-existent values.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+case object None extends Option[All];
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
new file mode 100644
index 0000000000..c19748c875
--- /dev/null
+++ b/src/library/scala/Option.scala
@@ -0,0 +1,70 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Option.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+import Predef._;
+
+
+/** This class represents optional values. Instances of <code>Option</code>
+ * are either instances of case class <code>Some</code> or it is case
+ * object <code>None</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.0, 16/07/2003
+ */
+trait Option[+A] extends Iterable[A] {
+
+ def isEmpty: Boolean = this match {
+ case None => true
+ case _ => false
+ }
+
+ def get: A = this match {
+ case None => error("None.get")
+ case Some(x) => x
+ }
+
+ def get[B >: A](default: B): B = this match {
+ case None => default
+ case Some(x) => x
+ }
+
+ def map[B](f: A => B): Option[B] = this match {
+ case None => None
+ case Some(x) => Some(f(x))
+ }
+
+ def flatMap[B](f: A => Option[B]): Option[B] = this match {
+ case None => None
+ case Some(x) => f(x)
+ }
+
+ def filter(p: A => Boolean): Option[A] = this match {
+ case None => None
+ case Some(x) => if (p(x)) Some(x) else None
+ }
+
+ override def foreach(f: A => Unit): Unit = this match {
+ case None => ()
+ case Some(x) => f(x)
+ }
+
+ def elements: Iterator[A] = this match {
+ case None => Iterator.empty
+ case Some(x) => Iterator.fromValues(x)
+ }
+
+ def toList: List[A] = this match {
+ case None => List()
+ case Some(x) => List(x)
+ }
+
+}
diff --git a/src/library/scala/Ordered.scala b/src/library/scala/Ordered.scala
new file mode 100644
index 0000000000..b8ef8c0ab9
--- /dev/null
+++ b/src/library/scala/Ordered.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Ordered.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** A trait for totally ordered data.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 23/04/2004
+ */
+trait Ordered[+a] {
+
+ /** Result of comparing `this' with operand `that'.
+ * returns `x' where
+ * <code>x &lt; 0</code> iff <code>this &lt; that</code>
+ * <code>x == 0</code> iff <code>this == that</code>
+ * <code>x &gt; 0</code> iff <code>this &gt; that</code>
+ */
+ def compareTo [b >: a <% Ordered[b]](that: b): Int;
+
+ def < [b >: a <% Ordered[b]](that: b): Boolean = (this compareTo that) < 0;
+
+ def > [b >: a <% Ordered[b]](that: b): Boolean = (this compareTo that) > 0;
+
+ def <= [b >: a <% Ordered[b]](that: b): Boolean = (this compareTo that) <= 0;
+
+ def >= [b >: a <% Ordered[b]](that: b): Boolean = (this compareTo that) >= 0;
+}
diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala
new file mode 100644
index 0000000000..9bea5386c5
--- /dev/null
+++ b/src/library/scala/PartialFunction.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:PartialFunction.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** A partial function of type <code>PartialFunction[A, B]</code> is a
+ * unary function where the domain does not include all values of type
+ * <code>A</code>. The function <code>isDefinedAt</code> allows to
+ * test dynamically, if a value is in the domain of the function.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+trait PartialFunction[-A, +B] extends AnyRef with Function1[A, B] {
+
+ /** Checks if a value is contained in the functions domain.
+ *
+ * @param x the value to test
+ * @return true, iff <code>x</code> is in the domain of this function.
+ */
+ def isDefinedAt(x: A): Boolean;
+}
diff --git a/src/library/scala/PartiallyOrdered.scala b/src/library/scala/PartiallyOrdered.scala
new file mode 100644
index 0000000000..424e50b77d
--- /dev/null
+++ b/src/library/scala/PartiallyOrdered.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:PartiallyOrdered.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** A trait 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
+ * <code>x &lt; 0</code> iff <code>this &lt; that</code>
+ * <code>x == 0</code> iff <code>this == that</code>
+ * <code>x &gt; 0</code> iff <code>this &gt; that</code>
+ */
+ def tryCompareTo [b >: a <% PartiallyOrdered[b]](that: b): Option[int];
+
+ def < [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x < 0 => true
+ case _ => false
+ }
+ def > [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x > 0 => true
+ case _ => false
+ }
+ def <= [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x <= 0 => true
+ case _ => false
+ }
+ def >= [b >: a <% PartiallyOrdered[b]](that: b): boolean =
+ (this tryCompareTo that) match {
+ case Some(x) if x >= 0 => true
+ case _ => false
+ }
+}
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
new file mode 100644
index 0000000000..94bd73b79d
--- /dev/null
+++ b/src/library/scala/Predef.scala
@@ -0,0 +1,359 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Predef.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** The <code>Predef</code> object provides definitions that are
+ * accessible in all Scala compilation units without explicit
+ * qualification.
+ */
+object Predef {
+
+ // 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 String = java.lang.String;
+ type NullPointerException = java.lang.NullPointerException;
+ type Throwable = java.lang.Throwable;
+
+ type Pair[+p, +q] = Tuple2[p, q];
+ def Pair[a, b](x: a, y: b) = Tuple2(x, y);
+
+ type Triple[+a, +b, +c] = Tuple3[a, b, c];
+ def Triple[a, b, c](x: a, y: b, z: c) = Tuple3(x, y, z);
+
+ def id[a](x: a): a = x;
+ def fst[a](x: a, y: Any): a = x;
+ def scd[a](x: Any, y: a): a = y;
+
+ val namespace$default = "";
+ val $scope = scala.xml.TopScope;
+
+ type Function[-a,+b] = Function1[a,b];
+
+ // arrays -----------------------------------------------------------
+
+ /** Create an array with given elements.
+ *
+ * @param xs the elements to put in the array
+ * @return the array containing elements xs.
+ */
+/*
+ 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 Array[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;
+ }
+ def Array(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 Array(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 Array(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 Array(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 Array(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 Array(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 Array(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 Array(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 Array(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;
+ }
+
+ // errors and asserts -------------------------------------------------
+
+ def error(message: String): All = throw new Error(message);
+
+ def exit: All = exit(0);
+
+ def exit(status: Int): All = {
+ java.lang.System.exit(status);
+ throw new Throwable()
+ }
+
+ def assert(assertion: Boolean): Unit = {
+ if (!assertion)
+ throw new Error("assertion failed");
+ }
+
+ def assert(assertion: Boolean, message: Any): Unit = {
+ if (!assertion)
+ throw new Error("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);
+ }
+
+ // views -------------------------------------------------------------
+
+ implicit def identity[a](x: a): a = x;
+
+ implicit def int2ordered(x: int): Ordered[int] = new Ordered[int] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: int <% Ordered[b]](y: b): int = y match {
+ case y1: int =>
+ if (x < y1) -1
+ else if (x > y1) 1
+ else 0
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: int): Ordered[int] = int2ordered(x);
+
+ implicit def char2ordered(x: char): Ordered[char] = new Ordered[char] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: char <% Ordered[b]](y: b): int = y match {
+ case y1: char =>
+ if (x < y1) -1
+ else if (x > y1) 1
+ else 0
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: char): Ordered[char] = char2ordered(x);
+
+ implicit def long2ordered(x: long): Ordered[long] = new Ordered[long] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: long <% Ordered[b]](y: b): int = y match {
+ case y1: long =>
+ if (x < y1) -1
+ else if (x > y1) 1
+ else 0
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: long): Ordered[long] = long2ordered(x);
+
+ implicit def float2ordered(x: float): Ordered[float] = new Ordered[float] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: float <% Ordered[b]](y: b): int = y match {
+ case y1: float =>
+ if (x < y1) -1
+ else if (x > y1) 1
+ else 0
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: float): Ordered[float] = float2ordered(x);
+
+ implicit def double2ordered(x: double): Ordered[double] = new Ordered[double] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: double <% Ordered[b]](y: b): int = y match {
+ case y1: double =>
+ if (x < y1) -1
+ else if (x > y1) 1
+ else 0
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: double): Ordered[double] = double2ordered(x);
+
+ implicit def boolean2ordered(x: boolean): Ordered[boolean] = new Ordered[boolean] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: boolean <% Ordered[b]](y: b): int = y match {
+ case y1: boolean =>
+ if (x == y1) 0
+ else if (x) 1
+ else -1
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: boolean): Ordered[boolean] = boolean2ordered(x);
+
+ implicit def array2ordered[A <% Ordered[A]](xs: Array[A]): Ordered[Array[A]] = new Ordered[Array[A]] with Proxy {
+ def self: Any = xs;
+ def compareTo[B >: Array[A] <% Ordered[B]](that: B): Int = that match {
+ case ys: Array[A] =>
+ var i, res = 0;
+ while ((i < xs.length) && (i < ys.length) && (res == 0)) {
+ res = xs(i) compareTo ys(i);
+ i = i + 1;
+ }
+ if (res != 0) res
+ else if (i < xs.length) 1
+ else if (i < ys.length) -1
+ else 0
+ case _ =>
+ -(that compareTo xs)
+ }
+ }
+ def view[A <% Ordered[A]](xs: Array[A]): Ordered[Array[A]] = array2ordered(xs);
+
+ private def first(xs: Int*): Int = xs.elements.find(x => x != 0) match {
+ case Some(r) => r
+ case _ => 0
+ }
+
+ /* We can't bootstrap currently with the following views included. We have to
+ * wait for the next release...
+ *
+ implicit def view[A <% Ordered[A], B <% Ordered[B]](x: Tuple2[A, B]): Ordered[Tuple2[A, B]] =
+ new Ordered[Tuple2[A, B]] with Proxy(x) {
+ def compareTo[T >: Tuple2[A, B] <% Ordered[T]](y: T): Int = y match {
+ case y1: Tuple2[A, B] => first(x._1.compareTo(y1._1),
+ x._2.compareTo(y1._2));
+ case _ => -(y compareTo x)
+ }
+ }
+
+ implicit def view[A <% Ordered[A], B <% Ordered[B], C <% Ordered[C]]
+ (x: Tuple3[A, B, C]): Ordered[Tuple3[A, B, C]] =
+ new Ordered[Tuple3[A, B, C]] with Proxy(x) {
+ def compareTo[T >: Tuple3[A, B, C] <% Ordered[T]](y: T): Int = y match {
+ case y1: Tuple3[A, B, C] => first(x._1.compareTo(y1._1),
+ x._2.compareTo(y1._2),
+ x._3.compareTo(y1._3));
+ case _ => -(y compareTo x)
+ }
+ }
+
+ implicit def view[A <% Ordered[A], B <% Ordered[B], C <% Ordered[C], D <% Ordered[D]]
+ (x: Tuple4[A, B, C, D]): Ordered[Tuple4[A, B, C, D]] =
+ new Ordered[Tuple4[A, B, C, D]] with Proxy(x) {
+ def compareTo[T >: Tuple4[A, B, C, D] <% Ordered[T]](y: T): Int = y match {
+ case y1: Tuple4[A, B, C, D] => first(x._1.compareTo(y1._1),
+ x._2.compareTo(y1._2),
+ x._3.compareTo(y1._3),
+ x._4.compareTo(y1._4));
+ case _ => -(y compareTo x)
+ }
+ }
+
+ implicit def view[A <% Ordered[A], B <% Ordered[B], C <% Ordered[C], D <% Ordered[D], E <% Ordered[E]]
+ (x: Tuple5[A, B, C, D, E]): Ordered[Tuple5[A, B, C, D, E]] =
+ new Ordered[Tuple5[A, B, C, D, E]] with Proxy(x) {
+ def compareTo[T >: Tuple5[A, B, C, D, E] <% Ordered[T]](y: T): Int = y match {
+ case y1: Tuple5[A, B, C, D, E] => first(x._1.compareTo(y1._1),
+ x._2.compareTo(y1._2),
+ x._3.compareTo(y1._3),
+ x._4.compareTo(y1._4),
+ x._5.compareTo(y1._5));
+ case _ => -(y compareTo x)
+ }
+ }
+ */
+
+ implicit def string2ordered(x: String): Ordered[String] = new Ordered[String] with Proxy {
+ def self: Any = x;
+ def compareTo [b >: String <% Ordered[b]](y: b): int = y match {
+ case y1: String => x compareTo y1;
+ case _ => -(y compareTo x)
+ }
+ }
+ def view(x: String): Ordered[String] = string2ordered(x);
+
+ implicit def array2seq[A](xs: Array[A]): Seq[A] = new Seq[A] {
+ def length = xs.length;
+ def elements = Iterator.fromArray(xs);
+ def apply(n: Int) = xs(n);
+ override def hashCode(): Int = xs.hashCode();
+ override def equals(y: Any): Boolean = (xs == y);
+ override protected def stringPrefix: String = "Array";
+ }
+ def view[A](xs: Array[A]): Seq[A] = array2seq(xs);
+
+ implicit def string2seq(str: String): Seq[Char] = new Seq[Char] {
+ def length = str.length();
+ def elements = Iterator.fromString(str);
+ def apply(n: Int) = str.charAt(n);
+ override def hashCode(): Int = str.hashCode();
+ override def equals(y: Any): Boolean = (str == y);
+ override protected def stringPrefix: String = "String";
+ }
+ def view(x: String): Seq[Char] = string2seq(x);
+
+ 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;
+}
diff --git a/src/library/scala/Proxy.scala b/src/library/scala/Proxy.scala
new file mode 100644
index 0000000000..5bf65c2ed4
--- /dev/null
+++ b/src/library/scala/Proxy.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Proxy.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** This class implements a simple proxy that forwards all calls to
+ * methods of class <code>Any</code> to another object <code>self</code>.
+ * Please note that only those methods can be forwarded that are
+ * overridable and public.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 26/04/2004
+ */
+trait Proxy {
+ def self: Any;
+ override def hashCode(): Int = self.hashCode();
+ override def equals(y: Any): Boolean = self.equals(y);
+ override def toString(): String = self.toString();
+}
diff --git a/src/library/scala/Ref.cs b/src/library/scala/Ref.cs
new file mode 100644
index 0000000000..660b07321c
--- /dev/null
+++ b/src/library/scala/Ref.cs
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $OldId: Ref.java,v 1.2 2002/03/12 13:16:04 zenger Exp $
+// $Id:Ref.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class [?T] extends scala.AnyRef;")]
+ [Serializable]
+ public class Ref : object {
+
+ [Meta("field ?T;")]
+ public object elem = null;
+
+ [Meta("constr (?T);")]
+ public Ref(object x)
+ {
+ elem = x;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Ref.java b/src/library/scala/Ref.java
new file mode 100644
index 0000000000..3c47ae5573
--- /dev/null
+++ b/src/library/scala/Ref.java
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $OldId: Ref.java,v 1.2 2002/03/12 13:16:04 zenger Exp $
+// $Id$
+
+package scala;
+
+/** @meta class [?T] extends java.lang.Object with java.io.Serializable;
+ */
+public class Ref extends java.lang.Object implements java.io.Serializable {
+
+ /** @meta field ?T;
+ */
+ public java.lang.Object elem = null;
+
+ /** @meta constr (?T);
+ */
+ public Ref(java.lang.Object x) {
+ elem = x;
+ }
+}
diff --git a/src/library/scala/ScalaObject.scala b/src/library/scala/ScalaObject.scala
new file mode 100644
index 0000000000..21c1fdbfba
--- /dev/null
+++ b/src/library/scala/ScalaObject.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, 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.
+ */
+ def $tag(): Int = 0;
+
+}
diff --git a/src/library/scala/Seq.scala b/src/library/scala/Seq.scala
new file mode 100644
index 0000000000..0298f5913e
--- /dev/null
+++ b/src/library/scala/Seq.scala
@@ -0,0 +1,194 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Seq.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+import Predef._;
+
+object Seq {
+
+ /** builds a singleton sequence
+ * @author buraq
+ */
+ 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
+ }
+
+ def view[A <% Ordered[A]](xs: Seq[A]): Ordered[Seq[A]] = new Ordered[Seq[A]] with Proxy {
+ def self: Any = xs;
+ def compareTo[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 compareTo ysit.next;
+ }
+ if (res != 0) res else if (xsit.hasNext) 1 else -1
+ case _ =>
+ -(that compareTo xs)
+ }
+ }
+}
+
+
+/** Class <code>Seq[A]</code> represents finite sequences of elements
+ * of type <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.0, 16/07/2003
+ */
+[serializable]
+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 the concatenation of two sequences.
+ *
+ * @return concatenation of this sequence with argument
+ * @author buraq
+ */
+ def concat[B >: A](that:Seq[B]): Seq[B] = new Seq[B] {
+ def length = Seq.this.length + that.length;
+ def elements: Iterator[B] = Seq.this.elements.append(that.elements);
+ def apply(i:Int) = {
+ if(Seq.this.isDefinedAt(i))
+ Seq.this.apply(i)
+ else
+ that.apply(i - Seq.this.length);
+ }
+ }
+
+ /** Is this partial function defined for the index <code>x</code>?
+ *
+ * @return true, iff <code>x</code> is a legal sequence index.
+ */
+ def isDefinedAt(x: Int): Boolean = (x >= 0) && (x < length);
+
+ /** Returns the index of the first occurence of the specified
+ * object in this sequence.
+ *
+ * @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;
+ }
+
+ /** 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 sub-sequence starting from index <code>n</code>.
+ */
+ def take(n: Int): Seq[A] = subseq(0, n);
+
+ /** Returns a new sub-sequence that drops the first <code>n</code>
+ * elements of this sequence.
+ */
+ def drop(n: Int): Seq[A] = subseq(n, length - n);
+
+ /** Returns a subsequence starting from index <code>from</code>
+ * consisting of <code>len</code> elements.
+ */
+ def subseq(from: Int, len: Int): Seq[A] =
+ if ((from + len) <= length) new Seq[A] {
+ def apply(n: Int): A = Seq.this.apply(n + from);
+ def length: Int = len;
+ def elements: Iterator[A] = new Iterator[A] {
+ var i = from;
+ def hasNext = (i < (from + len));
+ def next = {
+ val res = Seq.this.apply(i);
+ i = i + 1;
+ res
+ }
+ }
+ } else
+ error("cannot create subsequence");
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @return the given array <code>xs</code> filled with this list.
+ */
+ def copyToArray[B >: A](xs: Array[B], start: Int): Array[B] = {
+ val it = elements;
+ var i = start;
+ while (it.hasNext) {
+ xs(i) = it.next;
+ i = i + 1;
+ }
+ xs
+ }
+
+ /** Transform this sequence into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this sequence.
+ */
+ def toList: List[A] = elements.toList;
+
+ /** Customizes the <code>toString</code> method.
+ *
+ * @return a string representation of this sequence.
+ */
+ override def toString() = {
+ val iter = elements;
+ var res = stringPrefix + "(";
+ if (iter.hasNext) {
+ res = res + iter.next;
+ while (iter.hasNext)
+ res = res + ", " + iter.next;
+ }
+ res + ")"
+ }
+
+ /** Defines the prefix of the string representation.
+ */
+ protected def stringPrefix: String = "Seq";
+}
+
diff --git a/src/library/scala/SeqProxy.scala b/src/library/scala/SeqProxy.scala
new file mode 100644
index 0000000000..aa4496a8fe
--- /dev/null
+++ b/src/library/scala/SeqProxy.scala
@@ -0,0 +1,91 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:SeqProxy.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** Class <code>Seq[A]</code> represents finite sequences of elements
+ * of type <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @author Matthias Zenger
+ * @version 1.0, 16/07/2003
+ */
+trait SeqProxy[+A] extends Seq[A] with IterableProxy[A] {
+
+ def self: Seq[A];
+
+ /** Returns the length of the sequence.
+ *
+ * @return the sequence length.
+ */
+ def length: Int = self.length;
+
+ /** Access element number <code>n</code>.
+ *
+ * @return the element at index <code>n</code>.
+ */
+ def apply(n: Int): A = self.apply(n);
+
+ /** Is this partial function defined for the index <code>x</code>?
+ *
+ * @return true, iff <code>x</code> is a legal sequence index.
+ */
+ override def isDefinedAt(y: Int): Boolean = self.isDefinedAt(y);
+
+ /** Returns the index of the first occurence of the specified
+ * object in this sequence.
+ *
+ * @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.
+ */
+ override def indexOf[B >: A](elem: B): Int = self.indexOf(elem);
+
+ /** 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.
+ */
+ override def lastIndexOf[B >: A](elem: B): Int = self.lastIndexOf(elem);
+
+ /** Returns the sub-sequence starting from index <code>n</code>.
+ */
+ override def take(n: Int): Seq[A] = self.take(n);
+
+ /** Returns a new sub-sequence that drops the first <code>n</code>
+ * elements of this sequence.
+ */
+ override def drop(n: Int): Seq[A] = self.drop(n);
+
+ /** Returns a subsequence starting from index <code>from</code>
+ * consisting of <code>len</code> elements.
+ */
+ override def subseq(from: Int, len: Int): Seq[A] = self.subseq(from, len);
+
+ /** Fills the given array <code>xs</code> with the elements of
+ * this sequence starting at position <code>start</code>.
+ *
+ * @param xs the array to fill.
+ * @param start starting index.
+ * @return the given array <code>xs</code> filled with the elements
+ * of this sequence.
+ */
+ override def copyToArray[B >: A](xs: Array[B], start: Int): Array[B] = self.copyToArray(xs, start);
+
+ /** Transform this sequence into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this sequence.
+ */
+ override def toList: List[A] = self.toList;
+}
diff --git a/src/library/scala/SerialVersionUID.scala b/src/library/scala/SerialVersionUID.scala
new file mode 100644
index 0000000000..9b42c09411
--- /dev/null
+++ b/src/library/scala/SerialVersionUID.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:SerialVersionUID.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+*/
+
+package scala;
+
+case class SerialVersionUID(uid: Long) extends Attribute {}
diff --git a/src/library/scala/Short.cs b/src/library/scala/Short.cs
new file mode 100644
index 0000000000..5503b9360a
--- /dev/null
+++ b/src/library/scala/Short.cs
@@ -0,0 +1,129 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Short.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ [Meta("class extends scala.AnyVal;")]
+ [Serializable]
+ public abstract class Short : AnyVal {
+
+ public readonly short value;
+
+ public Short(short value)
+ {
+ this.value = value;
+ }
+
+ public override bool Equals(object other)
+ {
+ return (other is Short) && value == ((Short)other).value;
+ }
+ public override int GetHashCode()
+ {
+ return value;
+ }
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ [Meta("method []scala.Int;")]
+ public int __plus () { return +value; }
+ [Meta("method []scala.Int;")]
+ public int __minus () { return -value; }
+
+ public string __plus (string that) { return value + that; }
+
+ public bool __eq__eq (double that) { return value == that; }
+ public bool __bang__eq (double that) { return value != that; }
+ public bool __less (double that) { return value < that; }
+ public bool __greater (double that) { return value > that; }
+ public bool __less__eq (double that) { return value <= that; }
+ public bool __greater__eq(double that) { return value >= that; }
+ public double __plus (double that) { return value + that; }
+ public double __minus (double that) { return value - that; }
+ public double __times (double that) { return value * that; }
+ public double __div (double that) { return value / that; }
+ public double __percent (double that) { return value % that; }
+
+ [Meta("method []scala.Double;")]
+ public double coerce ( ) { return value; }
+
+ public bool __eq__eq (float that) { return value == that; }
+ public bool __bang__eq (float that) { return value != that; }
+ public bool __less (float that) { return value < that; }
+ public bool __greater (float that) { return value > that; }
+ public bool __less__eq (float that) { return value <= that; }
+ public bool __greater__eq(float that) { return value >= that; }
+ public float __plus (float that) { return value + that; }
+ public float __minus (float that) { return value - that; }
+ public float __times (float that) { return value * that; }
+ public float __div (float that) { return value / that; }
+ public float __percent (float that) { return value % that; }
+
+ [Meta("method []scala.Float;")]
+ public float coerce (float dummy) { return value ; }
+ [Meta("method []scala.Int;")]
+ public int __tilde ( ) { return ~value ; }
+
+ public int __less__less (int that) { return value << that; }
+ public int __less__less (long that) { return value << (int)that; }
+ public int __greater__greater(int that) { return value >> that; }
+ public int __greater__greater(long that) { return value >> (int)that; }
+ public int __greater__greater__greater(int that) { return (int)((uint)value >>that); }
+ public int __greater__greater__greater(long that) { return (int)((uint)value >>(int)that); }
+
+ public bool __eq__eq (long that) { return value == that; }
+ public bool __bang__eq (long that) { return value != that; }
+ public bool __less (long that) { return value < that; }
+ public bool __greater (long that) { return value > that; }
+ public bool __less__eq (long that) { return value <= that; }
+ public bool __greater__eq(long that) { return value >= that; }
+ public long __plus (long that) { return value + that; }
+ public long __minus (long that) { return value - that; }
+ public long __times (long that) { return value * that; }
+ public long __div (long that) { return value / that; }
+ public long __percent (long that) { return value % that; }
+ public long __bar (long that) { return value | that; }
+ public long __amp (long that) { return value & that; }
+ public long __up (long that) { return value ^ that; }
+
+ [Meta("method []scala.Long;")]
+ public long coerce (long dummy) { return value ; }
+
+ public bool __eq__eq (int that) { return value == that; }
+ public bool __bang__eq (int that) { return value != that; }
+ public bool __less (int that) { return value < that; }
+ public bool __greater (int that) { return value > that; }
+ public bool __less__eq (int that) { return value <= that; }
+ public bool __greater__eq(int that) { return value >= that; }
+ public int __plus (int that) { return value + that; }
+ public int __minus (int that) { return value - that; }
+ public int __times (int that) { return value * that; }
+ public int __div (int that) { return value / that; }
+ public int __percent (int that) { return value % that; }
+ public int __bar (int that) { return value | that; }
+ public int __amp (int that) { return value & that; }
+ public int __up (int that) { return value ^ that; }
+
+ [Meta("method []scala.Int;")]
+ public int coerce (int dummy) { return value ; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Short.java b/src/library/scala/Short.java
new file mode 100644
index 0000000000..e800678202
--- /dev/null
+++ b/src/library/scala/Short.java
@@ -0,0 +1,186 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+/** @meta class extends scala.AnyVal; */
+public abstract class Short extends AnyVal implements java.io.Serializable {
+
+ public final short value;
+
+ public Short (short value) {
+ this.value = value;
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Short && value == ((Short )other).value;
+ }
+ public int hashCode() {
+ int bits = value;
+ return bits;
+ }
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /** @meta method []scala.Byte; */
+ public byte toByte() { return (byte)value; }
+
+ /** @meta method []scala.Short; */
+ public short toShort() { return (short)value; }
+
+ /** @meta method []scala.Char; */
+ public char toChar() { return (char)value; }
+
+ /** @meta method []scala.Int; */
+ public int toInt() { return (int)value; }
+
+ /** @meta method []scala.Long; */
+ public long toLong() { return (long)value; }
+
+ /** @meta method []scala.Float; */
+ public float toFloat() { return (float)value; }
+
+ /** @meta method []scala.Double; */
+ public double toDouble() { return (double)value; }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+ /** @meta method []scala.Int ; */
+ public int $plus ( ) { return +value ; }
+ /** @meta method []scala.Int ; */
+ public int $minus ( ) { return -value ; }
+
+ public String $plus (String that) { return value + that; }
+
+ public boolean $eq$eq (double that) { return value == that; }
+ public boolean $bang$eq (double that) { return value != that; }
+ public boolean $less (double that) { return value < that; }
+ public boolean $greater (double that) { return value > that; }
+ public boolean $less$eq (double that) { return value <= that; }
+ public boolean $greater$eq(double that) { return value >= that; }
+ public double $plus (double that) { return value + that; }
+ public double $minus (double that) { return value - that; }
+ public double $times (double that) { return value * that; }
+ public double $div (double that) { return value / that; }
+ public double $percent (double that) { return value % that; }
+
+ /** @meta method []scala.Double ; */
+ public double coerce ( ) { return value ; }
+
+ public boolean $eq$eq (float that) { return value == that; }
+ public boolean $bang$eq (float that) { return value != that; }
+ public boolean $less (float that) { return value < that; }
+ public boolean $greater (float that) { return value > that; }
+ public boolean $less$eq (float that) { return value <= that; }
+ public boolean $greater$eq(float that) { return value >= that; }
+ public float $plus (float that) { return value + that; }
+ public float $minus (float that) { return value - that; }
+ public float $times (float that) { return value * that; }
+ public float $div (float that) { return value / that; }
+ public float $percent (float that) { return value % that; }
+
+ /** @meta method []scala.Float ; */
+ public float coerce ( ) { return value ; }
+ /** @meta method []scala.Int ; */
+ public int $tilde ( ) { return ~value ; }
+
+ public int $less$less (int that) { return value << that; }
+ public int $less$less (long that) { return value << that; }
+ public int $greater$greater(int that) { return value >> that; }
+ public int $greater$greater(long that) { return value >> that; }
+ public int $greater$greater$greater(int that) { return value >>>that; }
+ public int $greater$greater$greater(long that) { return value >>>that; }
+
+ public boolean $eq$eq (long that) { return value == that; }
+ public boolean $bang$eq (long that) { return value != that; }
+ public boolean $less (long that) { return value < that; }
+ public boolean $greater (long that) { return value > that; }
+ public boolean $less$eq (long that) { return value <= that; }
+ public boolean $greater$eq(long that) { return value >= that; }
+ public long $plus (long that) { return value + that; }
+ public long $minus (long that) { return value - that; }
+ public long $times (long that) { return value * that; }
+ public long $div (long that) { return value / that; }
+ public long $percent (long that) { return value % that; }
+ public long $bar (long that) { return value | that; }
+ public long $amp (long that) { return value & that; }
+ public long $up (long that) { return value ^ that; }
+
+ /** @meta method []scala.Long ; */
+ public long coerce ( ) { return value ; }
+
+ public boolean $eq$eq (int that) { return value == that; }
+ public boolean $bang$eq (int that) { return value != that; }
+ public boolean $less (int that) { return value < that; }
+ public boolean $greater (int that) { return value > that; }
+ public boolean $less$eq (int that) { return value <= that; }
+ public boolean $greater$eq(int that) { return value >= that; }
+ public int $plus (int that) { return value + that; }
+ public int $minus (int that) { return value - that; }
+ public int $times (int that) { return value * that; }
+ public int $div (int that) { return value / that; }
+ public int $percent (int that) { return value % that; }
+ public int $bar (int that) { return value | that; }
+ public int $amp (int that) { return value & that; }
+ public int $up (int that) { return value ^ that; }
+
+ /** @meta method []scala.Int ; */
+ public int coerce ( ) { return value ; }
+
+
+ public boolean $eq$eq (char that) { return value == that; }
+ public boolean $bang$eq (char that) { return value != that; }
+ public boolean $less (char that) { return value < that; }
+ public boolean $greater (char that) { return value > that; }
+ public boolean $less$eq (char that) { return value <= that; }
+ public boolean $greater$eq(char that) { return value >= that; }
+ public int $plus (char that) { return value + that; }
+ public int $minus (char that) { return value - that; }
+ public int $times (char that) { return value * that; }
+ public int $div (char that) { return value / that; }
+ public int $percent (char that) { return value % that; }
+ public int $bar (char that) { return value | that; }
+ public int $amp (char that) { return value & that; }
+ public int $up (char that) { return value ^ that; }
+
+ public boolean $eq$eq (short that) { return value == that; }
+ public boolean $bang$eq (short that) { return value != that; }
+ public boolean $less (short that) { return value < that; }
+ public boolean $greater (short that) { return value > that; }
+ public boolean $less$eq (short that) { return value <= that; }
+ public boolean $greater$eq(short that) { return value >= that; }
+ public int $plus (short that) { return value + that; }
+ public int $minus (short that) { return value - that; }
+ public int $times (short that) { return value * that; }
+ public int $div (short that) { return value / that; }
+ public int $percent (short that) { return value % that; }
+ public int $bar (short that) { return value | that; }
+ public int $amp (short that) { return value & that; }
+ public int $up (short that) { return value ^ that; }
+
+ public boolean $eq$eq (byte that) { return value == that; }
+ public boolean $bang$eq (byte that) { return value != that; }
+ public boolean $less (byte that) { return value < that; }
+ public boolean $greater (byte that) { return value > that; }
+ public boolean $less$eq (byte that) { return value <= that; }
+ public boolean $greater$eq(byte that) { return value >= that; }
+ public int $plus (byte that) { return value + that; }
+ public int $minus (byte that) { return value - that; }
+ public int $times (byte that) { return value * that; }
+ public int $div (byte that) { return value / that; }
+ public int $percent (byte that) { return value % that; }
+ public int $bar (byte that) { return value | that; }
+ public int $amp (byte that) { return value & that; }
+ public int $up (byte that) { return value ^ that; }
+}
diff --git a/src/library/scala/Some.scala b/src/library/scala/Some.scala
new file mode 100644
index 0000000000..4d5d210ab8
--- /dev/null
+++ b/src/library/scala/Some.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Some.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** Class <code>Option[A]</code> represents existing values of type
+ * <code>A</code>.
+ *
+ * @author Martin Odersky
+ * @version 1.0, 16/07/2003
+ */
+final case class Some[+A1](x: A1) extends Option[A1];
diff --git a/src/library/scala/Stream.scala b/src/library/scala/Stream.scala
new file mode 100644
index 0000000000..a281577bf8
--- /dev/null
+++ b/src/library/scala/Stream.scala
@@ -0,0 +1,243 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Stream.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+/**
+ * The object <code>Stream</code> provides helper functions
+ * to manipulate streams.
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 1.1 08/08/03
+ */
+object Stream {
+
+ val empty: Stream[All] = new Stream[All] {
+ def isEmpty = true;
+ def head: All = error("head of empty stream");
+ def tail: Stream[All] = error("tail of empty stream");
+ def printElems(buf: StringBuffer, prefix: String): StringBuffer = buf;
+ }
+
+ def cons[a](hd: a, tl: => Stream[a]) = new Stream[a] {
+ 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
+ }
+ def printElems(buf: StringBuffer, prefix: String): StringBuffer = {
+ val buf1 = buf.append(prefix).append(hd);
+ if (tlDefined) printElems(buf1, ", ") else buf1 append ", ?";
+ }
+ }
+
+ def fromIterator[a](it: Iterator[a]): Stream[a] =
+ if (it.hasNext) cons(it.next, fromIterator(it)) else empty;
+
+ def concat[a](xs: Seq[Stream[a]]): Stream[a] = concat(xs.elements);
+
+ def concat[a](xs: Iterator[Stream[a]]): Stream[a] = {
+ if (xs.hasNext) xs.next append concat(xs)
+ else empty;
+ }
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + 1</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int): Stream[Int] =
+ range(start, end, 1);
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = v<sub>n</sub> + step</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @param step the increment value of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int, step: Int): Stream[Int] = {
+ def loop(lo: Int): Stream[Int] =
+ if (lo >= end) empty
+ else cons(lo, loop(lo + step));
+ loop(start)
+ }
+
+ /**
+ * Create a stream with element values
+ * <code>v<sub>n+1</sub> = step(v<sub>n</sub>)</code>
+ * where <code>v<sub>0</sub> = start</code>
+ * and <code>v<sub>i</sub> &lt; end</code>.
+ *
+ * @param start the start value of the stream
+ * @param end the end value of the stream
+ * @param step the increment function of the stream
+ * @return the stream starting at value <code>start</code>.
+ */
+ def range(start: Int, end: Int, step: Int => Int): Stream[Int] = {
+ def loop(lo: Int): Stream[Int] =
+ if (lo >= end) empty
+ else cons(lo, loop(step(lo)));
+ loop(start)
+ }
+}
+
+/**
+ * <p>The class <code>Stream</code> implements lazy lists where elements
+ * are only evaluated when they are needed. Here is an example:</p>
+ * <pre>
+ * <b>object</b> Main <b>with</b> Application {
+ *
+ * <b>def</b> from(n: Int): Stream[Int] =
+ * Stream.cons(n, from(n + 1));
+ *
+ * <b>def</b> sieve(s: Stream[Int]): Stream[Int] =
+ * Stream.cons(s.head, sieve(s.tail filter { x => x % s.head != 0 }));
+ *
+ * <b>def</b> primes = sieve(from(2));
+ *
+ * primes take 10 print
+ * }
+ * </pre>
+ *
+ * @author Martin Odersky, Matthias Zenger
+ * @version 1.1 08/08/03
+ */
+trait Stream[+a] extends Seq[a] {
+
+ def isEmpty: Boolean;
+ def head: a;
+ def tail: Stream[a];
+
+ def length: int = if (isEmpty) 0 else tail.length + 1;
+
+ def append[b >: a](rest: => Stream[b]): Stream[b] =
+ if (isEmpty) rest
+ else Stream.cons(head, tail.append(rest));
+
+ 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 }
+ }
+
+ def init: Stream[a] =
+ if (isEmpty) error("Stream.empty.init")
+ else if (tail.isEmpty) Stream.empty
+ else Stream.cons(head, tail.init);
+
+ def last: a =
+ if (isEmpty) error("Stream.empty.last")
+ else if (tail.isEmpty) head
+ else tail.last;
+
+ override def take(n: int): Stream[a] =
+ if (n == 0) Stream.empty
+ else Stream.cons(head, tail.take(n-1));
+
+ override def drop(n: int): Stream[a] =
+ if (n == 0) this
+ else tail.drop(n-1);
+
+ def apply(n: int) = drop(n).head;
+ def at(n: int) = drop(n).head;
+
+ def takeWhile(p: a => Boolean): Stream[a] =
+ if (isEmpty || !p(head)) Stream.empty
+ else Stream.cons(head, tail.takeWhile(p));
+
+ def dropWhile(p: a => Boolean): Stream[a] =
+ if (isEmpty || !p(head)) this
+ else tail.dropWhile(p);
+
+ def map[b](f: a => b): Stream[b] =
+ if (isEmpty) Stream.empty
+ else Stream.cons(f(head), tail.map(f));
+
+ override def foreach(f: a => unit): unit =
+ if (isEmpty) {}
+ else { f(head); tail.foreach(f) }
+
+ def filter(p: a => Boolean): Stream[a] =
+ if (isEmpty) this
+ else if (p(head)) Stream.cons(head, tail.filter(p))
+ else tail.filter(p);
+
+ override def forall(p: a => Boolean): Boolean =
+ isEmpty || (p(head) && tail.forall(p));
+
+ override def exists(p: a => Boolean): Boolean =
+ !isEmpty && (p(head) || tail.exists(p));
+
+ override def foldLeft[b](z: b)(f: (b, a) => b): b =
+ if (isEmpty) z
+ else tail.foldLeft[b](f(z, head))(f);
+
+ override def foldRight[b](z: b)(f: (a, b) => b): b =
+ if (isEmpty) z
+ else f(head, tail.foldRight(z)(f));
+
+ def reduceLeft[b >: a](f: (b, b) => b): b =
+ if (isEmpty) error("Stream.empty.reduceLeft")
+ else ((tail: Stream[b]) foldLeft (head: b))(f);
+
+ def reduceRight[b >: a](f: (b, b) => b): b =
+ if (isEmpty) error("Stream.empty.reduceRight")
+ else if (tail.isEmpty) head: b
+ else f(head, tail.reduceRight(f));
+
+ def flatMap[b](f: a => Stream[b]): Stream[b] =
+ if (isEmpty) Stream.empty
+ else f(head).append(tail.flatMap(f));
+
+ def reverse: Stream[a] =
+ foldLeft(Stream.empty: Stream[a])((xs, x) => Stream.cons(x, xs));
+
+ // The following method is not compilable without run-time type
+ // information. It should therefore be left commented-out for
+ // now.
+ // def toArray: Array[a] = {
+ // val xs = new Array[a](length);
+ // copyToArray(xs, 0);
+ // xs
+ // }
+
+ override def copyToArray[b >: a](xs: Array[b], start: int): Array[b] =
+ if (isEmpty) xs
+ else { xs(start) = head; tail.copyToArray(xs, start + 1) }
+
+ 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));
+
+ def print: unit =
+ if (isEmpty) Console.println("Stream.empty")
+ else {
+ Console.print(head);
+ Console.print(", ");
+ tail.print
+ }
+
+ override def toString() =
+ "Stream(" + printElems(new StringBuffer(), "") + ")";
+
+ def printElems(buf: StringBuffer, prefix: String): StringBuffer;
+}
diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala
new file mode 100644
index 0000000000..4e5805f545
--- /dev/null
+++ b/src/library/scala/Symbol.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:Symbol.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+
+/** Instances of <code>Symbol</code> can be created easily with
+ * Scala's built-in quote mechanism. For instance, the Scala term
+ * <code>'mysym</code> will invoke the constructor of the
+ * <code>Symbol</code> class in the following way:
+ * <code>new Symbol("mysym")</code>. .
+ *
+ * @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
+ }
+
+}
diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala
new file mode 100644
index 0000000000..620ad276bc
--- /dev/null
+++ b/src/library/scala/Tuple1.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple1[+T1](_1: T1) {
+ override def toString(): String = "(" + _1 + ")";
+}
diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala
new file mode 100644
index 0000000000..e830a4f769
--- /dev/null
+++ b/src/library/scala/Tuple2.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple2[+T1, +T2](_1: T1, _2: T2) {
+ override def toString(): String = "(" + _1 + "," + _2 + ")";
+}
diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala
new file mode 100644
index 0000000000..53ce97a5b1
--- /dev/null
+++ b/src/library/scala/Tuple3.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + ")";
+}
diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala
new file mode 100644
index 0000000000..419afd7eb1
--- /dev/null
+++ b/src/library/scala/Tuple4.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")";
+}
diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala
new file mode 100644
index 0000000000..24bca2d443
--- /dev/null
+++ b/src/library/scala/Tuple5.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + ")";
+}
diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala
new file mode 100644
index 0000000000..205afce10d
--- /dev/null
+++ b/src/library/scala/Tuple6.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + ")";
+}
diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala
new file mode 100644
index 0000000000..61dcac85b5
--- /dev/null
+++ b/src/library/scala/Tuple7.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + ")";
+}
diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala
new file mode 100644
index 0000000000..6857e876d3
--- /dev/null
+++ b/src/library/scala/Tuple8.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+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) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + ")";
+}
diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala
new file mode 100644
index 0000000000..50b3c66b40
--- /dev/null
+++ b/src/library/scala/Tuple9.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala;
+
+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) {
+ override def toString(): String = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + ")";
+}
diff --git a/src/library/scala/Unit.cs b/src/library/scala/Unit.cs
new file mode 100644
index 0000000000..44fd1aa3ca
--- /dev/null
+++ b/src/library/scala/Unit.cs
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:Unit.cs 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+using System;
+using scala.runtime;
+
+namespace scala
+{
+
+ public abstract class Unit : AnyVal {
+
+ public void value() {}
+
+ public Unit() {}
+
+ public override bool Equals(object other)
+ {
+ return other is Unit;
+ }
+ public override int GetHashCode()
+ {
+ int bits = 4041;
+ return bits;
+ }
+ public override string ToString()
+ {
+ return "()";
+ }
+
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __eq__eq (object other) { return Equals(other); }
+ [Meta("method (scala.Any)scala.Boolean;")]
+ public bool __bang__eq(object other) { return !Equals(other); }
+
+ public string __plus (string that) { return this + that; }
+
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/Unit.java b/src/library/scala/Unit.java
new file mode 100644
index 0000000000..dd50889c10
--- /dev/null
+++ b/src/library/scala/Unit.java
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala;
+
+public abstract class Unit extends AnyVal {
+
+ public final void value() {}
+
+ public Unit ( ) {
+
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof Unit;
+ }
+ public int hashCode() {
+ int bits = 4041;
+ return bits;
+ }
+ public String toString() {
+ return "()";
+ }
+
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $eq$eq (java.lang.Object other) { return equals(other); }
+ /** @meta method (scala.Any)scala.Boolean; */
+ public boolean $bang$eq(java.lang.Object other) { return !equals(other); }
+
+}
diff --git a/src/library/scala/_trait_.scala b/src/library/scala/_trait_.scala
new file mode 100644
index 0000000000..087508da64
--- /dev/null
+++ b/src/library/scala/_trait_.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+*/
+
+// $Id:_trait_.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+package scala;
+
+/** Temporary class.
+ * When this appears in the attribute list of an abstract class, the class
+ * is assumed to be a trait. Used to ensure that code that compiles under
+ * (old) <code>scalac</code> can also compile under <code>nsc</code>.
+ */
+class _trait_ extends Attribute {}
diff --git a/src/library/scala/cloneable.scala b/src/library/scala/cloneable.scala
new file mode 100644
index 0000000000..4067a3d732
--- /dev/null
+++ b/src/library/scala/cloneable.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:cloneable.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+*/
+
+package scala;
+
+class cloneable extends Attribute {}
diff --git a/src/library/scala/collection/BitSet.scala b/src/library/scala/collection/BitSet.scala
new file mode 100644
index 0000000000..bd5855c1de
--- /dev/null
+++ b/src/library/scala/collection/BitSet.scala
@@ -0,0 +1,82 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection;
+
+/** The class <code>BitSet</code> ...
+ *
+ * @author Burak Emir, Stephane Micheloud
+ * @version 1.0
+ */
+[_trait_] abstract class BitSet extends AnyRef with Function1[Int,Boolean] {
+
+ /** number of bits in this bitset */
+ def size: Int;
+
+ /** returns true if bit i is set */
+ def apply(i: Int): Boolean;
+
+ /** returns an iterator over the truth values of all bits */
+ final def booleanElements: Iterator[Boolean] = new Iterator[Boolean] {
+ var i = 0;
+ def hasNext: Boolean = i < size;
+ def next: Boolean = { i = i + 1; apply(i-1) }
+ }
+
+ /**
+ * Returns the subset of <code>[0..size]</code> whose elements are
+ * indices of bits set to <code>v</code>.
+ *
+ * @param v
+ */
+ final def toSet(v: Boolean) = {
+ var res = new immutable.TreeSet[Int]();
+ var j = 0;
+ while (j < size) {
+ if (v == apply(j))
+ res = res + j;
+ j = j + 1;
+ }
+ res
+ }
+
+ /**
+ * Checks if two bitsets are structurally identical.
+ *
+ * @return true, iff both bitsets contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = (
+ that.isInstanceOf[BitSet] &&
+ { val other = that.asInstanceOf[BitSet];
+ ( size == other.size) && (
+ Iterator.range(0, size) forall { i => apply(i) == other.apply(i)}
+ )
+ }
+ );
+
+ /**
+ * applies f to any index which is set to true.
+ */
+ def foreach(f: Int => Unit): Unit = toSet(true).foreach(f);
+
+ /**
+ * Returns a string representation of this bitset in hexadecimal form,
+ * e.g. the bitset 001100000001 (12 bits) is represented as "{0, 8, 9}".
+ *
+ * @return the string representation for this bitset
+ */
+ override def toString() =
+ toSet(true).toString();
+
+ /** returns number of Int cells needed to store n bits */
+ protected def memsize(n:Int) = (n >>> 5) + {
+ if((n & 0x1F) != 0) 1 else 0
+ };
+
+}
diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala
new file mode 100644
index 0000000000..14546e9e71
--- /dev/null
+++ b/src/library/scala/collection/Map.scala
@@ -0,0 +1,180 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection;
+
+/** This trait defines the interface of collections that unambiguously map
+ * keys to values (i.e. a key is mapped to at least one value).
+ * Trait <code>Map</code> may only be used for
+ * accessing elements from map implementations. Two different extensions
+ * of trait <code>Map</code> in the package <code>scala.collections.mutable</code>
+ * and <code>scala.collections.immutable</code> provide functionality for
+ * adding new key/value mappings to a map. The trait in the first package is
+ * implemented by maps that are modified destructively, whereas the trait in
+ * the second package is used by functional map implementations that rely on
+ * immutable data structures.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 02/05/2004
+ */
+trait Map[A, +B] extends AnyRef with PartialFunction[A, B] with Iterable[Pair[A, B]] {
+
+ /** Compute the number of key-to-value mappings.
+ *
+ * @return the number of mappings
+ */
+ def size: Int;
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ def get(key: A): Option[B];
+
+ /** Is this an empty map?
+ *
+ * @return 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
+ 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;
+ }
+
+ /** 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;
+ }
+
+ /** Executes the given function for all (key, value) pairs
+ * contained in this map.
+ *
+ * @param f the function to execute.
+ */
+ def foreach(f: (A, B) => Unit) = {
+ val iter = elements;
+ while (iter.hasNext) {
+ val Pair(key, value) = iter.next;
+ f(key, value);
+ }
+ }
+
+ /** Applies the given predicate to all (key, value) mappings
+ * contained in this map and returns true if this predicate
+ * yields true for all mappings.
+ *
+ * @param p the predicate
+ * @return true, iff p yields true for all mappings.
+ */
+ def forall(p: (A, B) => Boolean): Boolean = elements.forall {
+ case Pair(key, value) => p(key, value)
+ }
+
+ /** Applies the given predicate to all (key, value) mappings
+ * contained in this map and returns true if there is at least
+ * one mapping for which this predicate yields true.
+ *
+ * @param p the predicate
+ * @return true, iff there is at least one mapping for which
+ * p yields true.
+ */
+ def exists(p: (A, B) => Boolean): Boolean = elements.exists {
+ case Pair(key, value) => p(key, value)
+ }
+
+ /** Compares two maps structurally; i.e. checks if all mappings
+ * contained in this map are also contained in the other map,
+ * and vice versa.
+ *
+ * @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 Pair(key, value) => other.get(key) match {
+ case None => false;
+ case Some(otherval) => value == otherval;
+ }
+ }
+ case _ => false
+ }
+
+ /** Returns the mappings of this map as a list.
+ *
+ * @return a list containing all mappings
+ */
+ def toList: List[Pair[A, B]] = elements.toList;
+
+ /** Creates a string representation for this map.
+ *
+ * @return a string showing all mappings
+ */
+ override def toString() =
+ if (size == 0)
+ "{}"
+ else
+ "{" + {
+ val iter = elements;
+ var res = iter.next.toString();
+ while (iter.hasNext) {
+ res = res + ", " + iter.next;
+ }
+ res;
+ } + "}";
+
+ /** 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.
+ */
+ def default: B =
+ error("key not found")
+}
+
diff --git a/src/library/scala/collection/MapProxy.scala b/src/library/scala/collection/MapProxy.scala
new file mode 100644
index 0000000000..8284a628d2
--- /dev/null
+++ b/src/library/scala/collection/MapProxy.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection;
+
+
+/** This is a simple wrapper class for <code>scala.collection.Map</code>.
+ * 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[Pair[A, B]] {
+
+ def self: Map[A, B];
+
+ def size: Int = self.size;
+
+ 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 values: Iterator[B] = self.values;
+
+ override def foreach(f: (A, B) => Unit) = self.foreach(f);
+
+ override def toList: List[Pair[A, B]] = self.toList;
+}
diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala
new file mode 100644
index 0000000000..00ac17f6df
--- /dev/null
+++ b/src/library/scala/collection/Set.scala
@@ -0,0 +1,89 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection;
+
+
+/** This trait defines the interface of collections that do not contain
+ * duplicate elements. Trait <code>Set</code> may only be used for
+ * accessing elements from set implementations. Two different extensions
+ * of trait <code>Set</code> in the package <code>scala.collections.mutable</code>
+ * and <code>scala.collections.immutable</code> provide functionality for
+ * adding new elements to a set. The trait in the first package is implemented
+ * by sets the are modified destructively, whereas the trait in the second
+ * package is used by functional set implementations that rely on immutable
+ * data structures.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Set[A] extends AnyRef with Function1[A, Boolean] with Iterable[A] {
+
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ def size: Int;
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def contains(elem: A): Boolean;
+
+ /** This method allows sets to be interpreted as predicates.
+ * It returns true, iff this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def 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 <code>that</code>.
+ *
+ * @param that another set.
+ * @return true, iff the other set is a superset of this set.
+ */
+ 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 && this.elements.forall(other.contains)
+ case _ =>
+ false
+ }
+
+ /** Returns the elements of this set as a list.
+ *
+ * @return a list containing all set elements.
+ */
+ def toList: List[A] = elements.toList;
+
+ /** Returns a string representation of this set.
+ *
+ * @return a string showing all elements of this set.
+ */
+ override def toString(): String =
+ if (size == 0) "{}" else elements.toList.mkString("{", ", ", "}");
+}
diff --git a/src/library/scala/collection/SetProxy.scala b/src/library/scala/collection/SetProxy.scala
new file mode 100644
index 0000000000..0fc1931385
--- /dev/null
+++ b/src/library/scala/collection/SetProxy.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection;
+
+
+/** This is a simple wrapper class for <code>scala.collection.Set</code>.
+ * It is most useful for assembling customized set abstractions
+ * dynamically using object composition and forwarding.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+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);
+
+ override def foreach(f: A => Unit): Unit = self.foreach(f);
+
+ override def exists(p: A => Boolean): Boolean = self.exists(p);
+
+ override def toList: List[A] = self.toList;
+}
diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala
new file mode 100644
index 0000000000..61299bf069
--- /dev/null
+++ b/src/library/scala/collection/immutable/BitSet.scala
@@ -0,0 +1,117 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+/** The class <code>BitSet</code>provides an immutable bitset view on an
+ * int array. Instances can conveniently be created from instances of
+ * <code>mutable.ResizableBitSet</code>. Bit indices are between 0..(size-1) inclusive
+ *
+ * @param <code>n</code> represents the number of relevant bits
+ * @param ba: array of ints of length <code>n</code>&gt;&gt;&gt;5
+ * @param copy: if yes, then <code>ba</code> is copied and updates will
+ * not affect this bitset
+ *
+ * @author Burak Emir
+ * @version 1.0
+ */
+[serializable]
+class BitSet(n:Int, ba: Array[Int], copy: Boolean) extends collection.BitSet with Ordered[BitSet] {
+ import scala.runtime.compat.Platform.arraycopy;
+ /** lexicographic ordering */
+ def compareTo [b >: BitSet <% Ordered[b]](other: b): int = other match {
+ case that:BitSet =>
+ val it1 = this.toSet(true).elements;
+ val it2 = that.toSet(true).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.compareTo(this))
+ }
+
+
+ final def size = n;
+
+ protected val array: Array[Int] =
+ if (copy) {
+ val arr = new Array[Int](ba.length);
+ arraycopy(ba, 0, arr, 0, ba.length);
+ arr
+ }
+ else
+ ba;
+
+ /**
+ * Checks if two bitsets are structurally identical.
+ *
+ * @return true, iff both bitsets contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = (
+ that.isInstanceOf[BitSet] &&
+ { val other = that.asInstanceOf[BitSet];
+ (size == other.size) && ( size == 0 || {
+ var len = memsize( size );
+ var i = 0;
+ var res=true;
+ while(( i< len ) && res ) { // 32 x faster equality check
+ res = array(i) == other.array(i);
+ i = i + 1;
+ }
+ res
+ })
+ } || super.equals(that)
+ );
+
+ def this(rbs: mutable.BitSet) = {
+ this(rbs.size, rbs.toArray, false);
+ }
+
+ /** returns true if bit i is set
+ *
+ * @param i
+ */
+ def apply(i: Int):Boolean = {
+ val j = (i >>> 5);
+ val mask = (1 << (i & 0x1F));
+ (array(j) & mask) != 0;
+ }
+
+ def makeMutable = {
+ val rbs = new mutable.BitSet(size) ;
+ val it = this.toSet(true).elements;
+ while(it.hasNext) {
+ rbs.set(it.next)
+ }
+ rbs
+ }
+
+ def toArray: Array[Int] = {
+ val arr = new Array[Int](array.length);
+ arraycopy(arr, 0, array, 0, array.length);
+ arr
+ }
+}
diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala
new file mode 100644
index 0000000000..b6c9989531
--- /dev/null
+++ b/src/library/scala/collection/immutable/ListMap.scala
@@ -0,0 +1,150 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+
+object ListMap {
+ def Empty[A, B] = new ListMap[A, B];
+}
+
+/** This class implements immutable maps using a list-based data
+ * structure. Instances of <code>ListMap</code> represent
+ * empty maps; they can be either created by calling the constructor
+ * directly, or by applying the function <code>ListMap.Empty</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 09/07/2003
+ */
+[serializable]
+class ListMap[A, B] extends AnyRef with Map[A, B] {
+
+ /** This method returns a new ListMap instance mapping keys of the
+ * same type to values of type <code>C</code>.
+ */
+ def empty[C] = new ListMap[A, C];
+
+ /** Returns the number of mappings in this map.
+ *
+ * @return number of mappings.
+ */
+ def size: Int = 0;
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ def get(key: A): Option[B] = None;
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ */
+ def update(key: A, value: B): ListMap[A, B] = new Node(key, value);
+
+ /** This creates a new mapping without the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method returns the same map.
+ */
+ def -(key: A): ListMap[A, B] = this;
+
+ /** This returns an iterator over key-value pairs.
+ */
+ def elements: Iterator[Pair[A, B]] = toList.elements;
+
+ /** This return a list of key-value pairs.
+ */
+ override def toList: List[Pair[A, B]] = Nil;
+
+ /** Compares two maps for equality.
+ * Two maps are equal iff they contain exactly the
+ * same key-value pairs.
+ */
+ override def equals(obj: Any): Boolean =
+ if (obj.isInstanceOf[scala.collection.Map[A, B]]) {
+ val that = obj.asInstanceOf[scala.collection.Map[A, B]];
+ if (size != that.size) false else toList.forall {
+ case Pair(key, value) => that.get(key) match {
+ case None => false;
+ case Some(v) => v == value;
+ }
+ };
+ } else
+ false;
+
+ override def hashCode(): Int = 0;
+
+ protected class Node(key: A, value: B) extends ListMap[A, B] {
+ /** Returns the number of mappings in this map.
+ *
+ * @return number of mappings.
+ */
+ override def size: Int = ListMap.this.size + 1;
+
+ /** Is this an empty map?
+ *
+ * @return true, iff the map is empty.
+ */
+ override def isEmpty: Boolean = false;
+
+ /** 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.
+ */
+ override def apply(k: A): B = if (k == key) value else ListMap.this(k);
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(k: A): Option[B] =
+ if (k == key) Some(value) else ListMap.this.get(k);
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ */
+ override def update(k: A, v: B): ListMap[A, B] =
+ if (k == key) {
+ new ListMap.this.Node(k, v);
+ } else {
+ val tail = ListMap.this.update(k,v); new tail.Node(key, value)
+ }
+
+ /** This creates a new mapping without the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method returns the same map.
+ */
+ override def -(k: A): ListMap[A, B] =
+ if (k == key)
+ ListMap.this
+ else {
+ val tail = ListMap.this - k; new tail.Node(key, value)
+ }
+
+ /** This return a list of key-value pairs.
+ */
+ override def toList: List[Pair[A, B]] = Pair(key, value) :: ListMap.this.toList;
+
+ override def hashCode(): Int =
+ (key.hashCode() ^ value.hashCode()) + ListMap.this.hashCode();
+ }
+}
+
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
new file mode 100644
index 0000000000..305e54cb90
--- /dev/null
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -0,0 +1,118 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.immutable;
+
+
+object ListSet {
+ /** constructs an empty ListSet
+ */
+ def Empty[A] = new ListSet[A];
+}
+
+
+/** This class implements immutable sets using a list-based data
+ * structure. Instances of <code>ListSet</code> represent
+ * empty sets; they can be either created by calling the constructor
+ * directly, or by applying the function <code>ListSet.Empty</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 09/07/2003
+ */
+[serializable]
+class ListSet[A] extends AnyRef with Set[A] {
+
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ def size: Int = 0;
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def contains(elem: A): Boolean = false;
+
+ /** This method creates a new set with an additional element.
+ */
+ def +(elem: A): ListSet[A] = new Node(elem);
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ def -(elem: A): ListSet[A] = this;
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A] = toList.elements;
+
+ /** Transform this set into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this set.
+ */
+ override def toList: List[A] = Nil;
+
+ /** 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;
+
+ override def hashCode(): Int = 0;
+
+ protected class Node(elem: A) extends ListSet[A] {
+ /** Returns the number of elements in this set.
+ *
+ * @return number of set elements.
+ */
+ override def size = ListSet.this.size + 1;
+
+ /** Checks if this set is empty.
+ *
+ * @return true, iff there is no element in the set.
+ */
+ override def isEmpty: Boolean = false;
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ override def contains(e: A) = (e == elem) || ListSet.this.contains(e);
+
+ /** This method creates a new set with an additional element.
+ */
+ override def +(e: A): ListSet[A] = if (contains(e)) this else new Node(e);
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ override def -(e: A): ListSet[A] = if (e == elem) ListSet.this else {
+ val tail = ListSet.this - e; new tail.Node(elem)
+ }
+
+ /** Transform this set into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this set.
+ */
+ override def toList: List[A] = elem :: ListSet.this.toList;
+
+ override def hashCode(): Int = elem.hashCode() + ListSet.this.hashCode();
+ }
+}
diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala
new file mode 100644
index 0000000000..b737f48886
--- /dev/null
+++ b/src/library/scala/collection/immutable/Map.scala
@@ -0,0 +1,144 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+
+/** This trait extends the Map interface of collections that unambiguously map
+ * keys to values (i.e. a key is mapped to at least one value).
+ * This trait 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
+ * <code>factory</code>, <code>update</code>, and -.
+ *
+ * @author Matthias Zenger
+ * @author Erik Stenman
+ * @version 1.1, 22/03/2004
+ */
+trait Map[A, B] extends AnyRef with scala.collection.Map[A, B] {
+
+ /** This method returns a new map instance of the same class
+ * mapping keys of the same type to values of type <code>C</code>.
+ */
+ def empty[C]: Map[A, C];
+
+ /** This method allows one to create a new map with an
+ * additional mapping from <code>key</code>
+ * to <code>value</code>. If the map contains already a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ */
+ def update(key: A, value: B): Map[A, B];
+
+ /** This creates a new mapping without the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method returns the same map.
+ */
+ def -(key: A): Map[A, B];
+
+ /** This method defines syntactic sugar for adding a
+ * mapping. It is typically used in the following way:
+ * <pre>
+ * map + key -> value;
+ * </pre>
+ */
+ def +(key: A): MapTo = new MapTo(key);
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that a mapping is represented
+ * by a <code>Pair</code> object who's first component denotes the
+ * key, and who's second component refers to the value.
+ */
+ def incl(mappings: Pair[A, B]*): Map[A, B] = incl(mappings);
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that each mapping is represented
+ * by an Iterator over <code>Pair</code> objects who's first component
+ * denotes the key, and who's second component refers to the value.
+ */
+ def incl(map: Iterable[Pair[A, B]]): Map[A, B] = {
+ val iter = map.elements;
+ var res = this;
+ while (iter.hasNext) {
+ val Pair(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.
+ */
+ def excl(keys: A*): Map[A, B] = excl(keys);
+
+ /** This method removes all the mappings for keys provided by an
+ * iterator over the elements of the <code>keys</code> object.
+ */
+ def excl(keys: Iterable[A]): Map[A, B] = {
+ val iter = keys.elements;
+ var res = this;
+ while (iter.hasNext) {
+ res = res - iter.next;
+ }
+ res;
+ }
+
+ /** This function transforms all the values of mappings contained
+ * in this map with function <code>f</code>.
+ */
+ def map[C](f: (A, B) => C): Map[A, C] = {
+ var res = empty[C];
+ elements foreach {
+ case Pair(key, value) => res = res.update(key, f(key, value));
+ }
+ res;
+ }
+
+ /** This method removes all the mappings for which the predicate
+ * <code>p</code> returns <code>false</code>.
+ */
+ def filter(p: (A, B) => Boolean): Map[A, B] = {
+ var res = this;
+ toList foreach {
+ case Pair(key, value) => if (!p(key, value)) { res = res.excl(key); }
+ }
+ res;
+ }
+
+ /** Returns a string representation of this map which shows
+ * all the mappings.
+ */
+ override def toString() =
+ if (size == 0)
+ "{}"
+ else
+ "{" + {
+ val iter = elements;
+ var res = mappingToString(iter.next);
+ while (iter.hasNext) {
+ res = res + ", " + mappingToString(iter.next);
+ }
+ res;
+ } + "}";
+
+ override def hashCode() = {
+ elements.foldLeft(0)((hash:Int,pair:AnyRef) => hash + pair.hashCode());
+ }
+
+ /** This method controls how a mapping is represented in the string
+ * representation provided by method <code>toString</code>.
+ */
+ def mappingToString(p: Pair[A, B]) = p._1.toString() + " -> " + p._2;
+
+ class MapTo(key: A) {
+ def ->(value: B) = update(key, value);
+ }
+}
+
diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala
new file mode 100644
index 0000000000..cb005d3b5e
--- /dev/null
+++ b/src/library/scala/collection/immutable/Queue.scala
@@ -0,0 +1,173 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+
+object Queue {
+ val Empty: Queue[All] = new Queue();
+}
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Erik Stenman
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class Queue[+A](elem: A*) extends Seq[A] {
+ protected val in: List[A] = Nil;
+ protected val out: List[A] = itToList(elem.elements);
+
+ protected def itToList[B >: A](elems: Iterator[B]): List[B] =
+ if (elems.hasNext) {
+ val hd = elems.next;
+ hd :: itToList(elems)
+ }
+ else
+ Nil;
+
+ protected def mkQueue[A](i: List[A], o: List[A]): Queue[A] =
+ new Queue[A]() {
+ override protected val in = i;
+ override protected val out = o
+ };
+
+ /** Returns the <code>n</code>-th element of this queue.
+ * The first element is at position 0.
+ *
+ * @param n index of the element to return
+ * @return the element at position <code>n</code> in this list.
+ * @throws java.lang.RuntimeException if the list is too short.
+ */
+ def apply(n: Int): A =
+ if (n < out.length) out.apply(n)
+ else in.reverse.apply(n - out.length);
+
+ /** 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.
+ */
+ def isEmpty: Boolean = in.isEmpty && out.isEmpty;
+
+ /** Returns the length of the queue.
+ */
+ def length = in.length + out.length;
+
+ /** Creates a new queue with element added at the end
+ * of the old queue.
+ *
+ * @param elem the element to insert
+ */
+ def +[B >: A](elem: B) = mkQueue(elem :: in, out);
+
+ /** Returns a new queue with all all elements provided by
+ * an <code>Iterable</code> object added at the end of
+ * the queue.
+ * The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def +[B >: A](iter: Iterable[B]) = {
+ var q: List[B] = in;
+ iter.elements.foreach(e => q = e :: q);
+ mkQueue(q, out);
+ }
+
+ /** Returns a new queue with all elements added.
+ *
+ * @param elems the elements to add.
+ */
+ def enqueue [B >: A](elems: B*) = this + elems;
+
+ /** Returns a tuple with the first element in the queue,
+ * and a new queue with this element removed.
+ *
+ * @return the first element of the queue.
+ */
+ def dequeue: Pair[A, Queue[A]] = {
+ val Pair(newOut, newIn) =
+ if (out.isEmpty) Pair(in.reverse, Nil)
+ else Pair(out, in);
+ if (newOut.isEmpty) error("queue empty");
+ else Pair(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.
+ *
+ * @return the first element.
+ */
+ def front: A =
+ if (out.isEmpty) {
+ if (in.isEmpty) error("queue empty") else in.last;
+ } else
+ out.head;
+
+ /** Returns a string representation of this queue. The resulting string
+ * begins with the string <code>start</code> and is finished by the string
+ * <code>end</code>. Inside, the string representations of elements (w.r.t.
+ * the method <code>toString()</code>) are separated by the string
+ * <code>sep</code>.
+ * <p/>
+ * Ex: <br/>
+ * <code>Queue(1, 2, 3).mkString("(", "; ", ")") = "(1; 2; 3)"</code>
+ *
+ * @param start starting string.
+ * @param sep separator string.
+ * @param end ending string.
+ * @return a string representation of this list.
+ */
+ def mkString(start: String, sep: String, end: String): String =
+ (out ::: in.reverse).mkString(start, sep, end);
+
+ /** Returns a string representation of this queue.
+ */
+ override def toString() = (out ::: in.reverse).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[Any] =>
+ /* 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: Pair[A,Queue[A]] = dequeue;
+ q._1.hashCode() + q._2.hashCode();
+ }
+}
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
new file mode 100644
index 0000000000..af3340e8f1
--- /dev/null
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -0,0 +1,81 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+
+/** This trait represents immutable sets. Concrete set implementations
+ * just have to provide functionality for the abstract methods in
+ * <code>scala.collection.Set</code> as well as for <code>+</code> and
+ * <code>-</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+trait Set[A] extends AnyRef with scala.collection.Set[A] {
+
+ /** This method creates a new set with an additional element.
+ */
+ def +(elem: A): Set[A];
+
+ /** <code>incl</code> can be used to add many elements to the set
+ * at the same time.
+ */
+ def incl(elems: A*): Set[A] = incl(elems);
+
+ /** This method will add all the elements provided by an iterator
+ * of the iterable object <code>that</code> to the set.
+ */
+ def incl(that: Iterable[A]): Set[A] = {
+ var res = this;
+ that.elements.foreach(elem => res = res + elem);
+ res;
+ }
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ def -(elem: A): Set[A];
+
+ /** <code>excl</code> removes many elements from the set.
+ */
+ def excl(elems: A*): Set[A] = excl(elems);
+
+ /** This method removes all the elements provided by an iterator
+ * of the iterable object <code>that</code> from the set.
+ */
+ def excl(that: Iterable[A]): Set[A] = {
+ var res = this;
+ that.elements.foreach(elem => res = res - elem);
+ res;
+ }
+
+ /** This method computes an intersection with set <code>that</code>.
+ * It removes all the elements that are not present in <code>that</code>.
+ */
+ def intersect(that: scala.collection.Set[A]): Set[A] = filter(that.contains);
+
+ /** Method <code>filter</code> removes all elements from the set for
+ * which the predicate <code>p</code> yields the value <code>false</code>.
+ */
+ def filter(p: A => Boolean): Set[A] = {
+ var res = this;
+ toList foreach {
+ elem => if (!p(elem)) { res = res - elem; }
+ }
+ res;
+ }
+
+ /** hashcode for this set */
+ override def hashCode() = {
+ elements.foldLeft(0)((hash: Int, e: A) => hash + e.hashCode());
+ }
+
+}
+
diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala
new file mode 100644
index 0000000000..46b15794a3
--- /dev/null
+++ b/src/library/scala/collection/immutable/Stack.scala
@@ -0,0 +1,139 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.immutable;
+
+
+object Stack {
+ def Empty[A] = new Stack[A];
+}
+
+/** This class implements immutable stacks using a list-based data
+ * structure. Instances of <code>Stack</code> represent
+ * empty stacks; they can be either created by calling the constructor
+ * directly, or by applying the function <code>Stack.Empty</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/07/2003
+ */
+[serializable]
+class Stack[+A] extends Seq[A] {
+
+ /** Checks if this stack is empty.
+ *
+ * @return true, iff there is no element on the stack.
+ */
+ 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] = {
+ var res: Stack[B] = this;
+ elems.elements.foreach { elem => res = res + elem; }
+ res
+ }
+
+ /** 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 = error("no element on stack");
+
+ /** Removes the top element from the stack.
+ *
+ * @return the new stack without the former top element.
+ */
+ def pop: Stack[A] = error("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 = error("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] = toList.elements;
+
+ /** Creates a list of all stack elements in LIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = Nil;
+
+ /** 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 =
+ if (obj.isInstanceOf[Stack[A]])
+ toList.equals((obj.asInstanceOf[Stack[A]]).toList);
+ else
+ false;
+
+ /** 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 +[C >: B](elem: C): Stack[C] = new Node(elem);
+ override def +[C >: B](elems: Iterable[C]): Stack[C] = super.+(elems);
+ 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 toList: List[B] = elem :: Stack.this.toList;
+ override def hashCode(): Int = elem.hashCode() + Stack.this.hashCode();
+ }
+
+}
diff --git a/src/library/scala/collection/immutable/Tree.scala b/src/library/scala/collection/immutable/Tree.scala
new file mode 100644
index 0000000000..fdb3f8cf46
--- /dev/null
+++ b/src/library/scala/collection/immutable/Tree.scala
@@ -0,0 +1,374 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, 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;
+
+/** 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.
+ * <p/>
+ * This implementation does not balance the trees after deletions.
+ * Since deletions don't increase the height of a tree, this should
+ * be OK in most applications. A balance method is provided for those
+ * cases where rebalancing is needed.
+ * <p/>
+ * The tree consists of entries conatining a key with an order.
+ * <p/>
+ * When instanciating the tree an order for the keys has to be
+ * supplied.
+ *
+ * @author Erik Stenman
+ * @author Michel Schinz
+ * @version 1.1, 2005-01-20
+ */
+//[serializable]
+abstract class Tree[A <% Ordered[A], B]() extends AnyRef with java.io.Serializable {
+ /* Data structure:
+ ** - size:Int - the number of elements in the tree.
+ ** - tree:T, which is composed of nodes of the form:
+ ** - GBNode(key: A, entry:B, smaller:T, bigger:T),
+ ** - and the "empty tree" node GBLeaf.
+ **
+ ** Original balance condition h(T) <= ceil(c * log(|T|)) has been
+ ** changed to the similar (but not quite equivalent) condition
+ ** 2 ^ h(T) <= |T| ^ c.
+ **
+ */
+
+ /** The type returned when creating a new tree.
+ * This type should be defined by concrete implementations
+ * e.g. <pre>
+ * class C[T](...) extends Tree[A,B](...) {
+ * type This = C[T];
+ * </pre>
+ */
+ protected type This <: Tree[A,B];
+ protected def getThis: This;
+
+ /**
+ * The type of nodes that the tree is build from.
+ */
+ protected type aNode = GBTree[A,B];
+
+ private val empty: aNode = GBLeaf[A,B]();
+
+ /** The nodes in the tree.
+ */
+ protected def tree: aNode = empty;
+
+ /** This abstract method should be defined by a concrete implementation
+ ** C[T] as something like:
+ ** <pre>
+ ** override def New(sz:Int,t:aNode):This {
+ ** new C[T](order) {
+ ** override def size=sz;
+ ** override protected def tree:aNode=t;
+ ** }
+ ** </pre>
+ ** The concrete implementation should also override the def of This
+ ** <code>override type This = C[T];</code>
+ **
+ */
+ protected def New(sz: Int, t: aNode): This;
+
+ /** The size of the tree, returns 0 (zero) if the tree is empty.
+ ** @Returns The number of nodes in the tree as an integer.
+ **/
+ def size: Int = 0;
+
+ /**
+ * A new tree with the entry added is returned,
+ * assuming that key is <em>not</em> in the tree.
+ */
+ protected def add(key: A, entry: B): This = {
+ val newSize = size+1;
+ New(newSize, tree.insert(key, entry, newSize * newSize).node);
+ }
+
+ /**
+ * A new tree with the entry added is returned,
+ * if key is <em>not</em> in the tree, otherwise
+ * the key is updated with the new entry.
+ */
+ protected def updateOrAdd(key: A, entry: B): This = {
+ if (tree.isDefinedAt(key))
+ New(size,tree.update(key,entry))
+ else
+ add(key,entry);
+ }
+
+ /** Removes the key from the tree. */
+ 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. */
+ private def delete(key:A): This =
+ New(size - 1, tree.delete(key));
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ protected def findValue(key:A): Option[B] =
+ tree.get(key);
+
+ /**
+ * Gives you an iterator over all elements in the tree.
+ * The iterator structure corresponds to
+ * the call stack of an in-order traversal.
+ *
+ * Note: The iterator itself has a state, i.e., it is not functional.
+ */
+ protected def entries: Iterator[B] =
+ new Iterator[B] {
+ var iter = tree.mk_iter(scala.Nil);
+ def hasNext = !iter.isEmpty;
+ def next =
+ iter match {
+ case (GBNode(_,v,_,t)::iter_tail) => {
+ iter= t.mk_iter(iter_tail);
+ v;
+ }
+ case scala.Nil =>
+ error("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];
+}
+
+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;
+}
+
+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 Pair(subHeight, subSize) = subtree.count;
+ val totalHeight = 2 * scala.runtime.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.
+*/
+//[serializable]
+protected abstract class GBTree[A <% Ordered[A],B] extends AnyRef with java.io.Serializable {
+ 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:Pair[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[Pair[A,B]]): List[Pair[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 = Pair(1, 0);
+ def isDefinedAt(key:A) = false;
+ def get(_key:A) = None;
+ def apply(key:A) = error("key " + key + " not found");
+ def update(key:A, value:B) = error("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[Pair[A,B]]): List[Pair[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]] =
+ error("Take Smallest on empty tree");
+ def delete(_key:A) = error("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: Pair[Int,Int] = {
+ val Pair(sHeight, sSize) = smaller.count;
+ val Pair(bHeight, bSize) = bigger.count;
+ val mySize = sSize + bSize + 1;
+ if (mySize == 1)
+ Pair(1, mySize)
+ else
+ Pair(2 * scala.runtime.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
+ error("Key exists: " + newKey);
+ }
+
+ def toList(acc: List[Pair[A,B]]): List[Pair[A,B]] =
+ smaller.toList(Pair(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 Triple(key1, value1, larger1) = larger.takeSmallest;
+ GBNode(key1, value1, this, larger1)
+ }
+
+ def takeSmallest: Triple[A, B, aNode] = smaller match {
+ case GBLeaf() =>
+ Triple(key, value, bigger)
+ case _ =>
+ val Triple(key1, value1, smaller1) = smaller.takeSmallest;
+ Triple(key1, value1, GBNode(key, value, smaller1, bigger))
+ }
+
+ def balance(s:int): GBTree[A,B] =
+ balance_list(toList(scala.Nil), s);
+
+ protected def balance_list(list: List[Pair[A,B]], s:int): GBTree[A,B] = {
+ val empty = GBLeaf[A,B]();
+ def bal(list: List[Pair[A,B]], s:int): Pair[aNode,List[Pair[A,B]]] = {
+ if (s > 1) {
+ val sm = s - 1;
+ val s2 = sm / 2;
+ val s1 = sm - s2;
+ val Pair(t1, Pair(k, v) :: l1) = bal(list, s1);
+ val Pair(t2, l2) = bal(l1, s2);
+ val t = GBNode(k, v, t1, t2);
+ Pair(t, l2)
+ } else
+ if (s == 1) {
+ val Pair(k,v) :: rest = list;
+ Pair(GBNode(k, v, empty, empty), rest)
+ } else
+ Pair(empty, list)
+ }
+ bal(list, s)._1
+ }
+
+ override def hashCode() =
+ value.hashCode() + smaller.hashCode() + bigger.hashCode();
+}
diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala
new file mode 100644
index 0000000000..12814b7a41
--- /dev/null
+++ b/src/library/scala/collection/immutable/TreeMap.scala
@@ -0,0 +1,107 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+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] with java.io.Serializable {
+
+ 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.
+ */
+ protected def New(sz:Int,t:aNode):This = new TreeMap[A,B] {
+ override def size=sz;
+ override protected def tree:aNode=t;
+ }
+
+ /** A new TreeMap with the entry added is returned,
+ * if key is <em>not</em> in the TreeMap, otherwise
+ * the key is updated with the new entry.
+ */
+ def update(key:A, value:B) = updateOrAdd(key, Pair(key, value));
+
+ /** A new TreeMap with the entry added is returned,
+ * assuming that key is <em>not</em> in the TreeMap.
+ */
+ def insert(key:A,value:B) = add(key, Pair(key, value));
+
+ /** Removes the key from the TreeMap.
+ */
+ def -(key:A) = deleteAny(key);
+
+ /** Check if this map maps <code>key</code> to a value and return the
+ * value if it exists.
+ *
+ * @param key the key of the mapping of interest
+ * @return the value of the mapping, if it exists
+ */
+ override def get(key: A): Option[B] =
+ findValue(key) match {
+ case Some(Pair(_, value: B)) => 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;
+
+ /** Compares two maps structurally; i.e. checks if all mappings
+ * contained in this map are also contained in the other map,
+ * and vice versa.
+ *
+ * @return true, iff both maps contain exactly the same mappings.
+ */
+ override def equals(obj: Any): Boolean =
+ obj.isInstanceOf[scala.collection.Map[A, B]] && {
+ val that = obj.asInstanceOf[scala.collection.Map[A, B]];
+ size == that.size && elements.forall {
+ case Pair(key, value) => that.get(key) match {
+ case None => false;
+ case Some(v) => v == value;
+ }
+ }
+ };
+}
+
diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala
new file mode 100644
index 0000000000..bb3099e007
--- /dev/null
+++ b/src/library/scala/collection/immutable/TreeSet.scala
@@ -0,0 +1,69 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.immutable;
+
+
+/** This class implements immutable sets using a tree.
+ *
+ * @author Matthias Zenger
+ * @author Burak Emir
+ * @version 1.1, 03/05/2004
+ */
+//[serializable]
+class TreeSet[A <% Ordered[A]]() extends Tree[A, A] with Set[A] with java.io.Serializable {
+
+ override protected type This = TreeSet[A];
+ override protected def getThis: This = this;
+
+ protected def New(sz: Int, t: aNode): This = new TreeSet[A] {
+ override def size = sz;
+ override protected def tree: aNode = t;
+ }
+
+ /** Checks if this set contains element <code>elem</code>.
+ *
+ * @param elem the element to check for membership.
+ * @return true, iff <code>elem</code> is contained in this set.
+ */
+ def contains(elem: A): Boolean = !findValue(elem).isEmpty;
+
+ /** This method creates a new set with an additional element.
+ */
+ def +(elem: A): TreeSet[A] = updateOrAdd(elem, elem);
+
+ /** <code>-</code> can be used to remove a single element from
+ * a set.
+ */
+ def -(elem: A): TreeSet[A] = deleteAny(elem);
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ def elements: Iterator[A] = entries;
+
+ /** Transform this set into a list of all elements.
+ *
+ * @return a list which enumerates all elements of this set.
+ */
+ override def toList: List[A] =
+ tree.toList(scala.Nil) map (._2);
+
+ /** Compares two sets for equality.
+ * Two set are equal iff they contain the same elements.
+ */
+ override def equals(obj: Any): Boolean =
+ obj.isInstanceOf[scala.collection.Set[A]] && {
+ val that = obj.asInstanceOf[scala.collection.Set[A]];
+ (size == that.size) && toList.forall(that.contains);
+ }
+}
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
new file mode 100644
index 0000000000..e89e1a9c81
--- /dev/null
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -0,0 +1,148 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** An implementation of the Buffer trait 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] {
+
+ def apply(n: Int): A = {
+ if ((n < 0) || (n >= size))
+ error("cannot access element " + n + " in ArrayBuffer");
+ else
+ array(n);
+ }
+
+ /** 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] = {
+ ensureSize(size+1);
+ array(size) = elem;
+ size = size + 1;
+ this
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++(iter: Iterable[A]): Buffer[A] = { insertAll(size, iter); 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] = {
+ ensureSize(size+1);
+ copy(0, 1, size);
+ array(0) = elem;
+ size = size + 1;
+ this
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = { insertAll(0, iter); this }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit = {
+ if ((n < 0) || (n > size))
+ error("cannot insert element " + n + " in ListBuffer");
+ val xs = iter.elements.toList;
+ val len = xs.length;
+ ensureSize(size+len);
+ copy(n, n + len, size - n);
+ xs.copyToArray(array, n);
+ size = size + len;
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit = {
+ if ((n < 0) || (n >= size))
+ error("cannot update element " + n + " in ArrayBuffer");
+ 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.
+ */
+ def remove(n: Int): A = {
+ if ((n < 0) || (n >= size))
+ error("cannot remove element " + n + " in Buffer");
+ val res = array(n);
+ copy(n + 1, n, size - n - 1);
+ size = size - 1;
+ res
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear: Unit = {
+ size = 0;
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = {
+ val res = new ArrayBuffer[A];
+ res ++= this;
+ res
+ }
+
+ /** Checks if two buffers are structurally identical.
+ *
+ * @return true, iff both buffers contain the same sequence of elements.
+ */
+ override def equals(obj: Any): Boolean = obj match {
+ case that: ArrayBuffer[A] =>
+ elements.zip(that.elements).forall {
+ case Pair(thiselem, thatelem) => thiselem == thatelem;
+ }
+ case _ => false
+ }
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "ArrayBuffer";
+}
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
new file mode 100644
index 0000000000..40d0bf0529
--- /dev/null
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -0,0 +1,87 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable ;
+
+/** mutable, resizable bit sets, to represent dense sets of small integers
+ * Bit indices are between 0..(size-1) inclusive
+ * @author Burak Emir
+ * @param initSize: initial size in nbits
+ */
+[serializable]
+class BitSet(initSize: Int) extends scala.collection.BitSet {
+ import scala.runtime.compat.Platform.arraycopy;
+
+ /** default constructor, initial size of 512 bits */
+ def this() = this( 512 ); // ResizableArray.initialSize << 5
+
+ [serializable]
+ class ByteArray extends AnyRef with ResizableArray[Int] {
+
+ final def ensureBits(nbits: Int): Unit = {
+ super[ResizableArray].ensureSize(memsize( nbits ));
+ }
+ final def and(j: Int, mask:Int): Unit = {
+ array.update( j, array(j) & mask );
+ }
+ final def or(j: Int, mask:Int): Unit = {
+ array.update( j, array(j) | mask );
+ }
+ def get(j:Int, mask:Int):Boolean = {
+ (array(j) & mask) != 0;
+ }
+ def freeze: Array[Int] = {
+ val arr = new Array[Int]( array.length );
+ arraycopy(array, 0, arr, 0, arr.length);
+ arr
+ }
+ }
+
+ /** size of this bitset in nbytes */
+ var size: Int = initSize;
+ protected val internal = new ByteArray();
+ internal.ensureBits( size );
+
+ /** ensure that this bitset can store at least nbits bits */
+ def ensureSize(n: Int): Unit = {
+ internal.ensureBits( n );
+ if( size < n ) size = n;
+ }
+
+ /** calls set or clear for i-th bit */
+ final def set(i: Int, b: Boolean): Unit = if( b ) set(i) else clear(i);
+
+ /** sets i-th bit to true. Grows to size i+1 if needed. */
+ final def set(i: Int): Unit = {
+ ensureSize(i+1);
+ val j = (i >>> 5);
+ val mask = (1 << (i & 0x1F));
+ internal.or(j, mask);
+ }
+
+ /** clears i-th bit. Grows to size i+1 if needed. */
+ def clear(i: Int): Unit = {
+ ensureSize(i+1);
+ val j = (i >>> 5);
+ val mask = (1 << (i & 0x1F));
+ internal.and(j, ~mask);
+ }
+
+ /** gets i-th bit. Grows to size i+1 if needed. */
+ def apply(i: Int):Boolean = {
+ val j = (i >>> 5);
+ val mask = (1 << (i & 0x1F));
+ internal.get(j, mask);
+ }
+
+ def toArray: Array[Int] = internal.freeze;
+
+ def makeImmutable = new scala.collection.immutable.BitSet(this);
+
+}
diff --git a/src/library/scala/collection/mutable/Buffer.scala b/src/library/scala/collection/mutable/Buffer.scala
new file mode 100644
index 0000000000..f1e8d0fe9b
--- /dev/null
+++ b/src/library/scala/collection/mutable/Buffer.scala
@@ -0,0 +1,214 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** 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[Pair[Location, A]]] {
+
+ /** 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];
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +=(elem: A): Unit = this + elem;
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def ++(elems: Iterable[A]): Buffer[A] = this ++ elems.elements;
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def ++(iter: Iterator[A]): Buffer[A] = {
+ iter.foreach(e => this += e);
+ this
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def ++=(elems: Iterable[A]): Unit = this ++ elems.elements;
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def ++=(it: Iterator[A]): Unit = this ++ it;
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ def append(elems: A*): Unit = this ++ elems;
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ def appendAll(iter: Iterable[A]): Unit = this ++ iter;
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +:(elem: A): Buffer[A];
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def ++:(iter: Iterable[A]): Buffer[A] = {
+ iter.elements.toList.reverse.foreach(e => e +: this);
+ this
+ }
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ def prepend(elems: A*): Unit = elems ++: this;
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ def prependAll(elems: Iterable[A]): Unit = elems ++: this;
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ def insert(n: Int, elems: A*): Unit = insertAll(n, elems);
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit;
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit;
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ def remove(n: Int): A;
+
+ /** Removes the first <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the beginning
+ * of this buffer.
+ */
+ def trimStart(n: Int): Unit = {
+ var i = n;
+ while (i > 0) { remove(0); i = i - 1; }
+ }
+
+ /** Removes the last <code>n</code> elements.
+ *
+ * @param n the number of elements to remove from the end
+ * of this buffer.
+ */
+ def trimEnd(n: Int): Unit = {
+ var i = n;
+ while (i > 0) { remove(length - 1); i = i - 1; }
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear: Unit;
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ def <<(cmd: Message[Pair[Location, A]]): Unit = cmd match {
+ case Include(Pair(l, elem)) => l match {
+ case Start => prepend(elem);
+ case End => append(elem);
+ case Index(n) => insert(n, elem);
+ case _ => error("message " + cmd + " not understood");
+ }
+ case Update(Pair(l, elem)) => l match {
+ case Start => update(0, elem);
+ case End => update(length - 1, elem);
+ case Index(n) => update(n, elem);
+ case _ => error("message " + cmd + " not understood");
+ }
+ case Remove(Pair(l, _)) => l match {
+ case Start => remove(0);
+ case End => remove(length - 1);
+ case Index(n) => remove(n);
+ case _ => error("message " + cmd + " not understood");
+ }
+ case Reset() => clear;
+ case s: Script[Pair[Location, A]] => s.elements foreach <<;
+ case _ => error("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 = error("unsuitable as hash key");
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "Buffer";
+}
diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala
new file mode 100644
index 0000000000..c06202024a
--- /dev/null
+++ b/src/library/scala/collection/mutable/BufferProxy.scala
@@ -0,0 +1,147 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This is a simple proxy class for <code>scala.collection.mutable.Buffer</code>.
+ * 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.
+ */
+ def +(elem: A): Buffer[A] = self.+(elem);
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ override def +=(elem: A): Unit = self.+=(elem);
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++(iter: Iterable[A]): Buffer[A] = self.++(iter);
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++=(iter: Iterable[A]): Unit = self.++=(iter);
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ override def append(elems: A*): Unit = self.++=(elems);
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def appendAll(iter: Iterable[A]): Unit = self.appendAll(iter);
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ def +:(elem: A): Buffer[A] = self.+:(elem);
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = self.++:(iter);
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ override def prepend(elems: A*): Unit = self.prependAll(elems);
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def prependAll(elems: Iterable[A]): Unit = self.prependAll(elems);
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ override def insert(n: Int, elems: A*): Unit = self.insertAll(n, elems);
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit = self.insertAll(n, iter);
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit = self.update(n, newelem);
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ def remove(n: Int): A = self.remove(n);
+
+ /** Clears the buffer contents.
+ */
+ def clear: Unit = self.clear;
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ override def <<(cmd: Message[Pair[Location, A]]): Unit = self << cmd;
+
+ /** Return a clone of this buffer.
+ *
+ * @return a <code>Buffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = new BufferProxy[A] { def self = BufferProxy.this.self.clone() }
+}
diff --git a/src/library/scala/collection/mutable/DefaultMapModel.scala b/src/library/scala/collection/mutable/DefaultMapModel.scala
new file mode 100644
index 0000000000..6ae089bc3e
--- /dev/null
+++ b/src/library/scala/collection/mutable/DefaultMapModel.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This trait is used internally. It implements the mutable <code>Map</code>
+ * trait in terms of three functions: <code>findEntry</code>, <code>addEntry</code>,
+ * and <code>entries</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait DefaultMapModel[A, B] extends AnyRef with scala.collection.mutable.Map[A, B] {
+ protected type Entry = DefaultEntry[A,B];
+
+ protected def findEntry(key: A): Option[Entry];
+
+ protected def addEntry(e: Entry): Unit;
+
+ protected def entries: Iterator[Entry];
+
+ def get(key: A) = findEntry(key) match {
+ case None => None
+ case Some(e) => Some(e.value);
+ }
+
+ def update(key: A, value: B) = findEntry(key) match {
+ case None => addEntry(new Entry(key, value));
+ case Some(e) => e.value = value;
+ }
+
+ def elements = new Iterator[Pair[A, B]] {
+ val iter = entries;
+ def hasNext = iter.hasNext;
+ def next = iter.next.toPair;
+ }
+}
+
+[serializable]
+protected class DefaultEntry[A,B](k: A, v: B) extends AnyRef {
+ def key = k;
+ var value = v;
+ def toPair = Pair(k, value);
+ override def toString() = k.toString() + " -> " + value;
+}
diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala
new file mode 100644
index 0000000000..977f42b23a
--- /dev/null
+++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** This extensible class may be used as a basis for implementing double
+ * linked lists. Type variable <code>A</code> refers to the element type
+ * of the list, type variable <code>This</code> is used to model self
+ * types of linked lists.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+abstract class DoubleLinkedList[A, This <: DoubleLinkedList[A, This]]: This
+ extends SingleLinkedList[A, This] {
+
+ var prev: This = _;
+
+ override def append(that: This): Unit =
+ if (that == null)
+ ()
+ else if (next == null) {
+ next = that;
+ that.prev = this;
+ } else
+ next.append(that);
+
+ override def insert(that: This): Unit = if (that != null) {
+ that.append(next);
+ next = that;
+ that.prev = this;
+ }
+
+ def remove: Unit = {
+ if (next != null)
+ next.prev = prev;
+ if (prev != null)
+ prev.next = next;
+ prev = null;
+ next = null;
+ }
+}
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
new file mode 100644
index 0000000000..dcdde2e40c
--- /dev/null
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** This class implements mutable maps using a hashtable.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class HashMap[A, B] extends scala.collection.mutable.Map[A, B]
+ with HashTable[A]
+ with DefaultMapModel[A, B] {
+
+ def -=(key: A): Unit = removeEntry(key);
+
+ protected def entryKey(e: Entry) = e.key;
+
+ override def clear = {
+ initTable(table);
+ tableSize = 0;
+ }
+
+ override def clone(): Map[A, B] = {
+ val res = new HashMap[A, B];
+ res ++= this;
+ res
+ }
+}
diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala
new file mode 100644
index 0000000000..7f71b037b4
--- /dev/null
+++ b/src/library/scala/collection/mutable/HashSet.scala
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class implements mutable sets using a hashtable.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class HashSet[A] extends scala.collection.mutable.Set[A] with HashTable[A] {
+
+ def contains(elem: A): Boolean = findEntry(elem) match {
+ case None => false
+ case Some(_) => true
+ }
+
+ def +=(elem: A): Unit = findEntry(elem) match {
+ case None => addEntry(elem);
+ case Some(_) =>
+ }
+
+ def -=(elem: A): Unit = removeEntry(elem);
+
+ def elements = entries;
+
+ def clear = {
+ initTable(table);
+ tableSize = 0;
+ }
+
+ protected type Entry = A;
+
+ protected def entryKey(e: Entry) = e;
+
+ override def clone(): HashSet[A] = {
+ val res = new HashSet[A];
+ res ++= this;
+ res
+ }
+}
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
new file mode 100644
index 0000000000..984f33f561
--- /dev/null
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -0,0 +1,148 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+import Predef._;
+
+/** This class can be used to construct data structures that are based
+ * on hashtables. Class <code>HashTable[A]</code> implements a hashtable
+ * that maps keys of type <code>A</code> to values of the fully abstract
+ * member type <code>Entry</code>. Classes that make use of <code>HashTable</code>
+ * have to provide an implementation for <code>Entry</code> and implement the
+ * function <code>entryKey</code>.<p/>
+ *
+ * There are mainly two parameters that affect the performance of a hashtable:
+ * the <i>initial size</i> and the <i>load factor</i>. The <i>size</i>
+ * refers to the number of <i>buckets</i> in the hashtable, and the <i>load
+ * factor</i> is a measure of how full the hashtable is allowed to get before
+ * its size is automatically doubled. Both parameters may be changed by
+ * overriding the corresponding values in class <code>HashTable</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class HashTable[A] extends AnyRef {
+
+ /** The load factor for the hash table.
+ */
+ protected val loadFactor: Float = 0.75f;
+
+ /** The initial size of the hash table.
+ */
+ protected val initialSize: Int = 16;
+
+ /** The initial threshold
+ */
+ protected val initialThreshold: Int = newThreshold(initialSize);
+
+ /** The actual hash table.
+ */
+ protected var table: Array[List[Entry]] = new Array(initialSize);
+ initTable(table);
+
+ /** 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 map.
+ */
+ def size = tableSize;
+
+ protected def findEntry(key: A): Option[Entry] =
+ table(index(elemHashCode(key))).find(entryFor(key));
+
+ protected def addEntry(e: Entry): Unit = {
+ val h = index(elemHashCode(entryKey(e)));
+ table(h) = e :: table(h);
+ tableSize = tableSize + 1;
+ if (tableSize > threshold)
+ resize(2 * table.length);
+ }
+
+ protected def removeEntry(key: A): Unit = {
+ val old = findEntry(key);
+ old match {
+ case None =>
+ case Some(e) => {
+ val idx = index(elemHashCode(key));
+ table(idx) = table(idx).filter(e => !elemEquals(entryKey(e), key));
+ tableSize = tableSize - 1;
+ }
+ }
+ }
+
+ protected type Entry;
+
+ protected def entryKey(e: Entry): A;
+
+ protected def entries: Iterator[Entry] = new Iterator[Entry] {
+ val iterTable = table;
+ var idx = table.length - 1;
+ var xs = iterTable(idx);
+ scan();
+ def hasNext = !xs.isEmpty;
+ def next = {
+ val res = xs.head;
+ xs = xs.tail;
+ scan();
+ res;
+ }
+ def scan(): Unit = if (xs.isEmpty && (idx > 0)) {
+ idx = idx - 1;
+ xs = iterTable(idx);
+ scan();
+ }
+ }
+
+ private def entryFor(key: A) = (e: Entry => elemEquals(entryKey(e), key));
+
+ protected def initTable(tb: Array[List[Entry]]): Unit = {
+ var i = tb.length - 1;
+ while (i >= 0) {
+ tb(i) = Nil;
+ i = i - 1;
+ }
+ }
+
+ private def newThreshold(size: Int) =
+ (size * loadFactor).asInstanceOf[Int];
+
+ private def resize(newSize: Int) = {
+ val newTable: Array[List[Entry]] = new Array(newSize);
+ initTable(newTable);
+ var i = table.length - 1;
+ while (i >= 0) {
+ table(i).foreach { e => {
+ val idx = improve(elemHashCode(entryKey(e))) & (newSize - 1);
+ newTable(idx) = e :: newTable(idx);
+ }};
+ i = i - 1;
+ }
+ table = newTable;
+ 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);
+}
diff --git a/src/library/scala/collection/mutable/History.scala b/src/library/scala/collection/mutable/History.scala
new file mode 100644
index 0000000000..43be629602
--- /dev/null
+++ b/src/library/scala/collection/mutable/History.scala
@@ -0,0 +1,42 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** <code>History[A, B]</code> objects may subscribe to events of
+ * type <code>A</code> published by an object of type <code>B</code>.
+ * The history subscriber object records all published events
+ * up to maximum number of <code>maxHistory</code> events.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class History[A, B] extends AnyRef with Subscriber[A, B] with Iterable[Pair[B, A]] {
+
+ protected val log: Queue[Pair[B, A]] = new Queue[Pair[B, A]];
+
+ val maxHistory: Int = 1000;
+
+ def notify(pub: B, event: A): Unit = {
+ if (log.length >= maxHistory) {
+ val old = log.dequeue;
+ }
+ log.enqueue(Pair(pub, event));
+ }
+
+ def elements: Iterator[Pair[B, A]] = log.elements;
+
+ def events: Iterator[A] = log.elements.map { case Pair(_, e) => e }
+
+ def size: Int = log.length;
+
+ def clear: Unit = log.clear;
+}
diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala
new file mode 100644
index 0000000000..5167636b40
--- /dev/null
+++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala
@@ -0,0 +1,64 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class can be used as an adaptor to create mutable maps from
+ * immutable map implementations. Only method <code>empty</code> has
+ * to be redefined if the immutable map on which this mutable map is
+ * originally based is not empty. <code>empty</code> is supposed to
+ * return the representation of an empty map.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+[serializable]
+class ImmutableMapAdaptor[A, B](m: scala.collection.immutable.Map[A, B]) extends Map[A, B] {
+
+ protected var imap = m;
+
+ 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 values: Iterator[B] = imap.values;
+
+ def elements: Iterator[Pair[A, B]] = imap.elements;
+
+ override def foreach(f: (A, B) => Unit) = imap.foreach(f);
+
+ override def toList: List[Pair[A, B]] = imap.toList;
+
+ override def toString() = imap.toString();
+
+ def update(key: A, value: B): Unit = { imap = imap.update(key, value); }
+
+ def -=(key: A): Unit = { imap = imap - key; }
+
+ override def clear: Unit = { imap = empty; }
+
+ override def map(f: (A, B) => B): Unit = { imap = imap.map(f); }
+
+ override def filter(p: (A, B) => Boolean): Unit = { imap = imap.filter(p); }
+
+ override def mappingToString(p: Pair[A, B]) = imap.mappingToString(p);
+
+ protected def empty: scala.collection.immutable.Map[A, B] = m;
+}
diff --git a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala
new file mode 100644
index 0000000000..623074b3d9
--- /dev/null
+++ b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class can be used as an adaptor to create mutable sets from
+ * immutable set implementations. Only method <code>empty</code> has
+ * to be redefined if the immutable set on which this mutable set is
+ * originally based is not empty. <code>empty</code> is supposed to
+ * return the representation of an empty set.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+[serializable]
+class ImmutableSetAdaptor[A](s: scala.collection.immutable.Set[A]) extends Set[A] {
+
+ protected var set = s;
+
+ 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; }
+
+ def clear: Unit = { set = empty; }
+
+ protected def empty: scala.collection.immutable.Set[A] = s;
+}
diff --git a/src/library/scala/collection/mutable/JavaMapAdaptor.scala b/src/library/scala/collection/mutable/JavaMapAdaptor.scala
new file mode 100644
index 0000000000..3679e787e8
--- /dev/null
+++ b/src/library/scala/collection/mutable/JavaMapAdaptor.scala
@@ -0,0 +1,66 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class can be used as an adaptor to create mutable maps from
+ * Java classes that implementat the <code>java.util.Map</code> interface.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 21/07/2003
+ */
+class JavaMapAdaptor[A, B](jmap: java.util.Map) extends Map[A, B] {
+
+ def size: Int = jmap.size();
+
+ def get(key: A): Option[B] =
+ if (jmap.containsKey(key)) Some(jmap.get(key).asInstanceOf[B]) else None;
+
+ override def isEmpty: Boolean = jmap.isEmpty();
+
+ override def apply(key: A): B = jmap.get(key).asInstanceOf[B];
+
+ override def contains(key: A): Boolean = jmap.containsKey(key);
+
+ override def isDefinedAt(key: A) = jmap.containsKey(key);
+
+ override def keys: Iterator[A] = new Iterator[A] {
+ val iter = jmap.keySet().iterator();
+ def hasNext = iter.hasNext();
+ def next = iter.next().asInstanceOf[A];
+ }
+
+ override def values: Iterator[B] = new Iterator[B] {
+ val iter = jmap.values().iterator();
+ def hasNext = iter.hasNext();
+ def next = iter.next().asInstanceOf[B];
+ }
+
+ def elements: Iterator[Pair[A, B]] = new Iterator[Pair[A, B]] {
+ val iter = jmap.keySet().iterator();
+ def hasNext = iter.hasNext();
+ def next = {
+ val key = iter.next().asInstanceOf[A];
+ Pair(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/library/scala/collection/mutable/JavaSetAdaptor.scala b/src/library/scala/collection/mutable/JavaSetAdaptor.scala
new file mode 100644
index 0000000000..3279e85a13
--- /dev/null
+++ b/src/library/scala/collection/mutable/JavaSetAdaptor.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class can be used as an adaptor to create mutable sets from
+ * Java classes that implement interface <code>java.util.Set</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 19/09/2003
+ */
+class JavaSetAdaptor[A](jset: java.util.Set) extends Set[A] {
+
+ def size: Int = jset.size();
+
+ override def isEmpty: Boolean = jset.isEmpty();
+
+ def contains(elem: A): Boolean = jset.contains(elem);
+
+ def elements: Iterator[A] = new Iterator[A] {
+ val iter = jset.iterator();
+ def hasNext = iter.hasNext();
+ def next = iter.next().asInstanceOf[A];
+ }
+
+ def +=(elem: A): Unit = { val x = jset.add(elem); }
+
+ def -=(elem: A): Unit = { val x = jset.remove(elem); }
+
+ def clear: Unit = jset.clear();
+
+ override def clone(): Set[A] = {
+ val res = new HashSet[A];
+ res ++= this;
+ res;
+ }
+}
diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala
new file mode 100644
index 0000000000..c08928a04a
--- /dev/null
+++ b/src/library/scala/collection/mutable/LinkedList.scala
@@ -0,0 +1,34 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** This class implements single linked lists where both the head (<code>elem</code>)
+ * and the tail (<code>next</code>) are mutable.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class LinkedList[A](head: A, tail: LinkedList[A])
+ extends SingleLinkedList[A, LinkedList[A]]
+{
+ elem = head;
+ next = tail;
+
+ 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/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
new file mode 100644
index 0000000000..527741bbc9
--- /dev/null
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -0,0 +1,143 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** A list buffer uses a list internally to assemble sequences of elements
+ * incrementally by appending or prepending new elements. It is also
+ * possible to access and modify elements in a random access fashion
+ * via the index of the element in the sequence.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 15/03/2004
+ */
+class ListBuffer[A] extends Buffer[A] with MutableList[A] {
+
+ /** 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] = { appendElem(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] = { prependElem(elem); this }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ def insertAll(n: Int, iter: Iterable[A]): Unit = {
+ val it = iter.elements;
+ while (it.hasNext) {
+ val newelem = it.next;
+ if (n == 0)
+ prepend(newelem);
+ else if (n >= len)
+ append(newelem);
+ else {
+ var elem = first;
+ var i = n;
+ while (i > 1) {
+ elem = elem.next;
+ if (elem == null)
+ error("cannot insert element " + n + " in ListBuffer");
+ i = i - 1;
+ }
+ val old = elem.next;
+ elem.next = new LinkedList[A](newelem, old);
+ }
+ }
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ def update(n: Int, newelem: A): Unit = {
+ var elem = first;
+ var i = n;
+ while (i > 0) {
+ elem = elem.next;
+ if (elem == null)
+ error("cannot update element " + n + " in Buffer");
+ i = i - 1;
+ }
+ elem.elem = 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 = {
+ val old = apply(n);
+ if (n >= len)
+ error("cannot remove element " + n + " in Buffer");
+ if ((n == 0) && (len == 1)) {
+ first = null;
+ last = null;
+ } else if (n == 0) {
+ first = first.next;
+ } else {
+ var elem = first;
+ var i = n;
+ while (i > 1) {
+ elem = elem.next;
+ i = i - 1;
+ }
+ elem.next = elem.next.next;
+ if (n == (len - 1)) {
+ last = elem.next;
+ }
+ }
+ len = len - 1;
+ old;
+ }
+
+ /** Clears the buffer contents.
+ */
+ def clear: Unit = reset;
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = {
+ val res = new ListBuffer[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: ListBuffer[A] =>
+ elements.zip(that.elements).forall {
+ case Pair(thiselem, thatelem) => thiselem == thatelem;
+ }
+ case _ => false
+ }
+
+ /** Defines the prefix of the string representation.
+ */
+ override protected def stringPrefix: String = "ListBuffer";
+}
diff --git a/src/library/scala/collection/mutable/Location.scala b/src/library/scala/collection/mutable/Location.scala
new file mode 100644
index 0000000000..30abd06781
--- /dev/null
+++ b/src/library/scala/collection/mutable/Location.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** Class <code>Location</code> describes locations in messages implemented
+ * by class <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+trait 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/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala
new file mode 100644
index 0000000000..75f544193e
--- /dev/null
+++ b/src/library/scala/collection/mutable/Map.scala
@@ -0,0 +1,169 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** This trait represents mutable maps. Concrete map implementations
+ * just have to provide functionality for the abstract methods in
+ * <code>scala.collection.Map</code> as well as for <code>update</code>,
+ * and <code>remove</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 09/05/2004
+ */
+[cloneable]
+trait Map[A, B] extends AnyRef with scala.collection.Map[A, B] with Scriptable[Message[Pair[A, B]]] {
+
+ /** This method allows one to add a new mapping from <code>key</code>
+ * to <code>value</code> to the map. If the map already contains a
+ * mapping for <code>key</code>, it will be overridden by this
+ * function.
+ *
+ * @param key
+ * @param value
+ */
+ def update(key: A, value: B): Unit;
+
+ /** This method defines syntactic sugar for adding or modifying
+ * mappings. It is typically used in the following way:
+ * <pre>
+ * map += key -> value;
+ * </pre>
+ */
+ def +=(key: A): MapTo = new MapTo(key);
+
+ /** This method adds all the mappings provided by an iterator of
+ * parameter <code>map</code> to the map.
+ *
+ * @param map
+ */
+ def ++=(map: Iterable[Pair[A, B]]): Unit = ++=(map.elements);
+
+ /** This method adds all the mappings provided by an iterator of
+ * parameter <code>map</code> to the map.
+ *
+ * @param it
+ */
+ def ++=(it: Iterator[Pair[A, B]]): Unit = it foreach {
+ case Pair(key, value) => update(key, value);
+ }
+
+ /** <code>incl</code> can be used to add many mappings at the same time
+ * to the map. The method assumes that a mapping is represented
+ * by a <code>Pair</code> object who's first component denotes the
+ * key, and who's second component refers to the value.
+ *
+ * @param mappings
+ */
+ def incl(mappings: Pair[A, B]*): Unit = ++=(mappings.elements);
+
+ /** This method removes a mapping from the given <code>key</code>.
+ * If the map does not contain a mapping for the given key, the
+ * method does nothing.
+ */
+ def -=(key: A): Unit;
+
+ /** This method removes all the mappings for keys provided by an
+ * iterator over the elements of the <code>keys</code> object.
+ *
+ * @param keys
+ */
+ def --=(keys: Iterable[A]): Unit = --=(keys.elements);
+
+ /** This method removes all the mappings for keys provided by an
+ * iterator over the elements of the <code>keys</code> object.
+ *
+ * @param it
+ */
+ def --=(it: Iterator[A]): Unit = it foreach -=;
+
+ /** This method will remove all the mappings for the given sequence
+ * of keys from the map.
+ *
+ * @param keys
+ */
+ def excl(keys: A*): Unit = --=(keys.elements);
+
+ /** Removes all mappings from the map. After this operation is
+ * completed, the map is empty.
+ */
+ def clear: Unit = keys foreach -=;
+
+ /** This function transforms all the values of mappings contained
+ * in this map with function <code>f</code>.
+ *
+ * @param f
+ */
+ def map(f: (A, B) => B): Unit = elements foreach {
+ case Pair(key, value) => update(key, f(key, value));
+ }
+
+ /** This method removes all the mappings for which the predicate
+ * <code>p</code> returns <code>false</code>.
+ *
+ * @param p
+ */
+ def filter(p: (A, B) => Boolean): Unit = toList foreach {
+ case Pair(key, value) => if (!p(key, value)) -=(key);
+ }
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ def <<(cmd: Message[Pair[A, B]]): Unit = cmd match {
+ case Include(Pair(k, v)) => update(k, v);
+ case Update(Pair(k, v)) => update(k, v);
+ case Remove(Pair(k, _)) => this -= k;
+ case Reset() => clear;
+ case s: Script[Pair[A, B]] => s.elements foreach <<;
+ case _ => error("message " + cmd + " not understood");
+ }
+
+ /** Return a clone of this map.
+ *
+ * @return an map with the same elements.
+ */
+ override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]];
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable maps as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = error("unsuitable as hash key");
+
+ /** Returns a string representation of this map which shows
+ * all the mappings.
+ */
+ override def toString() =
+ if (size == 0)
+ "{}"
+ else
+ "{" + {
+ val iter = elements;
+ var res = mappingToString(iter.next);
+ while (iter.hasNext) {
+ res = res + ", " + mappingToString(iter.next);
+ }
+ res;
+ } + "}";
+
+ /** This method controls how a mapping is represented in the string
+ * representation provided by method <code>toString</code>.
+ *
+ * @param p
+ */
+ def mappingToString(p: Pair[A, B]) = p._1.toString() + " -> " + p._2;
+
+ class MapTo(key: A) {
+ def ->(value: B): Unit = update(key, value);
+ }
+
+}
diff --git a/src/library/scala/collection/mutable/MapProxy.scala b/src/library/scala/collection/mutable/MapProxy.scala
new file mode 100644
index 0000000000..8081e3a66a
--- /dev/null
+++ b/src/library/scala/collection/mutable/MapProxy.scala
@@ -0,0 +1,53 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This is a simple wrapper class for <code>scala.collection.mutable.Map</code>.
+ * 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 scala.collection.MapProxy[A, B] {
+
+ def self: Map[A, B];
+
+ def update(key: A, value: B): Unit = self.update(key, value);
+
+ override def ++=(map: Iterable[Pair[A, B]]): Unit = self ++= map;
+
+ override def ++=(it: Iterator[Pair[A, B]]): Unit = self ++= it;
+
+ override def incl(mappings: Pair[A, B]*): Unit = self ++= mappings;
+
+ def -=(key: A): Unit = self -= key;
+
+ override def --=(keys: Iterable[A]): Unit = self --= keys;
+
+ override def --=(it: Iterator[A]): Unit = self --= it;
+
+ override def excl(keys: A*): Unit = self --= keys;
+
+ override def clear: Unit = self.clear;
+
+ override def map(f: (A, B) => B): Unit = self.map(f);
+
+ override def filter(p: (A, B) => Boolean): Unit = self.filter(p);
+
+ override def toString() = self.toString();
+
+ override def mappingToString(p: Pair[A, B]) = self.mappingToString(p);
+
+ override def <<(cmd: Message[Pair[A, B]]): Unit = self << cmd;
+
+ override def clone(): Map[A, B] = new MapProxy[A, B] { def self = MapProxy.this.self.clone() }
+}
diff --git a/src/library/scala/collection/mutable/Message.scala b/src/library/scala/collection/mutable/Message.scala
new file mode 100644
index 0000000000..bd805c5d6e
--- /dev/null
+++ b/src/library/scala/collection/mutable/Message.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** Class <code>Message</code> represents messages that are issued by observable
+ * collection classes whenever a data structure is changed. Class <code>Message</code>
+ * has several subclasses for the various kinds of events: <code>Update</code>
+ * <code>Remove</code>, <code>Include</code>, <code>Reset</code>, and
+ * <code>Script</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Message[+A];
+
+/** This observable update refers to inclusion operations that add new elements
+ * to collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Include[+I](elem: I) extends Message[I];
+
+/** This observable update refers to destructive modification operations
+ * of elements from collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Update[+A](elem: A) extends Message[A];
+
+/** This observable update refers to removal operations of elements
+ * from collection classes.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Remove[+A](elem: A) extends Message[A];
+
+/** This command refers to reset operations.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+case class Reset[+A]() extends Message[A];
+
+/** Objects of this class represent compound messages consisting
+ * of a sequence of other messages.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+class Script[A] extends ArrayBuffer[Message[A]] with Message[A] {
+
+ override def toString(): String = {
+ var res = "Script(";
+ var it = elements;
+ var i = 1;
+ while (it.hasNext) {
+ if (i > 1)
+ res = res + ", ";
+ res = res + "[" + i + "] " + it.next;
+ i = i + 1;
+ }
+ res + ")";
+ }
+
+ override def hashCode(): Int = error("scripts are not suitable as hash keys");
+}
diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala
new file mode 100644
index 0000000000..0569d0b0c9
--- /dev/null
+++ b/src/library/scala/collection/mutable/MultiMap.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+/** This class is typically used as a mixin. It turns maps which map <code>A</code>
+ * to <code>Set[B]</code> objects into multi maps which map <code>A</code> to
+ * <code>B</code> objects.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait MultiMap[A, B] extends scala.collection.mutable.Map[A, scala.collection.mutable.Set[B]] {
+ protected def makeSet: scala.collection.mutable.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/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala
new file mode 100644
index 0000000000..37bb9ada63
--- /dev/null
+++ b/src/library/scala/collection/mutable/MutableList.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class is used internally to represent mutable lists. It is the
+ * basis for the implementation of the classes <code>Buffer</code>,
+ * <code>Stack</code>, and <code>Queue</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class MutableList[A] extends Seq[A] with PartialFunction[Int, A] {
+
+ protected var first: LinkedList[A] = null;
+ protected var last: LinkedList[A] = null;
+ protected var len: Int = 0;
+
+ /** Returns the length of this list.
+ */
+ def length: Int = len;
+
+ /** Returns the <code>n</code>th element of this list. This method
+ * yields an error if the element does not exist.
+ */
+ def apply(n: Int): A = get(n) match {
+ case None => error("element not found")
+ case Some(value) => value
+ }
+
+ /** Returns the <code>n</code>th element of this list or <code>None</code>
+ * if this element does not exist.
+ */
+ def get(n: Int): Option[A] = first.get(n);
+
+ protected def prependElem(elem: A): Unit = {
+ first = new LinkedList[A](elem, first);
+ if (len == 0)
+ last = first;
+ len = len + 1;
+ }
+
+ protected def appendElem(elem: A): Unit = {
+ if (len == 0)
+ prependElem(elem);
+ else {
+ last.next = new LinkedList[A](elem, null);
+ last = last.next;
+ len = len + 1;
+ }
+ }
+
+ protected def reset: Unit = {
+ first = null;
+ last = null;
+ len = 0;
+ }
+
+ /** Returns an iterator over all elements of this list.
+ */
+ def elements: Iterator[A] =
+ if (first == null) Nil.elements else first.elements;
+
+ /** Returns an instance of <code>scala.List</code> containing the same
+ * sequence of elements.
+ */
+ override def toList: List[A] = if (first == null) Nil else first.toList;
+
+ override protected def stringPrefix: String = "MutableList";
+}
diff --git a/src/library/scala/collection/mutable/ObservableBuffer.scala b/src/library/scala/collection/mutable/ObservableBuffer.scala
new file mode 100644
index 0000000000..e3439b1dff
--- /dev/null
+++ b/src/library/scala/collection/mutable/ObservableBuffer.scala
@@ -0,0 +1,74 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Buffer</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableBuffer</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class ObservableBuffer[A, This <: ObservableBuffer[A, This]]: This
+ extends Buffer[A]
+ with Publisher[Message[Pair[Location, A]] with Undoable, This] {
+
+ abstract override def +(element: A): Buffer[A] = {
+ super.+(element);
+ publish(new Include(Pair(End, element)) with Undoable {
+ def undo: Unit = trimEnd(1);
+ });
+ this
+ }
+
+ abstract override def +:(element: A): Buffer[A] = {
+ super.+:(element);
+ publish(new Include(Pair(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(Pair(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(Pair(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(Pair(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 = error("cannot undo"); });
+ }
+}
diff --git a/src/library/scala/collection/mutable/ObservableMap.scala b/src/library/scala/collection/mutable/ObservableMap.scala
new file mode 100644
index 0000000000..207a294753
--- /dev/null
+++ b/src/library/scala/collection/mutable/ObservableMap.scala
@@ -0,0 +1,48 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Map</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableMap</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class ObservableMap[A, B, This <: ObservableMap[A, B, This]]: This
+ extends scala.collection.mutable.Map[A, B]
+ with Publisher[Message[Pair[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(Pair(key, value)) with Undoable {
+ def undo = -=(key);
+ });
+ case Some(old) => super.update(key, value);
+ publish(new Update(Pair(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(Pair(key, old)) with Undoable {
+ def undo = update(key, old);
+ });
+ }
+
+ abstract override def clear: Unit = {
+ super.clear;
+ publish(new Reset with Undoable { def undo: Unit = error("cannot undo"); });
+ }
+}
diff --git a/src/library/scala/collection/mutable/ObservableSet.scala b/src/library/scala/collection/mutable/ObservableSet.scala
new file mode 100644
index 0000000000..656545d78e
--- /dev/null
+++ b/src/library/scala/collection/mutable/ObservableSet.scala
@@ -0,0 +1,39 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class is typically used as a mixin. It adds a subscription
+ * mechanism to the <code>Set</code> class into which this abstract
+ * class is mixed in. Class <code>ObservableSet</code> publishes
+ * events of the type <code>Message</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class ObservableSet[A, This <: ObservableSet[A, This]]: This
+ extends scala.collection.mutable.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 = error("cannot undo"); });
+ }
+}
diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala
new file mode 100644
index 0000000000..83552417cc
--- /dev/null
+++ b/src/library/scala/collection/mutable/PriorityQueue.scala
@@ -0,0 +1,180 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class implements priority queues using a heap. The
+ * elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> trait.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+//[serializable, cloneable]
+class PriorityQueue[A <% Ordered[A]] extends ResizableArray[A] with java.io.Serializable {
+ 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.
+ */
+ 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;
+ }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements;
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach { e => this += e };
+
+ /** 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.
+ *
+ * @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
+ error("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 error("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);
+ java.lang.System.arraycopy(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 Pair(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 = error("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 list of all elements.
+ */
+ def toList: List[A] = elements.toList;
+
+ /** 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/library/scala/collection/mutable/PriorityQueueProxy.scala b/src/library/scala/collection/mutable/PriorityQueueProxy.scala
new file mode 100644
index 0000000000..e78b98065f
--- /dev/null
+++ b/src/library/scala/collection/mutable/PriorityQueueProxy.scala
@@ -0,0 +1,94 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class implements priority queues using a heap. The
+ * elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> trait.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+abstract class PriorityQueueProxy[A <% Ordered[A]] extends PriorityQueue[A] with IterableProxy[A] {
+
+ def self: PriorityQueue[A];
+
+ /** Creates a new iterator over all elements contained in this
+ * object.
+ *
+ * @return the new iterator
+ */
+ override def elements: Iterator[A] = self.elements;
+
+ /** Returns the length of this priority queue.
+ */
+ override def length: Int = self.length;
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = self.isEmpty;
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = self += elem;
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter;
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it;
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = self ++= elems;
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue: A = self.dequeue;
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def max: A = self.max;
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear: Unit = self.clear;
+
+ /** Returns a regular queue containing the same elements.
+ */
+ override def toQueue: Queue[A] = self.toQueue;
+
+ /** This method clones the priority queue.
+ *
+ * @return a priority queue with the same elements.
+ */
+ override def clone(): PriorityQueue[A] = new PriorityQueueProxy[A] { def self = PriorityQueueProxy.this.self.clone() }
+}
diff --git a/src/library/scala/collection/mutable/Publisher.scala b/src/library/scala/collection/mutable/Publisher.scala
new file mode 100644
index 0000000000..ee442eccd2
--- /dev/null
+++ b/src/library/scala/collection/mutable/Publisher.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** <code>Publisher[A,This]</code> objects publish events of type <code>A</code>
+ * to all registered subscribers. When subscribing, a subscriber may specify
+ * a filter which can be used to constrain the number of events sent to the
+ * subscriber. Subscribers may suspend their subscription, or reactivate a
+ * suspended subscription. Class <code>Publisher</code> is typically used
+ * as a mixin. The type variable <code>This</code> models self types.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[_trait_] abstract class Publisher[A, This <: Publisher[A, This]]: 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/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala
new file mode 100644
index 0000000000..0d297f5e0d
--- /dev/null
+++ b/src/library/scala/collection/mutable/Queue.scala
@@ -0,0 +1,194 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+[serializable, cloneable]
+class Queue[A] extends MutableList[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ def isEmpty: Boolean = (first == null);
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ def +=(elem: A): Unit = appendElem(elem);
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements;
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param it an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach appendElem;
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ def enqueue(elems: A*): Unit = (this ++= elems);
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @return the first element of the queue.
+ */
+ def dequeue: A = {
+ if (first == null)
+ error("queue empty");
+ else {
+ val res = first.elem;
+ first = first.next;
+ if (first == 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 == null)
+ None
+ else if (p(first.elem)) {
+ val res: Option[A] = Some(first.elem);
+ first = first.next;
+ len = len - 1;
+ if (first == null) {
+ last = null;
+ } else if (first.next == 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 == null)
+ res;
+ else {
+ while (p(first.elem)) {
+ res += first.elem;
+ first = first.next;
+ len = len - 1;
+ if (first == null) {
+ last = null;
+ } else if (first.next == 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 != null) && !p(cell.next.elem)) {
+ cell = cell.next;
+ }
+ if (cell.next == null)
+ None
+ else {
+ val res: Option[LinkedList[A]] = Some(cell.next);
+ cell.next = cell.next.next;
+ if (cell.next == 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 Pair(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 = error("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/library/scala/collection/mutable/QueueProxy.scala b/src/library/scala/collection/mutable/QueueProxy.scala
new file mode 100644
index 0000000000..65c426a9c2
--- /dev/null
+++ b/src/library/scala/collection/mutable/QueueProxy.scala
@@ -0,0 +1,97 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** <code>Queue</code> objects implement data structures that allow to
+ * insert and retrieve elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 03/05/2004
+ */
+trait QueueProxy[A] extends Queue[A] with SeqProxy[A] {
+
+ def self: Queue[A];
+
+ /** Access element number <code>n</code>.
+ *
+ * @return the element at index <code>n</code>.
+ */
+ override def apply(n: Int): A = self.apply(n);
+
+ /** Returns the length of this queue.
+ */
+ override def length: Int = self.length;
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = self.isEmpty;
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = self += elem;
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter;
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it;
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = self ++= elems;
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @return the first element of the queue.
+ */
+ override def dequeue: A = self.dequeue;
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @return the first element.
+ */
+ override def front: A = self.front;
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear: Unit = self.clear;
+
+ /** Returns an iterator over all elements on the queue.
+ *
+ * @return an iterator over all queue elements.
+ */
+ override def elements: Iterator[A] = self.elements;
+
+ /** This method clones the queue.
+ *
+ * @return a queue with the same elements.
+ */
+ override def clone(): Queue[A] = new QueueProxy[A] { def self = QueueProxy.this.self.clone() }
+}
diff --git a/src/library/scala/collection/mutable/ResizableArray.scala b/src/library/scala/collection/mutable/ResizableArray.scala
new file mode 100644
index 0000000000..5f1c5f053c
--- /dev/null
+++ b/src/library/scala/collection/mutable/ResizableArray.scala
@@ -0,0 +1,64 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class is used internally to implement data structures that
+ * are based on resizable arrays.
+ *
+ * @author Matthias Zenger, Burak Emir
+ * @version 1.0, 03/05/2004
+ */
+[serializable]
+[_trait_] abstract class ResizableArray[A] extends AnyRef with Iterable[A] {
+ import scala.runtime.compat.Platform.arraycopy;
+
+ protected val initialSize: Int = 16;
+ protected var array: Array[A] = new Array[A](initialSize);
+ protected var size: Int = 0;
+
+ /** 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);
+ arraycopy(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) = {
+ arraycopy(array, m, array, n, len);
+ }
+
+ /** Returns the length of this resizable array.
+ */
+ def length: Int = 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) }
+ }
+}
diff --git a/src/library/scala/collection/mutable/RevertableHistory.scala b/src/library/scala/collection/mutable/RevertableHistory.scala
new file mode 100644
index 0000000000..c9bb1ef6d1
--- /dev/null
+++ b/src/library/scala/collection/mutable/RevertableHistory.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** A revertable history is a <code>History</code> object which supports
+ * an undo operation. Type variable <code>A</code> refers to the type
+ * of the published events, <code>B</code> denotes the publisher type.
+ * Type <code>B</code> is typically a subtype of <code>Publisher</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+class RevertableHistory[A <: Undoable, B] extends History[A, B] with Undoable {
+
+ /** Rollback the full history.
+ */
+ def undo: Unit = {
+ val old = log.toList.reverse;
+ clear;
+ old.foreach { case Pair(sub, event) => event.undo; }
+ }
+}
diff --git a/src/library/scala/collection/mutable/Scriptable.scala b/src/library/scala/collection/mutable/Scriptable.scala
new file mode 100644
index 0000000000..448109bde3
--- /dev/null
+++ b/src/library/scala/collection/mutable/Scriptable.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** Classes that implement the <code>Scriptable</code> trait 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/library/scala/collection/mutable/Set.scala b/src/library/scala/collection/mutable/Set.scala
new file mode 100644
index 0000000000..d493ee1560
--- /dev/null
+++ b/src/library/scala/collection/mutable/Set.scala
@@ -0,0 +1,111 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This trait represents mutable sets. Concrete set implementations
+ * just have to provide functionality for the abstract methods in
+ * <code>scala.collection.Set</code> as well as for <code>add</code>,
+ * <code>remove</code>, and <code>clear</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.1, 09/05/2004
+ */
+[cloneable]
+trait Set[A] extends AnyRef with scala.collection.Set[A] with Scriptable[Message[A]] {
+
+ /** This method allows one to add or remove an element <code>elem</code>
+ * from this set depending on the value of parameter <code>included</code>.
+ * Typically, one would use the following syntax:
+ * <pre>set(elem) = true</pre>
+ */
+ def update(elem: A, included: Boolean): Unit =
+ if (included) +=(elem) else -=(elem);
+
+ /** This method adds a new element to the set.
+ */
+ def +=(elem: A): Unit;
+
+ /** This method will add all the elements provided by an iterator
+ * of the iterable object <code>that</code> to the set.
+ */
+ def ++=(that: Iterable[A]): Unit = ++=(that.elements);
+
+ /** This method will add all the elements provided by an iterator
+ * of the iterable object <code>that</code> to the set.
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach +=;
+
+ /** <code>incl</code> can be used to add many elements to the set
+ * at the same time.
+ */
+ def incl(elems: A*): Unit = ++=(elems.elements);
+
+ /** <code>-=</code> can be used to remove a single element from
+ * a set.
+ */
+ def -=(elem: A): Unit;
+
+ /** This method removes all the elements provided by the
+ * the iterable object <code>that</code> from the set.
+ */
+ def --=(that: Iterable[A]): Unit = --=(that.elements);
+
+ /** This method removes all the elements provided by an iterator
+ * <code>it</code> from the set.
+ */
+ def --=(it: Iterator[A]): Unit = it foreach -=;
+
+ /** <code>excl</code> removes many elements from the set.
+ */
+ def excl(elems: A*): Unit = --=(elems.elements);
+
+ /** This method computes an intersection with set <code>that</code>.
+ * It removes all the elements that are not present in <code>that</code>.
+ */
+ def intersect(that: Set[A]): Unit = filter(that.contains);
+
+ /** Method <code>filter</code> removes all elements from the set for
+ * which the predicate <code>p</code> yields the value <code>false</code>.
+ */
+ def filter(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;
+
+ /** Send a message to this scriptable object.
+ *
+ * @param cmd the message to send.
+ */
+ def <<(cmd: Message[A]): Unit = cmd match {
+ case Include(elem) => this += elem;
+ case Remove(elem) => this -= elem;
+ case Reset() => clear;
+ case s: Script[A] => s.elements foreach <<;
+ case _ => error("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]];
+
+ /** 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 = error("unsuitable as hash key");
+}
diff --git a/src/library/scala/collection/mutable/SetProxy.scala b/src/library/scala/collection/mutable/SetProxy.scala
new file mode 100644
index 0000000000..4cd759a60d
--- /dev/null
+++ b/src/library/scala/collection/mutable/SetProxy.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This is a simple wrapper class for <code>scala.collection.mutable.Set</code>.
+ * 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 scala.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);
+
+ def clear: Unit = self.clear;
+
+ override def filter(p: A => Boolean): Unit = 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/library/scala/collection/mutable/SingleLinkedList.scala b/src/library/scala/collection/mutable/SingleLinkedList.scala
new file mode 100644
index 0000000000..b60d32ba1b
--- /dev/null
+++ b/src/library/scala/collection/mutable/SingleLinkedList.scala
@@ -0,0 +1,63 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This extensible class may be used as a basis for implementing linked
+ * list. Type variable <code>A</code> refers to the element type of the
+ * list, type variable <code>This</code> is used to model self types of
+ * linked lists.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+[serializable]
+abstract class SingleLinkedList[A, This <: SingleLinkedList[A, This]]: This extends AnyRef with Seq[A] {
+
+ var elem: A = _;
+
+ var next: This = _;
+
+ def length: Int = 1 + (if (next == null) 0 else next.length);
+
+ def append(that: This): Unit =
+ if (next == null) { next = that; } else next.append(that);
+
+ def insert(that: This): Unit = if (that != null) {
+ that.append(next);
+ next = that;
+ }
+
+ def apply(n: Int): A = {
+ if (n == 0) elem
+ else if (next == null) error("unknown element")
+ else next.apply(n - 1);
+ }
+
+ def get(n: Int): Option[A] = {
+ if (n == 0) Some(elem)
+ else if (next == null) None
+ else next.get(n - 1);
+ }
+
+ def elements: Iterator[A] = new Iterator[A] {
+ var elems = SingleLinkedList.this;
+ def hasNext = (elems != null);
+ def next = {
+ val res = elems.elem;
+ elems = elems.next;
+ res;
+ }
+ }
+
+ override def toList: List[A] =
+ if (next == null) (elem :: Nil) else (elem :: next.toList);
+
+}
diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala
new file mode 100644
index 0000000000..0cf269dba7
--- /dev/null
+++ b/src/library/scala/collection/mutable/Stack.scala
@@ -0,0 +1,132 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, 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
+ */
+ def isEmpty: Boolean = (first == null);
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ def +=(elem: A): Unit = prependElem(elem);
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ def ++=(iter: Iterable[A]): Unit = this ++= iter.elements;
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ def ++=(it: Iterator[A]): Unit = it foreach { e => prependElem(e) };
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ def push(elems: A*): Unit = (this ++= elems);
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @return the top element
+ */
+ def top: A = if (first == null) error("stack empty"); else first.elem;
+
+ /** Removes the top element from the stack.
+ */
+ def pop: A =
+ if (first != null) {
+ val res = first.elem;
+ first = first.next;
+ len = len - 1;
+ res
+ } else
+ error("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 Pair(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 = error("unsuitable as hash key");
+
+ /** Returns a textual representation of a stack as a string.
+ *
+ * @return the string representation of this stack.
+ */
+ override def toString(): String = toList.mkString("Stack(", ", ", ")");
+
+ /** 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
+ }
+}
diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala
new file mode 100644
index 0000000000..cfca6ca56c
--- /dev/null
+++ b/src/library/scala/collection/mutable/StackProxy.scala
@@ -0,0 +1,108 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** A stack implements a data structure which allows to store and retrieve
+ * objects in a last-in-first-out (LIFO) fashion.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 10/05/2004
+ */
+trait StackProxy[A] extends Stack[A] with SeqProxy[A] {
+
+ def self: Stack[A];
+
+ /** Access element number <code>n</code>.
+ *
+ * @return the element at index <code>n</code>.
+ */
+ override def apply(n: Int): A = self.apply(n);
+
+ /** Returns the length of this stack.
+ */
+ override def length: Int = self.length;
+
+ /** Checks if the stack is empty.
+ *
+ * @return true, iff there is no element on the stack
+ */
+ override def isEmpty: Boolean = self.isEmpty;
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ override def +=(elem: A): Unit = self += elem;
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = self ++= iter;
+
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = self ++= it;
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ override def push(elems: A*): Unit = self ++= elems;
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @return the top element
+ */
+ override def top: A = self.top;
+
+ /** Removes the top element from the stack.
+ */
+ override def pop: A = self.pop;
+
+ /**
+ * Removes all elements from the stack. After this operation completed,
+ * the stack will be empty.
+ */
+ override def clear: Unit = self.clear;
+
+ /** Returns an iterator over all elements on the stack. This iterator
+ * is stable with respect to state changes in the stack object; i.e.
+ * such changes will not be reflected in the iterator. The iterator
+ * issues elements in the order they were inserted into the stack
+ * (FIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ override def elements: Iterator[A] = self.elements;
+
+ /** Creates a list of all stack elements in FIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = self.toList;
+
+ /** This method clones the stack.
+ *
+ * @return a stack with the same elements.
+ */
+ override def clone(): Stack[A] = new StackProxy[A] { def self = StackProxy.this.self.clone() }
+}
diff --git a/src/library/scala/collection/mutable/Subscriber.scala b/src/library/scala/collection/mutable/Subscriber.scala
new file mode 100644
index 0000000000..30ca2d03e2
--- /dev/null
+++ b/src/library/scala/collection/mutable/Subscriber.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** <code>Subscriber[A, B]</code> objects may subscribe to events of
+ * type <code>A</code> published by an object of type <code>B</code>.
+ * <code>B</code> is typically a subtype of <code>Publisher</code>.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Subscriber[-A, -B] {
+ def notify(pub: B, event: A): Unit;
+}
diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
new file mode 100644
index 0000000000..e15c59b4b4
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
@@ -0,0 +1,189 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This trait should be used as a mixin. It synchronizes the <code>Buffer</code>
+ * methods of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait SynchronizedBuffer[A] extends Buffer[A] {
+
+ abstract override def length: Int = synchronized {
+ super.length;
+ }
+
+ abstract override def elements: Iterator[A] = synchronized {
+ super.elements;
+ }
+
+ abstract override def apply(n: Int): A = synchronized {
+ super.apply(n);
+ }
+
+ /** Append a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ abstract override def +(elem: A): Buffer[A] = synchronized {
+ super.+(elem);
+ }
+
+ /** Append a single element to this buffer.
+ *
+ * @param elem the element to append.
+ */
+ override def +=(elem: A): Unit = synchronized {
+ super.+=(elem);
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++(iter: Iterable[A]): Buffer[A] = synchronized {
+ super.++(iter);
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized {
+ super.++=(iter);
+ }
+
+ /** Appends a sequence of elements to this buffer.
+ *
+ * @param elems the elements to append.
+ */
+ override def append(elems: A*): Unit = synchronized {
+ super.++=(elems);
+ }
+
+ /** Appends a number of elements provided by an iterable object
+ * via its <code>elements</code> method.
+ *
+ * @param iter the iterable object.
+ */
+ override def appendAll(iter: Iterable[A]): Unit = synchronized {
+ super.appendAll(iter);
+ }
+
+ /** Prepend a single element to this buffer and return
+ * the identity of the buffer.
+ *
+ * @param elem the element to append.
+ */
+ abstract override def +:(elem: A): Buffer[A] = synchronized {
+ super.+:(elem);
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def ++:(iter: Iterable[A]): Buffer[A] = synchronized {
+ super.++:(iter);
+ }
+
+ /** Prepend an element to this list.
+ *
+ * @param elem the element to prepend.
+ */
+ override def prepend(elems: A*): Unit = synchronized {
+ super.prependAll(elems);
+ }
+
+ /** Prepends a number of elements provided by an iterable object
+ * via its <code>elements</code> method. The identity of the
+ * buffer is returned.
+ *
+ * @param iter the iterable object.
+ */
+ override def prependAll(elems: Iterable[A]): Unit = synchronized {
+ super.prependAll(elems);
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert the new elements at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param elems the new elements to insert.
+ */
+ override def insert(n: Int, elems: A*): Unit = synchronized {
+ super.insertAll(n, elems);
+ }
+
+ /** Inserts new elements at the index <code>n</code>. Opposed to method
+ * <code>update</code>, this method will not replace an element with a
+ * one. Instead, it will insert a new element at index <code>n</code>.
+ *
+ * @param n the index where a new element will be inserted.
+ * @param iter the iterable object providing all elements to insert.
+ */
+ abstract override def insertAll(n: Int, iter: Iterable[A]): Unit = synchronized {
+ super.insertAll(n, iter);
+ }
+
+ /** Replace element at index <code>n</code> with the new element
+ * <code>newelem</code>.
+ *
+ * @param n the index of the element to replace.
+ * @param newelem the new element.
+ */
+ abstract override def update(n: Int, newelem: A): Unit = synchronized {
+ super.update(n, newelem);
+ }
+
+ /** Removes the element on a given index position.
+ *
+ * @param n the index which refers to the element to delete.
+ */
+ abstract override def remove(n: Int): A = synchronized {
+ super.remove(n);
+ }
+
+ /** Clears the buffer contents.
+ */
+ abstract override def clear: Unit = synchronized {
+ super.clear;
+ }
+
+ override def <<(cmd: Message[Pair[Location, A]]): Unit = synchronized {
+ super.<<(cmd);
+ }
+
+ /** Return a clone of this buffer.
+ *
+ * @return an <code>ArrayBuffer</code> with the same elements.
+ */
+ override def clone(): Buffer[A] = synchronized {
+ super.clone();
+ }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use buffers as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized {
+ super.hashCode();
+ }
+}
diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala
new file mode 100644
index 0000000000..b0db7078de
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedMap.scala
@@ -0,0 +1,116 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This trait should be used as a mixin. It synchronizes the <code>Map</code>
+ * functions of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait SynchronizedMap[A, B] extends scala.collection.mutable.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 values: Iterator[B] = synchronized {
+ super.values;
+ }
+
+ override def foreach(f: (A, B) => Unit) = synchronized {
+ super.foreach(f);
+ }
+
+ override def toList: List[Pair[A, B]] = synchronized {
+ super.toList;
+ }
+
+ abstract override def update(key: A, value: B): Unit = synchronized {
+ super.update(key, value);
+ }
+
+ override def ++=(map: Iterable[Pair[A, B]]): Unit = synchronized {
+ super.++=(map);
+ }
+
+ override def ++=(it: Iterator[Pair[A, B]]): Unit = synchronized {
+ super.++=(it);
+ }
+
+ override def incl(mappings: Pair[A, B]*): Unit = synchronized {
+ super.++=(mappings);
+ }
+
+ abstract override def -=(key: A): Unit = synchronized {
+ super.-=(key);
+ }
+
+ override def --=(keys: Iterable[A]): Unit = synchronized {
+ super.--=(keys);
+ }
+
+ override def --=(it: Iterator[A]): Unit = synchronized {
+ super.--=(it);
+ }
+
+ override def excl(keys: A*): Unit = synchronized {
+ super.--=(keys);
+ }
+
+ override def clear: Unit = synchronized {
+ super.clear;
+ }
+
+ override def map(f: (A, B) => B): Unit = synchronized {
+ super.map(f);
+ }
+
+ override def filter(p: (A, B) => Boolean): Unit = synchronized {
+ super.filter(p);
+ }
+
+ override def toString() = synchronized {
+ super.toString();
+ }
+
+ override def <<(cmd: Message[Pair[A, B]]): Unit = synchronized {
+ super.<<(cmd);
+ }
+
+ override def clone(): Map[A, B] = synchronized {
+ super.clone();
+ }
+}
diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
new file mode 100644
index 0000000000..8b3078e74b
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
@@ -0,0 +1,97 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This class implements synchronized priority queues using a heap.
+ * The elements of the queue have to be ordered in terms of the
+ * <code>Ordered[T]</code> trait.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedPriorityQueue[A <% Ordered[A]] extends PriorityQueue[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty; }
+
+ /** Inserts a single element into the priority queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem); }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * into the priority queue.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter); }
+
+ /** Adds all elements provided by an iterator into the priority queue.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it); }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = synchronized { super.++=(elems); }
+
+ /** Returns the element with the highest priority in the queue,
+ * and removes this element from the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def dequeue: A = synchronized { super.dequeue; }
+
+ /** Returns the element with the highest priority in the queue,
+ * or throws an error if there is no element contained in the queue.
+ *
+ * @return the element with the highest priority.
+ */
+ override def max: A = synchronized { super.max; }
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear: Unit = synchronized { super.clear; }
+
+ /** Returns an iterator which yiels all the elements of the priority
+ * queue in descending priority order.
+ *
+ * @return an iterator over all elements sorted in descending order.
+ */
+ override def elements: Iterator[A] = synchronized { super.elements; }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that); }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode(); }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString(): String = synchronized { super.toString(); }
+}
diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala
new file mode 100644
index 0000000000..74fb9782b5
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala
@@ -0,0 +1,93 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This is a synchronized version of the <code>Queue[T]</code> class. It
+ * implements a data structure that allows one to insert and retrieve
+ * elements in a first-in-first-out (FIFO) manner.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedQueue[A] extends Queue[A] {
+
+ /** Checks if the queue is empty.
+ *
+ * @return true, iff there is no element in the queue.
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty; }
+
+ /** Inserts a single element at the end of the queue.
+ *
+ * @param elem the element to insert
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem); }
+
+ /** Adds all elements provided by an <code>Iterable</code> object
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter); }
+
+ /** Adds all elements provided by an iterator
+ * at the end of the queue. The elements are prepended in the order they
+ * are given out by the iterator.
+ *
+ * @param it an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it); }
+
+ /** Adds all elements to the queue.
+ *
+ * @param elems the elements to add.
+ */
+ override def enqueue(elems: A*): Unit = synchronized { super.++=(elems); }
+
+ /** Returns the first element in the queue, and removes this element
+ * from the queue.
+ *
+ * @return the first element of the queue.
+ */
+ override def dequeue: A = synchronized { super.dequeue; }
+
+ /** Returns the first element in the queue, or throws an error if there
+ * is no element contained in the queue.
+ *
+ * @return the first element.
+ */
+ override def front: A = synchronized { super.front; }
+
+ /** Removes all elements from the queue. After this operation is completed,
+ * the queue will be empty.
+ */
+ override def clear: Unit = synchronized { super.clear; }
+
+ /** Checks if two queues are structurally identical.
+ *
+ * @return true, iff both queues contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that); }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable queues as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode(); }
+
+ /** Returns a textual representation of a queue as a string.
+ *
+ * @return the string representation of this queue.
+ */
+ override def toString() = synchronized { super.toString(); }
+}
diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala
new file mode 100644
index 0000000000..743a5a85c4
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedSet.scala
@@ -0,0 +1,104 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This trait should be used as a mixin. It synchronizes the <code>Set</code>
+ * functions of the class into which it is mixed in.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait SynchronizedSet[A] extends scala.collection.mutable.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);
+ }
+
+ override def filter(p: A => Boolean) = synchronized {
+ super.filter(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/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala
new file mode 100644
index 0000000000..c21a17b22d
--- /dev/null
+++ b/src/library/scala/collection/mutable/SynchronizedStack.scala
@@ -0,0 +1,109 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** This is a synchronized version of the <code>Stack[T]</code> class. It
+ * implements a data structure which allows to store and retrieve
+ * objects in a last-in-first-out (LIFO) fashion.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 03/05/2004
+ */
+class SynchronizedStack[A] extends Stack[A] {
+
+ /** Checks if the stack is empty.
+ *
+ * @return true, iff there is no element on the stack
+ */
+ override def isEmpty: Boolean = synchronized { super.isEmpty }
+
+ /** Pushes a single element on top of the stack.
+ *
+ * @param elem the element to push onto the stack
+ */
+ override def +=(elem: A): Unit = synchronized { super.+=(elem); }
+
+ /** Pushes all elements provided by an <code>Iterable</code> object
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterable object
+ */
+ override def ++=(iter: Iterable[A]): Unit = synchronized { super.++=(iter); }
+
+ /** Pushes all elements provided by an iterator
+ * on top of the stack. The elements are pushed in the order they
+ * are given out by the iterator.
+ *
+ * @param iter an iterator
+ */
+ override def ++=(it: Iterator[A]): Unit = synchronized { super.++=(it); }
+
+ /** Pushes a sequence of elements on top of the stack. The first element
+ * is pushed first, etc.
+ *
+ * @param elems a sequence of elements
+ */
+ override def push(elems: A*): Unit = synchronized { super.++=(elems); }
+
+ /** Returns the top element of the stack. This method will not remove
+ * the element from the stack. An error is signaled if there is no
+ * element on the stack.
+ *
+ * @return the top element
+ */
+ override def top: A = synchronized { super.top; }
+
+ /** Removes the top element from the stack.
+ */
+ override def pop: A = synchronized { super.pop; }
+
+ /**
+ * Removes all elements from the stack. After this operation completed,
+ * the stack will be empty.
+ */
+ override def clear: Unit = synchronized { super.clear; }
+
+ /** Returns an iterator over all elements on the stack. This iterator
+ * is stable with respect to state changes in the stack object; i.e.
+ * such changes will not be reflected in the iterator. The iterator
+ * issues elements in the order they were inserted into the stack
+ * (FIFO order).
+ *
+ * @return an iterator over all stack elements.
+ */
+ override def elements: Iterator[A] = synchronized { super.elements; }
+
+ /** Creates a list of all stack elements in FIFO order.
+ *
+ * @return the created list.
+ */
+ override def toList: List[A] = synchronized { super.toList; }
+
+ /** Checks if two stacks are structurally identical.
+ *
+ * @return true, iff both stacks contain the same sequence of elements.
+ */
+ override def equals(that: Any): Boolean = synchronized { super.equals(that); }
+
+ /** The hashCode method always yields an error, since it is not
+ * safe to use mutable stacks as keys in hash tables.
+ *
+ * @return never.
+ */
+ override def hashCode(): Int = synchronized { super.hashCode(); }
+
+ /** Returns a textual representation of a stack as a string.
+ *
+ * @return the string representation of this stack.
+ */
+ override def toString() = synchronized { super.toString(); }
+}
diff --git a/src/library/scala/collection/mutable/Undoable.scala b/src/library/scala/collection/mutable/Undoable.scala
new file mode 100644
index 0000000000..62e7335411
--- /dev/null
+++ b/src/library/scala/collection/mutable/Undoable.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.collection.mutable;
+
+
+/** Classes that implement the <code>Undoable</code> trait provide an operation
+ * <code>undo</code> which can be used to undo the last operation.
+ *
+ * @author Matthias Zenger
+ * @version 1.0, 08/07/2003
+ */
+trait Undoable {
+
+ /** Undo the last operation.
+ */
+ def undo: Unit;
+}
diff --git a/src/library/scala/concurrent/Actor.scala b/src/library/scala/concurrent/Actor.scala
new file mode 100644
index 0000000000..4ba4ab3078
--- /dev/null
+++ b/src/library/scala/concurrent/Actor.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.concurrent;
+
+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 (Thread.currentThread() == this) in.receive(f);
+ else error("receive called not on own process");
+
+ def receiveWithin[a](msec: long)(f: PartialFunction[in.Message, a]): a =
+ if (Thread.currentThread() == this) in.receiveWithin(msec)(f);
+ else error("receiveWithin called not on own process");
+}
+
+
+
diff --git a/src/library/scala/concurrent/Channel.scala b/src/library/scala/concurrent/Channel.scala
new file mode 100644
index 0000000000..a57fd7f530
--- /dev/null
+++ b/src/library/scala/concurrent/Channel.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.concurrent;
+
+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;
+
+ 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 (written.next == null) {
+ nreaders = nreaders + 1; wait(); nreaders = nreaders - 1;
+ }
+ val x = written.elem;
+ written = written.next;
+ x
+ }
+}
diff --git a/src/library/scala/concurrent/Lock.scala b/src/library/scala/concurrent/Lock.scala
new file mode 100644
index 0000000000..a473c358c8
--- /dev/null
+++ b/src/library/scala/concurrent/Lock.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+class Lock {
+ var available = true;
+ def acquire = synchronized {
+ if (!available) wait();
+ available = false
+ }
+ def release = synchronized {
+ available = true;
+ notify()
+ }
+}
diff --git a/src/library/scala/concurrent/MailBox.scala b/src/library/scala/concurrent/MailBox.scala
new file mode 100644
index 0000000000..427d424b28
--- /dev/null
+++ b/src/library/scala/concurrent/MailBox.scala
@@ -0,0 +1,170 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+//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 {
+ if (msg == null) wait();
+ receiver(msg)
+ }
+
+ def receiveWithin(msec: long): a = synchronized {
+ if (msg == null) wait(msec);
+ receiver(if (msg != 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(Pair(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(Pair(receiver, withoutReceiver)) => {
+ receivers = withoutReceiver;
+ receiver.msg = msg;
+ receiver synchronized { receiver.notify() };
+ }
+ }
+ }
+
+ /**
+ * Block until there is a message in the mailbox for which the processor
+ * <code>f</code> is defined.
+ */
+ def receive[a](f: PartialFunction[Message, a]): a = {
+ val r = new Receiver(f);
+ scanSentMsgs(r);
+ r.receive()
+ }
+
+ /**
+ * Block until there is a message in the mailbox for which the processor
+ * <code>f</code> is defined or the timeout is over.
+ */
+ def receiveWithin[a](msec: long)(f: PartialFunction[Message, a]): a = {
+ val r = new Receiver(f);
+ scanSentMsgs(r);
+ r.receiveWithin(msec)
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////
+
+/**
+* Module for dealing with queues.
+*/
+trait QueueModule[a] {
+ /** Type of queues. */
+ type t;
+ /** Create an empty queue. */
+ def make: t;
+ /** Append an element to a queue. */
+ def append(l: t, x: a): t;
+ /** Extract an element satisfying a predicate from a queue. */
+ def extractFirst(l: t, p: a => boolean): Option[Pair[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[Pair[a, t]] =
+ l match {
+ case Nil => None
+ case head :: tail =>
+ if (p(head))
+ Some(Pair(head, tail))
+ else
+ extractFirst(tail, p) match {
+ case None => None
+ case Some(Pair(x, without_x)) => Some(Pair(x, head :: without_x))
+ }
+ }
+ }
+}
+
+/** Efficient queue module creator based on linked lists. */
+trait LinkedListQueueCreator {
+ import scala.collection.mutable.LinkedList;
+ def queueCreate[a <: AnyRef]: QueueModule[a] = new QueueModule[a] {
+ type t = Pair[LinkedList[a], LinkedList[a]]; // fst = the list, snd = last elem
+ def make: t = {
+ val l = new LinkedList[a](null, null);
+ Pair(l, l)
+ }
+ def append(l: t, x: a): t = {
+ val atTail = new LinkedList(x, null);
+ l._2 append atTail;
+ Pair(l._1, atTail)
+ }
+ def extractFirst(l: t, p: a => boolean): Option[Pair[a, t]] = {
+ var xs = l._1;
+ var xs1 = xs.next;
+ while (xs1 != null && !p(xs1.elem)) {
+ xs = xs1;
+ xs1 = xs1.next;
+ }
+ if (xs1 != null) {
+ xs.next = xs1.next;
+ if (xs.next == null)
+ Some(Pair(xs1.elem, Pair(l._1, xs)))
+ else
+ Some(Pair(xs1.elem, l))
+ }
+ else
+ None
+ }
+ }
+}
+
diff --git a/src/library/scala/concurrent/NameServer.scala b/src/library/scala/concurrent/NameServer.scala
new file mode 100644
index 0000000000..b7646e6deb
--- /dev/null
+++ b/src/library/scala/concurrent/NameServer.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+object NameServer {
+
+ val names = new scala.collection.mutable.HashMap[Symbol, Process];
+
+ def register(name: Symbol, proc: Process) = {
+ if (names.contains(name)) error("Name:" + name + " already registred");
+ names += name -> proc;
+ }
+
+ def unregister(name: Symbol) = {
+ if (names.contains(name))
+ names -= name;
+ else
+ error("Name:" + name + " not registred");
+ }
+
+ def whereis(name: Symbol): Option[Process] =
+ names.get(name);
+
+ def send(name: Symbol, msg: MailBox#Message) =
+ names(name).send(msg);
+
+}
diff --git a/src/library/scala/concurrent/Process.scala b/src/library/scala/concurrent/Process.scala
new file mode 100644
index 0000000000..950220da35
--- /dev/null
+++ b/src/library/scala/concurrent/Process.scala
@@ -0,0 +1,78 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+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);
+
+ def self: Process = {
+ if (Thread.currentThread().isInstanceOf[Process])
+ Thread.currentThread().asInstanceOf[Process]
+ else error("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(Tuple3('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/library/scala/concurrent/SyncChannel.scala b/src/library/scala/concurrent/SyncChannel.scala
new file mode 100644
index 0000000000..6cab7b2ad6
--- /dev/null
+++ b/src/library/scala/concurrent/SyncChannel.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+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/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala
new file mode 100644
index 0000000000..0e1b9fd38c
--- /dev/null
+++ b/src/library/scala/concurrent/SyncVar.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+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/library/scala/concurrent/TIMEOUT.scala b/src/library/scala/concurrent/TIMEOUT.scala
new file mode 100644
index 0000000000..d665fdf649
--- /dev/null
+++ b/src/library/scala/concurrent/TIMEOUT.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+case class TIMEOUT();
diff --git a/src/library/scala/concurrent/jolib.scala b/src/library/scala/concurrent/jolib.scala
new file mode 100644
index 0000000000..08611be513
--- /dev/null
+++ b/src/library/scala/concurrent/jolib.scala
@@ -0,0 +1,75 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+/**
+* Library for using join-calculus concurrent primitives in Scala.
+*/
+object jolib {
+
+ type Pattern = List[Signal];
+
+ type Rule = PartialFunction[List[Any], unit];
+
+ /////////////////// JOIN DEFINITION /////////////////////////
+
+ class Join {
+
+ private var ruls: List[Pair[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: Pair[Pattern, Rule]*) =
+ ruls = rs.asInstanceOf[List[Pair[Pattern, Rule]]];
+
+ def tryMatch =
+ (ruls find { case Pair(p, _) => canMatch(p) }) match {
+ case None => () => ();
+ case Some(Pair(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/library/scala/concurrent/ops.scala b/src/library/scala/concurrent/ops.scala
new file mode 100644
index 0000000000..04bee676ec
--- /dev/null
+++ b/src/library/scala/concurrent/ops.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-04, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.concurrent;
+
+
+object ops {
+
+ def spawn(p: => Unit) = {
+ val t = new Thread() { override def run() = p; }
+ t.start()
+ }
+
+ def future[a](p: => a): () => a = {
+ val result = new SyncVar[a];
+ spawn { result set p }
+ () => result.get
+ }
+
+ def par[a, b](xp: => a, yp: => b): Pair[a, b] = {
+ val y = new SyncVar[b];
+ spawn { y set yp }
+ Pair(xp, y.get)
+ }
+
+ 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/library/scala/concurrent/pilib.scala b/src/library/scala/concurrent/pilib.scala
new file mode 100644
index 0000000000..6ce7a560af
--- /dev/null
+++ b/src/library/scala/concurrent/pilib.scala
@@ -0,0 +1,189 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, 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 <b>pilib</b> library looks like:
+*<pre>
+*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
+*}
+*</pre>
+*
+* @see <a href="http://scala.epfl.ch/docu/related.html">PiLib: A Hosted Language for Pi-Calculus Style Concurrency</a>
+* @author Vincent Cremet, Martin Odersky
+*/
+object pilib {
+
+ /////////////////////////// SPAWN //////////////////////////////
+
+ /**
+ * Run several processes in parallel using the following syntax:
+ * spawn &lt; p_1 | ... | p_n &gt;
+ */
+ trait 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. */
+ 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. */
+ private def matches(gs1: List[UGP], gs2: List[UGP]): Option[Triple[() => unit, () => Any, () => Any]] =
+ Pair(gs1, gs2) match {
+ case Pair(Nil, _) => None
+ case Pair(_, Nil) => None
+ case Pair(UGP(a1, d1, v1, c1) :: rest1, UGP(a2, d2, v2, c2) :: rest2) =>
+ if (a1 == a2 && d1 == !d2)
+ Some(Triple(() => 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.
+ */
+ 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(Triple(log, c1, c2)) => {
+ log();
+ s1.set(c1);
+ s2.set(c2);
+ rest
+ }
+ }
+ }
+
+ /** Pi-calculus non-deterministic choice. */
+ def choice[a](s: GP[a]*): a = {
+ val sum = Sum(s.asInstanceOf[List[GP[a]]] map { x => x.untyped });
+ synchronized { sums = compare(sum, sums) };
+ (sum.continue).asInstanceOf[a]
+ }
+
+
+}
+
diff --git a/src/library/scala/dbc/DataType.scala b/src/library/scala/dbc/DataType.scala
new file mode 100644
index 0000000000..b984169350
--- /dev/null
+++ b/src/library/scala/dbc/DataType.scala
@@ -0,0 +1,66 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+/** An ISO-9075:2003 (SQL) data type. Mappings between SQL types and
+ * database specific types should be provided by the database driver.
+ */
+abstract class DataType {
+
+ /** Tests whether this datatype is equivalent to another. Usually, two
+ * types are defined as equivalent if they are equal. Two types can be
+ * equivalent without being equal if values of those types will be
+ * encoded in the same native Scala type.
+ */
+ def isEquivalent(datatype: DataType): Boolean;
+
+ /** Tests whether this datatype is equivalent or a subtype of another
+ * datatype. Type <code>A</code> is said to be subtype of type
+ * <code>B</code> if any value of type <code>A</code> can be
+ * represented as a value of type <code>B</code>.
+ */
+ def isSubtypeOf(datatype: DataType): Boolean;
+
+ /** The native Scala type in which values of this SQL type will be
+ * encoded.
+ */
+ type NativeType <: Any;
+
+ /** The native Scala type in which values of this SQL type will be
+ * encoded. This must point to the same type as <code>NativeType</code>.
+ */
+ def nativeTypeId: DataType.Id;
+
+ /** Whether the value can take the null value, None when this property is
+ * unknown.
+ */
+ def nullable: Option[Boolean] = None;
+
+ /** The SQL name of the type */
+ def sqlString: String = "UNDEFINED DATA TYPE"
+
+}
+
+object DataType {
+
+ type Id = Int;
+
+ val OBJECT : Id = 10;
+ val BOOLEAN : Id = 20;
+ val BYTE : Id = 30;
+ val SHORT : Id = 31;
+ val INT : Id = 32;
+ val LONG : Id = 33;
+ val BIG_INTEGER: Id = 34;
+ val BIG_DECIMAL: Id = 35;
+ val FLOAT : Id = 40;
+ val DOUBLE : Id = 41;
+ val STRING : Id = 50;
+
+}
diff --git a/src/library/scala/dbc/Database.scala b/src/library/scala/dbc/Database.scala
new file mode 100644
index 0000000000..28270184b5
--- /dev/null
+++ b/src/library/scala/dbc/Database.scala
@@ -0,0 +1,186 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+import java.sql._;
+
+/** A link to a database. The <code>Database</code> abstract class must
+ * be specialised for every different DBMS.
+ *
+ * @author Gilles Dubochet
+ */
+case class Database(dbms: Vendor) {
+
+ class Closed extends Exception;
+
+ /** A lock used for operations that need to be atomic for this database
+ * instance. */
+ private val lock: scala.concurrent.Lock = new scala.concurrent.Lock();
+
+ /** The vendor of the DBMS that contains this database. */
+ private val vendor: Vendor = dbms;
+
+ /** The Database connections available to use. */
+ private var availableConnections: List[Connection] = Nil;
+
+ /** The connections that are currently in use. */
+ private var usedConnections: List[Connection] = Nil;
+
+ /** Whether the database no longer accepts new connections. */
+ private var closing: Boolean = false;
+
+ /** Retrieves a connection from the available connection pool or creates
+ * a new one.
+ *
+ * @returns A connection that can be used to access the database.
+ */
+ private def getConnection: Connection = {
+ if (closing) {
+ throw new Closed;
+ } else {
+ availableConnections match {
+ case Nil => {
+ lock.acquire;
+ val connection = vendor.getConnection;
+ usedConnections = connection :: usedConnections;
+ lock.release;
+ connection
+ }
+ case connection :: cs => {
+ lock.acquire;
+ availableConnections = cs;
+ usedConnections = connection :: usedConnections;
+ lock.release;
+ connection;
+ }
+ }
+ }
+ }
+
+ /** Closes a connection to this database. A closed connection might
+ * also return to the available connection pool if the latter is depleted.
+ *
+ * @param connection The connection that should be closed.
+ */
+ private def closeConnection(connection: Connection): Unit = {
+ if (closing) {
+ connection.close();
+ } else {
+ lock.acquire;
+ usedConnections = usedConnections.remove(e => (e.equals(connection)));
+ if (availableConnections.length < vendor.retainedConnections)
+ availableConnections = connection :: availableConnections
+ else
+ connection.close();
+ lock.release;
+ }
+ }
+
+ /** ..
+ */
+ def close: Unit = {
+ closing = true;
+ for (val conn <- availableConnections) conn.close();
+ }
+
+ /** Executes a statement that returns a relation on this database.
+ *
+ * @param relationStatement The statement to execute.
+ * @return The relation returned by the database for this statement.
+ */
+ def executeStatement(relationStatement: statement.Relation): result.Relation =
+ executeStatement(relationStatement, false);
+
+ /** Executes a statement that returns a relation on this database.
+ *
+ * @param relationStatement The statement to execute.
+ * @param debug Whether debugging information should be printed on the console.
+ * @return The relation returned by the database for this statement.
+ */
+ def executeStatement(relationStatement: statement.Relation,
+ debug: Boolean): result.Relation =
+ new scala.dbc.result.Relation {
+ val statement = relationStatement;
+ if (debug) Console.println("## " + statement.sqlString);
+ private val connection = getConnection;
+ val sqlResult = connection.createStatement().executeQuery(statement.sqlString);
+ closeConnection(connection);
+ statement.typeCheck(this);
+ }
+
+ /** Executes a statement that updates the state of the database.
+ *
+ * @param statusStatement The statement to execute.
+ * @return The status of the database after the statement has been executed.
+ */
+ def executeStatement(statusStatement: statement.Status): result.Status[Unit] =
+ executeStatement(statusStatement, false);
+
+ /** Executes a statement that updates the state of the database.
+ *
+ * @param statusStatement The statement to execute.
+ * @param debug Whether debugging information should be printed on the console.
+ * @return The status of the database after the statement has been executed.
+ */
+ def executeStatement(statusStatement: statement.Status,
+ debug: Boolean): result.Status[Unit] =
+ new scala.dbc.result.Status[Unit] {
+ val statement = statusStatement;
+ if (debug) Console.println("## " + statement.sqlString);
+ def result = ();
+ private val connection = getConnection;
+ val jdbcStatement: java.sql.Statement = connection.createStatement();
+ jdbcStatement.execute(statement.sqlString);
+ val touchedCount = Some(jdbcStatement.getUpdateCount());
+ closeConnection(connection);
+ }
+
+ /** Executes a list of statements or other operations inside a transaction.
+ * Only statements are protected in a transaction, other Scala code is not.
+ *
+ * @param transactionStatement The transaction to execute as a closure.
+ * @return The status of the database after the transaction has been executed.
+ */
+ def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType]): result.Status[ResultType] =
+ executeStatement(transactionStatement, false);
+
+ /** Executes a list of statements or other operations inside a transaction.
+ * Only statements are protected in a transaction, other Scala code is not.
+ *
+ * @param transactionStatement The transaction to execute as a closure.
+ * @param debug Whether debugging information should be printed on the console.
+ * @return The status of the database after the transaction has been executed.
+ */
+ def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType], debug: Boolean): result.Status[ResultType] = {
+ new scala.dbc.result.Status[ResultType] {
+ val touchedCount = None;
+ val statement = transactionStatement;
+ private val connection = getConnection;
+ connection.setAutoCommit(false);
+ val jdbcStatement: java.sql.Statement = connection.createStatement();
+ if (debug) Console.println("## " + transactionStatement.sqlStartString);
+ jdbcStatement.execute(transactionStatement.sqlStartString);
+ val result: ResultType = try {
+ val buffer = transactionStatement.transactionBody(Database.this);
+ if (debug) Console.println("## " + transactionStatement.sqlCommitString);
+ jdbcStatement.execute(transactionStatement.sqlCommitString);
+ buffer
+ } catch {
+ case e: Throwable => {
+ if (debug) Console.println("## " + transactionStatement.sqlAbortString);
+ jdbcStatement.execute(transactionStatement.sqlAbortString);
+ throw e;
+ }
+ }
+ connection.setAutoCommit(true);
+ closeConnection(connection);
+ }
+ }
+
+}
diff --git a/src/library/scala/dbc/Syntax.scala b/src/library/scala/dbc/Syntax.scala
new file mode 100644
index 0000000000..cde8112979
--- /dev/null
+++ b/src/library/scala/dbc/Syntax.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API tests **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+import java.math.{BigDecimal, BigInteger};
+
+
+/** This class ..
+ *
+ */
+object Syntax {
+
+ import syntax.DataTypeUtil;
+
+ /* Data types */
+ def boolean = DataTypeUtil.boolean;
+ def tinyint = DataTypeUtil.tinyint;
+ def smallint = DataTypeUtil.smallint;
+ def integer = DataTypeUtil.integer;
+ def bigint = DataTypeUtil.bigint;
+ def real = DataTypeUtil.real;
+
+ def numeric(precision: Int) = DataTypeUtil.numeric(precision);
+ def numeric(precision: Int, scale: Int) = DataTypeUtil.numeric(precision, scale);
+
+ def doublePrecision = DataTypeUtil.doublePrecision;
+ def character(length: Int) = DataTypeUtil.character(length);
+ def characterVarying(length: Int) = DataTypeUtil.characterVarying(length);
+ def characterLargeObject = DataTypeUtil.characterLargeObject;
+
+ /* Statements */
+ //def select
+
+ /* Other stuff */
+ def database (server: String, username: String, password: String): dbc.Database =
+ syntax.Database.database(server, username, password);
+
+}
diff --git a/src/library/scala/dbc/Utilities.scala b/src/library/scala/dbc/Utilities.scala
new file mode 100644
index 0000000000..46ca27a019
--- /dev/null
+++ b/src/library/scala/dbc/Utilities.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+/** An object offering transformation methods (views) on various values.
+ * This object's members must be visible in an expression to use value
+ * auto-conversion.
+ */
+object Utilities {
+
+ def view (obj: statement.expression.Constant): Value =
+ obj.constantValue;
+
+ def view (obj: Value): statement.expression.Constant =
+ new statement.expression.Constant {
+ val constantValue = obj;
+ }
+
+}
diff --git a/src/library/scala/dbc/Value.scala b/src/library/scala/dbc/Value.scala
new file mode 100644
index 0000000000..3ab2d0cbe5
--- /dev/null
+++ b/src/library/scala/dbc/Value.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+/** A SQL-99 value of any type. */
+abstract class Value {
+
+ /** The SQL-99 type of the value. */
+ val dataType: DataType;
+
+ type NativeType = dataType.type#NativeType;
+
+ val nativeValue: NativeType;
+
+ /** A SQL-99 compliant string representation of the value. */
+ def sqlString: String;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/Vendor.scala b/src/library/scala/dbc/Vendor.scala
new file mode 100644
index 0000000000..db44ddec42
--- /dev/null
+++ b/src/library/scala/dbc/Vendor.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc;
+
+import java.sql.{Connection, Driver};
+
+
+/** This class ..
+ */
+abstract class Vendor {
+
+ def nativeDriverClass: Class;
+ def uri: java.net.URI;
+ def user: String;
+ def pass: String;
+ def nativeProperties: java.util.Properties = {
+ val properties = new java.util.Properties();
+ properties.setProperty("user", user);
+ properties.setProperty("password", pass);
+ properties
+ }
+
+ def retainedConnections: Int;
+
+ def getConnection: Connection = {
+ val driver = nativeDriverClass.newInstance().asInstanceOf[Driver];
+ driver.connect(uri.toString(),nativeProperties)
+ }
+
+ def urlProtocolString: String;
+
+}
diff --git a/src/library/scala/dbc/datatype/ApproximateNumeric.scala b/src/library/scala/dbc/datatype/ApproximateNumeric.scala
new file mode 100644
index 0000000000..d75da1eb50
--- /dev/null
+++ b/src/library/scala/dbc/datatype/ApproximateNumeric.scala
@@ -0,0 +1,53 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A type category for all SQL types that store varying-precision
+ * numbers.
+ */
+abstract class ApproximateNumeric[Type] (
+ override val nativeTypeId: DataType.Id
+) extends datatype.Numeric[Type](nativeTypeId) {
+
+ def isEquivalent(datatype: DataType) = datatype match {
+ case dt: ApproximateNumeric[Type] =>
+ (nativeTypeId == dt.nativeTypeId &&
+ precisionRadix == dt.precisionRadix &&
+ precision == dt.precision &&
+ signed == dt.signed)
+ case _ =>
+ false
+ }
+
+ def isSubtypeOf (datatype:DataType) = datatype match {
+ case dt:ApproximateNumeric[Type] =>
+ (nativeTypeId == dt.nativeTypeId &&
+ precisionRadix == dt.precisionRadix &&
+ precision <= dt.precision &&
+ signed == dt.signed)
+ case _ =>
+ false
+ }
+
+ /** A SQL-99 compliant string representation of the type.
+ * <h3>Compatibility notice</h3> This method assumes that a real
+ * uses 32 bits and a double 64. This is not defined in the
+ * standard but is usually the case.
+ */
+ override def sqlString: java.lang.String = Tuple2(precisionRadix,precision) match {
+ case Tuple2(2,64) => "REAL"
+ case Tuple2(2,128) => "DOUBLE PRECISION"
+ case Tuple2(2,p) =>
+ throw exception.UnsupportedFeature("SQL-99 does not support an approximate numeric type with a binary defined precision other than 16, 32 and 64 bits");
+ case Tuple2(10,p) => "FLOAT (" + p.toString() + ")"
+ case Tuple2(pr,_) =>
+ throw exception.UnsupportedFeature("SQL-99 does not support the precision of an approximate numeric type to be defined in a radix other than 2 or 10");
+ }
+
+}
diff --git a/src/library/scala/dbc/datatype/Boolean.scala b/src/library/scala/dbc/datatype/Boolean.scala
new file mode 100644
index 0000000000..7c68ab9c7d
--- /dev/null
+++ b/src/library/scala/dbc/datatype/Boolean.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** The SQL type for a truth value. */
+class Boolean extends DataType {
+
+ def isEquivalent (datatype:DataType) = datatype match {
+ case dt:Boolean => true
+ case _ => false
+ }
+
+ def isSubtypeOf (datatype:DataType) = isEquivalent(datatype);
+
+ type NativeType = scala.Boolean;
+ val nativeTypeId = DataType.BOOLEAN;
+
+ /** A SQL-99 compliant string representation of the type. */
+ override def sqlString: java.lang.String = "BOOLEAN";
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/datatype/Character.scala b/src/library/scala/dbc/datatype/Character.scala
new file mode 100644
index 0000000000..ded08c5602
--- /dev/null
+++ b/src/library/scala/dbc/datatype/Character.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API tests **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A SQL type for a string of characters of arbitrary length with
+ * arbitrary character set.
+ */
+abstract class Character extends CharacterString {
+
+ def isEquivalent(datatype: DataType) = datatype match {
+ case dt: Character =>
+ length == dt.length && encoding == dt.encoding
+ case _ =>
+ false
+ }
+
+ def isSubtypeOf(datatype: DataType) = datatype match {
+ case dt: Character =>
+ length >= dt.length && encoding == dt.encoding
+ case _ =>
+ false
+ }
+
+ /** The length of the string defined in characters. */
+ def length: Int;
+
+ /** A SQL-99 compliant string representation of the type. */
+ override def sqlString: java.lang.String = "CHARACTER (" + length.toString() + ")";
+
+}
diff --git a/src/library/scala/dbc/datatype/CharacterLargeObject.scala b/src/library/scala/dbc/datatype/CharacterLargeObject.scala
new file mode 100644
index 0000000000..adbd979f6e
--- /dev/null
+++ b/src/library/scala/dbc/datatype/CharacterLargeObject.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A SQL type for an unbounded length string of characters with arbitrary
+ * character set. */
+class CharacterLargeObject extends CharacterString {
+
+ def isEquivalent (datatype:DataType) = datatype match {
+ case dt:CharacterLargeObject => {
+ encoding == dt.encoding
+ }
+ case _ => false
+ }
+
+ def isSubtypeOf (datatype:DataType) = isEquivalent(datatype);
+
+ /** A SQL-99 compliant string representation of the type. */
+ override def sqlString: java.lang.String = "CHARACTER LARGE OBJECT";
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/datatype/CharacterString.scala b/src/library/scala/dbc/datatype/CharacterString.scala
new file mode 100644
index 0000000000..e937d10b9e
--- /dev/null
+++ b/src/library/scala/dbc/datatype/CharacterString.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A type category for all SQL types that store strings of characters. */
+abstract class CharacterString extends String {
+
+ type NativeType = java.lang.String;
+ val nativeTypeId = DataType.STRING;
+
+ /** The name of the character set in which the string is encoded. */
+ def encoding: Option[java.lang.String] = None;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/datatype/CharacterVarying.scala b/src/library/scala/dbc/datatype/CharacterVarying.scala
new file mode 100644
index 0000000000..b7f743ce0b
--- /dev/null
+++ b/src/library/scala/dbc/datatype/CharacterVarying.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A SQL type for a varying length string of characters with arbitrary
+ * maximal length and arbitrary character set.
+ */
+abstract class CharacterVarying extends CharacterString {
+
+ def isEquivalent(datatype: DataType) = datatype match {
+ case dt: CharacterVarying =>
+ length == dt.length && encoding == dt.encoding
+ case _ =>
+ false
+ }
+
+ def isSubtypeOf(datatype: DataType) = datatype match {
+ case dt: CharacterVarying =>
+ length >= dt.length && encoding == dt.encoding
+ case _ =>
+ false
+ }
+
+ /** The maximal length of the string defined in characters. */
+ def length: Int;
+
+ /** A SQL-99 compliant string representation of the type. */
+ override def sqlString: java.lang.String =
+ "CHARACTER VARYING (" + length.toString() + ")";
+
+}
diff --git a/src/library/scala/dbc/datatype/ExactNumeric.scala b/src/library/scala/dbc/datatype/ExactNumeric.scala
new file mode 100644
index 0000000000..9152a7e928
--- /dev/null
+++ b/src/library/scala/dbc/datatype/ExactNumeric.scala
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A type category for all SQL types that store constant-precision
+ * numbers.
+ */
+abstract class ExactNumeric[Type](
+ override val nativeTypeId: DataType.Id
+) extends datatype.Numeric[Type](nativeTypeId) {
+
+ def isEquivalent(datatype: DataType) = datatype match {
+ case dt: ExactNumeric[Type] =>
+ (nativeTypeId == dt.nativeTypeId &&
+ precisionRadix == dt.precisionRadix &&
+ precision == dt.precision &&
+ scale == dt.scale &&
+ signed == dt.signed)
+ case _ =>
+ false
+ }
+
+ def isSubtypeOf(datatype: DataType) = datatype match {
+ case dt: ExactNumeric[Type] =>
+ (nativeTypeId == dt.nativeTypeId &&
+ precisionRadix == dt.precisionRadix &&
+ precision <= dt.precision &&
+ scale <= dt.scale &&
+ signed == dt.signed)
+ case _ =>
+ false
+ }
+
+ /** The number of digits used after the decimal point. */
+ def scale: Int;
+
+ /** A SQL-99 compliant string representation of the type.
+ * <h3>Compatibility notice</h3> This method assumes that an integer
+ * uses 32 bits, a small 16 and a big 64. This is not defined in the
+ * standard but is usually the case.
+ */
+ override def sqlString: java.lang.String = Tuple3(precisionRadix,precision,scale) match {
+ case Tuple3(2,16,0) => "SMALLINT"
+ case Tuple3(2,32,0) => "INTEGER"
+ case Tuple3(2,64,0) => "BIGINT"
+ case Tuple3(2,java.lang.Integer.MAX_VALUE,0) => "BIGINT"
+ case Tuple3(2,p,s) =>
+ throw exception.UnsupportedFeature("SQL-99 does not support an exact numeric type with a binary defined precision other than 16, 32 and 64 bits");
+ case Tuple3(10,p,0) => "NUMERIC (" + p.toString() + ")"
+ case Tuple3(10,p,s) => "NUMERIC (" + p.toString() + ", " + s.toString() + ")"
+ case Tuple3(pr,_,_) =>
+ throw exception.UnsupportedFeature("SQL-99 does not support the precision of an exact numeric type to be defined in a radix other than 2 or 10");
+ }
+
+}
diff --git a/src/library/scala/dbc/datatype/Factory.scala b/src/library/scala/dbc/datatype/Factory.scala
new file mode 100644
index 0000000000..13d9cd35e2
--- /dev/null
+++ b/src/library/scala/dbc/datatype/Factory.scala
@@ -0,0 +1,246 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+import java.sql.Types._;
+import java.math.BigInteger;
+import java.math.BigDecimal;
+
+object Factory {
+
+ final val java_lang_Integer_SIZE = 32;
+ final val java_lang_Long_SIZE = 64;
+
+ /** Returns a mullable property formated as a boolean option */
+ def isNullable (metadata:java.sql.ResultSetMetaData, index:Int): Option[scala.Boolean] =
+ metadata.isNullable(index) match {
+ case java.sql.ResultSetMetaData.columnNoNulls => Some(false);
+ case java.sql.ResultSetMetaData.columnNullable => Some(true);
+ case java.sql.ResultSetMetaData.columnNoNulls => None;
+ }
+
+ /** Returns the binary precision for an integer field. This should only be
+ * used to find precision for integer numbers. It assumes that
+ * bytes cannot be used partially (result % 8 = 0). */
+ def bytePrecision (precision:Int, signed:scala.Boolean, safe:scala.Boolean): Int = {
+ val decimalPrecision = precision + (if (safe) 1 else 0);
+ Pair(signed,decimalPrecision) match {
+ case Pair(_,0) => java.lang.Integer.MAX_VALUE // That's a bit of a hack.
+ case Pair(_,dp) if (dp <= 3) => 8
+ case Pair(_,dp) if (dp <= 5) => 16
+ case Pair(true,dp) if (dp <= 7) => 24
+ case Pair(false,dp) if (dp <= 8) => 24
+ case Pair(_,dp) if (dp <= 10) => 32
+ case Pair(true,dp) if (dp <= 12) => 40
+ case Pair(false,dp) if (dp <= 13) => 40
+ case Pair(_,dp) if (dp <= 15) => 48
+ case Pair(_,dp) if (dp <= 17) => 56
+ case Pair(true,dp) if (dp <= 19) => 64
+ case Pair(false,dp) if (dp <= 20) => 64
+ case Pair(_,dp) if (dp <= 22) => 72
+ case Pair(true,dp) if (dp <= 24) => 80
+ case Pair(false,dp) if (dp <= 25) => 80
+ case Pair(_,dp) if (dp <= 27) => 88
+ case Pair(_,dp) if (dp <= 29) => 96
+ case Pair(_,dp) if (dp <= 32) => 104
+ case Pair(_,dp) if (dp <= 34) => 112
+ case Pair(true,dp) if (dp <= 36) => 120
+ case Pair(false,dp) if (dp <= 37) => 120
+ case Pair(_,dp) if (dp <= 39) => 128
+ case _ => java.lang.Integer.MAX_VALUE
+ }
+ }
+
+ def create (metadata:java.sql.ResultSetMetaData, index:Int): DataType = {
+ metadata.getColumnType(index) match {
+ /* Boolean data types. */
+ case BOOLEAN => new datatype.Boolean {
+ override val nullable = isNullable(metadata,index);
+ }
+ case BIT => new datatype.Boolean {
+ override val nullable = isNullable(metadata,index);
+ }
+ /* Fixed precision numeric data types. */
+ case DECIMAL => {
+ Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match {
+ case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
+ new datatype.ExactNumeric[Int](DataType.INT) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
+ new datatype.ExactNumeric[Long](DataType.LONG) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(_,true) =>
+ new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(_,false) =>
+ new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ }
+ }
+ case NUMERIC => {
+ Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match {
+ case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
+ new datatype.ExactNumeric[Int](DataType.INT) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
+ new datatype.ExactNumeric[Long](DataType.LONG) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(_,true) =>
+ new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ case Pair(_,false) =>
+ new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 10;
+ val precision = metadata.getPrecision(index);
+ val signed = metadata.isSigned(index);
+ val scale = metadata.getScale(index);
+ }
+ }
+ }
+ /* Fixed precision integer data types. */
+ case BIGINT =>
+ new datatype.ExactNumeric[Long](DataType.LONG) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 64;
+ val signed = metadata.isSigned(index);
+ val scale = 0;
+ }
+ case INTEGER =>
+ new datatype.ExactNumeric[Int](DataType.INT) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 32;
+ val signed = metadata.isSigned(index);
+ val scale = 0;
+ }
+ case SMALLINT =>
+ new datatype.ExactNumeric[Short](DataType.SHORT) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 16;
+ val signed = metadata.isSigned(index);
+ val scale = 0;
+ }
+ case TINYINT =>
+ new datatype.ExactNumeric[Byte](DataType.BYTE) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 8;
+ val signed = metadata.isSigned(index);
+ val scale = 0;
+ }
+ /* Floating point numeric data types. */
+ case REAL =>
+ new datatype.ApproximateNumeric[Float](DataType.FLOAT) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 64;
+ val signed = metadata.isSigned(index);
+ }
+ case DOUBLE =>
+ new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 128;
+ val signed = metadata.isSigned(index);
+ }
+ case FLOAT =>
+ new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
+ override val nullable = isNullable(metadata,index);
+ val precisionRadix = 2;
+ val precision = 128;
+ val signed = metadata.isSigned(index);
+ }
+ /* Character string data types. */
+ case CHAR => new datatype.Character {
+ override val nullable = isNullable(metadata,index);
+ val length = metadata.getColumnDisplaySize(index);
+ }
+ case CLOB => new datatype.CharacterLargeObject {
+ override val nullable = isNullable(metadata,index);
+ }
+ case LONGVARCHAR => {
+ if (metadata.getColumnDisplaySize(index) >= 0)
+ new datatype.CharacterVarying {
+ override val nullable = isNullable(metadata,index);
+ def length = metadata.getColumnDisplaySize(index);
+ }
+ else // A PostgreSQL Hack
+ new datatype.CharacterLargeObject {
+ override val nullable = isNullable(metadata,index);
+ }
+ }
+ case VARCHAR => {
+ if (metadata.getColumnDisplaySize(index) >= 0)
+ new datatype.CharacterVarying {
+ override val nullable = isNullable(metadata,index);
+ def length = metadata.getColumnDisplaySize(index);
+ }
+ else // A PostgreSQL Hack
+ new datatype.CharacterLargeObject {
+ override val nullable = isNullable(metadata,index);
+ }
+ }
+ /* Undefined cases. */
+ case OTHER => new datatype.Unknown {
+ override val nullable = isNullable(metadata, index);
+ }
+ /* Unsupported data types. */
+ case REF | ARRAY | STRUCT =>
+ error ("I don't support composite data types yet.");
+ case DATALINK | DISTINCT | JAVA_OBJECT | NULL =>
+ error ("I won't support strange data types.");
+ /* Unsupported binary string data types. */
+ case BINARY | BLOB | LONGVARBINARY | VARBINARY =>
+ error ("I don't support binary string data types yet.");
+ /* Unsupported date and time data types. */
+ case DATE | TIME | TIMESTAMP =>
+ error ("I don't support date and time data types yet.");
+ /* Default case */
+ case x => error ("I don't know about this ("+metadata.getColumnTypeName(index)+") JDBC type.")
+ }
+ }
+}
diff --git a/src/library/scala/dbc/datatype/Numeric.scala b/src/library/scala/dbc/datatype/Numeric.scala
new file mode 100644
index 0000000000..ef3eee1f32
--- /dev/null
+++ b/src/library/scala/dbc/datatype/Numeric.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A type category for all SQL types that store numbers. */
+abstract class Numeric[Type](_nativeTypeId: DataType.Id) extends DataType {
+
+ type NativeType = Type;
+ val nativeTypeId = _nativeTypeId;
+
+ /** The radix in which the precision (and scale when appliable) is defined.
+ * ISO-9075 only allows 2 and 10 for this value.
+ */
+ def precisionRadix: Int;
+
+ /** The number of significant digits for that number. */
+ def precision: Int;
+
+ /** Whether the number is signed or not. */
+ def signed: scala.Boolean;
+
+}
diff --git a/src/library/scala/dbc/datatype/String.scala b/src/library/scala/dbc/datatype/String.scala
new file mode 100644
index 0000000000..7d409e6c2d
--- /dev/null
+++ b/src/library/scala/dbc/datatype/String.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** A type category for all SQL types that store strings of elements.
+ */
+abstract class String extends DataType {
+
+ /** The maximal possible length of the string defined in characters.
+ * This is an implementation-specific value.
+ */
+ def maxLength: Option[Int] = None;
+
+}
diff --git a/src/library/scala/dbc/datatype/Unknown.scala b/src/library/scala/dbc/datatype/Unknown.scala
new file mode 100644
index 0000000000..1e7895eb46
--- /dev/null
+++ b/src/library/scala/dbc/datatype/Unknown.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.datatype;
+
+/** The SQL type for a truth value. */
+class Unknown extends DataType {
+
+ def isEquivalent(datatype: DataType) = datatype match {
+ case dt: Unknown =>
+ nativeTypeId == dt.nativeTypeId
+ case _ =>
+ false
+ }
+
+ def isSubtypeOf(datatype: DataType) = true;
+
+ type NativeType = Object;
+ val nativeTypeId = DataType.OBJECT;
+
+ /** A SQL-99 compliant string representation of the type. */
+ override def sqlString: java.lang.String =
+ error("The 'UNKNOWN' data type cannot be represented.");
+
+}
diff --git a/src/library/scala/dbc/exception/IncompatibleSchema.scala b/src/library/scala/dbc/exception/IncompatibleSchema.scala
new file mode 100644
index 0000000000..6095fbec82
--- /dev/null
+++ b/src/library/scala/dbc/exception/IncompatibleSchema.scala
@@ -0,0 +1,15 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.exception;
+
+/** A type category for all SQL types that store constant-precision numbers. */
+case class IncompatibleSchema (
+ expectedSchema: List[DataType],
+ foundSchema: List[DataType]
+) extends Exception; \ No newline at end of file
diff --git a/src/library/scala/dbc/exception/UnsupportedFeature.scala b/src/library/scala/dbc/exception/UnsupportedFeature.scala
new file mode 100644
index 0000000000..9fbaed81d7
--- /dev/null
+++ b/src/library/scala/dbc/exception/UnsupportedFeature.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.exception;
+
+/** A type category for all SQL types that store constant-precision numbers. */
+case class UnsupportedFeature (msg: String) extends Exception; \ No newline at end of file
diff --git a/src/library/scala/dbc/result/Field.scala b/src/library/scala/dbc/result/Field.scala
new file mode 100644
index 0000000000..af129d18b7
--- /dev/null
+++ b/src/library/scala/dbc/result/Field.scala
@@ -0,0 +1,60 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.result;
+
+import scala.dbc.datatype._;
+import scala.dbc.value._;
+
+/** An ISO-9075:2003 (SQL) table field. */
+abstract class Field {
+
+ /** The content (value) of the field. The type of this value is undefined,
+ * transformation into a useful type will be done by an automatic view
+ * function defined in the field object. */
+ def content: Value;
+
+ final def value[Type <: Value]: Type =
+ content.asInstanceOf[Type];
+
+ final def exactNumericValue[NativeType] =
+ content.asInstanceOf[dbc.value.ExactNumeric[NativeType]];
+
+ final def approximateNumericValue[NativeType] =
+ content.asInstanceOf[dbc.value.ApproximateNumeric[NativeType]];
+
+ final def booleanValue =
+ content.asInstanceOf[dbc.value.Boolean];
+
+ final def characterValue =
+ content.asInstanceOf[dbc.value.Character];
+
+ final def characterLargeObjectValue =
+ content.asInstanceOf[dbc.value.CharacterLargeObject];
+
+ final def characterVaryingValue =
+ content.asInstanceOf[dbc.value.CharacterVarying];
+
+ final def unknownValue =
+ content.asInstanceOf[dbc.value.Unknown];
+
+ /** The tuple that contains this field. */
+ def originatingTuple: Tuple;
+
+ /** The field metadata attached to this field. */
+ def metadata: FieldMetadata;
+
+}
+
+object Field {
+
+ implicit def view (field:Field): Value = field.content;
+
+
+
+}
diff --git a/src/library/scala/dbc/result/FieldMetadata.scala b/src/library/scala/dbc/result/FieldMetadata.scala
new file mode 100644
index 0000000000..97c5bdb3a3
--- /dev/null
+++ b/src/library/scala/dbc/result/FieldMetadata.scala
@@ -0,0 +1,32 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.result;
+
+/** Informations attached to a field about its content and its relationship to the originating database. */
+abstract class FieldMetadata {
+
+ /** The name of the field. */
+ def name: String;
+
+ /** The index of the field in the tuple. */
+ def index: Int;
+
+ /** The expected type of the field. This information is used for automatic transformation of the field value into a usable type. */
+ def datatype: DataType;
+
+ /** The name of the catalog in the database from which the field originates */
+ def catalog: String;
+
+ /** The name of the schema in the database from which the field originates */
+ def schema: String;
+
+ /** The name of the table in the database from which the field originates */
+ def table: String;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/result/Relation.scala b/src/library/scala/dbc/result/Relation.scala
new file mode 100644
index 0000000000..006b6dbf07
--- /dev/null
+++ b/src/library/scala/dbc/result/Relation.scala
@@ -0,0 +1,68 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.result;
+
+/** An ISO-9075:2003 (SQL) table. This is equivalent to a relation in the
+ * relational model. */
+abstract class Relation extends Object with Iterable[Tuple] {
+
+ /** The statement that generated this relation. */
+ def statement: scala.dbc.statement.Relation;
+
+ /** A JDBC result containing this relation. */
+ protected def sqlResult: java.sql.ResultSet;
+
+ /** A JDBC metadata object attached to the relation. */
+ protected def sqlMetadata: java.sql.ResultSetMetaData = sqlResult.getMetaData();
+
+ /** Metadata about all fields in a tuple of the relation. */
+ def metadata: List[FieldMetadata] =
+ for (val count <- List.range(1, sqlMetadata.getColumnCount()+1)) yield
+ new FieldMetadata {
+ val name: String = sqlMetadata.getColumnName(count);
+ val index: Int = count;
+ val datatype: DataType = dbc.datatype.Factory.create(sqlMetadata,count);
+ val catalog: String = sqlMetadata.getCatalogName(count);
+ val schema: String = sqlMetadata.getSchemaName(count);
+ val table: String = sqlMetadata.getTableName(count);
+ }
+
+ /** Metadata about the field at the given index. If there is no such
+ * field <code>None</code> is returned instead. */
+ def metadataFor (index:Int): Option[FieldMetadata] =
+ try {Some(metadata(index))} catch {case e => None}
+
+ /** Metadata about the field with the given column name. If there is no
+ * such field, <code>None</code> is returned instead. */
+ def metadataFor (name:String): Option[FieldMetadata] =
+ metadata.find(f=>(f.name==name));
+
+ /** An iterator on the tuples of the relation.
+ * <h3>Caution</h3> A Relation only has one single iterator, due to limitations
+ * in DBMS. This means that if this method is called multiple times, all returned
+ * iterators will share the same state. */
+ def elements: Iterator[Tuple] = new Iterator[Tuple] {
+ protected val result: java.sql.ResultSet = Relation.this.sqlResult;
+ def hasNext: Boolean = !(result.isLast());
+ def next: Tuple = {
+ if (result.next()) {
+ new Tuple {
+ val me = this;
+ val originatingRelation = Relation.this;
+ val fields: List[Field] = for (val fieldMetadata <- metadata) yield
+ new Field {
+ val metadata = fieldMetadata;
+ val content = dbc.value.Factory.create(result,metadata.index,metadata.datatype);
+ val originatingTuple = me;
+ }
+ }
+ } else error("next on empty iterator")
+ }
+ }
+}
diff --git a/src/library/scala/dbc/result/Status.scala b/src/library/scala/dbc/result/Status.scala
new file mode 100644
index 0000000000..56d83d4ae6
--- /dev/null
+++ b/src/library/scala/dbc/result/Status.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.result;
+
+import scala.dbc.datatype._;
+
+/** An object containing the status of a query */
+abstract class Status[ResultType] {
+
+ /** The statement that generated this status result. */
+ def statement: scala.dbc.statement.Statement;
+
+ /** The number of elements modified or added by this statement. */
+ def touchedCount: Option[Int];
+
+ def result: ResultType;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/result/Tuple.scala b/src/library/scala/dbc/result/Tuple.scala
new file mode 100644
index 0000000000..41c2f1f6d1
--- /dev/null
+++ b/src/library/scala/dbc/result/Tuple.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.result;
+
+/** An ISO-9075:2003 (SQL) table row. This is equivalent to a tuple in the relational model. */
+abstract class Tuple {
+
+ /** All the fields contained in the tuple. */
+ def fields: List[Field];
+
+ /** The relation that contains the tuple. */
+ def originatingRelation: Relation;
+
+ /** The field at the given index. If there is no such field (that is the index is out of bounds), <code>None</code> is returned instead. */
+ def apply (index:Int): Field =
+ try {
+ fields(index)
+ } catch {
+ case e =>
+ throw new java.lang.IndexOutOfBoundsException("Field at index "+index+" does not exist in relation");
+ }
+
+ /** The field with the given column name. If there is no such field, <code>None</code> is returned instead. */
+ def apply (name:String): Field = {
+ def findField (fields: List[Field], name:String): Field = fields match {
+ case Nil => throw new java.lang.IndexOutOfBoundsException("Field '"+name+"' does not exist in relation")
+ case field :: _ if (field.metadata.name == name) => field
+ case field :: fields => findField (fields, name)
+ }
+ findField (fields, name);
+ }
+}
diff --git a/src/library/scala/dbc/statement/AccessMode.scala b/src/library/scala/dbc/statement/AccessMode.scala
new file mode 100644
index 0000000000..815f8b3c37
--- /dev/null
+++ b/src/library/scala/dbc/statement/AccessMode.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+abstract class AccessMode {
+ def sqlString: String;
+}
+
+object AccessMode {
+ case object ReadOnly extends AccessMode {
+ def sqlString = "READ ONLY";
+ }
+ case object ReadWrite extends AccessMode {
+ def sqlString = "READ WRITE"
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/DerivedColumn.scala b/src/library/scala/dbc/statement/DerivedColumn.scala
new file mode 100644
index 0000000000..020304f979
--- /dev/null
+++ b/src/library/scala/dbc/statement/DerivedColumn.scala
@@ -0,0 +1,32 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+abstract class DerivedColumn {
+
+ /** The value for the column. This value can be of any type but must be
+ * calculated from fields that appear in a relation that takes part
+ * in the query. */
+ def valueExpression: Expression;
+
+ /** A new name for this field. This name must be unique for the query in
+ * which the column takes part. */
+ def asClause: Option[String];
+
+ /** A SQL-99 compliant string representation of the derived column
+ * sub-statement. This only has a meaning inside a select statement. */
+ def sqlString: String = (
+ valueExpression.sqlInnerString +
+ (asClause match {
+ case None => ""
+ case Some(ac) => " AS " + ac
+ })
+ );
+
+}
diff --git a/src/library/scala/dbc/statement/Expression.scala b/src/library/scala/dbc/statement/Expression.scala
new file mode 100644
index 0000000000..51cada90bb
--- /dev/null
+++ b/src/library/scala/dbc/statement/Expression.scala
@@ -0,0 +1,25 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** An expression that calculates some value from fields. */
+abstract class Expression extends Relation {
+
+ def fieldTypes: List[DataType] = Nil;
+
+ /** A SQL-99 compliant string representation of the expression. */
+ def sqlString: String = {
+ "SELECT " + sqlInnerString
+ }
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String;
+
+}
diff --git a/src/library/scala/dbc/statement/Insert.scala b/src/library/scala/dbc/statement/Insert.scala
new file mode 100644
index 0000000000..23f93ec4a0
--- /dev/null
+++ b/src/library/scala/dbc/statement/Insert.scala
@@ -0,0 +1,32 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+import scala.dbc.statement.expression._;
+
+/** An insertion of values into a table. */
+case class Insert (
+ insertionTarget: String,
+ insertionData: InsertionData
+) extends Status {
+
+ /** A SQL-99 compliant string representation of the select statement. */
+ def sqlString: String = (
+ "INSERT INTO " +
+ insertionTarget +
+ " " + insertionData.sqlString
+ );
+
+ /** The name of the table where the data should be added. */
+ //def insertionTarget: String;
+
+ /** The data that will be added tot he table. */
+ //def insertionData: InsertionData;
+
+}
diff --git a/src/library/scala/dbc/statement/InsertionData.scala b/src/library/scala/dbc/statement/InsertionData.scala
new file mode 100644
index 0000000000..2d6f370319
--- /dev/null
+++ b/src/library/scala/dbc/statement/InsertionData.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+import scala.dbc.statement.expression._;
+
+/** Data to be inserted into a table in an <code>Insert</code>. */
+abstract class InsertionData {
+ def sqlString: String;
+}
+
+object InsertionData {
+ /** Insertion of data resulting from a query on the database. */
+ case class Subquery (query:Relation) extends InsertionData {
+ def sqlString = query.sqlString;
+ }
+ /** Insertion of data as explicitly defined values. */
+ case class Constructor (
+ columnNames:Option[List[String]],
+ columnValues:List[Expression]
+ ) extends InsertionData {
+ def sqlString = (
+ (columnNames match {
+ case None => ""
+ case Some(cn) => cn.mkString(" (",", ",")")
+ }) +
+ " VALUES" +
+ columnValues.map(e=>e.sqlInnerString).mkString(" (",", ",")")
+ )
+ }
+}
diff --git a/src/library/scala/dbc/statement/IsolationLevel.scala b/src/library/scala/dbc/statement/IsolationLevel.scala
new file mode 100644
index 0000000000..f63ebe39e8
--- /dev/null
+++ b/src/library/scala/dbc/statement/IsolationLevel.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+abstract class IsolationLevel {
+ def sqlString: String;
+}
+
+object IsolationLevel {
+ case object ReadUncommitted extends IsolationLevel {
+ def sqlString = "ISOLATION LEVEL READ UNCOMMITTED"
+ }
+ case object ReadCommitted extends IsolationLevel {
+ def sqlString = "ISOLATION LEVEL READ COMMITTED"
+ }
+ case object RepeatableRead extends IsolationLevel {
+ def sqlString = "ISOLATION LEVEL REPEATABLE READ"
+ }
+ case object Serializable extends IsolationLevel {
+ def sqlString = "ISOLATION LEVEL SERIALIZABLE"
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/JoinType.scala b/src/library/scala/dbc/statement/JoinType.scala
new file mode 100644
index 0000000000..60d14cf968
--- /dev/null
+++ b/src/library/scala/dbc/statement/JoinType.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A join behaviour in a <code>Jointure</code>. */
+abstract class JoinType {
+ /** A SQL-99 string representation of the join behaviour. */
+ def sqlString: String;
+}
+
+object JoinType {
+ /** A join behaviour where a joined tuple is created only when a
+ * corresponding tuple exists in both original relations. */
+ case object Inner extends JoinType {
+ val sqlString = "INNER JOIN"
+ }
+ /** A join behaviour family where a joined tuple is created even when a
+ * tuple has no corresponding tuple in the other relation. The fields
+ * populated by values of the other tuple will receive the NULL value.
+ */
+ abstract class Outer extends JoinType;
+ object Outer {
+ /** An outer join behaviour where there will be at least on tuple for
+ * every tuple in the left relation. */
+ case object Left extends Outer {
+ val sqlString = "LEFT OUTER JOIN"
+ }
+ /** An outer join behaviour where there will be at least on tuple for
+ * every tuple in the right relation. */
+ case object Right extends Outer {
+ val sqlString = "RIGHT OUTER JOIN"
+ }
+ /** An outer join behaviour where there will be at least on tuple for
+ * every tuple in both right and left relations. */
+ case object Full extends Outer {
+ val sqlString = "FULL OUTER JOIN"
+ }
+ }
+}
diff --git a/src/library/scala/dbc/statement/Jointure.scala b/src/library/scala/dbc/statement/Jointure.scala
new file mode 100644
index 0000000000..b2ea55d5c9
--- /dev/null
+++ b/src/library/scala/dbc/statement/Jointure.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A jointure between two relations. */
+abstract class Jointure extends Relation {
+
+ /** The relation on the left part of the join. */
+ def leftRelation: Relation;
+
+ /** The relation on the right part of the join. */
+ def rightRelation: Relation;
+
+ /** The type of the jointure. */
+ def joinType: JoinType;
+
+ /** The condition on which the jointure needs be done. */
+ def joinCondition: Option[Expression];
+
+ /** A SQL-99 compliant string representation of the relation statement. */
+ def sqlString: String = {
+ "SELECT * FROM " + sqlInnerString
+ }
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside a query. */
+ def sqlInnerString: String = (
+ leftRelation.sqlInnerString + " " +
+ joinType.sqlString + " " +
+ rightRelation.sqlInnerString +
+ (joinCondition match {
+ case Some(jc) => jc.sqlString
+ case None => ""
+ })
+ )
+
+}
diff --git a/src/library/scala/dbc/statement/Relation.scala b/src/library/scala/dbc/statement/Relation.scala
new file mode 100644
index 0000000000..a6e1a283c9
--- /dev/null
+++ b/src/library/scala/dbc/statement/Relation.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A statement that returns a relation. */
+abstract class Relation extends Statement {
+
+ def isCompatibleType: (DataType,DataType)=>Boolean =
+ ((dt,wdt)=>dt.isSubtypeOf(wdt));
+
+ def typeCheck (relation: result.Relation): Unit = {
+ val sameType: Boolean = (
+ relation.metadata.length == fieldTypes.length &&
+ (relation.metadata.zip(fieldTypes).forall({case Pair(field,expectedType) =>
+ isCompatibleType(field.datatype, expectedType)}))
+ );
+ if (!sameType)
+ throw new exception.IncompatibleSchema(fieldTypes,relation.metadata.map(field=>field.datatype));
+ }
+
+ def fieldTypes: List[DataType];
+
+ def sqlTypeString: String =
+ if (fieldTypes.isEmpty)
+ "UNTYPED"
+ else
+ fieldTypes.map(dt=>dt.sqlString).mkString("RELATION (",", ",")");
+
+ /** A SQL-99 compliant string representation of the statement. */
+ def sqlString: String;
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String;
+
+ /** Executes the statement on the given database. */
+ def execute (database: scala.dbc.Database): scala.dbc.result.Relation = {
+ database.executeStatement(this);
+ }
+
+ def execute (database:scala.dbc.Database, debug:Boolean): scala.dbc.result.Relation = {
+ database.executeStatement(this,debug);
+ }
+
+}
diff --git a/src/library/scala/dbc/statement/Select.scala b/src/library/scala/dbc/statement/Select.scala
new file mode 100644
index 0000000000..47c449d0e1
--- /dev/null
+++ b/src/library/scala/dbc/statement/Select.scala
@@ -0,0 +1,91 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A statement that when executed on a database will return a relation.
+ * The returned relation will be a subset of a table in the database or
+ * a jointure between such subsets. */
+abstract class Select extends Relation {
+
+ /** Defines if duplicated tuples should be removed from the returned
+ * relation. <h3>Compatibility notice</h3> Some DBMS (PostgreSQL) allow
+ * uniqueness constrains on an arbitrary field instead of the entire
+ * tuple. */
+ def setQuantifier: Option[SetQuantifier];
+
+ /** Defines the output fields that a tuple in the returned relation will
+ * contain, and their content with respect to the tables in the
+ * database. If the fields are not specified (that is the list is
+ * empty), all possible input fields will be returned. <h3>Compatibility
+ * notice</h3> SQL's qualified asterisk select sublist is not
+ * available. */
+ def selectList: List[DerivedColumn];
+
+ /** Defines the relations from which the query will obtain its data.*/
+ def fromClause: List[Relation];
+
+ /** Defines condition that must be true in the returned relation's tuples.
+ * This value expression must return a boolean or boolean-compatible
+ * value. This condition is applied before any GROUP BY clause. */
+ def whereClause: Option[Expression];
+
+ /** Defines the grouping of the returned relation's tuples. One tuple is
+ * returned for every group. The value of <code>selectList</code> must
+ * use aggregate functions for calculation. */
+ def groupByClause: Option[List[Expression]];
+
+ /** Defines conditions that must be true in the returned relation's tuples.
+ * The value expression must return a boolean can only refer to fields
+ * that are grouped or to any field from inside an aggregate function. */
+ def havingClause: Option[Expression];
+
+ /* def windowClause: Option[_]; */
+
+ /** A SQL-99 compliant string representation of the select statement. */
+ def sqlString: String = (
+ "SELECT" +
+ (setQuantifier match {
+ case None => ""
+ case Some(sq) => " " + sq.sqlString
+ }) +
+ (selectList match {
+ case Nil => " *"
+ case _ => (" " + selectList.tail.foldLeft(selectList.head.sqlString)
+ ((name:String, dc:DerivedColumn) => name + ", " + dc.sqlString))
+ }) +
+ (fromClause match {
+ case Nil => error("Empty from clause is not allowed")
+ case _ => (" FROM " + fromClause.tail.foldLeft(fromClause.head.sqlInnerString)
+ ((name:String, rel:Relation) => name + ", " + rel.sqlInnerString))
+ }) +
+ (whereClause match {
+ case None => ""
+ case Some(expr) => " WHERE " + expr.sqlInnerString
+ }) +
+ (groupByClause match {
+ case None => ""
+ case Some(gbl) => gbl match {
+ case Nil => error("Empty group by clause is not allowed")
+ case _ =>
+ (" GROUP BY " +
+ gbl.tail.foldLeft(gbl.head.sqlInnerString)
+ ((name:String, gb) => name + ", " + gb.sqlInnerString))
+ }
+ }) +
+ (havingClause match {
+ case None => ""
+ case Some(expr) => " HAVING " + expr.sqlString
+ })
+ );
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside a query. */
+ def sqlInnerString: String = "("+sqlString+")";
+
+}
diff --git a/src/library/scala/dbc/statement/SetClause.scala b/src/library/scala/dbc/statement/SetClause.scala
new file mode 100644
index 0000000000..292879d3d0
--- /dev/null
+++ b/src/library/scala/dbc/statement/SetClause.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+import scala.dbc.statement.expression._;
+
+/** Data to be inserted into a table in an <code>Insert</code>. */
+case class SetClause (name:String, expr:Expression) {
+ val value: Pair[String,Expression] = Pair(name,expr);
+ def sqlString: String =
+ value._1 + " = " + value._2.sqlInnerString;
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/SetQuantifier.scala b/src/library/scala/dbc/statement/SetQuantifier.scala
new file mode 100644
index 0000000000..a2fbbb854a
--- /dev/null
+++ b/src/library/scala/dbc/statement/SetQuantifier.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A set quantifier that defines the collection type of a relation. */
+abstract class SetQuantifier {
+ /** A SQL-99 compliant string representation of the set quantifier. */
+ def sqlString: String;
+}
+
+object SetQuantifier {
+ /** A set quantifier that defines a relation as being a bag. That means
+ * that duplicates are allowed. */
+ case object AllTuples extends SetQuantifier {
+ /** A SQL-99 compliant string representation of the set quantifier. */
+ def sqlString: String = "ALL";
+ }
+ /** A set quantifier that defines a relation as being a set. That means
+ * that duplicates are not allowed and will be pruned. */
+ case object DistinctTuples extends SetQuantifier {
+ /** A SQL-99 compliant string representation of the set quantifier. */
+ def sqlString: String = "DISTINCT";
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/Statement.scala b/src/library/scala/dbc/statement/Statement.scala
new file mode 100644
index 0000000000..64f0967483
--- /dev/null
+++ b/src/library/scala/dbc/statement/Statement.scala
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** An ISO-9075:2003 (SQL) statement. */
+abstract class Statement {
+
+}
diff --git a/src/library/scala/dbc/statement/Status.scala b/src/library/scala/dbc/statement/Status.scala
new file mode 100644
index 0000000000..61ab479199
--- /dev/null
+++ b/src/library/scala/dbc/statement/Status.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A statement that changes the status of the database. */
+abstract class Status extends Statement {
+
+ /** A SQL-99 compliant string representation of the statement. */
+ def sqlString: String;
+
+ /** Executes the statement on the given database. */
+ def execute (database: scala.dbc.Database): scala.dbc.result.Status[Unit] = {
+ database.executeStatement(this);
+ }
+
+ def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[Unit] = {
+ database.executeStatement(this,debug);
+ }
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/Table.scala b/src/library/scala/dbc/statement/Table.scala
new file mode 100644
index 0000000000..18a065e221
--- /dev/null
+++ b/src/library/scala/dbc/statement/Table.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A reference to a table in the database.
+ * @author Gilles Dubochet
+ * @version 1.0 */
+abstract class Table extends Relation {
+
+ /** The name of the table in the database. */
+ def tableName: String;
+
+ /** The name that the table will be called in the enclosing statement. */
+ def tableRename: Option[String];
+
+ /** A SQL-99 compliant string representation of the relation statement. */
+ def sqlString: String = {
+ "SELECT * FROM " + tableName
+ }
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside a query. */
+ def sqlInnerString: String = (
+ tableName +
+ (tableRename match {
+ case None => ""
+ case Some(rename) => " AS " + rename
+ })
+ )
+}
diff --git a/src/library/scala/dbc/statement/Transaction.scala b/src/library/scala/dbc/statement/Transaction.scala
new file mode 100644
index 0000000000..b87c0ccc35
--- /dev/null
+++ b/src/library/scala/dbc/statement/Transaction.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+/** A statement that changes the status of the database. */
+case class Transaction [ResultType] (
+ transactionBody: (scala.dbc.Database=>ResultType),
+ accessMode: Option[AccessMode],
+ isolationLevel: Option[IsolationLevel]
+) extends Statement {
+
+ /** A SQL-99 compliant string representation of the statement. */
+ def sqlStartString: String = (
+ "START TRANSACTION" +
+ (Pair(accessMode,isolationLevel) match {
+ case Pair(None,None) => ""
+ case Pair(Some(am),None) => " " + am.sqlString
+ case Pair(None,Some(il)) => " " + il.sqlString
+ case Pair(Some(am),Some(il)) => " " + am.sqlString + ", " + il.sqlString
+ })
+ );
+
+ def sqlCommitString: String = {
+ "COMMIT"
+ }
+
+ def sqlAbortString: String = {
+ "ROLLBACK"
+ }
+
+ //def transactionBody: (()=>Unit);
+
+ //def accessMode: Option[AccessMode];
+
+ //def isolationLevel: Option[IsolationLevel];
+
+ def execute (database: scala.dbc.Database): scala.dbc.result.Status[ResultType] = {
+ database.executeStatement(this);
+ }
+
+ def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[ResultType] = {
+ database.executeStatement(this,debug);
+ }
+
+}
diff --git a/src/library/scala/dbc/statement/Update.scala b/src/library/scala/dbc/statement/Update.scala
new file mode 100644
index 0000000000..bc541200c4
--- /dev/null
+++ b/src/library/scala/dbc/statement/Update.scala
@@ -0,0 +1,43 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement;
+
+import scala.dbc.statement.expression._;
+
+/** An update of the state of a table. */
+case class Update (
+ updateTarget: String,
+ setClauses: List[SetClause],
+ whereClause: Option[Expression]
+) extends Status {
+
+
+ /** A SQL-99 compliant string representation of the select statement. */
+ def sqlString: String = (
+ "UPDATE " +
+ updateTarget +
+ " SET " + setClauses.map(sc=>sc.sqlString).mkString("",", ","") +
+ (whereClause match {
+ case None => ""
+ case Some(expr) => " WHERE " + expr.sqlString
+ })
+ );
+
+ /** The name of the table that should be updated. */
+ //def updateTarget: String;
+
+ /** The data that will be added tot he table. */
+ //def setClauses: List[SetClause];
+
+ /** Defines condition that must be true in the tuples that will be updated.
+ * This value expression must return a boolean or boolean-compatible
+ * value. */
+ //def whereClause: Option[scala.dbc.statement.expression.Expression];
+
+}
diff --git a/src/library/scala/dbc/statement/expression/Aggregate.scala b/src/library/scala/dbc/statement/expression/Aggregate.scala
new file mode 100644
index 0000000000..d0dfd6a133
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/Aggregate.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class Aggregate extends Expression {
+
+ def aggregateName: String;
+
+ def setFunction: SetFunction;
+
+ def filterClause: Option[Expression];
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = (
+ aggregateName +
+ "(" + setFunction.sqlString + ")" +
+ (filterClause match {
+ case None => ""
+ case Some(fc) => " FILTER (WHERE " + fc.sqlString + ")"
+ })
+ )
+
+}
diff --git a/src/library/scala/dbc/statement/expression/BinaryOperator.scala b/src/library/scala/dbc/statement/expression/BinaryOperator.scala
new file mode 100644
index 0000000000..a0d964a798
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/BinaryOperator.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class BinaryOperator extends Expression {
+
+ /** The name of the operator. */
+ def operator: String;
+
+ /** The expression applied on the left of the operator. */
+ def leftOperand: Expression;
+
+ /** The expression applied on the right of the operator. */
+ def rightOperand: Expression;
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = {
+ leftOperand.sqlInnerString + " " + operator + " " + rightOperand.sqlInnerString
+ }
+
+}
diff --git a/src/library/scala/dbc/statement/expression/Constant.scala b/src/library/scala/dbc/statement/expression/Constant.scala
new file mode 100644
index 0000000000..12a089ea48
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/Constant.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class Constant extends Expression {
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = constantValue.sqlString;
+
+ /** The value of the constant. */
+ def constantValue: Value;
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/expression/Default.scala b/src/library/scala/dbc/statement/expression/Default.scala
new file mode 100644
index 0000000000..2b84a6ce4f
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/Default.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+case object Default extends Expression {
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = "DEFAULT";
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/expression/Field.scala b/src/library/scala/dbc/statement/expression/Field.scala
new file mode 100644
index 0000000000..55b7c96053
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/Field.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class Field extends Expression {
+
+ /** The name of the schema in the database where the field is located. */
+ def schemaName: Option[String] = None;
+
+ /** The name of the table in the database where the field is located. */
+ def tableName: Option[String];
+
+ /** The name of the field in the database. */
+ def fieldName: String;
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = (
+ (schemaName match {
+ case None => ""
+ case Some(sn) => sn + "."
+ }) +
+ (tableName match {
+ case None => ""
+ case Some(tn) => tn + "."
+ }) + fieldName
+ )
+
+}
diff --git a/src/library/scala/dbc/statement/expression/FunctionCall.scala b/src/library/scala/dbc/statement/expression/FunctionCall.scala
new file mode 100644
index 0000000000..030b05812b
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/FunctionCall.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+case class FunctionCall (
+ functionName: String,
+ arguments: List[Expression]
+) extends Expression {
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = {
+ functionName + "(" + arguments.mkString("",", ","") + ")"
+ }
+
+ /** The name of the function to call. */
+ //def functionName: String;
+
+ /** A list of all argument expressions to pass to the function, in order. */
+ //def arguments: List[Expression];
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/expression/Select.scala b/src/library/scala/dbc/statement/expression/Select.scala
new file mode 100644
index 0000000000..bce9a5d002
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/Select.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class Select extends Expression {
+
+ /** The actual select statement */
+ def selectStatement: statement.Select;
+
+ /** A SQL-99 compliant string representation of the expression. */
+ override def sqlString: String = selectStatement.sqlString;
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = "("+selectStatement.sqlString+")";
+
+}
diff --git a/src/library/scala/dbc/statement/expression/SetFunction.scala b/src/library/scala/dbc/statement/expression/SetFunction.scala
new file mode 100644
index 0000000000..6a3ba37d2d
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/SetFunction.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class SetFunction {
+ /** A SQL-99 compliant string representation of the set quantifier. */
+ def sqlString: String;
+}
+
+object SetFunction {
+ abstract class Asterisk extends SetFunction {
+ def sqlString = "(*)";
+ }
+ abstract class General extends SetFunction {
+ def setQuantifier: Option[SetQuantifier];
+ def valueExpression: Expression;
+ def sqlString = (
+ "(" +
+ (setQuantifier match {
+ case None => ""
+ case Some(sq) => sq.sqlString + " "
+ }) +
+ valueExpression.sqlString + ")"
+ );
+ }
+ abstract class Binary extends SetFunction {
+ def sqlString = error("Binary set function is not supported yet.");
+ }
+}
diff --git a/src/library/scala/dbc/statement/expression/TypeCast.scala b/src/library/scala/dbc/statement/expression/TypeCast.scala
new file mode 100644
index 0000000000..25d1874381
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/TypeCast.scala
@@ -0,0 +1,27 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+case class TypeCast (
+ expression: Expression,
+ castType: DataType
+) extends Expression {
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = {
+ "CAST (" + expression.sqlInnerString + " AS " + castType.sqlString + ")";
+ }
+
+ /** The expression that will be casted. */
+ //def expression: Expression;
+
+ /** The type to which to cast. */
+ //def castType: scala.dbc.datatype.DataType;
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/statement/expression/UnaryOperator.scala b/src/library/scala/dbc/statement/expression/UnaryOperator.scala
new file mode 100644
index 0000000000..1e7ab028f7
--- /dev/null
+++ b/src/library/scala/dbc/statement/expression/UnaryOperator.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.statement.expression;
+
+abstract class UnaryOperator extends Expression {
+
+ /** The name of the operator */
+ def operator: String;
+
+ /** Whether the operator comes before the operand or not. */
+ def operatorIsLeft: Boolean;
+
+ /** The operand applied to the operator. */
+ def operand: Expression;
+
+ /** A SQL-99 compliant string representation of the relation sub-
+ * statement. This only has a meaning inside another statement. */
+ def sqlInnerString: String = operatorIsLeft match {
+ case true => operator + " " + operand.sqlInnerString;
+ case false => operand.sqlInnerString + " " + operator;
+ }
+}
diff --git a/src/library/scala/dbc/syntax/DataTypeUtil.scala b/src/library/scala/dbc/syntax/DataTypeUtil.scala
new file mode 100644
index 0000000000..1df3d20317
--- /dev/null
+++ b/src/library/scala/dbc/syntax/DataTypeUtil.scala
@@ -0,0 +1,94 @@
+/* __ *\
+** ________ ___ / / ___ Scala API tests **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.syntax;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+object DataTypeUtil {
+
+ final val java_lang_Integer_SIZE = 32;
+ final val java_lang_Long_SIZE = 64;
+
+ def boolean = new datatype.Boolean;
+ def tinyint = new datatype.ExactNumeric[Byte](dbc.DataType.BYTE) {
+ val precisionRadix = 2;
+ val precision = 8;
+ val signed = true;
+ val scale = 0;
+ }
+ def smallint = new datatype.ExactNumeric[Short](dbc.DataType.SHORT) {
+ val precisionRadix = 2;
+ val precision = 16;
+ val signed = true;
+ val scale = 0;
+ }
+ def integer = new datatype.ExactNumeric[Int](dbc.DataType.INT) {
+ val precisionRadix = 2;
+ val precision = 32;
+ val signed = true;
+ val scale = 0;
+ }
+ def bigint = new datatype.ExactNumeric[Long](dbc.DataType.LONG) {
+ val precisionRadix = 2;
+ val precision = 64;
+ val signed = true;
+ val scale = 0;
+ }
+ def numeric (_precision:Int): DataType = numeric(_precision,0);
+ def numeric (_precision:Int, _scale:Int): DataType =
+ Pair(datatype.Factory.bytePrecision(_precision,true,true),_scale == 0) match {
+ case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
+ new datatype.ExactNumeric[Int](DataType.INT) {
+ val precisionRadix = 10;
+ val precision = _precision;
+ val signed = true;
+ val scale = 0;
+ }
+ case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
+ new datatype.ExactNumeric[Long](DataType.LONG) {
+ val precisionRadix = 10;
+ val precision = _precision;
+ val signed = true;
+ val scale = 0;
+ }
+ case Pair(_,true) =>
+ new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
+ val precisionRadix = 10;
+ val precision = _precision;
+ val signed = true;
+ val scale = 0;
+ }
+ case Pair(_,false) =>
+ new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
+ val precisionRadix = 10;
+ val precision = _precision;
+ val signed = true;
+ val scale = _scale;
+ }
+ }
+ def real = new datatype.ApproximateNumeric[Float](DataType.FLOAT) {
+ val precisionRadix = 2;
+ val precision = 64;
+ val signed = true;
+ }
+ def doublePrecision = new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
+ val precisionRadix = 2;
+ val precision = 128;
+ val signed = true;
+ }
+ def character (_length: Int) = new datatype.Character {
+ val length = _length;
+ }
+ def characterVarying (_length: Int) = new datatype.CharacterVarying {
+ def length = _length;
+ }
+ def characterLargeObject = new datatype.CharacterLargeObject;
+
+}
diff --git a/src/library/scala/dbc/syntax/Database.scala b/src/library/scala/dbc/syntax/Database.scala
new file mode 100644
index 0000000000..d819931e95
--- /dev/null
+++ b/src/library/scala/dbc/syntax/Database.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API tests **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.syntax;
+
+import java.net.URI;
+
+object Database {
+
+ def database (server:String, username:String, password:String): dbc.Database = {
+ val uri = new URI(server);
+ // Java 1.5 if (uri.toString().contains("postgres")) {
+ if (uri.toString().indexOf("postgres") != -1) {
+ new dbc.Database(new vendor.PostgreSQL {
+ val uri = new URI(server);
+ val user = username;
+ val pass = password;
+ })
+ } else {
+ throw new Exception("No DBMS vendor support could be found for the given URI");
+ }
+ }
+
+}
diff --git a/src/library/scala/dbc/syntax/Statement.scala b/src/library/scala/dbc/syntax/Statement.scala
new file mode 100644
index 0000000000..c4dd2e7434
--- /dev/null
+++ b/src/library/scala/dbc/syntax/Statement.scala
@@ -0,0 +1,270 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.syntax;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import StatementExpression._;
+
+/*
+
+ASSUMPTIONS:
+
+IMPROVABLE:
+For type safety, all types must be defined. If one is missing, none is taken into account.
+It is possible to redefine many types or renamings for a field, in that case,
+ only the last one is taken into account ("a" as "b" as "c" of boolean as "e" of integer
+ is equivalent to "a" as "e" of integer).
+
+FIXED:
+
+*/
+
+object Statement {
+
+ // SELECT ZYGOTE ...
+
+ def select: SelectZygote = new SelectZygote {
+ val setQuantifier = None;
+ }
+ def selectBag: SelectZygote = new SelectZygote {
+ val setQuantifier = Some(statement.SetQuantifier.AllTuples);
+ }
+ def selectSet: SelectZygote = new SelectZygote {
+ val setQuantifier = Some(statement.SetQuantifier.DistinctTuples);
+ }
+
+ abstract class SelectZygote {
+ def setQuantifier: Option[statement.SetQuantifier];
+ def fields (sdc:SelectDerivedColumns): SelectOf = new SelectOf {
+ val setQuantifier = SelectZygote.this.setQuantifier;
+ val selectList = sdc.selectList;
+ val selectTypes = sdc.selectTypes;
+ }
+ }
+
+ abstract class SelectDerivedField {
+ def fieldValue: StatementField;
+ def fieldRename: Option[String] = {val x = None; x}
+ def fieldType: Option[dbc.DataType] = {val x = None; x}
+ def as (rename:String): SelectDerivedField = new SelectDerivedField {
+ val fieldValue = SelectDerivedField.this.fieldValue;
+ override val fieldRename = Some(rename);
+ override val fieldType = SelectDerivedField.this.fieldType;
+ }
+ def of (datatype:dbc.DataType): SelectDerivedField = new SelectDerivedField {
+ val fieldValue = SelectDerivedField.this.fieldValue;
+ override val fieldRename = SelectDerivedField.this.fieldRename;
+ override val fieldType = Some(datatype);
+ }
+ }
+
+ implicit def view (fv:StatementField): SelectDerivedField = new SelectDerivedField {
+ val fieldValue = fv;
+ }
+
+ implicit def view (fv:String): SelectDerivedField = new SelectDerivedField {
+ val fieldValue: StatementField = StatementExpression.view(fv);
+ }
+
+ abstract class SelectDerivedColumns {
+ def selectList: List[statement.DerivedColumn];
+ def selectTypes: List[DataType];
+ def and (sdc:SelectDerivedColumns): SelectDerivedColumns = new SelectDerivedColumns {
+ val selectList = SelectDerivedColumns.this.selectList ::: sdc.selectList;
+ val selectTypes =
+ if (SelectDerivedColumns.this.selectTypes.isEmpty | sdc.selectTypes.isEmpty)
+ Nil
+ else
+ SelectDerivedColumns.this.selectTypes ::: sdc.selectTypes;
+ }
+ }
+
+ implicit def view (sdf:SelectDerivedField): SelectDerivedColumns = new SelectDerivedColumns {
+ val selectList = List(new statement.DerivedColumn {
+ val valueExpression = sdf.fieldValue.toStatement;
+ val asClause = sdf.fieldRename;
+ });
+ val selectTypes = if (sdf.fieldType.isEmpty) Nil else List(sdf.fieldType.get);
+ }
+
+ implicit def view (sdfs:String): SelectDerivedColumns = {
+ val sdf: SelectDerivedField = sdfs;
+ view(sdf);
+ }
+
+ // SELECT OF ...
+
+ abstract class SelectOf {
+ def setQuantifier: Option[statement.SetQuantifier];
+ def selectList: List[statement.DerivedColumn];
+ def selectTypes: List[DataType];
+ def from (sst:SelectSourceTables): SelectBeyond = new SelectBeyond {
+ val setQuantifier = SelectOf.this.setQuantifier;
+ val selectList = SelectOf.this.selectList;
+ val selectTypes = SelectOf.this.selectTypes;
+ val fromClause = sst.fromClause;
+ val whereClause = None;
+ val groupByClause = None;
+ val havingClause = None;
+ }
+ }
+
+ abstract class SelectSourceTable {
+ def fromRelation: statement.Relation;
+ def innerJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = new statement.Jointure {
+ val leftRelation = SelectSourceTable.this.fromRelation;
+ val rightRelation = sst.fromRelation;
+ val joinType = statement.JoinType.Inner;
+ val joinCondition = None;
+ val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
+ }
+ }
+ def leftOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = new statement.Jointure {
+ val leftRelation = SelectSourceTable.this.fromRelation;
+ val rightRelation = sst.fromRelation;
+ val joinType = statement.JoinType.Outer.Left;
+ val joinCondition = None;
+ val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
+ }
+ }
+ def rightOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = new statement.Jointure {
+ val leftRelation = SelectSourceTable.this.fromRelation;
+ val rightRelation = sst.fromRelation;
+ val joinType = statement.JoinType.Outer.Right;
+ val joinCondition = None;
+ val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
+ }
+ }
+ def fullOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = new statement.Jointure {
+ val leftRelation = SelectSourceTable.this.fromRelation;
+ val rightRelation = sst.fromRelation;
+ val joinType = statement.JoinType.Outer.Full;
+ val joinCondition = None;
+ val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
+ }
+ }
+ }
+
+ implicit def view (sct:String): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = new statement.Table {
+ val tableName = sct;
+ val tableRename = None;
+ val fieldTypes = Nil;
+ }
+ }
+
+ implicit def view (sct:statement.Select): SelectSourceTable = new SelectSourceTable {
+ val fromRelation = sct;
+ }
+
+ abstract class SelectSourceTables {
+ def fromClause: List[statement.Relation];
+ def join (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables {
+ val fromClause = SelectSourceTables.this.fromClause ::: List(sct.fromRelation);
+ }
+ }
+
+ implicit def view (sct:String): SelectSourceTables = new SelectSourceTables {
+ val fromClause = List(new statement.Table {
+ val tableName = sct;
+ val tableRename = None;
+ val fieldTypes = Nil;
+ });
+ }
+
+ implicit def view (sct:statement.Select): SelectSourceTables = new SelectSourceTables {
+ val fromClause = List(sct);
+ }
+
+ implicit def view (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables {
+ val fromClause = List(sct.fromRelation);
+ }
+
+ // SELECT BEYOND ...
+
+ abstract class SelectBeyond {
+ def setQuantifier: Option[statement.SetQuantifier];
+ def selectList: List[statement.DerivedColumn];
+ def selectTypes: List[DataType];
+ def fromClause: List[statement.Relation];
+ def whereClause: Option[statement.Expression];
+ def groupByClause: Option[List[statement.Expression]];
+ def havingClause: Option[statement.Expression];
+ def where (se:StatementExpression): SelectBeyond = new SelectBeyond {
+ val setQuantifier = SelectBeyond.this.setQuantifier;
+ val selectList = SelectBeyond.this.selectList;
+ val selectTypes = SelectBeyond.this.selectTypes;
+ val fromClause = SelectBeyond.this.fromClause;
+ val whereClause = Some(se.toStatement);
+ val groupByClause = SelectBeyond.this.groupByClause;
+ val havingClause = SelectBeyond.this.havingClause;
+ }
+ def groupBy (sgb:SelectGroupBy): SelectBeyond = new SelectBeyond {
+ val setQuantifier = SelectBeyond.this.setQuantifier;
+ val selectList = SelectBeyond.this.selectList;
+ val selectTypes = SelectBeyond.this.selectTypes;
+ val fromClause = SelectBeyond.this.fromClause;
+ val whereClause = SelectBeyond.this.whereClause;
+ val groupByClause = Some(sgb.groupByClause);
+ val havingClause = SelectBeyond.this.havingClause;
+ }
+ def having (se:StatementExpression): SelectBeyond = new SelectBeyond {
+ val setQuantifier = SelectBeyond.this.setQuantifier;
+ val selectList = SelectBeyond.this.selectList;
+ val selectTypes = SelectBeyond.this.selectTypes;
+ val fromClause = SelectBeyond.this.fromClause;
+ val whereClause = SelectBeyond.this.whereClause;
+ val groupByClause = SelectBeyond.this.groupByClause;
+ val havingClause = Some(se.toStatement);
+ }
+ }
+
+ implicit def view (sb:SelectBeyond): statement.Select = new statement.Select {
+ val setQuantifier = sb.setQuantifier;
+ val selectList = sb.selectList;
+ val fromClause = sb.fromClause;
+ val whereClause = sb.whereClause;
+ val groupByClause = sb.groupByClause;
+ val havingClause = sb.havingClause;
+ val fieldTypes = sb.selectTypes;
+ }
+
+ abstract class SelectGroupBy {
+ def groupByClause: List[statement.Expression];
+ def then (se:StatementExpression): SelectGroupBy = new SelectGroupBy {
+ val groupByClause =
+ SelectGroupBy.this.groupByClause ::: List(se.toStatement);
+ }
+ def then (se:String): SelectGroupBy = new SelectGroupBy {
+ val groupByClause =
+ SelectGroupBy.this.groupByClause ::: List(new statement.expression.Field {
+ val tableName = None;
+ val fieldName = se;
+ });
+ }
+ }
+
+ implicit def view (se:StatementExpression): SelectGroupBy = new SelectGroupBy {
+ val groupByClause = List(se.toStatement);
+ }
+
+ implicit def view (se:String): SelectGroupBy = new SelectGroupBy {
+ val groupByClause = List(new statement.expression.Field {
+ val tableName = None;
+ val fieldName = se;
+ });
+ }
+
+}
diff --git a/src/library/scala/dbc/syntax/StatementExpression.scala b/src/library/scala/dbc/syntax/StatementExpression.scala
new file mode 100644
index 0000000000..e03be2a476
--- /dev/null
+++ b/src/library/scala/dbc/syntax/StatementExpression.scala
@@ -0,0 +1,217 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.syntax;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+abstract class StatementExpression {
+
+ def toStatement: statement.Expression;
+
+ def and (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "AND";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def or (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "OR";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def == (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "=";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def < (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "<";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def > (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = ">";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def <= (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "<=";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def >= (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = ">=";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def <> (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "<>";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def isNull: StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "IS NULL";
+ val operatorIsLeft = false;
+ val operand = StatementExpression.this.toStatement;
+ }
+ }
+ def isNotNull: StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "IS NOT NULL";
+ val operatorIsLeft = false;
+ val operand = StatementExpression.this.toStatement;
+ }
+ }
+ def + (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "+";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def - (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "-";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def * (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "*";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def / (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "/";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def % (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "%";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def ^ (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "^";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def not : StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "!";
+ val operatorIsLeft = false;
+ val operand = StatementExpression.this.toStatement;
+ }
+ }
+ def || (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "||";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def like (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "LIKE";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def similar (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "SIMILAR";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = se.toStatement;
+ }
+ }
+ def in (se:statement.Select): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.BinaryOperator {
+ val operator = "IN";
+ val leftOperand = StatementExpression.this.toStatement;
+ val rightOperand = new statement.expression.Select {
+ val selectStatement = se;
+ };
+ }
+ }
+
+}
+
+object StatementExpression {
+
+ def not (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "NOT";
+ val operatorIsLeft = true;
+ val operand = se.toStatement;
+ }
+ }
+ def abs (se:StatementExpression): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "@";
+ val operatorIsLeft = true;
+ val operand = se.toStatement;
+ }
+ }
+ def exists (se:statement.Select): StatementExpression = new StatementExpression {
+ val toStatement = new statement.expression.UnaryOperator {
+ val operator = "EXISTS";
+ val operatorIsLeft = true;
+ val operand = new statement.expression.Select {
+ val selectStatement = se;
+ };
+ }
+ }
+
+ abstract class StatementField extends StatementExpression {
+ def fieldName: String;
+ def tableName: Option[String] = None;
+ def in (tn:String): StatementField = new StatementField {
+ val fieldName = StatementField.this.fieldName;
+ override val tableName = Some(tn);
+ }
+ def toStatement: statement.expression.Field = new statement.expression.Field {
+ override val schemaName = None;
+ val tableName = StatementField.this.tableName;
+ val fieldName = StatementField.this.fieldName;
+ }
+ }
+
+ implicit def view (ef:String): StatementField = new StatementField {
+ val fieldName = ef;
+ }
+
+
+
+
+}
diff --git a/src/library/scala/dbc/value/ApproximateNumeric.scala b/src/library/scala/dbc/value/ApproximateNumeric.scala
new file mode 100644
index 0000000000..4b0c495f54
--- /dev/null
+++ b/src/library/scala/dbc/value/ApproximateNumeric.scala
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+abstract class ApproximateNumeric [Type] extends Value {
+
+ val dataType: datatype.ApproximateNumeric[Type];
+
+ def sqlString = nativeValue.toString();
+
+ }
+
+object ApproximateNumeric {
+
+ def view (obj:value.ApproximateNumeric[Float]): Float = obj.nativeValue;
+ def view (obj:value.ApproximateNumeric[Double]): Double = obj.nativeValue;
+
+}
diff --git a/src/library/scala/dbc/value/Boolean.scala b/src/library/scala/dbc/value/Boolean.scala
new file mode 100644
index 0000000000..fa20a066af
--- /dev/null
+++ b/src/library/scala/dbc/value/Boolean.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+abstract class Boolean extends Value {
+
+ val dataType: datatype.Boolean;
+
+ def sqlString = if (nativeValue) "TRUE" else "FALSE";
+
+}
+
+object Boolean {
+
+ def view (obj:value.Boolean): scala.Boolean = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/Character.scala b/src/library/scala/dbc/value/Character.scala
new file mode 100644
index 0000000000..1d5433b991
--- /dev/null
+++ b/src/library/scala/dbc/value/Character.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+/** A SQL-99 value of type character string. */
+abstract class Character extends Value {
+
+ override val dataType: datatype.Character;
+
+ /** An SQL-99 compliant string representation of the value. */
+ def sqlString: String = {
+ "'" + nativeValue + "'"
+ }
+
+}
+
+/** An object offering transformation methods (views) on the value.
+ * This object must be visible in an expression to use value auto-
+ * conversion. */
+object Character {
+
+ /** A character string value as a native string. */
+ def view (obj:value.Character): String = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/CharacterLargeObject.scala b/src/library/scala/dbc/value/CharacterLargeObject.scala
new file mode 100644
index 0000000000..c4fb7097e0
--- /dev/null
+++ b/src/library/scala/dbc/value/CharacterLargeObject.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+/** A SQL-99 value of type character large object. */
+abstract class CharacterLargeObject extends Value {
+
+ override val dataType: datatype.CharacterLargeObject;
+
+ /** An SQL-99 compliant string representation of the value. */
+ def sqlString: String = {
+ "'" + nativeValue + "'"
+ }
+
+}
+
+/** An object offering transformation methods (views) on the value.
+ * This object must be visible in an expression to use value auto-
+ * conversion. */
+object CharacterLargeObject {
+
+ /** A character large object value as a native string. */
+ def view (obj:value.CharacterLargeObject): String = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/CharacterVarying.scala b/src/library/scala/dbc/value/CharacterVarying.scala
new file mode 100644
index 0000000000..61142e536c
--- /dev/null
+++ b/src/library/scala/dbc/value/CharacterVarying.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+/** A SQL-99 value of type character varying string. */
+abstract class CharacterVarying extends Value {
+
+ override val dataType: datatype.CharacterVarying;
+
+ /** An SQL-99 compliant string representation of the value. */
+ def sqlString: String = {
+ "'" + nativeValue + "'"
+ }
+
+}
+
+/** An object offering transformation methods (views) on the value.
+ * This object must be visible in an expression to use value auto-
+ * conversion. */
+object CharacterVarying {
+
+ /** A character varying string value as a native string. */
+ def view (obj:value.CharacterVarying): String = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/Conversion.scala b/src/library/scala/dbc/value/Conversion.scala
new file mode 100644
index 0000000000..5c5dda4220
--- /dev/null
+++ b/src/library/scala/dbc/value/Conversion.scala
@@ -0,0 +1,153 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+import java.math._;
+
+object Conversion {
+
+ class Illegal (msg:String) extends Exception(msg);
+
+ implicit def view (value:Value): Byte = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to byte: "+value)
+ }
+ }
+
+ implicit def view (value:Value): Short = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.SHORT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to short: "+value)
+ }
+ }
+
+ implicit def view (value:Value): Int = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.SHORT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.INT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to int: "+value)
+ }
+ }
+
+ implicit def view (value:Value): Long = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.SHORT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.INT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.LONG) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to long: "+value)
+ }
+ }
+
+ implicit def view (value:Value): BigInteger = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ new BigInteger(v.nativeValue.toString(),10)
+ } else if (value.dataType.nativeTypeId == DataType.SHORT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
+ new BigInteger(v.nativeValue.toString(),10)
+ } else if (value.dataType.nativeTypeId == DataType.INT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
+ new BigInteger(v.nativeValue.toString(),10)
+ } else if (value.dataType.nativeTypeId == DataType.LONG) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
+ new BigInteger(v.nativeValue.toString(),10)
+ } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to big integer: "+value)
+ }
+ }
+
+ implicit def view (value:Value): BigDecimal = {
+ if (value.dataType.nativeTypeId == DataType.BYTE) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
+ new BigDecimal(v.nativeValue.toString())
+ } else if (value.dataType.nativeTypeId == DataType.SHORT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
+ new BigDecimal(v.nativeValue.toString())
+ } else if (value.dataType.nativeTypeId == DataType.INT) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
+ new BigDecimal(v.nativeValue.toString())
+ } else if (value.dataType.nativeTypeId == DataType.LONG) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
+ new BigDecimal(v.nativeValue.toString())
+ } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]];
+ new BigDecimal(v.nativeValue)
+ } else if (value.dataType.nativeTypeId == DataType.BIG_DECIMAL) {
+ val v = value.asInstanceOf[dbc.value.ExactNumeric[BigDecimal]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to big decimal: "+value)
+ }
+ }
+
+ implicit def view (value:Value): Float = {
+ if (value.dataType.nativeTypeId == DataType.FLOAT) {
+ val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to float: "+value)
+ }
+ }
+
+ implicit def view (value:Value): Double = {
+ if (value.dataType.nativeTypeId == DataType.FLOAT) {
+ val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]];
+ v.nativeValue.coerce
+ } else if (value.dataType.nativeTypeId == DataType.DOUBLE) {
+ val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Double]];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to double: "+value)
+ }
+ }
+
+ implicit def view (value:Value): scala.Boolean = {
+ if (value.dataType.nativeTypeId == DataType.BOOLEAN) {
+ val v = value.asInstanceOf[dbc.value.Boolean];
+ v.nativeValue
+ } else {
+ throw new Illegal("Cannot convert value to boolean: "+value)
+ }
+ }
+
+ implicit def view (value:Value): String = value match {
+ case v:dbc.value.Character => v.nativeValue;
+ case v:dbc.value.CharacterLargeObject => v.nativeValue;
+ case v:dbc.value.CharacterVarying => v.nativeValue;
+ case _ => throw new Illegal("Cannot convert value to string")
+ }
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/ExactNumeric.scala b/src/library/scala/dbc/value/ExactNumeric.scala
new file mode 100644
index 0000000000..f3e1a54aac
--- /dev/null
+++ b/src/library/scala/dbc/value/ExactNumeric.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+import java.math.BigInteger;
+import java.math.BigDecimal;
+
+abstract class ExactNumeric [Type] extends Value {
+
+ val dataType: datatype.ExactNumeric[Type];
+
+ def sqlString = nativeValue.toString();
+
+}
+
+object ExactNumeric {
+
+ def view (obj:value.ExactNumeric[Byte]): Byte = obj.nativeValue;
+ def view (obj:value.ExactNumeric[Short]): Short = obj.nativeValue;
+ def view (obj:value.ExactNumeric[Int]): Int = obj.nativeValue;
+ def view (obj:value.ExactNumeric[Long]): Long = obj.nativeValue;
+ def view (obj:value.ExactNumeric[BigInteger]): BigInteger = obj.nativeValue;
+ def view (obj:value.ExactNumeric[BigDecimal]): BigDecimal = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/value/Factory.scala b/src/library/scala/dbc/value/Factory.scala
new file mode 100644
index 0000000000..b24f985354
--- /dev/null
+++ b/src/library/scala/dbc/value/Factory.scala
@@ -0,0 +1,91 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+import java.math.BigInteger;
+import java.math.BigDecimal;
+
+object Factory {
+
+ def create (result: java.sql.ResultSet, index: Int, expectedDataType: DataType): Value = {
+ expectedDataType.nativeTypeId match {
+ case DataType.OBJECT =>
+ new value.Unknown {
+ val dataType = expectedDataType.asInstanceOf[datatype.Unknown];
+ val nativeValue: Object = result.getObject(index);
+ }
+ case DataType.STRING => {
+ expectedDataType match {
+ case t:datatype.Character =>
+ new value.Character {
+ val dataType = t;
+ val nativeValue: String = result.getString(index);
+ }
+ case t:datatype.CharacterVarying =>
+ new value.CharacterVarying {
+ val dataType = t;
+ val nativeValue: String = result.getString(index);
+ }
+ case t:datatype.CharacterLargeObject =>
+ new value.CharacterLargeObject {
+ val dataType = t;
+ val nativeValue: String = result.getString(index);
+ }
+ }
+ }
+ case DataType.BOOLEAN =>
+ new value.Boolean {
+ val dataType = expectedDataType.asInstanceOf[datatype.Boolean];
+ val nativeValue: scala.Boolean = result.getBoolean(index);
+ }
+ case DataType.FLOAT =>
+ new value.ApproximateNumeric[Float] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Float]];
+ val nativeValue: Float = result.getFloat(index);
+ }
+ case DataType.DOUBLE =>
+ new value.ApproximateNumeric[Double] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Double]];
+ val nativeValue: Double = result.getDouble(index);
+ }
+ case DataType.BYTE =>
+ new value.ExactNumeric[Byte] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Byte]];
+ val nativeValue: Byte = result.getByte(index);
+ }
+ case DataType.SHORT =>
+ new value.ExactNumeric[Short] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Short]];
+ val nativeValue: Short = result.getShort(index);
+ }
+ case DataType.INT =>
+ new value.ExactNumeric[Int] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Int]];
+ val nativeValue: Int = result.getInt(index);
+ }
+ case DataType.LONG =>
+ new value.ExactNumeric[Long] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Long]];
+ val nativeValue:Long = result.getLong(index);
+ }
+ case DataType.BIG_INTEGER =>
+ new value.ExactNumeric[BigInteger] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigInteger]];
+ val nativeValue: BigInteger = result.getBigDecimal(index).unscaledValue();
+ }
+ case DataType.BIG_DECIMAL =>
+ new value.ExactNumeric[BigDecimal] {
+ val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigDecimal]];
+ val nativeValue: BigDecimal = result.getBigDecimal(index);
+ }
+
+ }
+ }
+
+}
diff --git a/src/library/scala/dbc/value/Unknown.scala b/src/library/scala/dbc/value/Unknown.scala
new file mode 100644
index 0000000000..b40df69011
--- /dev/null
+++ b/src/library/scala/dbc/value/Unknown.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.value;
+
+abstract class Unknown extends Value {
+
+ val dataType: datatype.Unknown;
+
+ def sqlString = error ("An 'ANY' value cannot be represented.");
+
+}
+
+object UnknownType {
+
+ def view (obj:value.Unknown): Object = obj.nativeValue;
+
+} \ No newline at end of file
diff --git a/src/library/scala/dbc/vendor/PostgreSQL.scala b/src/library/scala/dbc/vendor/PostgreSQL.scala
new file mode 100644
index 0000000000..2653ed714a
--- /dev/null
+++ b/src/library/scala/dbc/vendor/PostgreSQL.scala
@@ -0,0 +1,23 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.dbc.vendor;
+
+abstract class PostgreSQL extends Vendor {
+
+ def uri:java.net.URI;
+ def user:String;
+ def pass:String;
+
+ val retainedConnections = 5;
+
+ val nativeDriverClass = Class.forName("org.postgresql.Driver");
+
+ val urlProtocolString = "jdbc:postgresql:"
+
+} \ No newline at end of file
diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala
new file mode 100644
index 0000000000..ef61e01317
--- /dev/null
+++ b/src/library/scala/io/Position.scala
@@ -0,0 +1,92 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.io;
+
+/** 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 &lt; line2) || (line1 == line2 &amp;&amp; column1 &lt; column2)
+ * implies
+ * encode(line1,column1) &lt;= encode(line2,column2)
+ * @author Burak Emir (translated from work by Matthias Zengers 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 )
+ error(line+" < 0");
+ if(( line == 0 )&&(column != 0))
+ error(line+","+column+" not allowed");
+ if( column < 0 )
+ error(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 StringBuffer();
+ sb.append(line(pos));
+ sb.append(':');
+ sb.append(column(pos));
+ sb.toString();
+ }
+}
diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala
new file mode 100644
index 0000000000..a22657e4be
--- /dev/null
+++ b/src/library/scala/io/Source.scala
@@ -0,0 +1,252 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.io;
+
+import java.io.{ File, FileInputStream, PrintStream };
+
+/** convenience methods to create an iterable representation of a source
+ * file
+ * @author buraq
+ */
+object Source {
+
+ /** creates Source from array of bytes, with empty description
+ */
+ def fromBytes(bytes: Array[Byte]): Source =
+ fromString(new String(bytes));
+
+ /** creates Source from array of bytes with given encoding, with empty description
+ */
+ def fromBytes(bytes: Array[Byte], enc: String): Source =
+ fromString(new String(bytes, enc));
+
+ /** creates Source from a single char */
+ 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
+ */
+ 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
+ */
+ 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.
+ */
+ 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);
+ }
+
+ def setFileDescriptor(file: File, s: Source): Source = {
+ s.descr = new StringBuffer()
+ .append( "file:" )
+ .append( file.getAbsolutePath() )
+ .toString();
+ s
+ }
+
+ def fromURL(s:String): Source =
+ fromURL(new java.net.URL(s));
+
+ 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
+ }
+
+}
+
+/** an iterable representation of source files.
+ * calling method reset returns an identical, resetted source
+ *
+ * @author buraq
+ */
+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
+ */
+ def getLine(line: Int): String = {
+ val buf = new StringBuffer();
+ 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 java.lang.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 );
+ res
+ }
+
+ /** 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 */
+ def reportError(pos: Int, msg: String): Unit = {
+ report(pos, msg, java.lang.System.out);
+ }
+
+ def reportError(pos: Int, msg: String, out: PrintStream): Unit = {
+ nerrors = nerrors + 1;
+ report(pos, msg, java.lang.System.out);
+ }
+
+ def report(pos: Int, msg: String, out: PrintStream): Unit = {
+ val line = Position.line(pos);
+ val col = Position.column(pos);
+ Console.println(descr+":"+line+":"+col+": "+msg);
+ Console.println(getLine(line));
+ var i = 1;
+ while( i < col ) {
+ Console.print(' ');
+ i = i + 1;
+ }
+ Console.println('^');
+ }
+
+ /** reports a warning message to java.lang.System.out */
+ def reportWarning(pos: Int, msg: String): Unit =
+ reportWarning(pos, msg, java.lang.System.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/library/scala/mobile/Code.scala b/src/library/scala/mobile/Code.scala
new file mode 100644
index 0000000000..1ce9997a3d
--- /dev/null
+++ b/src/library/scala/mobile/Code.scala
@@ -0,0 +1,234 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.mobile;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+
+/** The class <code>Code</code> provides <code>apply</code> methods
+ * with different arities (actually up to 9 parameters) to invoke
+ * a function simply by specifying its name and argument types.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> url = <b>new</b> URL("http://scala.epfl.ch/classes/examples.jar");
+ * <b>val</b> obj = <b>new</b> Location(url) create "examples.sort";
+ * <b>val</b> ar = Array(6, 2, 8, 5, 1);
+ * obj[Array[Int], Unit]("println")(ar);
+ * obj[Array[Int], Unit]("sort")(ar);
+ * obj[Array[Int], Unit]("println")(ar);</pre>
+ *
+ * @see <a href="Location-class.html">Location</a>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Code(clazz: java.lang.Class) {
+
+ private type JObject = java.lang.Object;
+
+ private var instance: JObject = _;
+
+ ///////////////////////////// apply methods ///////////////////////////////
+
+ def apply[R](funName: String) =
+ () => {
+ val args = Predef.Array[JObject]();
+ val types = Predef.Array[Class]();
+ applyFun(funName, args, types).asInstanceOf[R];
+ };
+
+ def apply[A0, R](funName: String) =
+ (_0: A0) => {
+ val p = boxValue(_0);
+ val args = Predef.Array(p._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1);
+ val types = Predef.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 = Predef.Array(p0._1, p1._1, p2._1, p3._1, p4._1, p5._1, p6._1, p7._1, p8._1);
+ val types = Predef.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 => Pair(new java.lang.Byte(x), java.lang.Byte.TYPE)
+ case x: Boolean => Pair(new java.lang.Boolean(x), java.lang.Boolean.TYPE)
+ case x: Char => Pair(new java.lang.Character(x), java.lang.Character.TYPE)
+ case x: Short => Pair(new java.lang.Short(x), java.lang.Short.TYPE)
+ case x: Int => Pair(new java.lang.Integer(x), java.lang.Integer.TYPE)
+ case x: Long => Pair(new java.lang.Long(x), java.lang.Long.TYPE)
+ case x: Float => Pair(new java.lang.Float(x), java.lang.Float.TYPE)
+ case x: Double => Pair(new java.lang.Double(x), java.lang.Double.TYPE)
+ case _ =>
+ val x = value.asInstanceOf[JObject];
+ Pair(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 == null) {
+ instance = try {
+ clazz.newInstance();
+ } catch { case _ =>
+ val cs = clazz.getConstructors();
+//Console.println("cs.length=" + cs.length);
+ if (cs.length > 0) {
+ cs(0).newInstance(Predef.Array(""))
+ } else {
+ error("class " + clazz.getName() + " has no public constructor");
+ null
+ }
+ }
+ }
+ obj = instance;
+ }
+ val result = method.invoke(obj, args);
+ if (result == 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/library/scala/mobile/Location.scala b/src/library/scala/mobile/Location.scala
new file mode 100644
index 0000000000..c6f7d57648
--- /dev/null
+++ b/src/library/scala/mobile/Location.scala
@@ -0,0 +1,96 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.mobile;
+
+import java.net._;
+
+import scala.collection.mutable._;
+
+
+/** The class <code>Location</code> provides a <code>create</code>
+ * method to instantiate objects from a network location by
+ * specifying the URL address of the jar/class file.<p/>
+ *
+ * An update of the jar/class file should not break your code as far
+ * as the used class names and method signatures are the same.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> url = <b>new</b> URL("http://scala.epfl.ch/classes/examples.jar");
+ * <b>val</b> obj = <b>new</b> Location(url) create "examples.sort";</pre>
+ *
+ * @see <a href="Code-class.html">Code</a>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+class Location(url: URL) {
+
+ /** A cache containing all class loaders of this location.
+ */
+ private var lcache: Map[URL, ClassLoader] = new HashMap;
+
+ /** The class loader associated with this location.
+ */
+ private val loader = if (url == null)
+ ClassLoader.getSystemClassLoader()
+ else
+ lcache.get(url) match {
+ case Some(cl) =>
+ cl
+ case _ =>
+ val cl = new URLClassLoader(Predef.Array(url));
+ lcache(url) = cl;
+ cl
+ };
+
+ /** A cache containing all classes of this location.
+ */
+ private var ccache: Map[String, java.lang.Class] = new HashMap;
+
+ /** Return the code description for the string <code>className</code>
+ * at this location.
+ *
+ * @param the name of the class
+ * @return the code description corresponding to <code>className</code>
+ */
+ def create(className: String) = new Code(
+ ccache.get(className) match {
+ case Some(clazz) =>
+ clazz
+ case _ =>
+ val clazz = if (loader.loadClass(className).isInterface()) {
+ // Scala source: class A { ... };
+ // Java bytecode: interface A.class + class A$class.class
+ loader.loadClass(className + "$class");
+ }
+ else {
+ // Scala source: object A { ... };
+ // Java bytecode: interface A.class + class A$.class
+ loader.loadClass(className + "$");
+ }
+ ccache(className) = clazz;
+ clazz
+ }
+ );
+
+}
+
+/** The object <code>Location</code> can be used to instantiate
+ * objects on the same Java VM. It is just provided to illustrate
+ * the special case where resources are available locally.<p/>
+ *
+ * Example:<pre>
+ * <b>val</b> obj = Location.create("xcode.Math");
+ * <b>val</b> x = obj[Int, Int]("square")(5);</pre>
+ *
+ * @author Stephane Micheloud
+ * @version 1.0, 04/05/2004
+ */
+object Location extends Location(null);
diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala
new file mode 100644
index 0000000000..b354bd753f
--- /dev/null
+++ b/src/library/scala/reflect/Code.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect;
+
+abstract class Code;
+
+case class Ident(sym: Symbol) extends Code;
+case class Select(qual: Code, sym: Symbol) extends Code;
+case class Literal(value: Any) extends Code;
+case class Apply(fun: Code, args: List[Code]) extends Code;
+case class TypeApply(fun: Code, args: List[Type]) extends Code;
+case class Function(params: List[Symbol], body: Code) extends Code;
+case class This(sym: Symbol) extends Code;
diff --git a/src/library/scala/reflect/Print.scala b/src/library/scala/reflect/Print.scala
new file mode 100644
index 0000000000..decfe933cc
--- /dev/null
+++ b/src/library/scala/reflect/Print.scala
@@ -0,0 +1,113 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect;
+
+object Print extends Function1[Any, String] {
+
+ def apply (any: Any): String = {
+ if (any.isInstanceOf[TypedCode[Any]])
+ apply(any.asInstanceOf[TypedCode[Any]])
+ else if (any.isInstanceOf[Code])
+ apply(any.asInstanceOf[Code])
+ else if (any.isInstanceOf[Symbol])
+ apply(any.asInstanceOf[Symbol])
+ else if (any.isInstanceOf[Type])
+ apply(any.asInstanceOf[Type])
+ else "UnknownAny"
+ }
+
+ def apply (typedCode: TypedCode[Any]): String =
+ Print(typedCode.code);
+
+ def apply (code: Code): String = code match {
+ case reflect.Ident(sym) =>
+ "Ident (" + Print(sym) + ")"
+ case reflect.Select(qual, sym) =>
+ "Select (" + Print(qual) + " from " + Print(sym) + ")"
+ case reflect.Literal(value) =>
+ "Literal (" + value + ")"
+ case reflect.Apply(fun, args) =>
+ ("Apply (" + Print(fun) + " on " +
+ ((args match {
+ case Nil => "nothing "
+ case _ :: _ => args.map(Print).mkString("", ", ", "")
+ }):String) + ")")
+ case reflect.TypeApply(fun, args) =>
+ ("TypeApply (" + Print(fun) + " on " +
+ ((args match {
+ case Nil => "nothing"
+ case _ :: _ => args.map(Print).mkString("", ", ", "")
+ }):String) + ")")
+ case reflect.Function(params, body) =>
+ ("Function (" +
+ ((params match {
+ case Nil => "nothing"
+ case _ :: _ => params.map(Print).mkString("", ", ", "")
+ }):String) + " is " + Print(body) + ")")
+ case reflect.This(sym) =>
+ "This (" + Print(sym) + ")"
+ case _ => "UnknownCode"
+ }
+
+ def apply (symbol: Symbol): String = symbol match {
+ case reflect.Class(name) =>
+ "Class (" + name + ")"
+ case reflect.Method(name, datatype) =>
+ "Method (" + name + " of " + Print(datatype) + ")"
+ case reflect.Field(name, datatype) =>
+ "Field (" + name + " of " + Print(datatype) + ")"
+ case reflect.TypeField(name, datatype) =>
+ "TypeField (" + name + " of " + Print(datatype) + ")"
+ case reflect.LocalValue(owner, name, datatype) =>
+ ("LocalValue (" + name + " owned by " + Print(owner) +
+ " of " + Print(datatype) + ")")
+ case reflect.LocalMethod(owner, name, datatype) =>
+ ("LocalMethod (" + name + " owned by " + Print(owner) +
+ " of " + Print(datatype) + ")")
+ case reflect.NoSymbol => "NoSymbol"
+ case reflect.RootSymbol => "RootSymbol"
+ case _ => "UnknownSymbol"
+ }
+
+ def apply (datatype: Type): String = datatype match {
+ case reflect.NoPrefix => "NoPrefix"
+ case reflect.NoType => "NoType"
+ case reflect.NamedType(name) =>
+ "NamedType (" + name + ")"
+ case reflect.PrefixedType(prefix, symbol) =>
+ "PrefixedType (" + Print(symbol) + " in " + Print(prefix) + ")"
+ case reflect.SingleType(prefix, symbol) =>
+ "SingleType (" + Print(symbol) + " in " + Print(prefix) + ")"
+ case reflect.ThisType(clazz) =>
+ "ThisType (" + Print(clazz) + ")"
+ case reflect.AppliedType(datatype, args) =>
+ ("AppliedType (" + Print(datatype) + " on " +
+ ((args match {
+ case Nil => "nothing"
+ case _ :: _ => args.map(Print).mkString("", ", ", "")
+ }):String) + ")")
+ case reflect.TypeBounds(lo, hi) =>
+ "TypeBounds (" + Print(lo) + " to " + Print(hi) + ")"
+ case reflect.MethodType(formals, resultType) =>
+ ("MethodType (" +
+ ((formals match {
+ case Nil => "nothing"
+ case _ :: _ => formals.map(Print).mkString("", ", ", "")
+ }):String) + " is " + Print(resultType) + ")")
+ case reflect.PolyType(typeParams, typeBounds, resultType) =>
+ ("PolyType (" + (typeParams zip typeBounds).map{
+ case Pair(typeParam, Pair(lo, hi)) =>
+ Print(lo) + " < " + Print(typeParam) + " < " + Print(hi)
+ }.mkString("", ", ", "") + " to " + Print(resultType) + ")")
+ case _ => "UnknownType"
+ }
+
+}
diff --git a/src/library/scala/reflect/Symbol.scala b/src/library/scala/reflect/Symbol.scala
new file mode 100644
index 0000000000..14be8e9317
--- /dev/null
+++ b/src/library/scala/reflect/Symbol.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.reflect;
+
+abstract class Symbol {
+ val owner: Symbol;
+ val name: String;
+ val tpe: Type;
+}
+
+abstract class GlobalSymbol(val fullname: String) extends Symbol {
+ private val pointIndex = fullname.lastIndexOf('.');
+ val owner: Symbol =
+ if (pointIndex < 0) RootSymbol else Class(fullname.substring(0, pointIndex));
+ val name: String =
+ if (pointIndex < 0) fullname else fullname.substring(pointIndex, fullname.length());
+}
+
+abstract class LocalSymbol extends Symbol {}
+
+case class Class(override val fullname: String) extends GlobalSymbol(fullname) {
+ val tpe = NamedType(fullname);
+}
+
+case class Method(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname);
+
+case class Field(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname);
+
+case class TypeField(override val fullname: String, tpe: Type) extends GlobalSymbol(fullname);
+
+case class LocalValue(owner: Symbol, name: String, tpe: Type) extends LocalSymbol;
+
+case class LocalMethod(owner: Symbol, name: String, tpe: Type) extends LocalSymbol;
+
+case object NoSymbol extends Symbol {
+ val owner = null;
+ val name = null;
+ val tpe = NoType
+}
+
+case object RootSymbol extends Symbol {
+ val owner = NoSymbol;
+ val name = "<root>";
+ val tpe = NoPrefix
+}
diff --git a/src/library/scala/reflect/Type.scala b/src/library/scala/reflect/Type.scala
new file mode 100644
index 0000000000..c0b86162f6
--- /dev/null
+++ b/src/library/scala/reflect/Type.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect;
+
+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 &lt;: lo &gt;: 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[Pair[Type, Type]], resultType: Type) extends Type;
+
+/** */
+class ImplicitMethodType(formals: List[Type], restpe: Type) extends MethodType(formals, restpe);
diff --git a/src/library/scala/reflect/TypedCode.scala b/src/library/scala/reflect/TypedCode.scala
new file mode 100644
index 0000000000..38ce0512c7
--- /dev/null
+++ b/src/library/scala/reflect/TypedCode.scala
@@ -0,0 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.reflect;
+
+class TypedCode[T](val code: Code) {
+}
+
diff --git a/src/library/scala/remote.scala b/src/library/scala/remote.scala
new file mode 100644
index 0000000000..825cfbdc44
--- /dev/null
+++ b/src/library/scala/remote.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:$
+*/
+
+package scala;
+
+class remote extends Attribute {}
diff --git a/src/library/scala/runtime/AtomicReference.java b/src/library/scala/runtime/AtomicReference.java
new file mode 100644
index 0000000000..7eb4abdb0e
--- /dev/null
+++ b/src/library/scala/runtime/AtomicReference.java
@@ -0,0 +1,54 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+/**
+ * Blocking (i.e. non-atomic) placeholder for Java 1.5's
+ * <code>java.util.concurrent.atomic.AtomicReference</code> class.
+ */
+
+public class AtomicReference implements java.io.Serializable {
+ private Object value;
+
+ public AtomicReference(Object value) {
+ this.value = value;
+ }
+
+ public Object get() {
+ return value;
+ }
+
+ public Object getAndSet(Object update) {
+ Object previousValue = value;
+ value = update;
+ return previousValue;
+ }
+
+ public void set(Object update) {
+ value = update;
+ }
+
+ public synchronized boolean compareAndSet(Object expected, Object update) {
+ if (value == expected) {
+ value = update;
+ return true;
+ } else
+ return false;
+ }
+
+ public boolean weakCompareAndSet(Object expected, Object update) {
+ return compareAndSet(expected, update);
+ }
+
+ public String toString() {
+ return value.toString();
+ }
+}
diff --git a/src/library/scala/runtime/BooleanRef.java b/src/library/scala/runtime/BooleanRef.java
new file mode 100644
index 0000000000..f0ebcabe97
--- /dev/null
+++ b/src/library/scala/runtime/BooleanRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, 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/library/scala/runtime/BoxedAnyArray.scala b/src/library/scala/runtime/BoxedAnyArray.scala
new file mode 100644
index 0000000000..ac37a62427
--- /dev/null
+++ b/src/library/scala/runtime/BoxedAnyArray.scala
@@ -0,0 +1,154 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+/** 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[Object](length);
+ private val hash = boxed.hashCode();
+ private var unboxed: Object = null;
+ private var elemTag: String = null;
+
+ def apply(index: Int): Object = synchronized {
+ if (unboxed == null)
+ boxed(index);
+ else if (elemTag == ScalaRunTime.IntTag)
+ BoxedInt.box(unboxed.asInstanceOf[Array[Int]](index))
+ else if (elemTag == ScalaRunTime.DoubleTag)
+ BoxedDouble.box(unboxed.asInstanceOf[Array[Double]](index))
+ else if (elemTag == ScalaRunTime.FloatTag)
+ BoxedFloat.box(unboxed.asInstanceOf[Array[Float]](index))
+ else if (elemTag == ScalaRunTime.LongTag)
+ BoxedLong.box(unboxed.asInstanceOf[Array[Long]](index))
+ else if (elemTag == ScalaRunTime.CharTag)
+ BoxedChar.box(unboxed.asInstanceOf[Array[Char]](index))
+ else if (elemTag == ScalaRunTime.ByteTag)
+ BoxedByte.box(unboxed.asInstanceOf[Array[Byte]](index))
+ else if (elemTag == ScalaRunTime.ShortTag)
+ BoxedShort.box(unboxed.asInstanceOf[Array[Short]](index))
+ else if (elemTag == ScalaRunTime.BooleanTag)
+ BoxedBoolean.box(unboxed.asInstanceOf[Array[Boolean]](index))
+ else
+ unboxed.asInstanceOf[Array[Object]](index)
+ }
+
+ def update(index: Int, elem: Object): Unit = synchronized {
+ if (unboxed == null)
+ boxed(index) = elem;
+ else if (elemTag == ScalaRunTime.IntTag)
+ unboxed.asInstanceOf[Array[Int]](index) = elem.asInstanceOf[BoxedNumber].intValue()
+ else if (elemTag == ScalaRunTime.DoubleTag)
+ unboxed.asInstanceOf[Array[Double]](index) = elem.asInstanceOf[BoxedNumber].doubleValue()
+ else if (elemTag == ScalaRunTime.FloatTag)
+ unboxed.asInstanceOf[Array[Float]](index) = elem.asInstanceOf[BoxedNumber].floatValue()
+ else if (elemTag == ScalaRunTime.LongTag)
+ unboxed.asInstanceOf[Array[Long]](index) = elem.asInstanceOf[BoxedNumber].longValue()
+ else if (elemTag == ScalaRunTime.CharTag)
+ unboxed.asInstanceOf[Array[Char]](index) = elem.asInstanceOf[BoxedNumber].charValue()
+ else if (elemTag == ScalaRunTime.ByteTag)
+ unboxed.asInstanceOf[Array[Byte]](index) = elem.asInstanceOf[BoxedNumber].byteValue()
+ else if (elemTag == ScalaRunTime.ShortTag)
+ unboxed.asInstanceOf[Array[Short]](index) = elem.asInstanceOf[BoxedNumber].shortValue()
+ else if (elemTag == ScalaRunTime.BooleanTag)
+ unboxed.asInstanceOf[Array[Boolean]](index) = elem.asInstanceOf[BoxedBoolean].value
+ else
+ unboxed.asInstanceOf[Array[Object]](index) = elem
+ }
+
+ def unbox(elemTag: String): Object = synchronized {
+ if (unboxed == null) {
+ this.elemTag = elemTag;
+ if (elemTag == ScalaRunTime.IntTag) {
+ val newvalue = new Array[Int](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].intValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.DoubleTag) {
+ val newvalue = new Array[Double](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].doubleValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.FloatTag) {
+ val newvalue = new Array[Float](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].floatValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.LongTag) {
+ val newvalue = new Array[Long](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].longValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.CharTag) {
+ val newvalue = new Array[Char](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].charValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.ByteTag) {
+ val newvalue = new Array[Byte](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].byteValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.ShortTag) {
+ val newvalue = new Array[Short](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedNumber].shortValue();
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == ScalaRunTime.BooleanTag) {
+ val newvalue = new Array[Boolean](length);
+ var i = 0;
+ while (i < length) {
+ newvalue(i) = boxed(i).asInstanceOf[BoxedBoolean].value;
+ i = i + 1
+ }
+ unboxed = newvalue;
+ } else if (elemTag == boxed.getClass().getComponentType()) {
+ unboxed = boxed;
+ } else {
+ unboxed = java.lang.reflect.Array.newInstance(Class.forName(elemTag), length);
+ System.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 == null) boxed == other else unboxed == other)
+ );
+
+ override def hashCode(): Int = hash;
+}
+
diff --git a/src/library/scala/runtime/BoxedArray.scala b/src/library/scala/runtime/BoxedArray.scala
new file mode 100644
index 0000000000..29b4ccf0e2
--- /dev/null
+++ b/src/library/scala/runtime/BoxedArray.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.runtime;
+
+/** A class representing Array[T]
+ */
+abstract class BoxedArray extends PartialFunction[Int, Object] with Seq[Object] {
+ /** The length of the array */
+ def length: Int;
+
+ /** The element at given index */
+ def apply(index: Int): Object;
+
+ /** Update element at given index */
+ def update(index: Int, elem: Object): 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.
+ */
+ def unbox(elemTag: String): Object;
+
+ override def isDefinedAt(x: Int): Boolean = 0 <= x && x < length;
+
+ override def toString(): String = {
+ val buf = new StringBuffer();
+ buf.append("Array(");
+ val len = length;
+ var i = 0;
+ while (i < len) { buf.append(apply(i)); i = i + 1 }
+ buf.append(")");
+ buf.toString()
+ }
+
+ def elements = new Iterator[Object] {
+ var index = 0;
+ def hasNext: Boolean = index < length;
+ def next: Object = { val i = index; index = i + 1; apply(i) }
+ }
+}
diff --git a/src/library/scala/runtime/BoxedBoolean.java b/src/library/scala/runtime/BoxedBoolean.java
new file mode 100644
index 0000000000..ad7ec887e4
--- /dev/null
+++ b/src/library/scala/runtime/BoxedBoolean.java
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, 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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return other instanceof BoxedBoolean && value == ((BoxedBoolean) other).value;
+ }
+
+ public int hashCode() {
+ return value ? 1 : 0;
+ }
+
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
diff --git a/src/library/scala/runtime/BoxedBooleanArray.scala b/src/library/scala/runtime/BoxedBooleanArray.scala
new file mode 100644
index 0000000000..27b4af2643
--- /dev/null
+++ b/src/library/scala/runtime/BoxedBooleanArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedBooleanArray(val value: Array[Boolean]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedBoolean.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedBoolean].value
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedBooleanArray] && value == other.asInstanceOf[BoxedBooleanArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedByte.java b/src/library/scala/runtime/BoxedByte.java
new file mode 100644
index 0000000000..b29570081e
--- /dev/null
+++ b/src/library/scala/runtime/BoxedByte.java
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedByteArray.scala b/src/library/scala/runtime/BoxedByteArray.scala
new file mode 100644
index 0000000000..e011b8e805
--- /dev/null
+++ b/src/library/scala/runtime/BoxedByteArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedByteArray(val value: Array[Byte]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedByte.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].byteValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedByteArray] && value == other.asInstanceOf[BoxedByteArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedChar.java b/src/library/scala/runtime/BoxedChar.java
new file mode 100644
index 0000000000..02b81e111d
--- /dev/null
+++ b/src/library/scala/runtime/BoxedChar.java
@@ -0,0 +1,59 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedCharArray.scala b/src/library/scala/runtime/BoxedCharArray.scala
new file mode 100644
index 0000000000..49e3cba25c
--- /dev/null
+++ b/src/library/scala/runtime/BoxedCharArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedCharArray(val value: Array[Char]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedChar.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].charValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedCharArray] && value == other.asInstanceOf[BoxedCharArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedDouble.java b/src/library/scala/runtime/BoxedDouble.java
new file mode 100644
index 0000000000..98736f03a4
--- /dev/null
+++ b/src/library/scala/runtime/BoxedDouble.java
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedDoubleArray.scala b/src/library/scala/runtime/BoxedDoubleArray.scala
new file mode 100644
index 0000000000..752ab99950
--- /dev/null
+++ b/src/library/scala/runtime/BoxedDoubleArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedDoubleArray(val value: Array[Double]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedDouble.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].doubleValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedDoubleArray] && value == other.asInstanceOf[BoxedDoubleArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedFloat.java b/src/library/scala/runtime/BoxedFloat.java
new file mode 100644
index 0000000000..630ee6bece
--- /dev/null
+++ b/src/library/scala/runtime/BoxedFloat.java
@@ -0,0 +1,49 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedFloatArray.scala b/src/library/scala/runtime/BoxedFloatArray.scala
new file mode 100644
index 0000000000..bdf25b8f6b
--- /dev/null
+++ b/src/library/scala/runtime/BoxedFloatArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedFloatArray(val value: Array[Float]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedFloat.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].floatValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedFloatArray] && value == other.asInstanceOf[BoxedFloatArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedInt.java b/src/library/scala/runtime/BoxedInt.java
new file mode 100644
index 0000000000..9842fde1ad
--- /dev/null
+++ b/src/library/scala/runtime/BoxedInt.java
@@ -0,0 +1,59 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedIntArray.scala b/src/library/scala/runtime/BoxedIntArray.scala
new file mode 100644
index 0000000000..9d0db5b233
--- /dev/null
+++ b/src/library/scala/runtime/BoxedIntArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedIntArray(val value: Array[Int]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedInt.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].intValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedIntArray] && value == other.asInstanceOf[BoxedIntArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedLong.java b/src/library/scala/runtime/BoxedLong.java
new file mode 100644
index 0000000000..ebc86e4c92
--- /dev/null
+++ b/src/library/scala/runtime/BoxedLong.java
@@ -0,0 +1,50 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedLongArray.scala b/src/library/scala/runtime/BoxedLongArray.scala
new file mode 100644
index 0000000000..624e992e01
--- /dev/null
+++ b/src/library/scala/runtime/BoxedLongArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedLongArray(val value: Array[Long]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedLong.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].longValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedLongArray] && value == other.asInstanceOf[BoxedLongArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedNumber.java b/src/library/scala/runtime/BoxedNumber.java
new file mode 100644
index 0000000000..a21abab2db
--- /dev/null
+++ b/src/library/scala/runtime/BoxedNumber.java
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $OldId: RunTime.java,v 1.13 2002/11/19 12:01:40 paltherr Exp $
+// $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/library/scala/runtime/BoxedObjectArray.scala b/src/library/scala/runtime/BoxedObjectArray.scala
new file mode 100644
index 0000000000..12ff59da8c
--- /dev/null
+++ b/src/library/scala/runtime/BoxedObjectArray.scala
@@ -0,0 +1,29 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+final class BoxedObjectArray(val value: Array[Object]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = value(index);
+
+ def update(index: Int, elem: Object): Unit = { value(index) = elem }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any): Boolean = (
+ value == other ||
+ other.isInstanceOf[BoxedObjectArray] && value == other.asInstanceOf[BoxedObjectArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
diff --git a/src/library/scala/runtime/BoxedShort.java b/src/library/scala/runtime/BoxedShort.java
new file mode 100644
index 0000000000..f1074c7b7f
--- /dev/null
+++ b/src/library/scala/runtime/BoxedShort.java
@@ -0,0 +1,59 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+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 final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ 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/library/scala/runtime/BoxedShortArray.scala b/src/library/scala/runtime/BoxedShortArray.scala
new file mode 100644
index 0000000000..01e00c5a21
--- /dev/null
+++ b/src/library/scala/runtime/BoxedShortArray.scala
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+[serializable]
+final class BoxedShortArray(val value: Array[Short]) extends BoxedArray {
+
+ def length: Int = value.length;
+
+ def apply(index: Int): Object = BoxedShort.box(value(index));
+
+ def update(index: Int, elem: Object): Unit = {
+ value(index) = elem.asInstanceOf[BoxedNumber].shortValue()
+ }
+
+ def unbox(elemTag: String): Object = value;
+
+ override def equals(other: Any) = (
+ value == other ||
+ other.isInstanceOf[BoxedShortArray] && value == other.asInstanceOf[BoxedShortArray].value
+ );
+
+ override def hashCode(): Int = value.hashCode();
+}
+
diff --git a/src/library/scala/runtime/BoxedUnit.java b/src/library/scala/runtime/BoxedUnit.java
new file mode 100644
index 0000000000..91e5f5d03a
--- /dev/null
+++ b/src/library/scala/runtime/BoxedUnit.java
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.runtime;
+
+public final class BoxedUnit
+ implements java.io.Serializable
+{
+
+ public final static BoxedUnit UNIT = new BoxedUnit();
+
+ private BoxedUnit() { }
+
+ public final boolean $eq$eq(java.lang.Object other) {
+ return equals(other);
+ }
+
+ public final boolean $bang$eq(java.lang.Object other) {
+ return !equals(other);
+ }
+
+ public boolean equals(java.lang.Object other) {
+ return this == other;
+ }
+
+ public int hashCode() {
+ return 0;
+ }
+
+ public String toString() {
+ return "()";
+ }
+}
diff --git a/src/library/scala/runtime/ByteRef.java b/src/library/scala/runtime/ByteRef.java
new file mode 100644
index 0000000000..f4a98b8ff6
--- /dev/null
+++ b/src/library/scala/runtime/ByteRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class ByteRef implements java.io.Serializable {
+ public byte elem;
+ public ByteRef(byte elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/CharRef.java b/src/library/scala/runtime/CharRef.java
new file mode 100644
index 0000000000..71d3666b4e
--- /dev/null
+++ b/src/library/scala/runtime/CharRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class CharRef implements java.io.Serializable {
+ public char elem;
+ public CharRef(char elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/DoubleRef.java b/src/library/scala/runtime/DoubleRef.java
new file mode 100644
index 0000000000..a0fd0ff68b
--- /dev/null
+++ b/src/library/scala/runtime/DoubleRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class DoubleRef implements java.io.Serializable {
+ public double elem;
+ public DoubleRef(double elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/ExceptionHandling.cs b/src/library/scala/runtime/ExceptionHandling.cs
new file mode 100644
index 0000000000..0a59308f99
--- /dev/null
+++ b/src/library/scala/runtime/ExceptionHandling.cs
@@ -0,0 +1,33 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+using System;
+using scala;
+
+namespace scala.runtime {
+
+ public abstract class RunTime {
+
+ public interface Runnable {
+ void run();
+ }
+
+ public static Exception tryCatch(Runnable runnable) {
+ try {
+ runnable.run();
+ return null;
+ } catch (Exception exception) {
+ return exception;
+ }
+ }
+
+ }
+
+}
diff --git a/src/library/scala/runtime/ExceptionHandling.java b/src/library/scala/runtime/ExceptionHandling.java
new file mode 100644
index 0000000000..293d2cad8e
--- /dev/null
+++ b/src/library/scala/runtime/ExceptionHandling.java
@@ -0,0 +1,24 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, 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/library/scala/runtime/FNV_Hash.java b/src/library/scala/runtime/FNV_Hash.java
new file mode 100644
index 0000000000..6259c33efb
--- /dev/null
+++ b/src/library/scala/runtime/FNV_Hash.java
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+/**
+ * Provide methods to compute the various kinds of Fowler / Noll / Vo
+ * (FNV) hash.
+ *
+ * @author Michel Schinz
+ */
+
+public class FNV_Hash {
+ public static final int INIT = -2128831035;
+
+ public static int hashStep8(int current, int newInt8) {
+ return (current * 16777619) ^ newInt8;
+ }
+
+ public static int hashStep32(int current, int newInt32) {
+ final int v1 = hashStep8(current, newInt32 >> 24);
+ final int v2 = hashStep8(v1, (newInt32 >> 16) & 0xFF);
+ final int v3 = hashStep8(v2, (newInt32 >> 8) & 0xFF);
+ return hashStep8(v3, newInt32 & 0xFF);
+ }
+
+ public static int hash32(byte[] bytes) {
+ final int len = bytes.length;
+
+ int h = INIT;
+ for (int i = 0; i < len; ++i)
+ h = hashStep8(h, bytes[i]);
+
+ return h;
+ }
+
+ public static int hash32(String str) {
+ try {
+ return hash32(str.getBytes("UTF-8"));
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new Error(e);
+ }
+ }
+}
diff --git a/src/library/scala/runtime/FloatRef.java b/src/library/scala/runtime/FloatRef.java
new file mode 100644
index 0000000000..dc8c332b66
--- /dev/null
+++ b/src/library/scala/runtime/FloatRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class FloatRef implements java.io.Serializable {
+ public float elem;
+ public FloatRef(float elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/IOMap.java b/src/library/scala/runtime/IOMap.java
new file mode 100644
index 0000000000..e93b3c4a9d
--- /dev/null
+++ b/src/library/scala/runtime/IOMap.java
@@ -0,0 +1,171 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+/**
+ * Purely functional maps from integers to objects. Implemented as
+ * red-black trees.
+ *
+ * @author Michel Schinz
+ * @version 1.0
+ */
+
+public class IOMap implements java.io.Serializable {
+
+ /** The map class itself */
+ public static class T implements java.io.Serializable {
+ public case N(int c, T l, T r, int k, Object v);
+ public case E;
+ }
+
+ public static final T EMPTY = T.E;
+
+ // Node colors (Black and Red)
+ private static final int B = 0;
+ private static final int R = 1;
+
+ public static class ConflictException extends Exception {
+ public final int key;
+ public final Object oldValue, newValue;
+
+ public ConflictException(int key, Object oldValue, Object newValue) {
+ this.key = key;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+ public Throwable fillInStackTrace() {
+ // do nothing, to speed up things
+ return this;
+ }
+ }
+
+ public Object resolveConflict(int k, Object oldV, Object newV)
+ throws ConflictException {
+ throw new ConflictException(k, oldV, newV);
+ }
+
+ public T put(T map, int key, Object value) throws ConflictException {
+ switch (putAux(map, key, value)) {
+ case N(_, T l, T r, int k, Object v):
+ return T.N(B, l, r, k, v);
+ default:
+ throw new Error();
+ }
+ }
+
+ private T putAux(T map, int key, Object value) throws ConflictException {
+ switch (map) {
+ case N(int c, T l, T r, int k, Object v):
+ if (key < k)
+ return balance(T.N(c, putAux(l, key, value), r, k, v));
+ else if (key > k)
+ return balance(T.N(c, l, putAux(r, key, value), k, v));
+ else
+ return T.N(c, l, r, k, resolveConflict(k, v, value));
+ case E:
+ return T.N(R, T.E, T.E, key, value);
+ default:
+ throw new Error();
+ }
+ }
+
+ private T balance(T t) {
+ switch (t) {
+ case N(B,
+ N(R, N(R, T a, T b, int xK, Object xV), T c, int yK, Object yV),
+ T d,
+ int zK, Object zV):
+ return T.N(R, T.N(B, a, b, xK, xV), T.N(B, c, d, zK, zV), yK, yV);
+ case N(B,
+ N(R, T a, N(R, T b, T c, int yK, Object yV), int xK, Object xV),
+ T d,
+ int zK, Object zV):
+ return T.N(R, T.N(B, a, b, xK, xV), T.N(B, c, d, zK, zV), yK, yV);
+ case N(B,
+ T a,
+ N(R, N(R, T b, T c, int yK, Object yV), T d, int zK, Object zV),
+ int xK, Object xV):
+ return T.N(R, T.N(B, a, b, xK, xV), T.N(B, c, d, zK, zV), yK, yV);
+ case N(B,
+ T a,
+ N(R, T b, N(R, T c, T d, int zK, Object zV), int yK, Object yV),
+ int xK, Object xV):
+ return T.N(R, T.N(B, a, b, xK, xV), T.N(B, c, d, zK, zV), yK, yV);
+ default:
+ return t;
+ }
+ }
+
+ public Object get(T map, int key) {
+ switch (map) {
+ case N(_, T l, T r, int k, Object v):
+ if (key < k)
+ return get(l, key);
+ else if (key > k)
+ return get(r, key);
+ else
+ return v;
+ case E:
+ return null;
+ default:
+ throw new Error("unexpected node " + this);
+ }
+ }
+
+ public int size(T map) {
+ switch (map) {
+ case N(_, T l, T r, _, _):
+ return size(l) + size(r) + 1;
+ case E:
+ return 0;
+ default:
+ throw new Error("unexpected node " + this);
+ }
+ }
+
+ public int depth(T map) {
+ switch (map) {
+ case N(_, T l, T r, _, _):
+ return Math.max(depth(l), depth(r)) + 1;
+ case E:
+ return 0;
+ default:
+ throw new Error("unexpected node " + this);
+ }
+ }
+}
+
+// class RBTest {
+// static class MyIOMap extends IOMap {
+// public Object resolveConflict(int k, Object oldV, Object newV) {
+// throw new Error("conflict!!!");
+// }
+// }
+
+// public static void main(String[] args) {
+// MyIOMap map = new MyIOMap();
+// MyIOMap.T t = map.EMPTY;
+
+// long start = System.currentTimeMillis();
+// for (int i = 0; i < args.length; ++i) {
+// t = map.put(t, FNV_Hash.hash32(args[i]), new Integer(i));
+// }
+
+// for (int i = 0; i < args.length; ++i) {
+// map.get(t, FNV_Hash.hash32(args[i]));
+// }
+// long end = System.currentTimeMillis();
+// System.out.println("time: " + (end - start) + "ms");
+
+// System.out.println("size = " + map.size(t));
+// System.out.println("depth = " + map.depth(t));
+// }
+// }
diff --git a/src/library/scala/runtime/IntRef.java b/src/library/scala/runtime/IntRef.java
new file mode 100644
index 0000000000..1f5feacec7
--- /dev/null
+++ b/src/library/scala/runtime/IntRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class IntRef implements java.io.Serializable {
+ public int elem;
+ public IntRef(int elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/InterpreterSupport.java b/src/library/scala/runtime/InterpreterSupport.java
new file mode 100644
index 0000000000..9272583ca1
--- /dev/null
+++ b/src/library/scala/runtime/InterpreterSupport.java
@@ -0,0 +1,108 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+/** This class provides support methods for the interpreter. */
+public class InterpreterSupport {
+
+ //########################################################################
+ // Public classes
+
+ /** This interface provides method to show definitions. */
+ public static interface DefinitionPrinter {
+
+ /** This method is invoked for each non-value definition. */
+ public void showDefinition(String signature);
+
+ /** This method is invoked for each value definition. */
+ public void showValueDefinition(String signature, Object value);
+
+ }
+
+ /** This class describes an evaluation result. */
+ public static class EvaluationResult {
+
+ /** The value of the result */
+ public final Object value;
+
+ /** The type of the result */
+ public final String type;
+
+ /** Creates a new instance */
+ public EvaluationResult(Object value, String type) {
+ this.value = value;
+ this.type = type;
+ }
+ }
+
+ //########################################################################
+ // Private Variables
+
+ private static final ThreadLocal printer = new ThreadLocal();
+ private static final ThreadLocal result = new ThreadLocal();
+
+ //########################################################################
+ // Public Functions
+
+ /** Sets the definition printer of the current thread. */
+ public static void setDefinitionPrinter(DefinitionPrinter object) {
+ printer.set(object);
+ }
+
+ /** Returns the definition printer of the current thread. */
+ public static DefinitionPrinter getDefinitionPrinter() {
+ return (DefinitionPrinter)printer.get();
+ }
+
+ /**
+ * This function is invoked for each non-value definition. It
+ * forwards the call to the current thread's definition printer.
+ *
+ * @meta method (java.lang.String, scala.Any) scala.Unit;
+ */
+ public static void showDefinition(String signature) {
+ DefinitionPrinter printer = getDefinitionPrinter();
+ if (printer != null) printer.showDefinition(signature);
+ }
+
+ /**
+ * This method is invoked for each value definition. It forwards
+ * the call to the current thread's definition printer.
+ *
+ * @meta method (java.lang.String, scala.Any) scala.Unit;
+ */
+ public static void showValueDefinition(String signature, Object value) {
+ DefinitionPrinter printer = getDefinitionPrinter();
+ if (printer != null) printer.showValueDefinition(signature, value);
+ }
+
+ /**
+ * Sets the evaluation result of the current thread.
+ *
+ * @meta method (scala.Any, java.lang.String) scala.Unit;
+ */
+ public static void setEvaluationResult(Object value, String type) {
+ result.set(new EvaluationResult(value, type));
+ }
+
+ /**
+ * Returns and resets the evaluation result of the current
+ * thread. A null value indicates that the last evaluation had no
+ * result (only definitions).
+ */
+ public static EvaluationResult getAndResetEvaluationResult() {
+ Object object = result.get();
+ result.set(null);
+ return (EvaluationResult)object;
+ }
+
+ //########################################################################
+}
diff --git a/src/library/scala/runtime/LongRef.java b/src/library/scala/runtime/LongRef.java
new file mode 100644
index 0000000000..863472c666
--- /dev/null
+++ b/src/library/scala/runtime/LongRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class LongRef implements java.io.Serializable {
+ public long elem;
+ public LongRef(long elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/MetaAttribute.cs b/src/library/scala/runtime/MetaAttribute.cs
new file mode 100644
index 0000000000..28ab499bdd
--- /dev/null
+++ b/src/library/scala/runtime/MetaAttribute.cs
@@ -0,0 +1,34 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+using System;
+
+namespace scala.runtime
+{
+ /// <summary>
+ /// Stores additional meta-information about classes and members.
+ /// Used to augment type information in classes from the scala
+ /// library written in Java.
+ /// </summary>
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Field
+ | AttributeTargets.Constructor | AttributeTargets.Method,
+ AllowMultiple = false, Inherited = false)]
+ public class MetaAttribute : Attribute
+ {
+ // keeps a textual representation of the pico-style attributes
+ // used in some classes of the runtime library
+ public readonly string meta;
+ public MetaAttribute(string meta)
+ {
+ this.meta = meta;
+ }
+ }
+}
diff --git a/src/library/scala/runtime/ObjectRef.java b/src/library/scala/runtime/ObjectRef.java
new file mode 100644
index 0000000000..c5ba9fb640
--- /dev/null
+++ b/src/library/scala/runtime/ObjectRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.runtime;
+
+public class ObjectRef implements java.io.Serializable {
+ public Object elem;
+ public ObjectRef(Object elem) { this.elem = elem; }
+}
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
new file mode 100644
index 0000000000..8bdabef3c0
--- /dev/null
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -0,0 +1,90 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id:ScalaRunTime.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+
+package scala.runtime;
+
+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";
+
+ trait 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 == null)
+ result.asInstanceOf$erased[b]
+ // !!! else if (exception is LocalReturn)
+ // !!! // ...
+ else if (handler isDefinedAt exception)
+ handler(exception)
+ else
+ throw exception;
+
+ def Finally(handler: Unit): a =
+ if (exception == null)
+ result.asInstanceOf$erased[a]
+ else
+ throw exception;
+ }
+
+ def caseFields(x: CaseClass): List[Any] = {
+ val arity = x.caseArity;
+ def fields(from: Int): List[Any] =
+ if (from >= arity) List()
+ else x.caseElement(from) :: fields(from + 1);
+ fields(0)
+ }
+
+ def _toString(x: CaseClass): String = {
+ caseFields(x).mkString(x.caseName + "(", ",", ")")
+ }
+
+ def _hashCode(x: CaseClass): Int = {
+ var code = x.getClass().hashCode();
+ val arity = x.caseArity;
+ var i = 0;
+ while (i < arity) {
+ code = code * 41 + x.caseElement(i).hashCode();
+ i = i + 1
+ }
+ code
+ }
+
+ def _equals(x: CaseClass, y: Any): Boolean = y match {
+ case y1: CaseClass =>
+ (x.getClass() eq y1.getClass()) && {
+ val arity = x.caseArity;
+ var i = 0;
+ while (i < arity && x.caseElement(i) == y1.caseElement(i))
+ i = i + 1;
+ i == arity
+ }
+ case _ =>
+ false
+ }
+
+ def Seq[a](xs: a*): Seq[a] = null; // interpreted specially by new backend.
+}
diff --git a/src/library/scala/runtime/ShortRef.java b/src/library/scala/runtime/ShortRef.java
new file mode 100644
index 0000000000..3cada1fab8
--- /dev/null
+++ b/src/library/scala/runtime/ShortRef.java
@@ -0,0 +1,16 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, 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/library/scala/runtime/SymtabAttribute.cs b/src/library/scala/runtime/SymtabAttribute.cs
new file mode 100644
index 0000000000..fcb273a857
--- /dev/null
+++ b/src/library/scala/runtime/SymtabAttribute.cs
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+using System;
+
+namespace scala.runtime
+{
+ /// <summary>
+ /// Stores the symbol table for every top-level Scala class.
+ /// </summary>
+
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ public class SymtabAttribute : Attribute
+ {
+ // stores scalac symbol table
+ public readonly byte[] symtab;
+
+ // indicates if the type should be considered by the compiler;
+ // used for synthetic classes introduced by the Scala compiler
+ public readonly bool shouldLoadClass;
+
+ public SymtabAttribute(byte[] symtab)
+ {
+ this.symtab = symtab;
+ this.shouldLoadClass = true;
+ }
+
+ public SymtabAttribute() {
+ this.symtab = new byte[0];
+ this.shouldLoadClass = false;
+ }
+ }
+}
diff --git a/src/library/scala/runtime/compat/Math.scala b/src/library/scala/runtime/compat/Math.scala
new file mode 100644
index 0000000000..147ffeb0f9
--- /dev/null
+++ b/src/library/scala/runtime/compat/Math.scala
@@ -0,0 +1,36 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime.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.MIN_VALUE;
+ val MAX_FLOAT = java.lang.Float.MIN_VALUE;
+ val MIN_DOUBLE = java.lang.Double.MIN_VALUE;
+ val MAX_DOUBLE = java.lang.Double.MAX_VALUE;
+
+ 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/library/scala/runtime/compat/Platform.scala b/src/library/scala/runtime/compat/Platform.scala
new file mode 100644
index 0000000000..282421a981
--- /dev/null
+++ b/src/library/scala/runtime/compat/Platform.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime.compat;
+
+object Platform {
+ def arraycopy(src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: int): Unit =
+ System.arraycopy(src, srcPos, dest, destPos, length);
+ def getClass(obj: AnyRef) = obj.getClass();
+ def getClassName(obj: AnyRef) = obj.getClass().getName();
+ def printStackTrace(exc: java.lang.Throwable) = exc.printStackTrace();
+ def getMessage(exc: java.lang.Throwable) = exc.getMessage();
+ def split(str: String, separator: Char): Array[String] = {
+ str.split(separator.toString());
+ }
+
+ def currentThread = java.lang.Thread.currentThread();
+
+ def parseByte(s: String): Byte = java.lang.Byte.parseByte(s);
+ def parseShort(s: String): Short = java.lang.Short.parseShort(s);
+ def parseInt(s: String): Int = java.lang.Integer.parseInt(s);
+ def parseLong(s: String): Long = java.lang.Long.parseLong(s);
+ def parseFloat(s: String): Float = java.lang.Float.parseFloat(s);
+ def parseDouble(s: String): Double = java.lang.Double.parseDouble(s);
+
+ def isDigit(c: Char): Boolean = java.lang.Character.isDigit(c);
+}
diff --git a/src/library/scala/runtime/compat/StringBuilder.scala b/src/library/scala/runtime/compat/StringBuilder.scala
new file mode 100644
index 0000000000..bfb790723e
--- /dev/null
+++ b/src/library/scala/runtime/compat/StringBuilder.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime.compat;
+
+class StringBuilder {
+ val str = new StringBuffer();
+ def append(x: Any): StringBuilder = {
+ str.append(x);
+ this
+ }
+ def append(x: String): StringBuilder = {
+ str.append(x);
+ this
+ }
+ def length(): Int = str.length();
+ override def toString() = str.toString();
+}
diff --git a/src/library/scala/runtime/matching/Address.scala b/src/library/scala/runtime/matching/Address.scala
new file mode 100644
index 0000000000..3f548e402f
--- /dev/null
+++ b/src/library/scala/runtime/matching/Address.scala
@@ -0,0 +1,30 @@
+package scala.runtime.matching ;
+
+object Address {
+ def empty = new Address();
+}
+
+//import List.list2ordered;
+
+/** Address holds the path in reverse Dewey notation
+*/
+class Address( l:Int* ) extends Ordered[Address] {
+
+ private val list:List[Int] = l.toList;
+
+ def compareTo [b >: Address <% Ordered[b]](y: b): int = y match {
+ case o:Address => list.reverse.compareTo(o.list.reverse)
+ //(xs => List.view(xs)(Predef.int2ordered));
+ case _ => -(y compareTo this)
+ }
+
+ def down: Address = new Address( ( 1 :: list ):_* );
+
+ /** precond: p is nonempty */
+ def right: Address = list match {
+ case i :: rest => new Address( ((i+1) :: rest ):_* )
+ }
+
+ override def toString() = list.mkString("Address(",".",")");
+
+}
diff --git a/src/library/scala/runtime/matching/NonTerm.scala b/src/library/scala/runtime/matching/NonTerm.scala
new file mode 100644
index 0000000000..35bc0f60ce
--- /dev/null
+++ b/src/library/scala/runtime/matching/NonTerm.scala
@@ -0,0 +1,52 @@
+package scala.runtime.matching ;
+
+import scala.collection.immutable ;
+
+abstract class NonTerm {
+
+ override def toString() = this match {
+ case TreeNT( i ) => "t"+i;
+ case h @ HedgeNT( i ) => "h"+i+{ if( h.nullable )"~" else "" };
+ }
+
+}
+
+/** tree nonterminal. holds set of binding variable indices.
+ */
+case class TreeNT(i:int) extends NonTerm with Ordered[TreeNT] {
+
+ var vset:immutable.Set[Int] = new immutable.TreeSet[Int]() ;
+
+ /** vset should be sorted to allow fast lookup */
+ def this( i:int, vset:immutable.Set[Int] ) = {
+ this( i );
+ this.vset = new immutable.TreeSet[Int]() incl vset ;
+ }
+
+ def compareTo [b >: TreeNT <% Ordered[b]](y: b): int = y match {
+ case TreeNT( y1 ) => i compareTo y1;
+ case _ => -(y compareTo this)
+ }
+};
+
+/** hedge nonterminals. holds nullable property.
+ */
+case class HedgeNT(i:int) extends NonTerm with Ordered[HedgeNT] {
+
+ var nullable:boolean = false;
+
+ def this( i:int, nullable:boolean ) = {
+ this( i );
+ this.nullable = nullable;
+ }
+
+ def compareTo [b >: HedgeNT <% Ordered[b]](y: b): int = y match {
+ case HedgeNT( y1 ) => i compareTo y1;
+ case _ => -(y compareTo this)
+ }
+};
+
+//case object EMPTYHEDGE extends HedgeNT( 0, true ) ;
+//case object ANYHEDGE extends HedgeNT( 1, true ) ;
+object ANYTREE extends TreeNT( 1 );
+
diff --git a/src/library/scala/runtime/matching/PatternTests.scala b/src/library/scala/runtime/matching/PatternTests.scala
new file mode 100644
index 0000000000..ea04481d58
--- /dev/null
+++ b/src/library/scala/runtime/matching/PatternTests.scala
@@ -0,0 +1,5 @@
+package scala.runtime.matching ;
+
+abstract class PatternTests extends Function2[Int,Any,Boolean]{
+ def apply(i:Int, inp:Any): Boolean;
+}
diff --git a/src/library/scala/runtime/matching/Rule.scala b/src/library/scala/runtime/matching/Rule.scala
new file mode 100644
index 0000000000..7bd6d40fd1
--- /dev/null
+++ b/src/library/scala/runtime/matching/Rule.scala
@@ -0,0 +1,102 @@
+package scala.runtime.matching ;
+
+/* hedge grammar rules */
+abstract class Rule extends Ordered[Rule] {
+
+ def compareTo [b >: Rule <% Ordered[b]](that: b): int = that match {
+ case r:Rule =>
+ if( rule_smaller( this, r ) )
+ -1
+ else if( rule_eq( this, r ) )
+ 0
+ else
+ 1
+ case _ => -(that compareTo this)
+ }
+
+ final def rule_smaller( r1:Rule, r2:Rule ):boolean = r1 match {
+ case HedgeRule( h1, _, hh1 ) => r2 match {
+ case HedgeRule( h2, _, hh2 ) =>
+ ((h1 == h2)&&( hh1.i < hh2.i )) || h1.i < h2.i;
+ case HedgeChainRule( h2, hh2 ) =>
+ ((h1 == h2)&&( hh1.i < hh2.i )) || h1.i < h2.i;
+ case _ => false;
+ }
+ case HedgeChainRule( h1, hh1 ) => r2 match {
+ case HedgeRule( h2, _, hh2 ) =>
+ ((h1 == h2)&&( hh1.i < hh2.i )) || h1.i < h2.i;
+ case HedgeChainRule( h2, hh2 ) =>
+ ((h1 == h2)&&( hh1.i < hh2.i )) || h1.i < h2.i;
+ case _ => false;
+ }
+ case TreeRule( t1, _, hh1 ) => r2 match {
+ case TreeRule( t2, _, hh2 ) =>
+ ((t1 == t2 )&&(hh1.i < hh2.i )) || t1.i < t2.i;
+ case AnyTreeRule( t2 ) => false;
+ case AnyNodeRule( t2, hh2 ) =>
+ ((t1 == t2 )&&(hh1.i < hh2.i )) || t1.i < t2.i;
+ case _ => true;
+ }
+ case AnyTreeRule( t1 ) => r2 match {
+ case TreeRule( _, _ , _ ) => true;
+ case AnyTreeRule( t2 ) => t1.i < t2.i;
+ case AnyNodeRule( t2, _ ) => true
+ case _ => true;
+ }
+ case AnyNodeRule( t1, hh1 ) => r2 match {
+ case TreeRule( t2, _, hh2 ) =>
+ ((t1 == t2 )&&(hh1.i < hh2.i )) || t1.i < t2.i;
+ case AnyTreeRule( t2 ) => false;
+ case AnyNodeRule( t2, hh2 ) =>
+ ((t1 == t2 )&&(hh1.i < hh2.i )) || t1.i < t2.i;
+ case _ => true;
+ }
+ };
+ final def rule_eq( r1:Rule, r2:Rule ):boolean = r1 == r2;
+
+
+ override def toString() = this match {
+ case HedgeChainRule( n, m ) =>
+ n.toString()+" ::= "+m.toString();
+
+ case TreeRule( n, label, n2 ) =>
+ (n.toString()+{ if( !n.vset.isEmpty ) n.vset.toString() else "" }+
+ " ::= "+label+"( "+n2.toString()+{if( n2.nullable ) "~" else ""}+" )")
+
+ case AnyTreeRule( n ) =>
+ n.toString()+{ if( !n.vset.isEmpty ) n.vset.toString() else "" }+" ::= _ ";
+
+ case AnyNodeRule( n, h ) =>
+ n.toString()+{ if( !n.vset.isEmpty ) n.vset.toString() else "" }+" ::= _ ( "+h.toString()+" )";
+
+ case HedgeRule( n, t, h ) =>
+ n.toString()+(
+ if( n.nullable ) "~" else " "
+ )+" ::= "+(
+ if( t == ANYTREE ) "_" else t.toString()
+ )+" "+h.toString();
+
+ }
+}
+
+abstract class TRule extends Rule;
+abstract class HRule extends Rule;
+/*
+a tree rule is of the from A -> s(B)
+where A,B are TreeNTs and s is an identifier (string).
+
+If s is the empty string, then the node label is arbitrary
+If HedgeNT is AnyHedgeNT, then the tree is arbitrary
+*/
+case class HedgeChainRule( n: HedgeNT, rhs: HedgeNT ) extends HRule;
+case class TreeRule( n:TreeNT, test:Int, h:HedgeNT ) extends TRule {
+ def this(i:Int, s:Int, n:Int ) = {
+ this( new TreeNT(i), s, new HedgeNT(n));
+ }
+};
+case class AnyTreeRule( n:TreeNT ) extends TRule {
+}
+case class AnyNodeRule( n:TreeNT, h:HedgeNT ) extends TRule {
+}
+case class HedgeRule( n:HedgeNT, t:TreeNT, h:HedgeNT ) extends HRule;
+
diff --git a/src/library/scala/runtime/matching/TestAlphabet.scala b/src/library/scala/runtime/matching/TestAlphabet.scala
new file mode 100644
index 0000000000..9ef4698ebc
--- /dev/null
+++ b/src/library/scala/runtime/matching/TestAlphabet.scala
@@ -0,0 +1,9 @@
+package scala.runtime.matching ;
+
+trait TestAlphabet;
+
+case class TestLabel(i: Int) extends TestAlphabet ;
+
+case object AnyNode extends TestAlphabet {
+ def view(x: Int): TestLabel = TestLabel(x);
+}
diff --git a/src/library/scala/serializable.scala b/src/library/scala/serializable.scala
new file mode 100644
index 0000000000..2b9ad9f177
--- /dev/null
+++ b/src/library/scala/serializable.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+*/
+
+package scala;
+
+class serializable extends Attribute {}
diff --git a/src/library/scala/testing/Benchmark.scala b/src/library/scala/testing/Benchmark.scala
new file mode 100644
index 0000000000..f6523a7271
--- /dev/null
+++ b/src/library/scala/testing/Benchmark.scala
@@ -0,0 +1,74 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+
+/**
+ * Scala benchmarking mini framework.
+ */
+
+package scala.testing;
+
+/** <code>Benchmark</code> can be used to quickly turn an existing
+ * class into a benchmark. Here is a short example:
+ *
+ * <pre>
+ * object sort1 extends Sorter with Benchmark {
+ * def run = sort(List.range(1, 1000));
+ * }
+ * </pre>
+ *
+ * The run method has to be defined by the user, who will perform
+ * the timed operation there.
+ * Run the benchmark as follows:
+ * <pre>
+ * scala sort1 5 times.log
+ * </pre>
+ * 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;
+
+ /** Run the benchmark the specified number of times
+ * and return a list with the execution times in milliseconds
+ * in reverse order of the execution */
+ def runBenchmark(noTimes: Int): List[Long] =
+
+ for (val i <- List.range(1, noTimes + 1)) yield {
+ val startTime = System.currentTimeMillis();
+ run;
+ val stopTime = System.currentTimeMillis();
+ System.gc();
+
+ 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
+
+ logFile.write(getClass().getName());
+ for (val t <- runBenchmark(Integer.parseInt(args(0))))
+ logFile.write("\t\t" + t);
+
+ logFile.write("\n");
+ logFile.flush();
+ } else
+ Console.println("Usage: scala benchmarks.program <runs> <logfile>");
+ }
+}
+
diff --git a/src/library/scala/testing/SUnit.scala b/src/library/scala/testing/SUnit.scala
new file mode 100644
index 0000000000..4faa0c9cd0
--- /dev/null
+++ b/src/library/scala/testing/SUnit.scala
@@ -0,0 +1,188 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.testing;
+
+/** unit testing methods in the spirit of JUnit framework.
+ * use these classes like this:
+<code>
+ 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 &lt;- r.failures()) {
+ Console.println(tf.toString())
+ }
+}
+</code>
+ */
+object SUnit {
+
+ /** a Test can be run with its result being collected */
+ trait Test {
+ def run(r: TestResult):Unit;
+ }
+
+ /** a TestCase defines the fixture to run multiple tests */
+ 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;
+ }
+
+ /** a 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 = {
+ val s = new StringBuffer();
+ for(val trElem <- thrownException.getStackTrace()) {
+ s.append(trElem.toString());
+ s.append('\n');
+ }
+ s.toString()
+ }
+ }
+
+ /** a TestResult collects the result of executing a test case */
+ class TestResult {
+ val buf =
+ new scala.collection.mutable.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) };
+ }
+
+ /** a 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 scala.collection.mutable.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 trait 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 */
+ def fail(msg:String): Unit =
+ throw new AssertFailed(msg);
+ }
+}
diff --git a/src/library/scala/testing/UnitTest.scala b/src/library/scala/testing/UnitTest.scala
new file mode 100644
index 0000000000..2f8878b2eb
--- /dev/null
+++ b/src/library/scala/testing/UnitTest.scala
@@ -0,0 +1,58 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, 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 + "\"") });
+
+ def setReporter( r:Report ) = {
+ this.report = r;
+ }
+
+ def assertSameElements[a]( actual:Seq[a] , expected: Seq[a] ):Unit =
+ if( actual.sameElements( expected ) )
+ report.ok
+ else
+ report.fail( actual.toString(), expected.toString() );
+
+ 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 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/library/scala/text/Document.scala b/src/library/scala/text/Document.scala
new file mode 100644
index 0000000000..40d5a3a7c4
--- /dev/null
+++ b/src/library/scala/text/Document.scala
@@ -0,0 +1,119 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.text;
+
+import java.io.PrintWriter;
+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.
+ */
+ 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 Triple(_, _, DocNil) :: z =>
+ fits(w, z)
+ case Triple(i, b, DocCons(h, t)) :: z =>
+ fits(w, Triple(i,b,h) :: Triple(i,b,t) :: z)
+ case Triple(_, _, DocText(t)) :: z =>
+ fits(w - t.length(), z)
+ case Triple(i, b, DocNest(ii, d)) :: z =>
+ fits(w, Triple(i + ii, b, d) :: z)
+ case Triple(_, false, DocBreak) :: z =>
+ fits(w - 1, z)
+ case Triple(_, true, DocBreak) :: z =>
+ true
+ case Triple(i, _, DocGroup(d)) :: z =>
+ fits(w, Triple(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 Triple(_, _, DocNil) :: z =>
+ fmt(k, z)
+ case Triple(i, b, DocCons(h, t)) :: z =>
+ fmt(k, Triple(i, b, h) :: Triple(i, b, t) :: z)
+ case Triple(i, _, DocText(t)) :: z =>
+ writer write t;
+ fmt(k + t.length(), z)
+ case Triple(i, b, DocNest(ii, d)) :: z =>
+ fmt(k, Triple(i + ii, b, d) :: z)
+ case Triple(i, true, DocBreak) :: z =>
+ writer write "\n";
+ spaces(i);
+ fmt(i, z)
+ case Triple(i, false, DocBreak) :: z =>
+ writer write " ";
+ fmt(k + 1, z)
+ case Triple(i, b, DocGroup(d)) :: z =>
+ val fitsFlat = fits(width - k, Triple(i, false, d) :: z);
+ fmt(k, Triple(i, !fitsFlat, d) :: z)
+ }
+
+ fmt(0, Triple(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/library/scala/transient.scala b/src/library/scala/transient.scala
new file mode 100644
index 0000000000..d051c80761
--- /dev/null
+++ b/src/library/scala/transient.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:transient.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+class transient extends Attribute {}
diff --git a/src/library/scala/util/automata/BaseBerrySethi.scala b/src/library/scala/util/automata/BaseBerrySethi.scala
new file mode 100644
index 0000000000..ec6a37b79f
--- /dev/null
+++ b/src/library/scala/util/automata/BaseBerrySethi.scala
@@ -0,0 +1,180 @@
+package scala.util.automata;
+
+import scala.util.regexp.Base;
+
+import scala.collection.mutable;
+import scala.collection.immutable;
+import scala.runtime.compat.Platform;
+
+/** 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 _ => error("unexpected pattern " + Platform.getClass(r));
+ }
+
+ /** 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 _ => error("unexpected pattern " + Platform.getClass(r));
+ }
+
+ // starts from the right-to-left
+ // precondition: pos is final
+ // pats are successor patterns of a Sequence node
+ 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);
+ return fol;
+ }
+
+ /** returns the first set of an expression, setting the follow set along
+ * the way
+ */
+ 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 _ => error("unexpected pattern: " + Platform.getClass(r));
+ }
+ }
+
+ /** returns "Sethi-length" of a pattern, creating the set of position
+ * along the way
+ */
+
+ // 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 _ => error("unexp pattern " + Platform.getClass(r));
+ }
+ }
+
+}
diff --git a/src/library/scala/util/automata/DetWordAutom.scala b/src/library/scala/util/automata/DetWordAutom.scala
new file mode 100644
index 0000000000..12049e0012
--- /dev/null
+++ b/src/library/scala/util/automata/DetWordAutom.scala
@@ -0,0 +1,56 @@
+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.
+ */
+abstract class DetWordAutom[T <: AnyRef] {
+
+ val nstates: Int;
+ val finals: Array[Int] ;
+ val delta: Array[Map[T,Int]];
+ val default: Array[Int] ;
+
+ def isFinal(q: Int) = finals(q) != 0;
+
+ def isSink(q: Int) = delta(q).isEmpty && default(q) == q;
+
+ def next(q: Int, label: T) = {
+ delta(q).get(label) match {
+ case Some(p) => p
+ case _ => default(q)
+ }
+ }
+
+ override def toString() = {
+ val sb = new StringBuffer();
+ 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 <- Iterator.range(0,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/library/scala/util/automata/Inclusion.scala b/src/library/scala/util/automata/Inclusion.scala
new file mode 100644
index 0000000000..4b155c7f06
--- /dev/null
+++ b/src/library/scala/util/automata/Inclusion.scala
@@ -0,0 +1,54 @@
+package scala.util.automata ;
+
+/** a fast test of language inclusion between minimal automata.
+ * inspired by the AMoRE automata library
+ * @author Burak
+ */
+trait Inclusion[A <: AnyRef] {
+
+ val labels: Seq[A];
+
+ /** returns true if dfa1 is included in 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/library/scala/util/automata/NondetWordAutom.scala b/src/library/scala/util/automata/NondetWordAutom.scala
new file mode 100644
index 0000000000..a0a2757233
--- /dev/null
+++ b/src/library/scala/util/automata/NondetWordAutom.scala
@@ -0,0 +1,101 @@
+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.toSet(true).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.toSet(true)) {
+ for(val i <- next(q,a).toSet(true)) {
+ x.set(i);
+ }
+ }
+ x.makeImmutable
+ }
+
+
+ def nextDefault(Q:immutable.BitSet): immutable.BitSet = {
+ val x = new mutable.BitSet(nstates);
+ for(val q <- Q.toSet(true)) {
+ for(val i <- default(q).toSet(true)) { //@todo: OR
+ x.set(i)
+ }
+ }
+ x.makeImmutable;
+ }
+
+ override def toString() = {
+ val sb = new StringBuffer();
+ 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 <- Iterator.range(0,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/library/scala/util/automata/SubsetConstruction.scala b/src/library/scala/util/automata/SubsetConstruction.scala
new file mode 100644
index 0000000000..ddf122dbe3
--- /dev/null
+++ b/src/library/scala/util/automata/SubsetConstruction.scala
@@ -0,0 +1,143 @@
+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 } ;
+
+ /** the set {0} */
+ final val _initialBitSet = {
+ val rbs = new mutable.BitSet(1);
+ rbs.set(0);
+ rbs.makeImmutable;
+ }
+
+ /** the set {} */
+ final val _sinkBitSet = {
+ new mutable.BitSet(1).makeImmutable;
+ }
+
+ final val _emptyBitSet = {
+ val rbs = new scala.collection.mutable.BitSet(1);
+ new BitSet(rbs);
+ }
+
+ def selectTag(Q:BitSet, finals:Array[Int]) = {
+ val it = Q.toSet(true).elements;
+ var mintag = scala.runtime.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/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala
new file mode 100644
index 0000000000..f361b6b174
--- /dev/null
+++ b/src/library/scala/util/automata/WordBerrySethi.scala
@@ -0,0 +1,275 @@
+package scala.util.automata ;
+
+import scala.util.regexp.WordExp ;
+
+import scala.collection.{immutable,
+ mutable,
+ Map } ;
+
+/** this turns a regexp into a NondetWordAutom using the
+ * celebrated position automata construction (also called Berry-Sethi or
+ * Glushkov)
+ */
+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 */
+ 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 */
+ 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
+ */
+ 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.set(q);
+ hmap.update(lab, x.makeImmutable);
+ }
+ 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.set(q);
+ defaultArr(k) = x.makeImmutable;
+ 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:this.lang._regexpT => automatonFrom(Sequ(z), 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/library/scala/util/grammar/HedgeRHS.scala b/src/library/scala/util/grammar/HedgeRHS.scala
new file mode 100644
index 0000000000..e435909eb9
--- /dev/null
+++ b/src/library/scala/util/grammar/HedgeRHS.scala
@@ -0,0 +1,12 @@
+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/library/scala/util/grammar/TreeRHS.scala b/src/library/scala/util/grammar/TreeRHS.scala
new file mode 100644
index 0000000000..e4d391e12f
--- /dev/null
+++ b/src/library/scala/util/grammar/TreeRHS.scala
@@ -0,0 +1,9 @@
+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/library/scala/util/logging/ConsoleLogger.scala b/src/library/scala/util/logging/ConsoleLogger.scala
new file mode 100644
index 0000000000..fabfa7a698
--- /dev/null
+++ b/src/library/scala/util/logging/ConsoleLogger.scala
@@ -0,0 +1,12 @@
+// $Id$
+
+package scala.util.logging;
+/**
+ * A ConsoleLogger is mixed into a concrete class who has class Logged
+ * among its base traits.
+ */
+trait ConsoleLogger {
+ /** logs argument to Console using Console.println
+ */
+ def log(msg:String): Unit = Console.println(msg);
+}
diff --git a/src/library/scala/util/logging/Logged.scala b/src/library/scala/util/logging/Logged.scala
new file mode 100644
index 0000000000..a19429c1f6
--- /dev/null
+++ b/src/library/scala/util/logging/Logged.scala
@@ -0,0 +1,23 @@
+// $Id$
+
+package scala.util.logging;
+
+/**
+ * Mixing in the trait Logged indicates that a class provides support
+ * for logging. For instance, a developer of a library writes
+ * <code>
+ class MyClass with Logged { ... do stuff, call log }
+ </code>
+ *
+ * The user of the library instantiates:
+ <code>
+ val x = new MyClass() with ConsoleLogger;
+ </code>
+ * and the logging will be sent to the Console.
+ */
+trait Logged {
+ /** this method should log the message given as argument somewhere
+ * as a side-effect
+ */
+ def log(msg:String): Unit = {};
+}
diff --git a/src/library/scala/util/parsing/CharInputStreamIterator.scala b/src/library/scala/util/parsing/CharInputStreamIterator.scala
new file mode 100644
index 0000000000..16ba724619
--- /dev/null
+++ b/src/library/scala/util/parsing/CharInputStreamIterator.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.util.parsing;
+
+import java.io._;
+
+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/library/scala/util/parsing/Parsers.scala b/src/library/scala/util/parsing/Parsers.scala
new file mode 100644
index 0000000000..e0064f12e5
--- /dev/null
+++ b/src/library/scala/util/parsing/Parsers.scala
@@ -0,0 +1,68 @@
+package scala.util.parsing;
+
+abstract class Parsers {
+
+ type inputType;
+
+ trait Parser[a] {
+
+ type Result = Option[Pair[a, inputType]];
+
+ def apply(in: inputType): Result;
+
+ def filter(pred: a => boolean) = new Parser[a] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => if (pred(x)) Some(Pair(x, in1)) else None
+ }
+ }
+
+ def map[b](f: a => b) = new Parser[b] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
+ }
+ }
+
+ def flatMap[b](f: a => Parser[b]) = new Parser[b] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => None
+ case Some(Pair(x, in1)) => f(x).apply(in1)
+ }
+ }
+
+ def ||| (p: => Parser[a]) = new Parser[a] {
+ def apply(in: inputType): Result = Parser.this.apply(in) match {
+ case None => p(in)
+ case s => s
+ }
+ }
+
+ def &&& [b](p: => Parser[b]): Parser[b] =
+ for (val _ <- this; val x <- p) yield x;
+ }
+
+ def 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/library/scala/util/parsing/SimpleTokenizer.scala b/src/library/scala/util/parsing/SimpleTokenizer.scala
new file mode 100644
index 0000000000..20a23a8492
--- /dev/null
+++ b/src/library/scala/util/parsing/SimpleTokenizer.scala
@@ -0,0 +1,46 @@
+package scala.util.parsing;
+
+class SimpleTokenizer(in: Iterator[char], delimiters: String) extends Iterator[String] {
+
+ val tracing = false;
+
+ private def max(x: int, y: char): int = if (x < y) y else x;
+
+ 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 StringBuffer();
+
+ 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) System.out.println("<" + buf.toString() + ">");
+ buf.toString()
+ }
+ }
+}
+
diff --git a/src/library/scala/util/regexp/Base.scala b/src/library/scala/util/regexp/Base.scala
new file mode 100644
index 0000000000..cfdaaac10f
--- /dev/null
+++ b/src/library/scala/util/regexp/Base.scala
@@ -0,0 +1,63 @@
+// $Id$
+
+package scala.util.regexp ;
+
+/** basic regular expressions */
+
+trait 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/library/scala/util/regexp/PointedHedgeExp.scala b/src/library/scala/util/regexp/PointedHedgeExp.scala
new file mode 100644
index 0000000000..27da6338db
--- /dev/null
+++ b/src/library/scala/util/regexp/PointedHedgeExp.scala
@@ -0,0 +1,25 @@
+// $Id$
+
+package scala.util.regexp ;
+
+/** pointed regular hedge expressions, a useful subclass of
+ * regular hedge expressions.
+ */
+trait 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/library/scala/util/regexp/SyntaxError.scala b/src/library/scala/util/regexp/SyntaxError.scala
new file mode 100644
index 0000000000..c6599df75c
--- /dev/null
+++ b/src/library/scala/util/regexp/SyntaxError.scala
@@ -0,0 +1,6 @@
+package scala.util.regexp ;
+
+/** this runtime exception is thrown if an attempt to instantiate a
+ * syntactically incorrect expression is detected */
+class SyntaxError(e: String)
+ extends java.lang.RuntimeException(e);
diff --git a/src/library/scala/util/regexp/WordExp.scala b/src/library/scala/util/regexp/WordExp.scala
new file mode 100644
index 0000000000..63817e0151
--- /dev/null
+++ b/src/library/scala/util/regexp/WordExp.scala
@@ -0,0 +1,24 @@
+// $Id$
+
+package scala.util.regexp ;
+
+/** regular word expressions.
+ */
+trait WordExp extends Base {
+
+ trait 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/library/scala/volatile.scala b/src/library/scala/volatile.scala
new file mode 100644
index 0000000000..905d95371e
--- /dev/null
+++ b/src/library/scala/volatile.scala
@@ -0,0 +1,12 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id:volatile.scala 5359 2005-12-16 16:33:49 +0100 (Fri, 16 Dec 2005) dubochet $
+\* */
+
+package scala;
+
+class volatile extends Attribute {}
diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala
new file mode 100644
index 0000000000..d37d6dbf56
--- /dev/null
+++ b/src/library/scala/xml/Atom.scala
@@ -0,0 +1,41 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** an XML node for text (PCDATA). 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 {
+
+ final override def typeTag$:Int = -1;
+
+ /** the constant "#PCDATA"
+ */
+ def label = "#PCDATA";
+
+ override def equals(x:Any) = x match {
+ case s:Atom[A] => data == s.data ;
+ case _ => false;
+ }
+
+ /** hashcode for this Text */
+ override def hashCode() =
+ data.hashCode();
+
+ /** returns text, with some characters escaped according to XML spec */
+ def toString(sb:StringBuffer) =
+ Utility.escape( data.toString(), sb );
+
+ override def text: String = data.toString();
+
+}
diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala
new file mode 100644
index 0000000000..4bf7a267f7
--- /dev/null
+++ b/src/library/scala/xml/Comment.scala
@@ -0,0 +1,45 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+import scala.collection.immutable ;
+
+/** an XML node for comments.
+ *
+ * @author Burak Emir
+ * @param text text contained in this node, may not contain "--"
+ */
+
+case class Comment(commentText: String) extends SpecialNode {
+
+ final override def typeTag$:Int = -3;
+
+ if( commentText.indexOf("--" ) != -1 )
+ throw new IllegalArgumentException("text containts \"--\"");
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ case Comment(x) => x.equals(commentText);
+ case _ => false
+ }
+
+ /** the constant &quot;#REM&quot; */
+ def label = "#REM";
+
+ /** hashcode for this Comment */
+ override def hashCode() = commentText.hashCode();
+
+ override def text = "";
+
+ /** appends &quot;<!-- text -->&quot; to this stringbuffer */
+ def toString(sb: StringBuffer) = {
+ sb.append("<!--").append(commentText).append("-->")
+ }
+}
diff --git a/src/library/scala/xml/Document.scala b/src/library/scala/xml/Document.scala
new file mode 100644
index 0000000000..38503eb834
--- /dev/null
+++ b/src/library/scala/xml/Document.scala
@@ -0,0 +1,84 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, 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.
+ */
+class Document extends NodeSeq {
+
+ /** 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/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
new file mode 100644
index 0000000000..6a6d70d1e6
--- /dev/null
+++ b/src/library/scala/xml/Elem.scala
@@ -0,0 +1,74 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+import scala.collection.mutable.ArrayBuffer;
+
+/** The case class <code>Elem</code> implements the Node trait,
+ * providing an immutable data object representing an XML element.
+ *
+ * @param prefix (may be null)
+ * @param label the element name
+ * @param attribute the attribute map
+ * @param child the children of this node
+ * @author Burak Emir
+ */
+// "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 (prefix != null && 0 == prefix.length())
+ scala.Predef.error("prefix of zero length, use null instead");
+
+ if (null == scope)
+ scala.Predef.error("scope is null");
+
+ //@todo: copy the children,
+ // setting namespace scope if necessary
+ // cleaning adjacent text nodes if necessary
+
+ //final val namespaceIntern = namespace$$.intern();
+ //final def namespace = namespaceIntern;
+
+ //final val labelIntern = label$$.intern();
+ //final def label = labelIntern;
+
+ final override def typeTag$: Int = 0;
+
+ override def hashCode(): Int = {
+ Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child);
+ }
+ /** Return 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 StringBuffer();
+ val it = child.elements;
+ while(it.hasNext) {
+ sb.append(it.next.text);
+ }
+ sb.toString()
+ }
+
+}
diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala
new file mode 100644
index 0000000000..3ae1ef6866
--- /dev/null
+++ b/src/library/scala/xml/EntityRef.scala
@@ -0,0 +1,40 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** an XML node for entity references
+ *
+ * @author buraq
+ * @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 = "";
+
+ /** appends "&amp; entityName;" to this stringbuffer */
+ def toString(sb:StringBuffer) =
+ sb.append("&").append(entityName).append(";");
+
+}
diff --git a/src/library/scala/xml/MalformedAttributeException.scala b/src/library/scala/xml/MalformedAttributeException.scala
new file mode 100644
index 0000000000..bcb4c0f393
--- /dev/null
+++ b/src/library/scala/xml/MalformedAttributeException.scala
@@ -0,0 +1,3 @@
+package scala.xml;
+
+case class MalformedAttributeException(msg:String) extends java.lang.RuntimeException(msg);
diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala
new file mode 100644
index 0000000000..285e3eb850
--- /dev/null
+++ b/src/library/scala/xml/MetaData.scala
@@ -0,0 +1,159 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+/** 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 */
+ def append(m: MetaData): MetaData =
+ next.append(copy(m));
+
+ def apply(s:String) = getValue(s);
+
+ def apply(uri:String, scp:NamespaceBinding, k:String)= getValue(uri, scp, k);
+
+ def containedIn1(m: MetaData): Boolean =
+ m.equals1(this) || containedIn1(m.next);
+
+ /** returns a copy of this MetaData item with next field set to argument */
+ 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;
+
+ //def containedIn(m:MetaData): Boolean;
+
+ //def deepCopy: MetaData;
+
+ //def deepCopy(tail:MetaData): MetaData;
+
+ /** 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 = new Iterator[MetaData] {
+ var x: MetaData = MetaData.this;
+ def hasNext = Null != x;
+ def next = {
+ val y = x;
+ x = x.next;
+ y
+ }
+ }
+
+ /* returns a sequences of "pseudo nodes" that contain attribute info.
+ not sure if this useful, and it violates contract for nodes...
+ def nodes = {
+ class NodeProxy(last:MetaData) extends Node {
+ override def prefix = last match {
+ case p:PrefixedAttribute => p.pre;
+ case _ => null
+ }
+ override def label = "@"+last.key;
+ override def child = Text(last.value);
+ override def text = last.value
+ }
+ val ns = new Array[Node](this.length);
+ var i = 0;
+ val it = elements;
+ while(it.hasNext) {
+ val a = it.next;
+ ns(i) = new NodeProxy(a);
+ i = i + 1;
+ }
+ val seq = array2seq(ns);
+ NodeSeq.fromSeq(seq);
+ }
+ */
+
+ /** shallow equals method */
+ def equals1(that: MetaData): Boolean;
+
+ /** filters this sequence of meta data */
+ 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 key of this MetaData item */
+ def value: String;
+
+ /** 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 */
+ def getValue(key: String): String;
+
+ /** gets value of qualified (prefixed) attribute with given key */
+ def getValue(namespace: String, owner: Node, key: String): String =
+ getValue(namespace, owner.scope, key);
+
+ /** gets value of qualified (prefixed) attribute with given key */
+ def getValue(namespace: String, scope: NamespaceBinding, key: String): String;
+ override def hashCode(): Int;
+
+ def toString1(): String = {
+ val sb = new StringBuffer();
+ toString1(sb);
+ sb.toString();
+ }
+
+ //appends string representations of single attribute to StringBuffer
+ def toString1(sb:StringBuffer): Unit;
+
+ override def toString(): String = {
+ val sb = new StringBuffer();
+ toString(sb);
+ sb.toString();
+ }
+
+ def toString(sb: StringBuffer): Unit = {
+ sb.append(' ');
+ toString1(sb);
+ next.toString(sb);
+ }
+
+ def wellformed(scope: NamespaceBinding): Boolean;
+
+}
diff --git a/src/library/scala/xml/Molecule.scala b/src/library/scala/xml/Molecule.scala
new file mode 100644
index 0000000000..d2141d069b
--- /dev/null
+++ b/src/library/scala/xml/Molecule.scala
@@ -0,0 +1,39 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** an XML node for a list of data items.
+ * @author buraq
+ * @param list a list of data items, space separated
+ */
+class Molecule[+A]( val list: List[A] ) extends SpecialNode {
+
+ final override def typeTag$:Int = -1;
+
+ /** the constant "#PCDATA"
+ */
+ def label = "#PCDATA";
+
+ final override def equals(x:Any) = x match {
+ case s:Molecule[A] => list == s.list ;
+ case _ => false;
+ }
+
+ /** hashcode for this Text */
+ override def hashCode() =
+ list.hashCode();
+
+ override def text = list.mkString(""," ","");
+
+ /** returns text, with some characters escaped according to XML spec */
+ def toString(sb:StringBuffer) =
+ sb.append(list.mkString(""," ",""))
+
+}
diff --git a/src/library/scala/xml/NamespaceBinding.scala b/src/library/scala/xml/NamespaceBinding.scala
new file mode 100644
index 0000000000..3ad7c49957
--- /dev/null
+++ b/src/library/scala/xml/NamespaceBinding.scala
@@ -0,0 +1,70 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+import Predef._;
+
+/** The class <code>NamespaceBinding</code> represents namespace bindings
+ * and scopes. The binding for the default namespace is treated as a null
+ * prefix. the absent namespace is represented with the null uri. Neither
+ * prefix nor uri may be empty, which is not checked.
+ *
+ * @version 1.0
+ * @author Burak Emir
+ */
+[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())
+ error("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 StringBuffer();
+ toString(sb, TopScope);
+ sb.toString();
+ }
+
+ def toString(stop: NamespaceBinding): String = {
+ val sb = new StringBuffer();
+ toString(sb, stop);
+ sb.toString();
+ }
+
+ def toString(sb:StringBuffer, stop:NamespaceBinding): Unit = {
+ if (this ne stop) { // contains?
+ sb.append(" xmlns");
+ if (prefix != null) {
+ sb.append(':').append(prefix)
+ }
+ sb.append('=')
+ .append('"')
+ .append(uri)
+ .append('"');
+ parent.toString(sb, stop); // copy(ignore)
+ }
+ }
+
+}
diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala
new file mode 100644
index 0000000000..2daf643d7a
--- /dev/null
+++ b/src/library/scala/xml/Node.scala
@@ -0,0 +1,145 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+import scala.collection.Map;
+
+/**
+ * This object provides methods
+ */
+object Node {
+
+ /** the constant empty attribute sequence */
+ final def NoAttributes: MetaData = Null;
+
+ /** the empty namespace */
+ val EmptyNamespace = "";
+
+}
+
+/**
+ * An abstract class representing XML with nodes of a labelled tree.
+ * This class contains an implementation of a subset of XPath for navigation.
+ *
+ * @author Burak Emir and others
+ * @version 1.1
+ */
+abstract class Node extends NodeSeq {
+
+ /** prefix of this node */
+ def prefix: String = null;
+
+ /** label of this node. I.e. "foo" for &lt;foo/&gt;) */
+ def label: String;
+
+ /** used internally. Atom/Molecule = -1 PI = -2 Comment = -3 EntityRef = -5 */
+ def typeTag$: Int = 0;
+
+ /** the namespace bindings */
+ def scope: NamespaceBinding = TopScope;
+
+ def namespace = getNamespace(prefix);
+
+ def getNamespace(_pre: String) =
+ if (scope == null) null else scope.getURI(_pre);
+
+ /**
+ * Looks up an unprefixed attribute in attributes of this node.
+ *
+ * @param key of queried attribute.
+ * @return value of <code>UnprefixedAttribute</code> with given key
+ * in attributes, if it exists, otherwise <code>null</code>.
+ */
+ final def attribute(key: String) =
+ attributes.getValue(key);
+
+ /**
+ * Looks up a prefixed attribute in attributes of this node.
+ *
+ * @param uri namespace of queried attribute (may not be null).
+ * @param key of queried attribute.
+ * @return value of <code>PrefixedAttribute</code> with given namespace
+ * and given key, otherwise <code>null</code>.
+ */
+ final def attribute(uri: String, key: String) =
+ attributes.getValue(uri, this, key);
+
+ /**
+ * Attribute axis - all attributes of this node, in order defined by attrib
+ */
+ def attributes: MetaData =
+ Null;
+
+ /** child axis (all children of this node) */
+ def child: Seq[Node];
+
+ /** descendant axis (all descendants of this node, not including not itself) */
+ def descendant: List[Node] =
+ child.toList.flatMap { x => x::x.descendant } ;
+
+ /** descendant axis (all descendants of this node, including this node) */
+ def descendant_or_self: List[Node] = this :: descendant;
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ 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 */
+ override def hashCode(): Int;
+ //Utility.hashCode(pre, label, attributes.hashCode(), child);
+
+
+ /** method for NodeSeq */
+ final def theSeq = this :: Nil;
+
+ /**
+ * String representation of this node
+ *
+ * @param stripComment if true, strips comment nodes from result
+ */
+ def toString(stripComment: Boolean): String =
+ Utility.toXML(this, stripComment);
+
+ /**
+ * Same as <code>toString(false)</code>.
+ *
+ * @see "toString(Boolean)"
+ */
+ override def toString(): String =
+ toString(false);
+
+ /**
+ * Appends qualified name of this node to <code>StringBuffer</code>.
+ *
+ * @param sb
+ * @return ..
+ */
+ def nameToString(sb: StringBuffer): StringBuffer = {
+ if (null != prefix) {
+ sb.append(prefix);
+ sb.append(':');
+ }
+ sb.append(label);
+ }
+
+ /**
+ * Returns a type symbol (e.g. DTD, XSD), default <code>null</code>.
+ */
+ def xmlType(): TypeSymbol = null;
+
+ override def text: String;
+
+}
diff --git a/src/library/scala/xml/NodeBuffer.scala b/src/library/scala/xml/NodeBuffer.scala
new file mode 100644
index 0000000000..b61e24181c
--- /dev/null
+++ b/src/library/scala/xml/NodeBuffer.scala
@@ -0,0 +1,55 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/**
+ * This class acts as a Buffer for nodes. If it is used as a sequence
+ * of nodes <code>Seq[Node]</code>, it must be ensured that no updates
+ * occur after that point, because <code>scala.xml.Node</code> is assumed
+ * to be immutable.
+ *
+ * Despite this being a sequence, don't use it as key in a hashtable.
+ * Calling the hashcode function will result in a runtime error.
+ */
+class NodeBuffer extends scala.collection.mutable.ArrayBuffer[Node] {
+
+ /**
+ * Append a single node to this buffer, returns reference on this
+ * NodeBuffer for convenience.
+ *
+ * Append an iterable object to this buffer, returns reference on
+ * this NodeBuffer for convenience.
+ *
+ * Append given string as a <code>scala.xml.Text</code> node to this
+ * buffer, returns reference on this NodeBuffer for convenience.
+ *
+ * @param n
+ */
+ def &+(o: Any): NodeBuffer = {
+ o match {
+ case n:Node => super.+(n);
+ case ns:Iterable[AnyRef] =>
+ val it = ns.elements;
+ while(it.hasNext) {
+ this &+ it.next;
+ if (it.hasNext)
+ this &+ " ";
+ }
+ case _ => super.+(Text(o.toString()));
+ }
+ this
+ }
+ /*
+ def +(o: AnyVal): NodeBuffer = {
+ super.+(Text(o.toString()));
+ this
+ }
+ */
+}
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala
new file mode 100644
index 0000000000..84d37d5790
--- /dev/null
+++ b/src/library/scala/xml/NodeSeq.scala
@@ -0,0 +1,104 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml ;
+
+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);
+}
+
+/** a wrapper around Seq[Node] that adds XPath and comprehension methods */
+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[Node] => 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.
+ */
+ def \(that: String):NodeSeq = {
+ var res: NodeSeq = NodeSeq.Empty;
+ that match {
+ case "_" =>
+ res = for( val x <- this; val y <- x.child: NodeSeq) yield { y }
+
+ case _ if (that.charAt(0) == '@') && (this.length == 1) =>
+ val k = that.substring(1);
+ val y = this(0);
+ val v = y.attribute(k);
+ if( v != null ) {
+ res = NodeSeq.fromSeq(Seq.single(Text(v)));
+ }
+
+ case _ =>
+ res = for( val x <- this; val y <- x.child: NodeSeq; y.label == that )
+ yield { y }
+ }
+ res
+ }
+
+ /** 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.
+ */
+
+ def \\ ( that:String ): NodeSeq = that match {
+ case "_" => for( val x <- this;
+ val y <- x.descendant_or_self: NodeSeq )
+ yield { y }
+ case _ if that.charAt(0) == '@' =>
+ val attrib = that.substring(1);
+ (for(val x <- this;
+ val y <- x.descendant_or_self: NodeSeq;
+ val z <- y \ that)
+ yield { z }):NodeSeq
+ case _ => for( val x <- this;
+ val y <- x.descendant_or_self: NodeSeq;
+ y.label == that)
+ yield { y }
+ }
+
+ override def toString():String = theSeq.elements.foldLeft ("") {
+ (s:String,x:Node) => s + x.toString()
+ }
+
+ def asList = elements.toList;
+
+ def map(f: Node => Node): NodeSeq = { val x = asList map f; x }
+
+ def flatMap(f:Node => NodeSeq): NodeSeq = { val y = asList flatMap { x => f(x).asList }; y }
+
+ def filter(f:Node => Boolean): NodeSeq = { val x = asList filter f; x }
+
+ def text: String = {
+ val sb = new StringBuffer();
+ val it = elements;
+ while(it.hasNext) {
+ sb.append(it.next.text);
+ }
+ sb.toString();
+ }
+}
diff --git a/src/library/scala/xml/NodeTraverser.scala b/src/library/scala/xml/NodeTraverser.scala
new file mode 100644
index 0000000000..690c85534d
--- /dev/null
+++ b/src/library/scala/xml/NodeTraverser.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+import parsing.MarkupHandler;
+
+trait NodeTraverser extends 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/library/scala/xml/Null.scala b/src/library/scala/xml/Null.scala
new file mode 100644
index 0000000000..5790a2fdfd
--- /dev/null
+++ b/src/library/scala/xml/Null.scala
@@ -0,0 +1,75 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+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[MetaData];
+
+ 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 getValue(key: String) = null;
+
+ /** gets value of qualified (prefixed) attribute with given key */
+ def getValue(namespace: String, scope: NamespaceBinding, key: String) =
+ null;
+
+ override def hashCode(): Int = 0;
+
+ override def toString1(): String = "";
+
+ //appends string representations of single attribute to StringBuffer
+ def toString1(sb:StringBuffer) = {};
+
+ override def toString(): String = "";
+
+ override def toString(sb: StringBuffer): Unit = {}
+
+ override def wellformed(scope: NamespaceBinding) = true;
+
+}
diff --git a/src/library/scala/xml/Parsing.scala b/src/library/scala/xml/Parsing.scala
new file mode 100644
index 0000000000..bc86d18e62
--- /dev/null
+++ b/src/library/scala/xml/Parsing.scala
@@ -0,0 +1,102 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.xml ;
+
+/** 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 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 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/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala
new file mode 100644
index 0000000000..4eb947e2c1
--- /dev/null
+++ b/src/library/scala/xml/PrefixedAttribute.scala
@@ -0,0 +1,87 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+/** prefixed attributes always have a non-null namespace
+ */
+class PrefixedAttribute(val pre: String,
+ val key: String,
+ val value: String,
+ val next: MetaData) extends MetaData {
+
+ // verify that value is a proper attribute value (references, no &lt;)
+ Utility.checkAttributeValue(value) match {
+ case null => ;
+ case msg => throw new MalformedAttributeException(msg);
+ }
+
+ /** Returns a copy of this unprefixed attribute with the given
+ * next field.
+ */
+ def copy(next: MetaData) =
+ new PrefixedAttribute(pre, key, value, next);
+
+ //** duplicates the MetaData (deep copy), not preserving order */
+ //def deepCopy: MetaData = deepCopy(null);
+
+ //** duplicates the MetaData (deep copy), prepending it to tail */
+ /*
+ def deepCopy(tail: MetaData): MetaData = {
+ val md = copy(tail);
+ if (null == next)
+ md
+ else
+ next.deepCopy(md)
+ }
+ */
+
+ def equals1(m: MetaData) =
+ (m.isPrefixed &&
+ (m.asInstanceOf[PrefixedAttribute].pre == pre) &&
+ (m.key == key) && (m.value == value));
+
+ def getNamespace(owner: Node) =
+ owner.getNamespace(pre);
+
+ /** forwards the call to next */
+ def getValue(key: String): String = next.getValue(key);
+
+ /** gets attribute value of qualified (prefixed) attribute with given key
+ */
+ def getValue(namespace: String, scope: NamespaceBinding, key: String): String = {
+ if (key == this.key && scope.getURI(pre) == namespace)
+ value
+ else
+ next.getValue(namespace, scope, key);
+ }
+
+ /** returns true */
+ final def isPrefixed = true;
+
+ override def hashCode() =
+ pre.hashCode() * 41 + key.hashCode() * 7 + value.hashCode() * 3 + next.hashCode();
+
+
+ def toString1(sb:StringBuffer): Unit = {
+ sb.append(pre);
+ sb.append(':');
+ sb.append(key);
+ sb.append('=');
+ Utility.appendQuoted(value, sb);
+ }
+
+ def wellformed(scope: NamespaceBinding): Boolean = {
+ (null == next.getValue(scope.getURI(pre), scope, key)
+ && next.wellformed(scope));
+ }
+
+}
+
diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala
new file mode 100644
index 0000000000..3410c5dd9a
--- /dev/null
+++ b/src/library/scala/xml/PrettyPrinter.scala
@@ -0,0 +1,274 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml ;
+
+import java.lang.StringBuffer ; /* Java dependency! */
+import scala.collection.Map ;
+
+/** 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.
+ *
+ * @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 */
+ 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 StringBuffer();
+ var i = s.indexOf(' ');
+ if(i > tmp || i == -1) throw new BrokenException(); // cannot break
+
+ var last:List[Int] = i::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 );
+ // backtrac
+ } catch {
+ case _:BrokenException => last = last.tail;
+ }
+ throw new BrokenException()
+ }
+
+ /** try to make indented box, if possible, else para */
+ 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;
+ }
+
+ protected def leafTag( n:Node ) = {
+ val sb = new StringBuffer("<");
+ 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 StringBuffer("<");
+ 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 StringBuffer("</");
+ n.nameToString(sb); //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb );
+ sb.append('>');
+ sb.toString();
+ }
+
+
+ protected def childrenAreLeaves(n: Node): Boolean = {
+ val it = n.child.elements;
+ while( it.hasNext )
+ it.next match {
+ case _:Atom[Any] | _: Molecule[Any] | _:Comment | _:EntityRef | _:ProcInstr =>
+ case _:Node =>
+ return false;
+ }
+ return 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 _:Atom[Any] | _:Molecule[Any] | _:Comment | _:EntityRef | _:ProcInstr =>
+ makeBox( ind, node.toString() );
+
+ case _:Node =>
+ val test = { val sb = new StringBuffer(); Utility.toXML(node, pscope, sb, false); sb.toString()};
+ if(childrenAreLeaves(node) && fits(test)) {
+ makeBox( ind, test );
+ } else {
+ val Pair(stg, len2) = startTag( node, pscope );
+ val etg = endTag( node );
+ if( stg.length() < width - cur ) { // start tag fits
+
+ makeBox( ind, stg );
+ makeBreak();
+ traverse( node.child.elements, node.scope, ind + step );
+ makeBox( ind, etg );
+
+ } else if( len2 < width - cur ) {
+ // <start label + attrs + tag + content + end tag
+ makeBox( ind, stg.substring( 0, len2 ));
+ makeBreak(); // todo: break the rest in pieces
+ /*{ //@todo
+ val sq:Seq[String] = stg.split(" ");
+ val it = sq.elements;
+ it.next;
+ for( val c <- it ) {
+ makeBox( ind+len2-2, c );
+ makeBreak();
+ }
+ }*/
+ makeBox( ind, stg.substring( len2, stg.length() ));
+ makeBreak();
+ traverse( node.child.elements, node.scope, ind + step );
+ makeBox( cur, etg );
+ } else { // give up
+ makeBox( ind, test );
+ makeBreak();
+ }
+ }
+ }
+
+ protected def traverse( it:Iterator[Node], scope:NamespaceBinding, ind: Int ): Unit = {
+ for( val c <- it ) {
+ traverse( c, scope, ind );
+ makeBreak();
+ }
+ }
+
+ /** appends a formatted string containing well-formed XML with
+ * given namespace to prefix mapping to the given stringbuffer
+ * @param n the node to be serialized
+ * @param pmap the namespace to prefix mapping
+ * @param sb the stringbuffer to append to
+ */
+ def format(n: Node, sb: StringBuffer ): Unit = { // entry point
+ format(n,null,sb)
+ }
+
+ def format(n: Node, pscope:NamespaceBinding, sb: StringBuffer): Unit = { // entry point
+ reset();
+ traverse( n, pscope, 0 );
+ var cur = 0;
+ //Console.println( items.reverse );
+ for( val b <- items.reverse ) b match {
+ case Break =>
+ sb.append('\n'); // on windows: \r\n ?
+ cur = 0;
+// while( cur < last ) {
+// sb.append(' ');
+// cur = cur + 1;
+// }
+
+ case Box(i, s) =>
+ while( cur < i ) {
+ sb.append(' ');
+ cur = cur + 1;
+ }
+ sb.append( s );
+ case Para( s ) =>
+ 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
+ */
+ 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
+ */
+ def format(n: Node, pscope: NamespaceBinding): String = {
+ val sb = new StringBuffer();
+ format( n, pscope, sb );
+ sb.toString();
+ }
+
+ /* returns a formatted string containing well-formed XML nodes with
+ * default namespace prefix mapping
+ */
+ 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 StringBuffer();
+ 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: StringBuffer ): Unit = {
+ for( val n <- nodes.elements ) {
+ sb.append(format( n, pscope ))
+ }
+ }
+}
diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala
new file mode 100644
index 0000000000..b4160139e6
--- /dev/null
+++ b/src/library/scala/xml/ProcInstr.scala
@@ -0,0 +1,63 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** 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;
+
+ val z:Seq[Char] = target; z match {
+ case Seq('X'|'x','M'|'m','L'|'l') =>
+ throw new IllegalArgumentException(target+" is reserved");
+ case _ =>
+ }
+
+ /** structural equality */
+ override def equals(x: Any): Boolean = x match {
+ case ProcInstr(x,y) => x.equals(target) && y.equals(proctext);
+ case _ => false
+ }
+
+ /** the constant "#PI" */
+ final def label = "#PI";
+
+ /** hashcode for this PI */
+ override def hashCode() = target.hashCode() * 7 + proctext.hashCode();
+
+
+ override def text = "";
+
+ /** appends &quot;&lt;?&quot; target (&quot; &quot;+text)?+&quot;?&gt;&quot;
+ * to this stringbuffer.
+ */
+ def toString(sb: StringBuffer) = {
+ sb
+ .append("<?")
+ .append(target);
+ if( proctext.length() > 0 ) {
+ sb
+ .append(' ')
+ .append(text);
+ };
+ sb.append("?>");
+ }
+}
diff --git a/src/library/scala/xml/SpecialNode.scala b/src/library/scala/xml/SpecialNode.scala
new file mode 100644
index 0000000000..1162287e2f
--- /dev/null
+++ b/src/library/scala/xml/SpecialNode.scala
@@ -0,0 +1,31 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** a special XML node is either text (PCDATA), a comment, a PI, or
+ * an entity ref
+**/
+abstract class SpecialNode extends Node {
+
+ /** always empty */
+ final override def attributes = Null;
+
+ /** always Node.EmptyNamespace */
+ final override def namespace = null;
+
+ /** always empty */
+ final def child = Nil;
+
+ final override def toString(): String =
+ toString(new StringBuffer()).toString();
+
+ def toString(sb:StringBuffer): StringBuffer ;
+
+}
diff --git a/src/library/scala/xml/Text.scala b/src/library/scala/xml/Text.scala
new file mode 100644
index 0000000000..507239cc8b
--- /dev/null
+++ b/src/library/scala/xml/Text.scala
@@ -0,0 +1,32 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+/** an XML node for text (PCDATA). 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 XML spec */
+ override def toString(sb:StringBuffer) =
+ Utility.escape( data.toString(), sb );
+
+}
diff --git a/src/library/scala/xml/TextBuffer.scala b/src/library/scala/xml/TextBuffer.scala
new file mode 100644
index 0000000000..448fd861d5
--- /dev/null
+++ b/src/library/scala/xml/TextBuffer.scala
@@ -0,0 +1,55 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.xml ;
+
+object TextBuffer {
+ def fromString(str: String): TextBuffer = {
+ new TextBuffer().append( str );
+ }
+}
+
+/** this classes 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 StringBuffer();
+ 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 */
+ 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 */
+ 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/library/scala/xml/TopScope.scala b/src/library/scala/xml/TopScope.scala
new file mode 100644
index 0000000000..ff3b3b7cba
--- /dev/null
+++ b/src/library/scala/xml/TopScope.scala
@@ -0,0 +1,28 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+case object TopScope extends NamespaceBinding(null, null, null) {
+
+ /*
+ override def contains(pre:String) = false;
+ */
+ override def getURI(_prefix: String) = null;
+
+ override def getPrefix(_uri: String) = null;
+
+ override def toString() = "";
+
+ override def toString(stop: NamespaceBinding) = "";
+
+ override def toString(sb: StringBuffer, ignore: NamespaceBinding) = {};
+
+}
diff --git a/src/library/scala/xml/TypeSymbol.scala b/src/library/scala/xml/TypeSymbol.scala
new file mode 100644
index 0000000000..1d5fba7ae6
--- /dev/null
+++ b/src/library/scala/xml/TypeSymbol.scala
@@ -0,0 +1,11 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $id: $
+
+package scala.xml; trait TypeSymbol {}
diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala
new file mode 100644
index 0000000000..82d30ac804
--- /dev/null
+++ b/src/library/scala/xml/UnprefixedAttribute.scala
@@ -0,0 +1,70 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml;
+
+/** unprefixed attributes have the null namespace
+ */
+class UnprefixedAttribute(val key: String, val value: String, val next: MetaData) extends MetaData {
+
+ // verify that value is a proper attribute value (references, no &lt;)
+ Utility.checkAttributeValue(value) match {
+ case null => ;
+ case msg => throw new MalformedAttributeException(msg);
+ }
+
+ /** 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 == value);
+
+ /** returns null */
+ final def getNamespace(owner: Node): String =
+ null;
+
+ /**
+ * Gets value of unqualified (unprefixed) attribute with given key.
+ *
+ * @param key
+ * @return ..
+ */
+ def getValue(key: String): String =
+ if (key == this.key) value else next.getValue(key);
+
+ /**
+ * Forwards the call to next.
+ *
+ * @param namespace
+ * @param scope
+ * @param key
+ * @return ..
+ */
+ def getValue(namespace: String, scope: NamespaceBinding, key: String): String =
+ next.getValue(namespace, scope, key);
+
+ override def hashCode() =
+ key.hashCode() * 7 + value.hashCode() * 53 + next.hashCode();
+
+ /** returns false */
+ final def isPrefixed = false;
+
+ def toString1(sb:StringBuffer): Unit = {
+ sb.append(key);
+ sb.append('=');
+ Utility.appendQuoted(value, sb);
+ }
+
+ def wellformed(scope: NamespaceBinding): Boolean =
+ (null == next.getValue(null, scope, key)) && next.wellformed(scope);
+
+}
+
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
new file mode 100644
index 0000000000..2737e75d58
--- /dev/null
+++ b/src/library/scala/xml/Utility.scala
@@ -0,0 +1,244 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml;
+
+import java.lang.StringBuffer;
+import scala.collection.mutable;
+
+/**
+ * Utility functions for processing instances of bound and not bound XML
+ * classes, as well as escaping text nodes
+ */
+object Utility extends AnyRef with parsing.TokenTests {
+
+ def view(s: String): Text = Text(s);
+
+ /* escapes the characters &lt; &gt; &amp; and &quot; from string */
+ final def escape(text: String): String =
+ escape(text, new StringBuffer()).toString();
+
+
+ /* appends escaped string to s */
+ final def escape(text: String, s: StringBuffer): StringBuffer = {
+ for (val c <- Iterator.fromString(text)) c match {
+ case '<' => s.append("&lt;");
+ case '>' => s.append("&gt;");
+ case '&' => s.append("&amp;");
+ case '"' => s.append("&quot;");
+ case _ => s.append(c);
+ }
+ s
+ }
+
+ /**
+ * Returns a set of all namespaces used in a sequence of nodes
+ * and all their descendants, including the empty namespaces.
+ *
+ * @param nodes
+ */
+
+ def collectNamespaces(nodes: Seq[Node]): mutable.Set[String] = {
+ var m = new mutable.HashSet[String]();
+ val it = nodes.elements;
+ while (it.hasNext)
+ collectNamespaces(it.next, m);
+ m
+ }
+
+ /** adds all namespaces in node to set */
+ def collectNamespaces(n: Node, set: mutable.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);
+ }
+ }
+
+ /** string representation of an XML node, with comments stripped the comments
+ * @see "toXML(Node, Boolean)"
+ */
+ def toXML(n: Node): String = toXML(n, true);
+
+ /**
+ * String representation of a Node. uses namespace mapping from
+ * <code>defaultPrefixes(n)</code>.
+ *
+ * @param n
+ * @param stripComment
+ *
+ * @todo define a way to escape literal characters to &amp;xx; references
+ */
+ def toXML(n: Node, stripComment: Boolean): String = {
+ val sb = new StringBuffer();
+ 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: StringBuffer, stripComment: Boolean): Unit = {
+ x match {
+
+ case c: Comment if !stripComment =>
+ c.toString(sb)
+
+ case x: SpecialNode =>
+ x.toString(sb)
+
+ case _ =>
+ // print tag with namespace declarations
+ sb.append('<');
+ x.nameToString(sb);
+ if (x.attributes != null) {
+ x.attributes.toString(sb)
+ }
+ x.scope.toString(sb, pscope);
+ sb.append('>');
+ for (val c <- x.child.elements) {
+ toXML(c, x.scope, sb, stripComment);
+ }
+ sb.append("</");
+ x.nameToString(sb);
+ sb.append('>')
+
+ }
+ }
+
+
+ /** returns prefix of qualified name if any */
+ final def prefix(name: String): Option[String] = {
+ val i = name.indexOf(':');
+ 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!=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()
+ }
+ */
+
+ def systemLiteralToString(s: String): String = {
+ val sb = new StringBuffer();
+ systemLiteralToString(sb, s);
+ sb.toString();
+ }
+
+ def systemLiteralToString(sb: StringBuffer, s: String): StringBuffer = {
+ sb.append("SYSTEM ");
+ appendQuoted(s, sb);
+ }
+
+ def publicLiteralToString(s: String): String = {
+ val sb = new StringBuffer();
+ systemLiteralToString(sb, s);
+ sb.toString();
+ }
+
+ def publicLiteralToString(sb: StringBuffer, s: String): StringBuffer = {
+ sb.append("PUBLIC \"").append(s).append('"')
+ }
+
+ /**
+ * Appends &quot;s&quot; if s does not contain &quot;, &apos;s&apos;
+ * otherwise
+ *
+ * @param s
+ * @param sb
+ */
+ def appendQuoted(s: String, sb: StringBuffer) = {
+ val ch = if (s.indexOf('"') == -1) '"' else '\'';
+ sb.append(ch).append(s).append(ch)
+ }
+
+ /**
+ * Appends &quot;s&quot; and escapes and &quot; i s with \&quot;
+ *
+ * @param s
+ * @param sb
+ */
+ def appendEscapedQuoted(s: String, sb: StringBuffer) = {
+ sb.append('"');
+ val z:Seq[Char] = s;
+ for( val c <- z ) c match {
+ case '"' => sb.append('\\'); sb.append('"');
+ case _ => sb.append( c );
+ }
+ sb.append('"')
+ }
+
+ def getName(s: String, index: Int): String = {
+ var i = index;
+ val sb = new StringBuffer();
+ 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 */
+ 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== 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;
+ }
+ return null;
+ }
+
+}
diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala
new file mode 100644
index 0000000000..1fadac7fe8
--- /dev/null
+++ b/src/library/scala/xml/XML.scala
@@ -0,0 +1,75 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.xml ;
+
+import scala.xml.parsing.NoBindingFactoryAdapter ;
+import org.xml.sax.InputSource;
+
+// import scala.xml.Utility ;
+
+/** functions to load and save XML elements. use this when data binding is not
+** desired, i.e. when XML is handled using Symbol nodes
+**/
+object XML {
+
+ import java.io._ ;
+
+ // functions for generic xml loading, saving
+
+ /** loads XML from given file */
+ final def loadFile( file: File ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource(
+ new FileInputStream( file )
+ ));
+
+ /** loads XML from given file descriptor */
+ final def loadFile( fileDesc: FileDescriptor ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource(
+ new FileInputStream( fileDesc )
+ ));
+
+ /** loads XML from given file */
+ final def loadFile( fileName:String ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource(
+ new FileInputStream( fileName )
+ ));
+
+ /** loads XML from given InputStream */
+ final def load( is:InputStream ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource( is ));
+
+ /** loads XML from given Reader */
+ final def load( reader:Reader ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource( reader ));
+
+ /** loads XML from given sysID */
+ final def load( sysID:String ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( new InputSource( sysID ));
+
+ /** loads XML from a given input source*/
+ final def load( source:InputSource ): scala.xml.Elem =
+ new NoBindingFactoryAdapter().loadXML( source );
+
+ /** saves XML to filename with encoding ISO-8859-1 */
+ final def save( filename:String, doc:Elem ):Unit = {
+ /* using NIO classes of JDK 1.4 */
+ import java.io.{FileOutputStream,Writer};
+ import java.nio.channels.{Channels,FileChannel};
+
+ val fos = new FileOutputStream( filename );
+ val w:Writer = Channels.newWriter( fos.getChannel(), "ISO-8859-1" );
+
+ /* 2do: optimize by giving writer parameter to toXML*/
+ w.write( Utility.toXML( doc ));
+
+ w.close();
+ fos.close();
+ }
+
+}
diff --git a/src/library/scala/xml/dtd/ContentModel.scala b/src/library/scala/xml/dtd/ContentModel.scala
new file mode 100644
index 0000000000..78132dcc4a
--- /dev/null
+++ b/src/library/scala/xml/dtd/ContentModel.scala
@@ -0,0 +1,200 @@
+package scala.xml.dtd ;
+
+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 StringBuffer();
+ toString(r, sb);
+ sb.toString();
+ }
+
+ /* precond: rs.length >= 1 */
+ private def toString(rs: Seq[RegExp], sb: StringBuffer, 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: StringBuffer): StringBuffer = 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:StringBuffer): StringBuffer = {
+ 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 StringBuffer();
+ toString(sb);
+ sb.toString();
+ }
+
+ def toString(sb:StringBuffer): StringBuffer;
+ /*
+ 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 {
+ def toString(sb:StringBuffer): StringBuffer = sb.append("(#PCDATA)");
+}
+case object EMPTY extends ContentModel {
+ def toString(sb:StringBuffer): StringBuffer = sb.append("EMPTY");
+}
+case object ANY extends ContentModel {
+ def toString(sb:StringBuffer): StringBuffer = 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
+ }
+ }
+ */
+ def toString(sb:StringBuffer): StringBuffer = {
+ 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
+ }
+ }
+ */
+ def toString(sb:StringBuffer): StringBuffer =
+ ContentModel.toString(r, sb);
+}
diff --git a/src/library/scala/xml/dtd/ContentModelParser.scala b/src/library/scala/xml/dtd/ContentModelParser.scala
new file mode 100644
index 0000000000..08232d118d
--- /dev/null
+++ b/src/library/scala/xml/dtd/ContentModelParser.scala
@@ -0,0 +1,144 @@
+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/library/scala/xml/dtd/DTD.scala b/src/library/scala/xml/dtd/DTD.scala
new file mode 100644
index 0000000000..9cf55f7077
--- /dev/null
+++ b/src/library/scala/xml/dtd/DTD.scala
@@ -0,0 +1,48 @@
+package scala.xml.dtd;
+
+import scala.io.Source;
+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 StringBuffer();
+ 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/library/scala/xml/dtd/Decl.scala b/src/library/scala/xml/dtd/Decl.scala
new file mode 100644
index 0000000000..1e151a5c84
--- /dev/null
+++ b/src/library/scala/xml/dtd/Decl.scala
@@ -0,0 +1,182 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml.dtd ;
+
+abstract class Decl ;
+
+abstract class MarkupDecl extends Decl {
+
+ final override def toString(): String = {
+ toString(new StringBuffer()).toString();
+ }
+
+ def toString(sb: StringBuffer): StringBuffer;
+
+}
+
+/** an element declaration
+ */
+case class ElemDecl(name: String, contentModel: ContentModel) extends MarkupDecl with DtdTypeSymbol {
+
+ //def mixed = ; // to do
+
+ def toString(sb: StringBuffer): StringBuffer = {
+ sb
+ .append("<!ELEMENT ")
+ .append(name)
+ .append(' ');
+
+ ContentModel.toString(contentModel, sb);
+ sb.append('>');
+ }
+
+} // ElemDecl
+
+case class AttListDecl(name: String, attrs:List[AttrDecl]) extends MarkupDecl with DtdTypeSymbol {
+
+ def toString(sb: StringBuffer): StringBuffer = {
+ sb
+ .append("<!ATTLIST ")
+ .append(name)
+ .append('\n')
+ .append(attrs.mkString("","\n",">"));
+ }
+}
+
+/** an attribute declaration. at this point, the tpe is a string. Future
+ * versions might provide a way to access the attribute types more
+ * directly.
+ */
+case class AttrDecl( name:String, tpe:String, default:DefaultDecl ) {
+
+ final override def toString(): String =
+ toString(new StringBuffer()).toString();
+
+ final def toString(sb: StringBuffer): StringBuffer = {
+ 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 {
+
+ final def toString(sb: StringBuffer): StringBuffer = {
+ sb.append("<!ENTITY ").append( name ).append(' ');
+ entdef.toString(sb).append('>');
+ }
+}
+
+/** a parameter entity declaration */
+case class ParameterEntityDecl(name: String, entdef: EntityDef) extends EntityDecl {
+
+ final def toString(sb: StringBuffer): StringBuffer = {
+ sb.append("<!ENTITY % ").append( name ).append(' ');
+ entdef.toString(sb).append('>');
+ }
+}
+
+/** an unparsed entity declaration */
+case class UnparsedEntityDecl( name:String, extID:ExternalID, notation:String ) extends EntityDecl {
+ final def toString(sb: StringBuffer): StringBuffer = {
+ sb.append("<!ENTITY ").append( name ).append(' ');
+ extID.toString(sb).append(" NDATA ").append(notation).append('>');
+ }
+}
+/** a notation declaration */
+case class NotationDecl( name:String, extID:ExternalID ) extends MarkupDecl {
+ final def toString(sb: StringBuffer): StringBuffer = {
+ sb.append("<!NOTATION ").append( name ).append(' ');
+ extID.toString(sb);
+ }
+}
+
+abstract class EntityDef {
+ final override def toString(): String =
+ toString(new StringBuffer()).toString();
+
+ def toString(sb: StringBuffer): StringBuffer;
+}
+
+case class IntDef(value:String) extends EntityDef {
+ private def validateValue(): Unit = {
+ var tmp = value;
+ var ix = tmp.indexOf('%');
+ while( ix != -1) {
+ val iz = tmp.indexOf(';', ix);
+ if(iz == -1 && iz == ix + 1)
+ error("no % allowed in entity value, except for parameter-entity-references");
+ else {
+ val n = tmp.substring(ix, iz);
+
+ if( !Utility.isName( n ))
+ throw new IllegalArgumentException("interal entity def: \""+n+"\" must be an XML Name");
+
+ tmp = tmp.substring(iz+1, tmp.length());
+ ix = tmp.indexOf('%');
+ }
+ }
+ }
+ validateValue();
+
+ final def toString(sb: StringBuffer): StringBuffer =
+ Utility.appendQuoted(value, sb);
+
+}
+
+case class ExtDef(extID:ExternalID) extends EntityDef {
+ final def toString(sb: StringBuffer): StringBuffer =
+ extID.toString(sb);
+}
+
+
+
+/** a parsed entity reference */
+case class PEReference(ent:String) extends MarkupDecl {
+ if( !Utility.isName( ent ))
+ throw new IllegalArgumentException("ent must be an XML Name");
+
+ final def toString(sb: StringBuffer): StringBuffer =
+ sb.append('%').append(ent).append(';');
+}
+
+
+// default declarations for attributes
+
+abstract class DefaultDecl {
+ override def toString(): String;
+ def toString(sb: StringBuffer): StringBuffer;
+}
+
+case object REQUIRED extends DefaultDecl {
+ final override def toString(): String = "#REQUIRED";
+ final def toString(sb:StringBuffer) = sb.append("#REQUIRED");
+}
+
+case object IMPLIED extends DefaultDecl {
+ final override def toString(): String = "#IMPLIED";
+ final def toString(sb:StringBuffer) = sb.append("#IMPLIED");
+}
+
+case class DEFAULT(fixed:boolean, attValue:String) extends DefaultDecl {
+ final override def toString(): String =
+ toString(new StringBuffer()).toString();
+
+ final def toString(sb:StringBuffer): StringBuffer = {
+ if(fixed)
+ sb.append("#FIXED ");
+ Utility.appendEscapedQuoted( attValue, sb );
+ }
+}
diff --git a/src/library/scala/xml/dtd/DocType.scala b/src/library/scala/xml/dtd/DocType.scala
new file mode 100644
index 0000000000..014c7046aa
--- /dev/null
+++ b/src/library/scala/xml/dtd/DocType.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.dtd;
+
+/** an XML node for document type declaration
+ *
+ * @author Burak Emir
+ * @param target name of this DOCTYPE
+ * @param extID None, or Some(external ID of this doctype)
+ * @param intSubset sequence of internal subset declarations
+**/
+
+case class DocType( name:String, extID:ExternalID, intSubset:Seq[dtd.Decl]) {
+
+ if( !Utility.isName( name ) )
+ throw new IllegalArgumentException(name+" must be an XML Name");
+
+ /** hashcode for this processing instruction */
+ final override def hashCode() = name.hashCode() + 7 * extID.hashCode() + 41*intSubset.toList.hashCode();
+
+ /** returns "&lt;!DOCTYPE + name + extID? + ("["+intSubSet+"]")? >" */
+ final override def toString() = {
+ val sb = new StringBuffer("<!DOCTYPE ");
+ sb.append( name );
+ sb.append(' ');
+ sb.append(extID.toString());
+ if( intSubset.length > 0 ) {
+ sb.append('[');
+ for( val d <- intSubset ) {
+ sb.append( d.toString() );
+ }
+ sb.append(']');
+ }
+ sb.append('>');
+ sb.toString();
+ }
+}
diff --git a/src/library/scala/xml/dtd/DtdTypeSymbol.scala b/src/library/scala/xml/dtd/DtdTypeSymbol.scala
new file mode 100644
index 0000000000..633e11e646
--- /dev/null
+++ b/src/library/scala/xml/dtd/DtdTypeSymbol.scala
@@ -0,0 +1 @@
+package scala.xml.dtd; trait DtdTypeSymbol {}
diff --git a/src/library/scala/xml/dtd/ElementValidator.scala b/src/library/scala/xml/dtd/ElementValidator.scala
new file mode 100644
index 0000000000..52ba82cb54
--- /dev/null
+++ b/src/library/scala/xml/dtd/ElementValidator.scala
@@ -0,0 +1,166 @@
+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[String] if (a.data.asInstanceOf[String].trim().length() == 0 ) =>
+ false; // always skip all-whitespace nodes
+
+ case _ =>
+ !skipPCDATA
+
+ }
+ case _ =>
+ x.namespace == 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.set(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 );
+ 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/library/scala/xml/dtd/ExternalID.scala b/src/library/scala/xml/dtd/ExternalID.scala
new file mode 100644
index 0000000000..965d330a99
--- /dev/null
+++ b/src/library/scala/xml/dtd/ExternalID.scala
@@ -0,0 +1,94 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.dtd;
+
+/** 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: StringBuffer): StringBuffer;
+
+ 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 */
+ final override def toString() =
+ Utility.systemLiteralToString( systemId );
+
+ final def toString(sb: StringBuffer): StringBuffer =
+ 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{
+ //Console.println("constructing PublicID \""+publicLiteral+"\" "+systemLiteral);
+
+ //Console.println("util returns "+checkPubID( publicLiteral ));
+
+ if( !checkPubID( publicId ))
+ throw new IllegalArgumentException(
+ "publicId must consist of PubidChars"
+ );
+ if( systemId != null && !checkSysID( systemId ) )
+ throw new IllegalArgumentException(
+ "can't use both \" and ' in systemId"
+ );
+
+ /** the constant "#PI" */
+ final def label = "#PI";
+
+ /** always empty */
+ final def attribute = Node.NoAttributes;
+
+ /** always empty */
+ final def child = Nil;
+
+ /** returns "PUBLIC "+publicId+" SYSTEM "+systemId */
+ final override def toString(): String = {
+ toString(new StringBuffer()).toString();
+ }
+
+ /** appends "PUBLIC "+publicId+" SYSTEM "+systemId to argument */
+ final def toString(sb: StringBuffer): StringBuffer = {
+ Utility.publicLiteralToString( sb, publicId ).append(' ');
+ if(systemId!=null)
+ Utility.systemLiteralToString( sb, systemId );
+ else
+ sb
+ }
+}
diff --git a/src/library/scala/xml/dtd/Scanner.scala b/src/library/scala/xml/dtd/Scanner.scala
new file mode 100644
index 0000000000..c51ac7cbec
--- /dev/null
+++ b/src/library/scala/xml/dtd/Scanner.scala
@@ -0,0 +1,87 @@
+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 StringBuffer();
+ do { sb.append( c ); next } while ( isNameChar( c ) ) ;
+ value = sb.toString();
+ NAME
+ }
+
+}
diff --git a/src/library/scala/xml/dtd/Tokens.scala b/src/library/scala/xml/dtd/Tokens.scala
new file mode 100644
index 0000000000..27935c1d08
--- /dev/null
+++ b/src/library/scala/xml/dtd/Tokens.scala
@@ -0,0 +1,32 @@
+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/library/scala/xml/dtd/ValidationException.scala b/src/library/scala/xml/dtd/ValidationException.scala
new file mode 100644
index 0000000000..337259ffb1
--- /dev/null
+++ b/src/library/scala/xml/dtd/ValidationException.scala
@@ -0,0 +1,33 @@
+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 StringBuffer();
+ 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/library/scala/xml/factory/Binder.scala b/src/library/scala/xml/factory/Binder.scala
new file mode 100644
index 0000000000..d387e90139
--- /dev/null
+++ b/src/library/scala/xml/factory/Binder.scala
@@ -0,0 +1,43 @@
+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/library/scala/xml/factory/LoggedNodeFactory.scala b/src/library/scala/xml/factory/LoggedNodeFactory.scala
new file mode 100644
index 0000000000..cb57069ac2
--- /dev/null
+++ b/src/library/scala/xml/factory/LoggedNodeFactory.scala
@@ -0,0 +1,78 @@
+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 with 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);
+}
+
+*/
+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/library/scala/xml/factory/NodeFactory.scala b/src/library/scala/xml/factory/NodeFactory.scala
new file mode 100644
index 0000000000..7564659c1a
--- /dev/null
+++ b/src/library/scala/xml/factory/NodeFactory.scala
@@ -0,0 +1,77 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id $
+\* */
+
+package scala.xml.factory;
+
+import scala.collection.Map ;
+import scala.collection.mutable ;
+
+[_trait_] abstract class NodeFactory[A <: Node] {
+
+ val ignoreComments = false;
+ val ignoreProcInstr = false;
+
+ /* default behaviour is to use hash-consing */
+ val cache = new 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/library/scala/xml/parsing/ConstructingHandler.scala b/src/library/scala/xml/parsing/ConstructingHandler.scala
new file mode 100644
index 0000000000..fac22b7015
--- /dev/null
+++ b/src/library/scala/xml/parsing/ConstructingHandler.scala
@@ -0,0 +1,24 @@
+package scala.xml.parsing;
+
+/** implementation of MarkupHandler that constructs nodes */
+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/library/scala/xml/parsing/ConstructingParser.scala b/src/library/scala/xml/parsing/ConstructingParser.scala
new file mode 100644
index 0000000000..fafabc916d
--- /dev/null
+++ b/src/library/scala/xml/parsing/ConstructingParser.scala
@@ -0,0 +1,61 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.parsing ;
+
+import scala.io.Source;
+
+object ConstructingParser {
+
+ def fromFile(inp: java.io.File, preserveWS: Boolean) = {
+ val p = new ConstructingParser(Source.fromFile(inp), preserveWS);
+ p.nextch;
+ p
+ }
+
+ def fromSource(inp: scala.io.Source, preserveWS: Boolean) = {
+ val p = new ConstructingParser(inp, preserveWS);
+ p.nextch;
+ p
+ }
+}
+
+/** an xml parser. parses XML and invokes callback methods of a MarkupHandler. Don't forget to call next.ch on a freshly
+ * instantiated parser in order to initialize it. If you get the parser from the object method, initialization is already done for you.
+ *
+ *<pre>
+object parseFromURL {
+ def main(args:Array[String]): Unit = {
+ val url = args(0);
+ val src = scala.io.Source.fromURL(url);
+ val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false); // fromSource initializes automatically
+ val doc = cpa.document();
+
+ // let's see what it is
+ val ppr = new scala.xml.PrettyPrinter(80,5);
+ val ele = doc.docElem;
+ Console.println("finished parsing");
+ val out = ppr.format(ele);
+ Console.println(out);
+ }
+}
+</pre>
+ */
+class ConstructingParser(inp: Source, presWS:Boolean)
+extends ConstructingHandler
+with ExternalSources
+with MarkupParser {
+
+ // default impl. of Logged
+ override def log(msg:String): Unit = {}
+
+ val preserveWS = presWS;
+ val input = inp;
+}
+
diff --git a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala
new file mode 100644
index 0000000000..14fd8ec9a7
--- /dev/null
+++ b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala
@@ -0,0 +1,16 @@
+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/library/scala/xml/parsing/ExternalSources.scala b/src/library/scala/xml/parsing/ExternalSources.scala
new file mode 100644
index 0000000000..d4a1511e99
--- /dev/null
+++ b/src/library/scala/xml/parsing/ExternalSources.scala
@@ -0,0 +1,76 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.parsing ;
+
+import scala.io.Source;
+import java.net._;
+import java.io._;
+
+trait ExternalSources : (ExternalSources with MarkupParser with MarkupHandler) {
+
+
+ private def externalSourceFromURL(url:URL): Source = {
+ val in =
+ new BufferedReader(
+ new InputStreamReader(
+ url.openStream()));
+
+ //@todo: replace this hack with proper Source implementation
+
+ val str = new StringBuffer();
+ var inputLine:String = null;
+
+ //while (inputLine = in.readLine()) != null) {
+ while ({inputLine = in.readLine(); inputLine} != 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/library/scala/xml/parsing/FactoryAdapter.scala b/src/library/scala/xml/parsing/FactoryAdapter.scala
new file mode 100644
index 0000000000..e23032ca70
--- /dev/null
+++ b/src/library/scala/xml/parsing/FactoryAdapter.scala
@@ -0,0 +1,344 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+package scala.xml.parsing ;
+
+import java.io._ ;
+import scala.collection.mutable.{HashMap,Stack};
+
+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 StringBuffer();
+ val attribStack = new Stack[MetaData];
+ val hStack = new Stack[Node]; // [ element ] contains siblings
+ val tagStack = new Stack[String];
+ var scopeStack = new Stack[NamespaceBinding];
+
+ var curTag : String = null ;
+ var capture:boolean = false;
+
+ // abstract methods
+
+ /** Tests if an XML element contains text.
+ * @return true if element named <code>localName</code> contains text.
+ */
+ def nodeContainsText( localName:String ):boolean ; // abstract
+
+ /** creates an new non-text(tree) node.
+ * @param elemName
+ * @param attribs
+ * @param chIter
+ * @return a new XML element.
+ */
+ def createNode(pre: String, elemName: String, attribs: MetaData, scope: NamespaceBinding, chIter: List[Node] ):Node; //abstract
+
+ /** creates a Text node.
+ * @param text
+ * @return a new Text node.
+ */
+ def createText( text:String ):Text; // abstract
+
+ //
+ // ContentHandler methods
+ //
+
+ val normalizeWhitespace = false;
+
+ /** Characters.
+ * @param ch
+ * @param offset
+ * @param length
+ */
+ override def characters(ch: Array[Char], offset: Int, length: Int): Unit = {
+
+ if (capture) {
+ if( normalizeWhitespace ) { // normalizing whitespace is not compliant, but useful */
+ var i:int = offset;
+ var ws:boolean = false;
+ while (i < offset + length) {
+ if ( Character.isWhitespace( ch(i) ) ) {
+ 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(':');
+ 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(':');
+ if(-1 != colon) { // prefixed attribute
+ val pre = qname.substring(0, colon);
+ val key = qname.substring(colon+1, qname.length());
+ if("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" == 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 == true) {
+ val text = buffer.toString();
+ if(( text.length() > 0 )&&( !( text.equals(" ")))) {
+ val _ = 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 != null ) {
+ v = child::v;
+ child = hStack.pop;
+ }
+
+ val colon = qname.indexOf(':');
+ val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length());
+
+ val scp = scopeStack.pop;
+ // create element
+ rootElem = if(-1 == colon)
+ createNode( null, localName, metaData, scp, v );
+ else
+ createNode( qname.substring(0,colon), localName, metaData, scp, v );
+
+ hStack.push(rootElem);
+
+ // set
+ curTag = tagStack.pop;
+
+ if (curTag != null) // root level
+ capture = nodeContainsText(curTag);
+ else
+ capture = 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 = {
+
+ System.err.print("[");
+ System.err.print(errtype);
+ System.err.print("] ");
+
+ var systemId = ex.getSystemId();
+ if (systemId != null) {
+ val index = systemId.lastIndexOf('/');
+ if (index != -1)
+ systemId = systemId.substring(index + 1);
+ //System.err.print(systemId);
+ }
+
+ System.err.print(':');
+ System.err.print(ex.getLineNumber());
+ System.err.print(':');
+ System.err.print(ex.getColumnNumber());
+ System.err.print(": ");
+ System.err.print(ex.getMessage());
+ System.err.println();
+ System.err.flush();
+
+ }
+
+ var rootElem : Node = null:Node;
+
+ //FactoryAdapter
+ // MAIN
+ //
+
+ /** load XML document
+ * @param source
+ * @return a new XML document object
+ */
+ def loadXML( source:InputSource ):Node = {
+
+ // variables
+ var parser:SAXParser = null;
+
+ // create parser
+ try {
+ val f = SAXParserFactory.newInstance();
+ f.setNamespaceAware( false );
+ parser = f.newSAXParser();
+ } catch {
+ case ( e:Exception ) => {
+ System.err.println("error: Unable to instantiate parser");
+ System.exit(-1);
+ }
+ }
+
+ // parse file
+ try {
+ //System.err.println("[parsing \"" + source + "\"]");
+ scopeStack.push(TopScope);
+ parser.parse( source, this );
+ scopeStack.pop;
+ } catch {
+ case ( e:SAXParseException ) => {
+ // ignore
+ }
+ case ( e:Exception ) => {
+ System.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
+ //System.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/library/scala/xml/parsing/FatalError.scala b/src/library/scala/xml/parsing/FatalError.scala
new file mode 100644
index 0000000000..bd007d0df9
--- /dev/null
+++ b/src/library/scala/xml/parsing/FatalError.scala
@@ -0,0 +1,3 @@
+package scala.xml.parsing ;
+
+case class FatalError(msg:String) extends java.lang.RuntimeException(msg);
diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala
new file mode 100644
index 0000000000..d90dea2752
--- /dev/null
+++ b/src/library/scala/xml/parsing/MarkupHandler.scala
@@ -0,0 +1,148 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.parsing;
+
+import scala.io.Source;
+import scala.collection.mutable.{ HashMap, Map }
+import scala.xml.dtd._ ;
+
+import scala.util.logging._;
+
+/** class that handles markup - provides callback methods to MarkupParser.
+ * the default is nonvalidating behaviour
+ *
+ * @todo can we ignore more entity declarations (i.e. those with extIDs)?
+ * @todo expanding entity references
+ */
+abstract class MarkupHandler extends AnyRef with Logged {
+
+ // impl. of Logged
+ //def log(msg:String) = {}
+
+ /** returns true is this markup handler is validing */
+ val isValidating: Boolean = false;
+
+ var decls: List[Decl] = Nil;
+
+ var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]();
+
+ def lookupElemDecl(Label: String): ElemDecl = {
+ def lookup(xs:List[Decl]): ElemDecl = xs match {
+ case (z @ ElemDecl(Label, _)) :: zs => return z;
+ case _::zs => lookup(zs);
+ case _ => return null
+ }
+ lookup(decls)
+ }
+
+ def replacementText( entityName: String ): Source = ent.get(entityName) match {
+ case Some(ParsedEntityDecl(_, IntDef(value))) =>
+ Source.fromString(value);
+ case Some(ParameterEntityDecl(_, IntDef(value))) =>
+ Source.fromString(" "+value+" ");
+ case Some(_) =>
+ Source.fromString("<!-- "+entityName+"; -->");
+ case None =>
+ Source.fromString("<!-- unknown entity "+entityName+"; -->")
+ }
+
+
+ //def checkChildren(pos:int, pre: String, label:String,ns:NodeSeq): Unit = {}
+
+ def endDTD(n:String): Unit = {}
+
+ /** callback method invoked by MarkupParser after start-tag of element.
+ *
+ * @param pos the position in the sourcefile
+ * @param pre the prefix
+ * @param label the local name
+ * @param attrs the attributes (metadata)
+ */
+ def elemStart(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding): Unit = {}
+
+ /** callback method invoked by MarkupParser after end-tag of element.
+ *
+ * @param pos the position in the sourcefile
+ * @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 sourcefile
+ * @param pre the prefix
+ * @param label the local name
+ * @param attrs the attributes (metadata)
+ * @param args the children of this element
+ */
+ def elem(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding, args: NodeSeq): NodeSeq;
+
+ /** callback method invoked by MarkupParser after parsing PI.
+ */
+ def procInstr(pos: Int, target: String, txt: String): NodeSeq;
+
+ /** callback method invoked by MarkupParser after parsing comment.
+ */
+ 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/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala
new file mode 100644
index 0000000000..09569bd106
--- /dev/null
+++ b/src/library/scala/xml/parsing/MarkupParser.scala
@@ -0,0 +1,1223 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+** $Id$
+\* */
+
+package scala.xml.parsing;
+
+import scala.io.Source;
+import scala.xml.dtd._ ;
+
+/**
+ * An XML parser.
+ *
+ * Parses XML 1.0, invokes callback methods of a MarkupHandler
+ * and returns whatever the markup handler returns. Use
+ * <code>ConstructingParser</code> if you just want to parse XML to
+ * construct instances of <code>scala.xml.Node</code>.
+ *
+ * While XML elements are returned, DTD declarations - if handled - are
+ * collected using side-effects.
+ */
+[_trait_] abstract class MarkupParser: (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 StringBuffer();
+
+ var dtd: DTD = null;
+
+ var eof: Boolean = false;
+
+ //
+ // methods
+ //
+
+ /** &lt;? prolog ::= xml S ... ?&gt;
+ */
+ def xmlProcInstr(): MetaData = {
+ xToken("xml");
+ xSpace;
+ val Pair(md,scp) = xAttributes(TopScope);
+ if(scp != TopScope)
+ reportSyntaxError("no xmlns definitions here, please.");
+ xToken('?');
+ xToken('>');
+ md
+ }
+
+ /** &lt;? prolog ::= xml S
+ * // this is a bit more lenient than necessary...
+ */
+ def prolog(): Tuple3[Option[String], Option[String], Option[Boolean]] = {
+
+ //Console.println("(DEBUG) prolog");
+ var n = 0;
+ var info_ver: Option[String] = None;
+ var info_enc: Option[String] = None;
+ var info_stdl: Option[Boolean] = None;
+
+ var m = xmlProcInstr();
+
+ xSpace;
+
+ m.getValue("version") match {
+ case null => ;
+ case "1.0" => info_ver = Some("1.0"); n = n + 1;
+ case _ => reportSyntaxError("cannot deal with versions != 1.0");
+ }
+
+ m.getValue("encoding") match {
+ case null => ;
+ case enc => if (!isValidIANAEncoding(enc.toString()))
+ reportSyntaxError("\"" + enc + "\" is not a valid encoding");
+ else {
+ info_enc = Some(enc.toString());
+ n = n + 1;
+ }
+ }
+ m.getValue("standalone") match {
+ case null => ;
+ case "yes" => info_stdl = Some(true); n = n + 1;
+ case "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.getValue("version") match {
+ case null => ;
+ case "1.0" => info_ver = Some("1.0"); n = n + 1;
+ case _ => reportSyntaxError("cannot deal with versions != 1.0");
+ }
+
+ m.getValue("encoding") match {
+ case null => ;
+ case enc => if (!isValidIANAEncoding(enc.toString()))
+ reportSyntaxError("\"" + enc + "\" is not a valid encoding");
+ else {
+ info_enc = Some(enc.toString());
+ n = n + 1;
+ }
+ }
+
+ if(m.length - n != 0) {
+ reportSyntaxError("VersionInfo EncodingDecl? or '?>' expected!");
+ }
+ //Console.println("[MarkupParser::textDecl] finished parsing textdecl");
+ Tuple2(info_ver, info_enc);
+ }
+
+ /**
+ *[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
+ *[23] XMLDecl ::= '&lt;?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+ *[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
+ *[25] Eq ::= S? '=' S?
+ *[26] VersionNum ::= '1.0'
+ *[27] Misc ::= Comment | PI | S
+ */
+
+ def document(): Document = {
+
+ //Console.println("(DEBUG) document");
+
+ 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();
+ 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);
+ }
+
+ val doc = new Document();
+ doc.children = children;
+ doc.docElem = theNode;
+ doc.version = info_prolog._1;
+ doc.encoding = info_prolog._2;
+ doc.standAlone = info_prolog._3;
+ doc.dtd = this.dtd;
+ return 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];
+ //throw new Exception("this is the end")
+ }
+ }
+ }
+
+ //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);
+ }
+
+ /** checks whether next character starts a Scala block, if yes, skip it.
+ * @return true if next character starts a scala block
+ def xCheckEmbeddedBlock:Boolean = {
+ xEmbeddedBlock =
+ enableEmbeddedExpressions && (ch == '{') && { nextch; ch != '{' };
+ return xEmbeddedBlock;
+ }
+ */
+
+ /** parse attribute and create namespace scope, metadata
+ * [41] Attributes ::= { S Name Eq AttValue }
+ */
+ def xAttributes(pscope:NamespaceBinding): Pair[MetaData,NamespaceBinding] = {
+ var scope: NamespaceBinding = pscope;
+ var aMap: MetaData = Null;
+ while (isNameStart(ch)) {
+ val pos = this.pos;
+
+ val qname = xName;
+ val _ = xEQ;
+ val value = xAttributeValue();
+
+ Utility.prefix(qname) match {
+ case Some("xmlns") =>
+ val prefix = qname.substring(6 /*xmlns:*/ , qname.length());
+ scope = new NamespaceBinding(prefix, value, scope);
+
+ case Some(prefix) =>
+ val key = qname.substring(prefix.length()+1, qname.length());
+ aMap = new PrefixedAttribute(prefix, key, value, aMap);
+
+ case _ =>
+ if( qname == "xmlns" )
+ scope = new NamespaceBinding(null, value, scope);
+ else
+ aMap = new UnprefixedAttribute(qname, value, aMap);
+ }
+
+ if ((ch != '/') && (ch != '>') && ('?' != ch))
+ xSpace;
+ }
+
+ if(!aMap.wellformed(scope))
+ reportSyntaxError( "double attribute");
+
+ Pair(aMap,scope)
+ }
+
+ /** attribute value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def xAttributeValue(): String = {
+ val endch = ch;
+ nextch;
+ while (ch != endch) {
+ if ('<' == ch)
+ reportSyntaxError( "'<' not allowed in attrib value" );
+ putChar(ch);
+ nextch;
+ }
+ nextch;
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+
+ // well-formedness constraint
+ normalizeAttributeValue(str)
+
+ }
+
+ /** entity value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def xEntityValue(): String = {
+ val endch = ch;
+ nextch;
+ while (ch != endch) {
+ putChar(ch);
+ nextch;
+ }
+ nextch;
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+ str
+ }
+
+
+ /** parse a start or empty tag.
+ * [40] STag ::= '&lt;' Name { S Attribute } [S]
+ * [44] EmptyElemTag ::= '&lt;' Name { S Attribute } [S]
+ */
+ protected def xTag(pscope:NamespaceBinding): Tuple3[String, MetaData, NamespaceBinding] = {
+ val qname = xName;
+
+ xSpaceOpt;
+ val Pair(aMap: MetaData, scope: NamespaceBinding) = {
+ if (isNameStart(ch))
+ xAttributes(pscope)
+ else
+ Pair(Null, pscope)
+ }
+ Triple(qname, aMap, scope);
+ }
+
+ /** [42] '&lt;' xmlEndTag ::= '&lt;' '/' Name S? '&gt;'
+ */
+ def xEndTag(n: String) = {
+ xToken('/');
+ val m = xName;
+ if (n != m)
+ reportSyntaxError("expected closing tag of " + n/* +", not "+m*/);
+ xSpaceOpt;
+ xToken('>')
+ }
+
+ /** '&lt;! CharData ::= [CDATA[ ( {char} - {char}"]]&gt;"{char} ) ']]&gt;'
+ *
+ * see [15]
+ */
+ def xCharData: NodeSeq = {
+ xToken("[CDATA[");
+ val pos1 = pos;
+ val sb: StringBuffer = new StringBuffer();
+ while (true) {
+ if (ch==']' &&
+ { sb.append(ch); nextch; ch == ']' } &&
+ { sb.append(ch); nextch; ch == '>' } ) {
+ sb.setLength(sb.length() - 2);
+ nextch;
+ return handle.text( pos1, sb.toString() );
+ } else sb.append( ch );
+ nextch;
+ }
+ throw FatalError("this cannot happen");
+ };
+
+ /** CharRef ::= "&amp;#" '0'..'9' {'0'..'9'} ";"
+ * | "&amp;#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";"
+ *
+ * see [66]
+ */
+ def xCharRef(ch: () => Char, nextch: () => Unit): String = {
+ 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(Predef.Array(i.asInstanceOf[char]))
+ }
+
+
+ /** Comment ::= '&lt;!--' ((Char - '-') | ('-' (Char - '-')))* '--&gt;'
+ *
+ * see [15]
+ */
+ def xComment: NodeSeq = {
+ val sb: StringBuffer = new StringBuffer();
+ 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 NodeBuffer class */
+ def appendText(pos: Int, ts: NodeBuffer, txt: String): Unit = {
+ if (preserveWS)
+ ts &+ handle.text(pos, txt);
+ else
+ for (val t <- TextBuffer.fromString(txt).toText) {
+ ts &+ handle.text(pos, t.text);
+ }
+ }
+
+ /** '&lt;' content1 ::= ... */
+ def content1(pscope: NamespaceBinding, ts: NodeBuffer): Unit = {
+ ch match {
+ case '!' =>
+ nextch;
+ if ('[' == ch) // CDATA
+ ts &+ xCharData;
+ else if ('D' == ch) // doctypedecl, parse DTD // @todo REMOVE HACK
+ parseDTD();
+ else // comment
+ ts &+ xComment;
+ case '?' => // PI
+ nextch;
+ ts &+ xProcInstr;
+ case _ =>
+ ts &+ element1(pscope); // child
+ }
+ }
+
+ /** content1 ::= '&lt;' content1 | '&amp;' charref ... */
+ def content(pscope: NamespaceBinding): NodeSeq = {
+ var ts = new NodeBuffer;
+ var exit = eof;
+ while (! exit) {
+ //Console.println("in content, ch = '"+ch+"' line="+scala.io.Position.line(pos));
+ /* if( xEmbeddedBlock ) {
+ ts.append( xEmbeddedExpr );
+ } else {*/
+ tmppos = pos;
+ exit = eof;
+ if(!eof)
+ ch match {
+ case '<' => // another tag
+ //Console.println("before ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos);
+ nextch;
+ //Console.println("after ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos);
+
+ if('/' ==ch)
+ exit = true; // end tag
+ else
+ content1(pscope, ts)
+ //case '{' =>
+/* if( xCheckEmbeddedBlock ) {
+ ts.appendAll(xEmbeddedExpr);
+ } else {*/
+ // val str = new StringBuffer("{");
+ // str.append(xText);
+ // appendText(tmppos, ts, str.toString());
+ /*}*/
+ // postcond: xEmbeddedBlock == false!
+ case '&' => // EntityRef or CharRef
+ nextch;
+ ch match {
+ case '#' => // CharacterRef
+ nextch;
+ val theChar = handle.text( tmppos,
+ xCharRef ({ ()=> ch },{ () => nextch }) );
+ xToken(';');
+ ts &+ theChar ;
+ case _ => // EntityRef
+ val n = xName ;
+ xToken(';');
+ n match {
+ case "lt" => ts &+ '<';
+ case "gt" => ts &+ '>';
+ case "amp" => ts &+ '&';
+ case "quote" => ts &+ '"';
+ case _ =>
+ /*
+ ts + handle.entityRef( tmppos, n ) ;
+ */
+ push( n );
+ }
+ }
+ case _ => // text content
+ //Console.println("text content?? pos = "+pos);
+ appendText(tmppos, ts, xText);
+ // here xEmbeddedBlock might be true
+ }
+ /*}*/
+ }
+ val list = ts.toList;
+ // 2do: optimize seq repr.
+ new NodeSeq {
+ val theSeq = list;
+ }
+ } // content(NamespaceBinding)
+
+ /** externalID ::= SYSTEM S syslit
+ * PUBLIC S pubid S syslit
+ */
+
+ def externalID(): ExternalID = ch match {
+ case 'S' =>
+ nextch;
+ xToken("YSTEM");
+ xSpace;
+ val sysID = systemLiteral();
+ new SystemID(sysID);
+ case 'P' =>
+ nextch; xToken("UBLIC");
+ xSpace;
+ val pubID = pubidLiteral();
+ xSpace;
+ val sysID = systemLiteral();
+ new PublicID(pubID, sysID);
+ }
+
+
+ /** parses document type declaration and assigns it to instance variable
+ * dtd.
+ *
+ * &lt;! parseDTD ::= DOCTYPE name ... >
+ */
+ def parseDTD(): Unit = { // dirty but fast
+ //Console.println("(DEBUG) parseDTD");
+ var extID: ExternalID = null;
+ if (this.dtd != 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();
+ handle.endDTD(n);
+ }
+
+ def element(pscope: NamespaceBinding): NodeSeq = {
+ xToken('<');
+ element1(pscope);
+ }
+
+ /** '&lt;' element ::= xmlTag1 '&gt;' { xmlExpr | '{' simpleExpr '}' } ETag
+ * | xmlTag1 '/' '&gt;'
+ */
+ def element1(pscope: NamespaceBinding): NodeSeq = {
+ val pos = this.pos;
+ val Tuple3(qname, aMap, scope) = xTag(pscope);
+ val Tuple2(pre, local) = Utility.prefix(qname) match {
+ case Some(p) => Pair(p,qname.substring(p.length()+1, qname.length()));
+ case _ => Pair(null,qname);
+ }
+ val ts = {
+ if (ch == '/') { // empty element
+ xToken('/');
+ xToken('>');
+ handle.elemStart(pos, pre, local, aMap, scope);
+ NodeSeq.Empty;
+ }
+ else { // element with content
+ xToken('>');
+ handle.elemStart(pos, pre, local, aMap, scope);
+ val tmp = content(scope);
+ xEndTag(qname);
+ tmp;
+ }
+ }
+ val res = handle.elem(pos, pre, local, aMap, scope, ts );
+ handle.elemEnd(pos, pre, local);
+ res
+ }
+
+ //def xEmbeddedExpr: MarkupType;
+
+ /** Name ::= (Letter | '_' | ':') (NameChar)*
+ *
+ * see [5] of XML 1.0 specification
+ */
+ def xName: String = {
+ if (isNameStart(ch)) {
+ while (isNameChar(ch)) {
+ putChar(ch);
+ nextch;
+ }
+ val n = cbuf.toString().intern();
+ cbuf.setLength(0);
+ n
+ } else {
+ reportSyntaxError("name expected");
+ new String()
+ }
+ }
+
+ /** scan [S] '=' [S]*/
+ def xEQ = { xSpaceOpt; xToken('='); xSpaceOpt }
+
+ /** skip optional space S? */
+ def xSpaceOpt = while (isSpace(ch) && !eof) { nextch; };
+
+ /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
+ def xSpace = {
+ if (isSpace(ch)) {
+ nextch; xSpaceOpt
+ }
+ else {
+ reportSyntaxError("whitespace expected");
+ }
+ }
+
+ /** '&lt;?' ProcInstr ::= Name [S ({Char} - ({Char}'&gt;?' {Char})]'?&gt;'
+ *
+ * see [15]
+ */
+ def xProcInstr: NodeSeq = {
+ val sb:StringBuffer = new StringBuffer();
+ 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('>');
+ return handle.procInstr(tmppos, n.toString(), sb.toString());
+ }
+
+ /** parse character data.
+ * precondition: xEmbeddedBlock == false (we are not in a scala block)
+ */
+ def xText: String = {
+ //if( xEmbeddedBlock ) throw FatalError("internal error: encountered embedded block"); // assert
+
+ /*if( xCheckEmbeddedBlock )
+ return ""
+ else {*/
+ //Console.println("in xText! ch = '"+ch+"'");
+ var exit = false;
+ while (! exit) {
+ //Console.println("LOOP in xText! ch = '"+ch+"' + pos="+pos);
+ putChar(ch);
+ val opos = pos;
+ nextch;
+
+ //Console.println("STILL LOOP in xText! ch = '"+ch+"' + pos="+pos+" opos="+opos);
+
+
+ exit = eof || /*{ nextch; xCheckEmbeddedBlock }||*/( ch == '<' ) || ( ch == '&' );
+ }
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+ str
+ /*}*/
+ }
+
+ /** attribute value, terminated by either ' or ". value may not contain &lt;.
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ */
+ def systemLiteral(): String = {
+ val endch = ch;
+ if (ch != '\'' && ch != '"')
+ reportSyntaxError("quote ' or \" expected");
+ nextch;
+ while (ch != endch) {
+ putChar(ch);
+ nextch;
+ }
+ nextch;
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+ str
+ }
+
+
+ /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" */
+ def pubidLiteral(): String = {
+ val endch = ch;
+ if (ch!='\'' && ch != '"')
+ reportSyntaxError("quote ' or \" expected");
+ nextch;
+ while (ch != endch) {
+ putChar(ch);
+ //Console.println("hello '"+ch+"'"+isPubIDChar(ch));
+ if(!isPubIDChar(ch))
+ reportSyntaxError("char '"+ch+"' is not allowed in public id");
+ nextch;
+ }
+ nextch;
+ val str = cbuf.toString();
+ cbuf.setLength(0);
+ str
+ }
+
+ //
+ // dtd parsing
+ //
+
+ def extSubset(): Unit = {
+ var textdecl:Tuple2[Option[String],Option[String]] = null;
+ if(ch=='<') {
+ nextch;
+ if(ch=='?') {
+ nextch;
+ textdecl = textDecl()
+ } else
+ markupDecl1();
+ }
+ while(!eof) {
+ markupDecl();
+ }
+ }
+
+ def markupDecl1() = {
+ def doInclude() = {
+ xToken('['); while(']' != ch) markupDecl(); nextch // ']'
+ }
+ def doIgnore() = {
+ xToken('['); while(']' != ch) nextch; nextch; // ']'
+ }
+ if('?' == ch) {
+ nextch;
+ xProcInstr; // simply ignore processing instructions!
+ } else {
+ xToken('!');
+ ch match {
+ case '-' =>
+ xComment ; // ignore comments
+
+ case 'E' =>
+ nextch;
+ if ('L' == ch) {
+ nextch;
+ elementDecl()
+ } else
+ entityDecl();
+
+ case 'A' =>
+ nextch;
+ attrDecl();
+
+ case 'N' =>
+ nextch;
+ notationDecl();
+
+ case '[' if inpStack.length >= extIndex =>
+ nextch;
+ xSpaceOpt;
+ ch match {
+ case '%' =>
+ nextch;
+ val ent = xName;
+ xToken(';');
+ xSpaceOpt;
+ /*
+ Console.println("hello, pushing!");
+ {
+ val test = replacementText(ent);
+ while(test.hasNext)
+ Console.print(test.next);
+ } */
+ push(ent);
+ xSpaceOpt;
+ //Console.println("hello, getting name");
+ val stmt = xName;
+ //Console.println("hello, got name");
+ xSpaceOpt;
+ //Console.println("how can we be eof = "+eof);
+
+ // eof = true because not external?!
+ //if(!eof)
+ // error("expected only INCLUDE or IGNORE");
+
+ //pop();
+
+
+ //Console.println("hello, popped");
+ stmt match {
+ // parameter entity
+ case "INCLUDE" =>
+ doInclude();
+ case "IGNORE" =>
+ doIgnore()
+ }
+ case 'I' =>
+ nextch;
+ ch match {
+ case 'G' =>
+ nextch;
+ xToken("NORE");
+ xSpaceOpt;
+ doIgnore()
+ case 'N' =>
+ nextch;
+ xToken("NCLUDE");
+ doInclude()
+ }
+ }
+ xToken(']');
+ xToken('>');
+
+ case _ =>
+ curInput.reportError(pos, "unexpected character '"+ch+"', expected some markupdecl");
+ while(ch!='>')
+ nextch;
+
+ }
+ }
+ }
+
+ def markupDecl(): Unit = ch match {
+ case '%' => // parameter entity reference
+ nextch;
+ val ent = xName;
+ xToken(';');
+ if(!isValidating)
+ handle.peReference(ent); // n-v: just create PE-reference
+ else
+ push(ent); // v: parse replacementText
+
+ //peReference
+ case '<' =>
+ nextch;
+ markupDecl1();
+
+ case _ if isSpace(ch) =>
+ xSpace;
+ case _ =>
+ reportSyntaxError("markupdecl: unexpected character '"+ch+"' #" + ch.asInstanceOf[Int]);
+ nextch;
+ }
+
+ /** "rec-xml/#ExtSubset" pe references may not occur within markup
+ declarations
+ */
+ def intSubset(): Unit = {
+ //Console.println("(DEBUG) intSubset()");
+ xSpace;
+ while (']' != ch) {
+ markupDecl()
+ }
+ }
+
+ /** &lt;! element := ELEMENT
+ */
+ def elementDecl(): Unit = {
+ xToken("EMENT");
+ xSpace;
+ val n = xName;
+ xSpace;
+ while ('>' != ch) {
+ //Console.println("["+ch+"]");
+ putChar(ch);
+ nextch;
+ }
+ //Console.println("END["+ch+"]");
+ nextch;
+ val cmstr = cbuf.toString();
+ cbuf.setLength(0);
+ handle.elemDecl(n, cmstr);
+ }
+
+ /** &lt;! attlist := ATTLIST
+ */
+ def attrDecl() = {
+ xToken("TTLIST");
+ xSpace;
+ val n = xName;
+ xSpace;
+ var attList: List[AttrDecl] = Nil;
+ // later: find the elemDecl for n
+ while ('>' != ch) {
+ val aname = xName;
+ //Console.println("attribute name: "+aname);
+ var defdecl: DefaultDecl = null;
+ xSpace;
+ // could be enumeration (foo,bar) parse this later :-/
+ while ('"' != ch && '\'' != ch && '#' != ch && '<' != ch) {
+ if(!isSpace(ch))
+ cbuf.append(ch);
+ nextch;
+ }
+ val atpe = cbuf.toString();
+ cbuf.setLength(0);
+ //Console.println("attr type: "+atpe);
+ ch match {
+ case '\'' | '"' =>
+ val defValue = xAttributeValue(); // default value
+ defdecl = DEFAULT(false, defValue);
+
+ case '#' =>
+ nextch;
+ xName match {
+ case "FIXED" =>
+ xSpace;
+ val defValue = xAttributeValue(); // default value
+ defdecl = DEFAULT(true, defValue);
+ case "IMPLIED" =>
+ defdecl = IMPLIED
+ case "REQUIRED" =>
+ defdecl = REQUIRED
+ }
+ case _ =>
+ }
+ xSpaceOpt;
+
+ attList = AttrDecl(aname, atpe, defdecl) :: attList;
+ cbuf.setLength(0);
+ }
+ nextch;
+ handle.attListDecl(n, attList.reverse);
+ }
+
+ /** &lt;! element := ELEMENT
+ */
+ def entityDecl() = {
+ //Console.println("entityDecl()");
+ var isParameterEntity = false;
+ var entdef: EntityDef = null;
+ xToken("NTITY");
+ xSpace;
+ if ('%' == ch) {
+ nextch;
+ isParameterEntity = true;
+ xSpace;
+ }
+ val n = xName;
+ xSpace;
+ ch match {
+ case 'S' | 'P' => //sy
+ val extID = externalID();
+ if(isParameterEntity) {
+
+ xSpaceOpt;
+ xToken('>');
+ handle.parameterEntityDecl(n, ExtDef(extID))
+
+ } else { // notation?
+
+ xSpace;
+ if ('>' != ch) {
+ xToken("NDATA");
+ xSpace;
+ val notat = xName;
+ xSpaceOpt;
+ xToken('>');
+ handle.unparsedEntityDecl(n, extID, notat);
+ } else {
+ nextch;
+ handle.parsedEntityDecl(n, ExtDef(extID));
+ }
+ }
+
+ case '"' | '\'' =>
+ val av = xEntityValue();
+ xSpaceOpt;
+ xToken('>');
+ if (isParameterEntity)
+ handle.parameterEntityDecl(n, IntDef(av));
+ else
+ handle.parsedEntityDecl(n, IntDef(av));
+ }
+
+ {}
+ } // entityDecl
+
+ /** 'N' notationDecl ::= "OTATION"
+ */
+ def notationDecl(): Unit = {
+ xToken("OTATION");
+ xSpace;
+ val notat = xName;
+ xSpace;
+ val extID = if (ch == 'S') {
+ externalID();
+ }
+ else if (ch == 'P') {
+ /** PublicID (without system, only used in NOTATION) */
+ nextch;
+ xToken("UBLIC");
+ xSpace;
+ val pubID = pubidLiteral();
+ xSpaceOpt;
+ val sysID = if (ch != '>')
+ systemLiteral()
+ else
+ null;
+ new PublicID(pubID, sysID);
+ } else
+ error("PUBLIC or SYSTEM expected");
+ 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 StringBuffer();
+ 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/library/scala/xml/parsing/NoBindingFactoryAdapter.scala b/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala
new file mode 100644
index 0000000000..d2400e33d3
--- /dev/null
+++ b/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala
@@ -0,0 +1,53 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2004, 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/library/scala/xml/parsing/TokenTests.scala b/src/library/scala/xml/parsing/TokenTests.scala
new file mode 100644
index 0000000000..86560fc12f
--- /dev/null
+++ b/src/library/scala/xml/parsing/TokenTests.scala
@@ -0,0 +1,145 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, 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 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(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('"') == -1 || s.indexOf('\'') == -1
+ }
+
+ def checkPubID(s: String): Boolean = {
+ //Console.println("checkPubID of \""+s+"\"");
+ if (s.length() > 0) {
+ val z: Seq[Char] = s;
+ val y = z.elements;
+ var c = ' ';
+ while (y.hasNext && isPubIDChar(c)) {
+ //Console.println(c);
+ c = y.next
+ };
+ !y.hasNext
+ }
+ else
+ true
+ }
+
+}
diff --git a/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala b/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala
new file mode 100644
index 0000000000..717ed52d79
--- /dev/null
+++ b/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala
@@ -0,0 +1,104 @@
+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/library/scala/xml/path/Expression.scala b/src/library/scala/xml/path/Expression.scala
new file mode 100644
index 0000000000..cf6c6d552f
--- /dev/null
+++ b/src/library/scala/xml/path/Expression.scala
@@ -0,0 +1,54 @@
+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/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala
new file mode 100644
index 0000000000..56bbc16201
--- /dev/null
+++ b/src/library/scala/xml/transform/BasicTransformer.scala
@@ -0,0 +1,124 @@
+package scala.xml.transform ;
+
+/** a trait for XML transformations */
+trait 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)
+ }
+ 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) )
+ error("transform must return single node for root");
+ else seq.elements.next;
+ }
+}
+
+/*
+class IdentityTransformer extends BasicTransformer {
+ override def transform(n: Node): Seq[Node] = n.match {
+ case <world/> => <xml-world/>
+ case _ => super.transform(n);
+ }
+}
+
+object Foo with Application {
+
+ val tr = new IdentityTransformer;
+ val n = tr( <hello><world/></hello> );
+ Console.println(n);
+
+ val tr2 = new RewriteRule {
+ final override val name = "A rule";
+ override def transform(n: Node) = n.match {
+ case <a/> => <b/><c/>
+ case _ => n
+ }
+ }
+ val tr3 = new RewriteRule {
+ final override val name = "E rule";
+ override def transform(n: Node) = n.match {
+ case <e/> => <f><f/></f>
+ case _ => n
+ }
+ }
+ val tr4 = new RuleTransformer(tr2, tr3);
+ val m = tr4( <hello><a/><e/></hello> );
+ Console.println(m);
+}
+*/
diff --git a/src/library/scala/xml/transform/RewriteRule.scala b/src/library/scala/xml/transform/RewriteRule.scala
new file mode 100644
index 0000000000..c00d33aa96
--- /dev/null
+++ b/src/library/scala/xml/transform/RewriteRule.scala
@@ -0,0 +1,13 @@
+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
+ */
+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/library/scala/xml/transform/RuleTransformer.scala b/src/library/scala/xml/transform/RuleTransformer.scala
new file mode 100644
index 0000000000..6a967105e7
--- /dev/null
+++ b/src/library/scala/xml/transform/RuleTransformer.scala
@@ -0,0 +1,14 @@
+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
+ }
+}
diff --git a/src/library/scala/xml/xsd/ContentModel.scala b/src/library/scala/xml/xsd/ContentModel.scala
new file mode 100644
index 0000000000..11e513d26d
--- /dev/null
+++ b/src/library/scala/xml/xsd/ContentModel.scala
@@ -0,0 +1,39 @@
+package scala.xml.xsd ;
+
+import scala.util.regexp.WordExp;
+import scala.util.automata._;
+
+object ContentModel extends WordExp {
+
+ type _labelT = ElemRef;
+ type _regexpT = RegExp;
+
+ object Translator extends WordBerrySethi {
+ override val lang: ContentModel.this.type = ContentModel.this;
+ import lang._ ;
+ }
+
+ case class ElemRef(name: String) extends Label {
+ override def toString() = name;
+ }
+
+ def fromSchema(nodes:Seq[Node]): List[RegExp] =
+ nodes.foldLeft (Nil:List[RegExp]) { (list, n:Node) => fromSchema(n)::list }.reverse;
+
+ def fromSchema(node:Node): RegExp = node.label match {
+ case "sequence" => Sequ(fromSchema(node.child):_*);
+ case "choice" => Alt(fromSchema(node.child):_*);
+ case "group" => Sequ(fromSchema(node.child):_*);
+ case "element" =>
+ val name = node.attribute("name").toString();
+ Letter(ElemRef(name)); // ouch, anonymous? references?
+ }
+}
+
+sealed abstract class ContentModel ;
+
+case class ELEMENTS(r:ContentModel.RegExp) extends ContentModel ;
+
+case class MIXED(r:ContentModel.RegExp) extends ContentModel ;
+
+case object SimpleContent extends ContentModel ;
diff --git a/src/library/scala/xml/xsd/Decl.scala b/src/library/scala/xml/xsd/Decl.scala
new file mode 100644
index 0000000000..18a61f3b2b
--- /dev/null
+++ b/src/library/scala/xml/xsd/Decl.scala
@@ -0,0 +1,26 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.xml.xsd ;
+
+abstract class Decl ;
+
+/** name - label of the element
+ * typeName - reference to a (possibly generated) type name
+ */
+case class ElemDecl(name: String, tpe: TypeSymbol) extends Decl;
+
+abstract class TypeDecl ;
+
+case class ComplexTypeDecl(name: String, derivedFrom: DerivSym, contentModel: ContentModel) extends TypeDecl;
+
+case class SimpleTypeDecl(name: String) extends TypeDecl;;
+
+abstract class xsdBuiltin(name: String) extends SimpleTypeDecl(name);
diff --git a/src/library/scala/xml/xsd/XsTypeSymbol.scala b/src/library/scala/xml/xsd/XsTypeSymbol.scala
new file mode 100644
index 0000000000..b553ad9f29
--- /dev/null
+++ b/src/library/scala/xml/xsd/XsTypeSymbol.scala
@@ -0,0 +1,38 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2005, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $id: $
+
+package scala.xml.xsd;
+
+trait XsTypeSymbol extends scala.xml.TypeSymbol ;
+
+object xsdAny extends XsTypeSymbol ;
+
+class SimpleTypeSymbol(val name: String) extends XsTypeSymbol {
+ var decl: SimpleTypeDecl = null;
+}
+
+class ComplexTypeSymbol(val name: String) extends XsTypeSymbol {
+ var decl: ComplexTypeDecl = null;
+}
+
+trait DerivSym;
+
+case class Extends(sym:XsTypeSymbol) extends DerivSym;
+
+case class Restricts(sym:XsTypeSymbol) extends DerivSym;
+
+object xsBoolean extends SimpleTypeSymbol("boolean") {}
+object xsDouble extends SimpleTypeSymbol("double") {}
+object xsFloat extends SimpleTypeSymbol("float") {}
+object xsInt extends SimpleTypeSymbol("int") {}
+object xsLong extends SimpleTypeSymbol("long") {}
+object xsShort extends SimpleTypeSymbol("short") {}
+object xsString extends SimpleTypeSymbol("string") {}
+object xsDate extends SimpleTypeSymbol("date") {}