Simplify: Make generated names more useful
authorBen Gamari <bgamari.foss@gmail.com>
Fri, 11 Mar 2016 14:24:49 +0000 (15:24 +0100)
committerBen Gamari <ben@smart-cactus.org>
Sat, 12 Mar 2016 11:03:19 +0000 (12:03 +0100)
makeTrivial is responsible for concocting names during simplification.
Previously, however, it would make no attempt to generate a name that
might be useful to later readers of the resulting Core. Here we add a
bit of state to SimplEnv: a finite depth stack of binders within which
we are currently simplifying. We then derive generated binders from this
context.

See #11676.

Open questions:
  * Is there a better way to accomplish this?
  * Is `maxContextDepth` too large/small?

Test Plan: Validate, look at Core.

Reviewers: austin, simonpj

Reviewed By: simonpj

Subscribers: thomie, simonpj

Differential Revision: https://phabricator.haskell.org/D1970

GHC Trac Issues: #11676

13 files changed:
compiler/simplCore/Simplify.hs
testsuite/tests/deSugar/should_compile/T2431.stderr
testsuite/tests/ghci.debugger/scripts/break009.stdout
testsuite/tests/ghci.debugger/scripts/break010.stdout
testsuite/tests/ghci.debugger/scripts/break011.stdout
testsuite/tests/ghci.debugger/scripts/break012.stdout
testsuite/tests/ghci.debugger/scripts/break028.stdout
testsuite/tests/ghci.debugger/scripts/print018.stdout
testsuite/tests/ghci.debugger/scripts/print031.stdout
testsuite/tests/roles/should_compile/Roles13.stderr
testsuite/tests/simplCore/should_compile/EvalTest.stdout
testsuite/tests/simplCore/should_compile/T9400.stderr
testsuite/tests/simplCore/should_compile/spec-inline.stderr

index 0e5da9b..e905300 100644 (file)
@@ -21,7 +21,7 @@ import Id
 import MkId             ( seqId, voidPrimId )
 import MkCore           ( mkImpossibleExpr, castBottomExpr )
 import IdInfo
-import Name             ( Name, mkSystemVarName, isExternalName )
+import Name             ( Name, mkSystemVarName, isExternalName, getOccFS )
 import Coercion hiding  ( substCo, substCoVar )
 import OptCoercion      ( optCoercion )
 import FamInstEnv       ( topNormaliseType_maybe )
@@ -458,14 +458,14 @@ prepareRhs :: TopLevelFlag -> SimplEnv -> OutId -> OutExpr -> SimplM (SimplEnv,
 prepareRhs top_lvl env id (Cast rhs co)    -- Note [Float coercions]
   | Pair ty1 _ty2 <- coercionKind co       -- Do *not* do this if rhs has an unlifted type
   , not (isUnliftedType ty1)            -- see Note [Float coercions (unlifted)]
-  = do  { (env', rhs') <- makeTrivialWithInfo top_lvl env sanitised_info rhs
+  = do  { (env', rhs') <- makeTrivialWithInfo top_lvl env (getOccFS id) sanitised_info rhs
         ; return (env', Cast rhs' co) }
   where
     sanitised_info = vanillaIdInfo `setStrictnessInfo` strictnessInfo info
                                    `setDemandInfo` demandInfo info
     info = idInfo id
 
-prepareRhs top_lvl env0 _ rhs0
+prepareRhs top_lvl env0 id rhs0
   = do  { (_is_exp, env1, rhs1) <- go 0 env0 rhs0
         ; return (env1, rhs1) }
   where
@@ -478,7 +478,7 @@ prepareRhs top_lvl env0 _ rhs0
     go n_val_args env (App fun arg)
         = do { (is_exp, env', fun') <- go (n_val_args+1) env fun
              ; case is_exp of
-                True -> do { (env'', arg') <- makeTrivial top_lvl env' arg
+                True -> do { (env'', arg') <- makeTrivial top_lvl env' (getOccFS id) arg
                            ; return (True, env'', App fun' arg') }
                 False -> return (False, env, App fun arg) }
     go n_val_args env (Var fun)
@@ -559,27 +559,33 @@ These strange casts can happen as a result of case-of-case
 -}
 
 makeTrivialArg :: SimplEnv -> ArgSpec -> SimplM (SimplEnv, ArgSpec)
-makeTrivialArg env (ValArg e) = do { (env', e') <- makeTrivial NotTopLevel env e
-                                   ; return (env', ValArg e') }
+makeTrivialArg env (ValArg e) = do
+    { (env', e') <- makeTrivial NotTopLevel env (fsLit "arg") e
+    ; return (env', ValArg e') }
 makeTrivialArg env arg        = return (env, arg)  -- CastBy, TyArg
 
-makeTrivial :: TopLevelFlag -> SimplEnv -> OutExpr -> SimplM (SimplEnv, OutExpr)
+makeTrivial :: TopLevelFlag -> SimplEnv
+            -> FastString  -- ^ a "friendly name" to build the new binder from
+            -> OutExpr -> SimplM (SimplEnv, OutExpr)
 -- Binds the expression to a variable, if it's not trivial, returning the variable
-makeTrivial top_lvl env expr = makeTrivialWithInfo top_lvl env vanillaIdInfo expr
+makeTrivial top_lvl env context expr =
+    makeTrivialWithInfo top_lvl env context vanillaIdInfo expr
 
-makeTrivialWithInfo :: TopLevelFlag -> SimplEnv -> IdInfo
-                    -> OutExpr -> SimplM (SimplEnv, OutExpr)
+makeTrivialWithInfo :: TopLevelFlag -> SimplEnv
+                    -> FastString
+                    -- ^ a "friendly name" to build the new binder from
+                    -> IdInfo -> OutExpr -> SimplM (SimplEnv, OutExpr)
 -- Propagate strictness and demand info to the new binder
 -- Note [Preserve strictness when floating coercions]
 -- Returned SimplEnv has same substitution as incoming one
-makeTrivialWithInfo top_lvl env info expr
+makeTrivialWithInfo top_lvl env context info expr
   | exprIsTrivial expr                          -- Already trivial
   || not (bindingOk top_lvl expr expr_ty)       -- Cannot trivialise
                                                 --   See Note [Cannot trivialise]
   = return (env, expr)
   | otherwise           -- See Note [Take care] below
   = do  { uniq <- getUniqueM
-        ; let name = mkSystemVarName uniq (fsLit "a")
+        ; let name = mkSystemVarName uniq context
               var = mkLocalIdOrCoVarWithInfo name expr_ty info
         ; env'  <- completeNonRecX top_lvl env False var var expr
         ; expr' <- simplVar env' var
@@ -2402,7 +2408,7 @@ mkDupableCont env (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_env = se, sc_cont
         --              in [...hole...] a
     do  { (env', dup_cont, nodup_cont) <- mkDupableCont env cont
         ; (_, se', arg') <- simplArg env' dup se arg
-        ; (env'', arg'') <- makeTrivial NotTopLevel env' arg'
+        ; (env'', arg'') <- makeTrivial NotTopLevel env' (fsLit "karg") arg'
         ; let app_cont = ApplyToVal { sc_arg = arg'', sc_env = se'
                                     , sc_dup = OkToDup, sc_cont = dup_cont }
         ; return (env'', app_cont, nodup_cont) }
index 0d7127d..c3b23ff 100644 (file)
@@ -17,46 +17,52 @@ T2431.$WRefl =
 -- RHS size: {terms: 4, types: 8, coercions: 0}
 absurd :: forall a. Int :~: Bool -> a
 [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>x]
-absurd = \ (@ a4) (x :: Int :~: Bool) -> case x of _ [Occ=Dead] { }
+absurd = \ (@ a) (x :: Int :~: Bool) -> case x of _ [Occ=Dead] { }
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a :: GHC.Types.TrName
+$trModule1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a = GHC.Types.TrNameS "main"#
+$trModule1 = GHC.Types.TrNameS "main"#
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a1 :: GHC.Types.TrName
+$trModule2 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a1 = GHC.Types.TrNameS "T2431"#
+$trModule2 = GHC.Types.TrNameS "T2431"#
 
 -- RHS size: {terms: 3, types: 0, coercions: 0}
 T2431.$trModule :: GHC.Types.Module
 [GblId, Caf=NoCafRefs, Str=DmdType]
-T2431.$trModule = GHC.Types.Module a a1
+T2431.$trModule = GHC.Types.Module $trModule1 $trModule2
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a2 :: GHC.Types.TrName
+$tc'Refl1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a2 = GHC.Types.TrNameS "'Refl"#
+$tc'Refl1 = GHC.Types.TrNameS "'Refl"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 T2431.$tc'Refl :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 T2431.$tc'Refl =
   GHC.Types.TyCon
-    15026191172322750497## 3898273167927206410## T2431.$trModule a2
+    15026191172322750497##
+    3898273167927206410##
+    T2431.$trModule
+    $tc'Refl1
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a3 :: GHC.Types.TrName
+$tc:~:1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a3 = GHC.Types.TrNameS ":~:"#
+$tc:~:1 = GHC.Types.TrNameS ":~:"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 T2431.$tc:~: :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 T2431.$tc:~: =
   GHC.Types.TyCon
-    9759653149176674453## 12942818337407067047## T2431.$trModule a3
+    9759653149176674453##
+    12942818337407067047##
+    T2431.$trModule
+    $tc:~:1
 
 
 
index d7f2d65..d870b8f 100644 (file)
@@ -1,4 +1,4 @@
 Breakpoint 0 activated at ../Test6.hs:5:8-11
 Stopped in Main.main, ../Test6.hs:5:8-11
-_result :: a2 = _
+_result :: a = _
 *** Exception: Prelude.head: empty list
index 0bc0da7..91e0d21 100644 (file)
@@ -1,5 +1,5 @@
 Breakpoint 0 activated at ../Test6.hs:5:8-11
 Stopped in Main.main, ../Test6.hs:5:8-11
-_result :: a2 = _
+_result :: a = _
 Stopped in Main.main, ../Test6.hs:5:8-11
-_result :: a2 = _
+_result :: a = _
index 5839067..c49db52 100644 (file)
@@ -1,5 +1,5 @@
 *** Exception: foo
-CallStack (from ImplicitParams):
+CallStack (from HasCallStack):
   error, called at <interactive>:2:1 in interactive:Ghci1
 Stopped in <exception thrown>, <unknown>
 _exception :: e = _
@@ -9,41 +9,41 @@ _exception :: e = _
 -2  : main (../Test7.hs:2:8-29)
 <end of history>
 Logged breakpoint at ../Test7.hs:2:18-28
-_result :: a3
+_result :: a
 Logged breakpoint at ../Test7.hs:2:8-29
-_result :: IO a3
+_result :: IO a
 no more logged breakpoints
 Logged breakpoint at ../Test7.hs:2:18-28
-_result :: a3
+_result :: a
 Stopped at <unknown>
 _exception :: e
 already at the beginning of the history
 _exception = SomeException
                (ErrorCallWithLocation
                   "foo"
-                  "CallStack (from ImplicitParams):
+                  "CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main")
-_result :: a3 = _
+_result :: a = _
 _exception :: SomeException = SomeException
                                 (ErrorCallWithLocation
                                    "foo"
-                                   "CallStack (from ImplicitParams):
+                                   "CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main")
 *** Exception: foo
-CallStack (from ImplicitParams):
+CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main
 Stopped in <exception thrown>, <unknown>
 _exception :: e = SomeException
                     (ErrorCallWithLocation
                        "foo"
-                       "CallStack (from ImplicitParams):
+                       "CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main")
 Stopped in <exception thrown>, <unknown>
 _exception :: e = SomeException
                     (ErrorCallWithLocation
                        "foo"
-                       "CallStack (from ImplicitParams):
+                       "CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main")
 *** Exception: foo
-CallStack (from ImplicitParams):
+CallStack (from HasCallStack):
   error, called at ../Test7.hs:2:18 in main:Main
index 539a894..904f0cd 100644 (file)
@@ -1,14 +1,14 @@
 Stopped in Main.g, break012.hs:5:10-18
-_result :: (t, a3 -> a3, (), a2 -> a2 -> a2) = _
+_result :: (t, a1 -> a1, (), a -> a -> a) = _
 a :: t = _
-b :: a4 -> a4 = _
+b :: a2 -> a2 = _
 c :: () = _
-d :: a2 -> a2 -> a2 = _
+d :: a -> a -> a = _
 a :: t
-b :: a4 -> a4
+b :: a2 -> a2
 c :: ()
-d :: a2 -> a2 -> a2
+d :: a -> a -> a
 a = (_t1::t)
-b = (_t2::a4 -> a4)
+b = (_t2::a2 -> a2)
 c = (_t3::())
-d = (_t4::a2 -> a2 -> a2)
+d = (_t4::a -> a -> a)
index 7907956..1acf578 100644 (file)
@@ -1,6 +1,6 @@
 Stopped in Main.g, break028.hs:15:23-24
-_result :: Id a4 = _
-x' :: Id a4 = _
+_result :: Id a = _
+x' :: Id a = _
 Stopped in Main.g.x', break028.hs:15:16-18
 _result :: Id Bool = _
 x :: Bool = False
index 65e4302..3f070f7 100644 (file)
@@ -1,9 +1,9 @@
 Breakpoint 0 activated at ../Test.hs:40:10-17
 Stopped in Test.Test2.poly, ../Test.hs:40:10-17
 _result :: () = _
-x :: a41 = _
-x = (_t1::a41)
-x :: a41
+x :: a = _
+x = (_t1::a)
+x :: a
 ()
 x = Unary
 x :: Unary
index 6a326a6..0a13e0a 100644 (file)
@@ -2,5 +2,5 @@ Breakpoint 0 activated at print031.hs:7:7-19
 MkT2 [Just (Phantom 1)]
 Stopped in Print031.f, print031.hs:7:7-19
 _result :: Bool = _
-x :: t (Phantom a6) = [Just (Phantom 1)]
+x :: t (Phantom a) = [Just (Phantom 1)]
 x = [Just (Phantom 1)]
index 3bd9d88..e9b8f1a 100644 (file)
@@ -3,80 +3,92 @@
 Result size of Tidy Core = {terms: 51, types: 20, coercions: 5}
 
 -- RHS size: {terms: 2, types: 2, coercions: 0}
-a :: Wrap Age -> Wrap Age
+convert1 :: Wrap Age -> Wrap Age
 [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType]
-a = \ (ds :: Wrap Age) -> ds
+convert1 = \ (ds :: Wrap Age) -> ds
 
 -- RHS size: {terms: 1, types: 0, coercions: 5}
 convert :: Wrap Age -> Int
 [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType]
 convert =
-  a
+  convert1
   `cast` (<Wrap Age>_R -> Roles13.N:Wrap[0] Roles13.N:Age[0]
           :: (Wrap Age -> Wrap Age) ~R# (Wrap Age -> Int))
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a1 :: GHC.Types.TrName
+$trModule1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a1 = GHC.Types.TrNameS "main"#
+$trModule1 = GHC.Types.TrNameS "main"#
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a2 :: GHC.Types.TrName
+$trModule2 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a2 = GHC.Types.TrNameS "Roles13"#
+$trModule2 = GHC.Types.TrNameS "Roles13"#
 
 -- RHS size: {terms: 3, types: 0, coercions: 0}
 Roles13.$trModule :: GHC.Types.Module
 [GblId, Caf=NoCafRefs, Str=DmdType]
-Roles13.$trModule = GHC.Types.Module a1 a2
+Roles13.$trModule = GHC.Types.Module $trModule1 $trModule2
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a3 :: GHC.Types.TrName
+$tc'MkAge1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a3 = GHC.Types.TrNameS "'MkAge"#
+$tc'MkAge1 = GHC.Types.TrNameS "'MkAge"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 Roles13.$tc'MkAge :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 Roles13.$tc'MkAge =
   GHC.Types.TyCon
-    1226019810264079099## 12180888342844277416## Roles13.$trModule a3
+    1226019810264079099##
+    12180888342844277416##
+    Roles13.$trModule
+    $tc'MkAge1
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a4 :: GHC.Types.TrName
+$tcAge1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a4 = GHC.Types.TrNameS "Age"#
+$tcAge1 = GHC.Types.TrNameS "Age"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 Roles13.$tcAge :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 Roles13.$tcAge =
   GHC.Types.TyCon
-    18304088376370610314## 1954648846714895105## Roles13.$trModule a4
+    18304088376370610314##
+    1954648846714895105##
+    Roles13.$trModule
+    $tcAge1
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a5 :: GHC.Types.TrName
+$tc'MkWrap1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a5 = GHC.Types.TrNameS "'MkWrap"#
+$tc'MkWrap1 = GHC.Types.TrNameS "'MkWrap"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 Roles13.$tc'MkWrap :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 Roles13.$tc'MkWrap =
   GHC.Types.TyCon
-    12402878715225676312## 13345418993613492500## Roles13.$trModule a5
+    12402878715225676312##
+    13345418993613492500##
+    Roles13.$trModule
+    $tc'MkWrap1
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a6 :: GHC.Types.TrName
+$tcWrap1 :: GHC.Types.TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a6 = GHC.Types.TrNameS "Wrap"#
+$tcWrap1 = GHC.Types.TrNameS "Wrap"#
 
 -- RHS size: {terms: 5, types: 0, coercions: 0}
 Roles13.$tcWrap :: GHC.Types.TyCon
 [GblId, Caf=NoCafRefs, Str=DmdType]
 Roles13.$tcWrap =
   GHC.Types.TyCon
-    5278920226786541118## 14554440859491798587## Roles13.$trModule a6
+    5278920226786541118##
+    14554440859491798587##
+    Roles13.$trModule
+    $tcWrap1
 
 
 
index 3f6ae06..3369d32 100644 (file)
@@ -3,19 +3,19 @@
 Result size of Tidy Core = {terms: 33, types: 20, coercions: 0}
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a :: TrName
+$trModule1 :: TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a = GHC.Types.TrNameS "main"#
+$trModule1 = GHC.Types.TrNameS "main"#
 
 -- RHS size: {terms: 2, types: 0, coercions: 0}
-a1 :: TrName
+$trModule2 :: TrName
 [GblId, Caf=NoCafRefs, Str=DmdType]
-a1 = GHC.Types.TrNameS "T9400"#
+$trModule2 = GHC.Types.TrNameS "T9400"#
 
 -- RHS size: {terms: 3, types: 0, coercions: 0}
 T9400.$trModule :: Module
 [GblId, Caf=NoCafRefs, Str=DmdType]
-T9400.$trModule = GHC.Types.Module a a1
+T9400.$trModule = GHC.Types.Module $trModule1 $trModule2
 
 -- RHS size: {terms: 22, types: 15, coercions: 0}
 main :: IO ()
index 061a81f..34af76c 100644 (file)
@@ -47,9 +47,9 @@ Roman.foo_$s$wgo [Occ=LoopBreaker]
 Roman.foo_$s$wgo =
   \ (sc :: GHC.Prim.Int#) (sc1 :: GHC.Prim.Int#) ->
     let {
-      a :: GHC.Prim.Int#
+      m :: GHC.Prim.Int#
       [LclId, Str=DmdType]
-      a =
+      m =
         GHC.Prim.+#
           (GHC.Prim.+#
              (GHC.Prim.+#
@@ -64,8 +64,8 @@ Roman.foo_$s$wgo =
           False ->
             case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.<# sc1 500#)
             of _ [Occ=Dead] {
-              False -> Roman.foo_$s$wgo (GHC.Prim.+# a a) (GHC.Prim.-# sc1 1#);
-              True -> Roman.foo_$s$wgo a (GHC.Prim.-# sc1 3#)
+              False -> Roman.foo_$s$wgo (GHC.Prim.+# m m) (GHC.Prim.-# sc1 1#);
+              True -> Roman.foo_$s$wgo m (GHC.Prim.-# sc1 3#)
             };
           True -> Roman.foo_$s$wgo sc (GHC.Prim.-# sc1 2#)
         };
@@ -87,9 +87,9 @@ Roman.$wgo =
       Just x ->
         case x of _ [Occ=Dead] { GHC.Types.I# ipv ->
         let {
-          a :: GHC.Prim.Int#
+          m :: GHC.Prim.Int#
           [LclId, Str=DmdType]
-          a =
+          m =
             GHC.Prim.+#
               (GHC.Prim.+#
                  (GHC.Prim.+#
@@ -97,7 +97,7 @@ Roman.$wgo =
                  ipv)
               ipv } in
         case w of _ [Occ=Dead] {
-          Nothing -> Roman.foo_$s$wgo a 10#;
+          Nothing -> Roman.foo_$s$wgo m 10#;
           Just n ->
             case n of _ [Occ=Dead] { GHC.Types.I# x2 ->
             case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.<=# x2 0#)
@@ -108,8 +108,8 @@ Roman.$wgo =
                   False ->
                     case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.<# x2 500#)
                     of _ [Occ=Dead] {
-                      False -> Roman.foo_$s$wgo (GHC.Prim.+# a a) (GHC.Prim.-# x2 1#);
-                      True -> Roman.foo_$s$wgo a (GHC.Prim.-# x2 3#)
+                      False -> Roman.foo_$s$wgo (GHC.Prim.+# m m) (GHC.Prim.-# x2 1#);
+                      True -> Roman.foo_$s$wgo m (GHC.Prim.-# x2 3#)
                     };
                   True -> Roman.foo_$s$wgo ipv (GHC.Prim.-# x2 2#)
                 };