summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2011-03-23 14:28:23 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2011-03-23 14:28:23 +0000
commit26643c870b0308e903eb097cae8bae78180c0f4a (patch)
tree58763275fb7adeff67f7434f777c76fe2346d77e /src/compiler
parentb40373367e6803349470ecabc3ef646f50353139 (diff)
downloadscala-26643c870b0308e903eb097cae8bae78180c0f4a.tar.gz
scala-26643c870b0308e903eb097cae8bae78180c0f4a.tar.bz2
scala-26643c870b0308e903eb097cae8bae78180c0f4a.zip
Merged revisions 24541-24548 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r24541 | odersky | 2011-03-22 17:46:49 +0100 (Tue, 22 Mar 2011) | 1 line Added headers with copyright messages. ........ r24542 | odersky | 2011-03-22 18:18:09 +0100 (Tue, 22 Mar 2011) | 1 line Added test that signatures conform to their erasures. Work in progress. Review by extempore. ........ r24543 | prokopec | 2011-03-22 19:22:21 +0100 (Tue, 22 Mar 2011) | 1 line Adding the `seq` method to all collections. Removing `pforeach`. ........ r24544 | prokopec | 2011-03-22 19:22:25 +0100 (Tue, 22 Mar 2011) | 6 lines Implementing foreach to work in parallel in ParIterableLike. Doing a bunch of refactoring around in the collection framework to ensure a parallel foreach is never called with a side-effecting method. This still leaves other parts of the standard library and the compiler unguarded. No review. ........ r24545 | prokopec | 2011-03-22 19:23:28 +0100 (Tue, 22 Mar 2011) | 3 lines Adding some tests for #3651. No review. ........ r24546 | odersky | 2011-03-22 23:59:03 +0100 (Tue, 22 Mar 2011) | 1 line Better signature avoidance. Review by extempore. ........ r24547 | extempore | 2011-03-23 08:59:18 +0100 (Wed, 23 Mar 2011) | 11 lines My early attempts to implement non-integral ranges in a way which was useful without having lots of floating point traps were less than successful. One of the bigger backfires is that the requirement not to round (trying, and failing anyway, to avoid surprises with methods like "contains") inflicts runtime errors. The simple way to improve this, which seems a good idea anyway, is to make the default math context something less inclined to exceptions. Default BigDecimal mc is now DECIMAL128. References #1812, #4201 and puts #4201 back to normal priority. Review by community. ........ r24548 | magarcia | 2011-03-23 13:33:27 +0100 (Wed, 23 Mar 2011) | 1 line sn.OClone caused checkinit failure when assigned to CompilerTermNames.clone_ . review by rytz. ........
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala38
-rw-r--r--src/compiler/scala/tools/nsc/interactive/BuildManager.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/ContextTrees.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Picklers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RangePositions.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Response.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/Tester.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala28
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala59
18 files changed, 147 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 9a1bafa27f..b8aa8d7a8f 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -572,22 +572,34 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
* in which case we treat every signature as valid. Medium term we
* should certainly write independent signature validation.
*/
- if (!SigParser.isParserAvailable || isValidSignature(sym, sig)) {
- val index = jmember.getConstantPool.addUtf8(sig).toShort
- if (opt.verboseDebug)
- atPhase(currentRun.erasurePhase) {
- println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)
- }
- val buf = ByteBuffer.allocate(2)
- buf putShort index
- addAttribute(jmember, tpnme.SignatureATTR, buf)
- }
- else clasz.cunit.warning(sym.pos,
+ if (SigParser.isParserAvailable && isValidSignature(sym, sig)) {
+ val normalizedTpe = atPhase(currentRun.erasurePhase)(erasure.prepareSigMap(memberTpe))
+ val bytecodeTpe = owner.thisType.memberInfo(sym)
+ if (sym.isType || (erasure.erasure(normalizedTpe) =:= bytecodeTpe)) {
+ val index = jmember.getConstantPool.addUtf8(sig).toShort
+ if (opt.verboseDebug)
+ atPhase(currentRun.erasurePhase) {
+ println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)
+ }
+ val buf = ByteBuffer.allocate(2)
+ buf putShort index
+ addAttribute(jmember, tpnme.SignatureATTR, buf)
+ } else {
+ if (sym.hasFlag(Flags.MIXEDIN))
+ ()// println("suppressing signature for mixedin "+sym)
+ else
+ clasz.cunit.warning(sym.pos,
+ """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
+ |signature: %s
+ |erasure type: %s
+ |if this is reproducible, please report bug at http://lampsvn.epfl.ch/trac/scala
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, bytecodeTpe))
+ }
+ } else clasz.cunit.warning(sym.pos,
"""|compiler bug: created invalid generic signature for %s in %s
|signature: %s
|if this is reproducible, please report bug at http://lampsvn.epfl.ch/trac/scala
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig)
- )
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
}
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
index 2827d97ae2..6771c5da64 100644
--- a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
@@ -1,3 +1,8 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scxala Solutions and LAMP/EPFL
+ * @author Iulian Dragos
+ * @author Hubert Plocinicak
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 05eaff9aa9..7b9a7fdb85 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
index 11aafea71a..fc48d4819c 100644
--- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index fd70907a57..155597b559 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala b/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala
index 3c3d986f81..397e83a362 100644
--- a/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala
+++ b/src/compiler/scala/tools/nsc/interactive/InteractiveReporter.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala
index c22b0b8a29..250f648250 100644
--- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
index ebe132e59b..55f8264020 100644
--- a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
+++ b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
@@ -1,3 +1,8 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ * @author Iulian Dragos
+ */
package scala.tools.nsc.interactive
/** A presentation compiler thread. This is a lightweight class, delegating most
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 0f2ea07ef0..27947d5e0e 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
index c451e0da5f..873ef50007 100644
--- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
index 3ea6342b60..67cf037a3a 100644
--- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
@@ -1,8 +1,8 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Iulian Dragos
+ * @author Hubert Plocinicak
*/
-
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/Response.scala b/src/compiler/scala/tools/nsc/interactive/Response.scala
index 67bb1633ad..fbb07b15ad 100644
--- a/src/compiler/scala/tools/nsc/interactive/Response.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Response.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
index 993277cad1..9ef7d33549 100644
--- a/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RichCompilationUnits.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala
index 2805bcf6ee..121f356c68 100644
--- a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
index a5849865c5..38ad73686a 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc.interactive
package tests
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala b/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala
index a7e1f74aaa..034db218ae 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/Tester.scala
@@ -1,3 +1,7 @@
+/* NSC -- new Scala compiler
+ * Copyright 2009-2011 Scala Solutions and LAMP/EPFL
+ * @author Martin Odersky
+ */
package scala.tools.nsc
package interactive
package tests
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 8c2966e494..f60bd17b32 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -186,7 +186,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val canEqual_ : NameType = "canEqual"
val checkInitialized: NameType = "checkInitialized"
val classOf: NameType = "classOf"
- val clone_ : NameType = sn.OClone
+ val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure
val conforms: NameType = "conforms"
val copy: NameType = "copy"
val delayedInit: NameType = "delayedInit"
@@ -195,19 +195,19 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val drop: NameType = "drop"
val elem: NameType = "elem"
val eq: NameType = "eq"
- val equals_ : NameType = sn.OEquals
+ val equals_ : NameType = if (forMSIL) "Equals" else "equals"
val error: NameType = "error"
val ex: NameType = "ex"
val false_ : NameType = "false"
val filter: NameType = "filter"
- val finalize_ : NameType = sn.OFinalize
+ val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize"
val find_ : NameType = "find"
val flatMap: NameType = "flatMap"
val foreach: NameType = "foreach"
val genericArrayOps: NameType = "genericArrayOps"
val get: NameType = "get"
val hasNext: NameType = "hasNext"
- val hashCode_ : NameType = sn.OHashCode
+ val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode"
val hash_ : NameType = "hash"
val head: NameType = "head"
val identity: NameType = "identity"
@@ -246,7 +246,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val toArray: NameType = "toArray"
val toList: NameType = "toList"
val toSeq: NameType = "toSeq"
- val toString_ : NameType = sn.OToString
+ val toString_ : NameType = if (forMSIL) "ToString" else "toString"
val true_ : NameType = "true"
val unapply: NameType = "unapply"
val unapplySeq: NameType = "unapplySeq"
@@ -430,12 +430,6 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val Invoke : TermName
val JavaLang : TermName
- val OClone : String
- val OEquals : String
- val OFinalize : String
- val OHashCode : String
- val OToString : String
-
val Boxed: immutable.Map[TypeName, TypeName]
}
@@ -533,12 +527,6 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val Invoke: TermName = "invoke"
final val JavaLang: TermName = "java.lang"
- final val OClone = "clone"
- final val OEquals = "equals"
- final val OFinalize = "finalize"
- final val OHashCode = "hashCode"
- final val OToString = "toString"
-
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
tpnme.Byte -> BoxedByte,
@@ -577,12 +565,6 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val Invoke: TermName = "Invoke"
final val JavaLang: TermName = "System"
- final val OClone = "MemberwiseClone"
- final val OEquals = "Equals"
- final val OFinalize = "Finalize"
- final val OHashCode = "GetHashCode"
- final val OToString = "ToString"
-
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> "System.Boolean",
tpnme.Byte -> "System.SByte", // a scala.Byte is signed and a System.SByte too (unlike a System.Byte)
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 3f94e165a1..bdc0a1bfac 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -231,11 +231,66 @@ abstract class Erasure extends AddInterfaces
// for debugging signatures: traces logic given system property
private val traceSig = util.Tracer(sys.props contains "scalac.sigs.trace")
+ val prepareSigMap = new TypeMap {
+ def squashBoxed(tp: Type): Type = tp.normalize match {
+ case t @ RefinedType(parents, decls) =>
+ val parents1 = parents mapConserve squashBoxed
+ if (parents1 eq parents) tp
+ else RefinedType(parents1, decls)
+ case t =>
+ if (boxedClass contains t.typeSymbol) ObjectClass.tpe
+ else tp
+ }
+ def apply(tp: Type): Type = tp.normalize match {
+ case tp1 @ TypeBounds(lo, hi) =>
+ val lo1 = squashBoxed(apply(lo))
+ val hi1 = squashBoxed(apply(hi))
+ if ((lo1 eq lo) && (hi1 eq hi)) tp1
+ else TypeBounds(lo1, hi1)
+ case tp1 @ TypeRef(pre, sym, args) =>
+ def argApply(tp: Type) = {
+ val tp1 = apply(tp)
+ if (tp1.typeSymbol == UnitClass) ObjectClass.tpe
+ else squashBoxed(tp1)
+ }
+ if (sym == ArrayClass && args.nonEmpty)
+ if (unboundedGenericArrayLevel(tp1) == 1) ObjectClass.tpe
+ else mapOver(tp1)
+ else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass)
+ ObjectClass.tpe
+ else if (sym == UnitClass)
+ BoxedUnitClass.tpe
+ else if (sym == NothingClass)
+ RuntimeNothingClass.tpe
+ else if (sym == NullClass)
+ RuntimeNullClass.tpe
+ else {
+ val pre1 = apply(pre)
+ val args1 = args mapConserve argApply
+ if ((pre1 eq pre) && (args1 eq args)) tp1
+ else TypeRef(pre1, sym, args1)
+ }
+ case tp1 @ MethodType(params, restpe) =>
+ val params1 = mapOver(params)
+ val restpe1 = if (restpe.normalize.typeSymbol == UnitClass) UnitClass.tpe else apply(restpe)
+ if ((params1 eq params) && (restpe1 eq restpe)) tp1
+ else MethodType(params1, restpe1)
+ case tp1 @ RefinedType(parents, decls) =>
+ val parents1 = parents mapConserve apply
+ if (parents1 eq parents) tp1
+ else RefinedType(parents1, decls)
+ case tp1: ClassInfoType =>
+ tp1
+ case tp1 =>
+ mapOver(tp1)
+ }
+ }
+
/** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return
* type for constructors.
*/
def javaSig(sym0: Symbol, info: Type): Option[String] = atPhase(currentRun.erasurePhase) {
- def jsig(tp: Type): String = jsig2(false, Nil, tp)
+ def jsig(tp: Type): String = jsig2(toplevel = false, Nil, tp)
// Unit in return position is 'V', but that cannot appear elsewhere.
def unboxedSig(tpe: Type, isReturnPosition: Boolean) = {
@@ -298,8 +353,6 @@ abstract class Erasure extends AddInterfaces
jsig(RuntimeNothingClass.tpe)
else if (sym == NullClass)
jsig(RuntimeNullClass.tpe)
- else if (isValueClass(sym))
- jsig(ObjectClass.tpe)
else if (sym.isClass) {
val preRebound = pre.baseType(sym.owner) // #2585
traceSig.seq("sym.isClass", Seq(sym.ownerChain, preRebound, sym0.enclClassChain)) {