--- In arrow notation, a variable bound by a proc (or enclosed let/kappa)
--- is not in scope to the left of an arrow tail (-<) or the head of (|..|).
--- For example
---
--- proc x -> (e1 -< e2)
---
--- Here, x is not in scope in e1, but it is in scope in e2. This can get
--- a bit complicated:
---
--- let x = 3 in
--- proc y -> (proc z -> e1) -< e2
---
--- Here, x and z are in scope in e1, but y is not. Here's how we track this:
--- a) Assign an "proc level" to each proc, being the number of
--- lexically-enclosing procs + 1.
--- b) Assign to each local variable the proc-level of its lexically
--- enclosing proc.
--- c) Keep a list of out-of-scope procs. When moving to the left of
--- an arrow-tail, add the proc-level of the immediately enclosing
--- proc to the list, and increment the proc-level so that variables
--- bound inside the expression are in scope.
--- d) When looking up a variable, complain if its proc-level is in
--- the banned list
-
-type ProcLevel = Int -- Always >= 0
-topProcLevel = 0 -- Not inside any proc
-
-data ArrowCtxt = ArrCtxt { proc_level :: ProcLevel, -- Current level
- proc_banned :: [ProcLevel] } -- Out of scope proc-levels
-
-topArrowCtxt = ArrCtxt { proc_level = topProcLevel, proc_banned = [] }
+{-
+In arrow notation, a variable bound by a proc (or enclosed let/kappa)
+is not in scope to the left of an arrow tail (-<) or the head of (|..|).
+For example
+
+ proc x -> (e1 -< e2)
+
+Here, x is not in scope in e1, but it is in scope in e2. This can get
+a bit complicated:
+
+ let x = 3 in
+ proc y -> (proc z -> e1) -< e2
+
+Here, x and z are in scope in e1, but y is not. We implement this by
+recording the environment when passing a proc (using newArrowScope),
+and returning to that (using escapeArrowScope) on the left of -< and the
+head of (|..|).
+-}
+
+data ArrowCtxt
+ = NoArrowCtxt
+ | ArrowCtxt (Env TcGblEnv TcLclEnv)
+
+-- Record the current environment (outside a proc)
+newArrowScope :: TcM a -> TcM a
+newArrowScope
+ = updEnv $ \env ->
+ env { env_lcl = (env_lcl env) { tcl_arrow_ctxt = ArrowCtxt env } }
+
+-- Return to the stored environment (from the enclosing proc)
+escapeArrowScope :: TcM a -> TcM a
+escapeArrowScope
+ = updEnv $ \ env -> case tcl_arrow_ctxt (env_lcl env) of
+ NoArrowCtxt -> env
+ ArrowCtxt env' -> env'