File: .lake/packages/lean4/src/lean/Lean/Elab/Do.lean

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.getDoSeqElems
code: private def getDoSeqElems (doSeq : Syntax) : List Syntax 
goal: List Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.getDoSeq
code: private def getDoSeq (doStx : Syntax) : Syntax 
goal: Lean.Syntax

full_name: Lean.Elab.Term.elabLiftMethod
code: @[builtin_term_elab liftMethod] def elabLiftMethod : TermElab 
goal: Lean.Elab.Term.TermElab

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.liftMethodDelimiter
code: /-- Return true if we should not lift `(<- ...)` actions nested in the syntax nodes with the given kind. -/
private def liftMethodDelimiter (k : SyntaxNodeKind) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.letDeclArgHasBinders
code: /-- Given `stx` which is a `letPatDecl`, `letEqnsDecl`, or `letIdDecl`, return true if it has binders. -/
private def letDeclArgHasBinders (letDeclArg : Syntax) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.letDeclHasBinders
code: /-- Return `true` if the given `letDecl` contains binders. -/
private def letDeclHasBinders (letDecl : Syntax) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.liftMethodForbiddenBinder
code: /-- Return true if we should generate an error message when lifting a method over this kind of syntax. -/
private def liftMethodForbiddenBinder (stx : Syntax) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.hasLiftMethod
code: private partial def hasLiftMethod : Syntax → Bool
  
goal: Lean.Syntax → Bool

full_name: Lean.Elab.Term.ExtractMonadResult.expectedType
code: structure ExtractMonadResult where
  m            : Expr
  returnType   : Expr
  expectedType : Expr
goal: Lean.Expr

full_name: Lean.Elab.Term.ExtractMonadResult.m
code: structure ExtractMonadResult where
  m            : Expr
  returnType   : Expr
  expectedType : Expr
goal: Lean.Expr

full_name: Lean.Elab.Term.ExtractMonadResult
code: structure ExtractMonadResult where
  m            : Expr
  returnType   : Expr
  expectedType : Expr
goal: Type

full_name: Lean.Elab.Term.ExtractMonadResult.returnType
code: structure ExtractMonadResult where
  m            : Expr
  returnType   : Expr
  expectedType : Expr
goal: Lean.Expr

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.mkUnknownMonadResult
code: private def mkUnknownMonadResult : MetaM ExtractMonadResult 
goal: Lean.MetaM Lean.Elab.Term.ExtractMonadResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.extractBind.extract?
code: private partial def extractBind (expectedType? : Option Expr) : TermElabM ExtractMonadResult 
goal: Lean.MetaM (Option Lean.Elab.Term.ExtractMonadResult)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.extractBind
code: private partial def extractBind (expectedType? : Option Expr) : TermElabM ExtractMonadResult 
goal: Lean.Elab.TermElabM Lean.Elab.Term.ExtractMonadResult

full_name: Lean.Elab.Term.Do.Var
code: abbrev Var 
goal: Type

full_name: Lean.Elab.Term.Do.Alt.patterns
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.Alt.rhs
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: σ

full_name: Lean.Elab.Term.Do.instInhabitedAlt
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: {a : Type} → [inst : Inhabited a] → Inhabited (Lean.Elab.Term.Do.Alt a)

full_name: Lean.Elab.Term.Do.Alt
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: Type

full_name: Lean.Elab.Term.Do.Alt.ref
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.Alt.vars
code: /-- A `doMatch` alternative. `vars` is the array of variables declared by `patterns`. -/
structure Alt (σ : Type) where
  ref      : Syntax
  vars     : Array Var
  patterns : Syntax
  rhs      : σ
  deriving Inhabited
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.AltExpr.funName
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.AltExpr.pvars
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: Array Lean.Syntax

full_name: Lean.Elab.Term.Do.instInhabitedAltExpr
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: {a : Type} → [inst : Inhabited a] → Inhabited (Lean.Elab.Term.Do.AltExpr a)

full_name: Lean.Elab.Term.Do.AltExpr.rhs
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: σ

full_name: Lean.Elab.Term.Do.AltExpr
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: Type

full_name: Lean.Elab.Term.Do.AltExpr.var?
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: Option Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.AltExpr.ref
code: /-- A `doMatchExpr` alternative. -/
structure AltExpr (σ : Type) where
  ref     : Syntax
  var?    : Option Var
  funName : Syntax
  pvars   : Array Syntax
  rhs     : σ
  deriving Inhabited
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.AltExpr.vars
code: def AltExpr.vars (alt : AltExpr σ) : Array Var 
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.Code.joinpoint
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.continue
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.break
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.ite
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.action
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.jmp
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Type

full_name: Lean.Elab.Term.Do.Code.decl
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.reassign
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.return
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.seq
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.instInhabitedCode
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Inhabited Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.match
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.matchExpr
code: /--
  Auxiliary datastructure for representing a `do` code block, and compiling "reassignments" (e.g., `x := x + 1`).
  We convert `Code` into a `Syntax` term representing the:
  - `do`-block, or
  - the visitor argument for the `forIn` combinator.

  We say the following constructors are terminals:
  - `break`:    for interrupting a `for x in s`
  - `continue`: for interrupting the current iteration of a `for x in s`
  - `return e`: for returning `e` as the result for the whole `do` computation block
  - `action a`: for executing action `a` as a terminal
  - `ite`:      if-then-else
  - `match`:    pattern matching
  - `jmp`       a goto to a join-point

  We say the terminals `break`, `continue`, `action`, and `return` are "exit points"

  Note that, `return e` is not equivalent to `action (pure e)`. Here is an example:
  ```
  def f (x : Nat) : IO Unit := do
  if x == 0 then
     return ()
  IO.println "hello"
  ```
  Executing `#eval f 0` will not print "hello". Now, consider
  ```
  def g (x : Nat) : IO Unit := do
  if x == 0 then
     pure ()
  IO.println "hello"
  ```
  The `if` statement is essentially a noop, and "hello" is printed when we execute `g 0`.

  - `decl` represents all declaration-like `doElem`s (e.g., `let`, `have`, `let rec`).
    The field `stx` is the actual `doElem`,
    `vars` is the array of variables declared by it, and `cont` is the next instruction in the `do` code block.
    `vars` is an array since we have declarations such as `let (a, b) := s`.

  - `reassign` is an reassignment-like `doElem` (e.g., `x := x + 1`).

  - `joinpoint` is a join point declaration: an auxiliary `let`-declaration used to represent the control-flow.

  - `seq a k` executes action `a`, ignores its result, and then executes `k`.
    We also store the do-elements `dbg_trace` and `assert!` as actions in a `seq`.

  A code block `C` is well-formed if
  - For every `jmp ref j as` in `C`, there is a `joinpoint j ps b k` and `jmp ref j as` is in `k`, and
    `ps.size == as.size` -/
inductive Code where
  | decl         (xs : Array Var) (doElem : Syntax) (k : Code)
  | reassign     (xs : Array Var) (doElem : Syntax) (k : Code)
  /-- The Boolean value in `params` indicates whether we should use `(x : typeof! x)` when generating term Syntax or not -/
  | joinpoint    (name : Name) (params : Array (Var × Bool)) (body : Code) (k : Code)
  | seq          (action : Syntax) (k : Code)
  | action       (action : Syntax)
  | break        (ref : Syntax)
  | continue     (ref : Syntax)
  | return       (ref : Syntax) (val : Syntax)
  /-- Recall that an if-then-else may declare a variable using `optIdent` for the branches `thenBranch` and `elseBranch`. We store the variable name at `var?`. -/
  | ite          (ref : Syntax) (h? : Option Var) (optIdent : Syntax) (cond : Syntax) (thenBranch : Code) (elseBranch : Code)
  | match        (ref : Syntax) (gen : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt Code))
  | matchExpr    (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr Code)) (elseBranch : Code)
  | jmp          (ref : Syntax) (jpName : Name) (args : Array Syntax)
  deriving Inhabited
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.Code.getRef?
code: def Code.getRef? : Code → Option Syntax
  
goal: Lean.Elab.Term.Do.Code → Option Lean.Syntax

full_name: Lean.Elab.Term.Do.VarSet
code: abbrev VarSet 
goal: Type

full_name: Lean.Elab.Term.Do.CodeBlock
code: /-- A code block, and the collection of variables updated by it. -/
structure CodeBlock where
  code  : Code
  uvars : VarSet := {}
goal: Type

full_name: Lean.Elab.Term.Do.CodeBlock.code
code: /-- A code block, and the collection of variables updated by it. -/
structure CodeBlock where
  code  : Code
  uvars : VarSet := {}
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.CodeBlock.uvars
code: /-- A code block, and the collection of variables updated by it. -/
structure CodeBlock where
  code  : Code
  uvars : VarSet := {}
goal: Lean.Elab.Term.Do.VarSet

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.varSetToArray
code: private def varSetToArray (s : VarSet) : Array Var 
goal: Array Lean.Elab.Term.Do.Var

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.varsToMessageData
code: private def varsToMessageData (vars : Array Var) : MessageData 
goal: Lean.MessageData

full_name: Lean.Elab.Term.Do.CodeBlocl.toMessageData.loop
code: partial def CodeBlocl.toMessageData (codeBlock : CodeBlock) : MessageData 
goal: Lean.Elab.Term.Do.Code → Lean.MessageData

full_name: Lean.Elab.Term.Do.CodeBlocl.toMessageData
code: partial def CodeBlocl.toMessageData (codeBlock : CodeBlock) : MessageData 
goal: Lean.MessageData

full_name: Lean.Elab.Term.Do.hasExitPointPred
code: /-- Return true if the give code contains an exit point that satisfies `p` -/
partial def hasExitPointPred (c : Code) (p : Code → Bool) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.hasExitPointPred.loop
code: /-- Return true if the give code contains an exit point that satisfies `p` -/
partial def hasExitPointPred (c : Code) (p : Code → Bool) : Bool 
goal: Lean.Elab.Term.Do.Code → Bool

full_name: Lean.Elab.Term.Do.hasExitPoint
code: def hasExitPoint (c : Code) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.hasReturn
code: def hasReturn (c : Code) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.hasTerminalAction
code: def hasTerminalAction (c : Code) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.hasBreakContinue
code: def hasBreakContinue (c : Code) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.hasBreakContinueReturn
code: def hasBreakContinueReturn (c : Code) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.mkAuxDeclFor
code: def mkAuxDeclFor {m} [Monad m] [MonadQuotation m] (e : Syntax) (mkCont : Syntax → m Code) : m Code 
goal: m Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.convertTerminalActionIntoJmp.loop
code: /-- Convert `action _ e` instructions in `c` into `let y ← e; jmp _ jp (xs y)`. -/
partial def convertTerminalActionIntoJmp (code : Code) (jp : Name) (xs : Array Var) : MacroM Code 
goal: Lean.Elab.Term.Do.Code → Lean.MacroM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.convertTerminalActionIntoJmp
code: /-- Convert `action _ e` instructions in `c` into `let y ← e; jmp _ jp (xs y)`. -/
partial def convertTerminalActionIntoJmp (code : Code) (jp : Name) (xs : Array Var) : MacroM Code 
goal: Lean.MacroM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.JPDecl
code: structure JPDecl where
  name : Name
  params : Array (Var × Bool)
  body : Code
goal: Type

full_name: Lean.Elab.Term.Do.JPDecl.name
code: structure JPDecl where
  name : Name
  params : Array (Var × Bool)
  body : Code
goal: Lean.Name

full_name: Lean.Elab.Term.Do.JPDecl.params
code: structure JPDecl where
  name : Name
  params : Array (Var × Bool)
  body : Code
goal: Array (Lean.Elab.Term.Do.Var × Bool)

full_name: Lean.Elab.Term.Do.JPDecl.body
code: structure JPDecl where
  name : Name
  params : Array (Var × Bool)
  body : Code
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.attachJP
code: def attachJP (jpDecl : JPDecl) (k : Code) : Code 
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.attachJPs
code: def attachJPs (jpDecls : Array JPDecl) (k : Code) : Code 
goal: Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.mkFreshJP
code: def mkFreshJP (ps : Array (Var × Bool)) (body : Code) : TermElabM JPDecl 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.JPDecl

full_name: Lean.Elab.Term.Do.addFreshJP
code: def addFreshJP (ps : Array (Var × Bool)) (body : Code) : StateRefT (Array JPDecl) TermElabM Name 
goal: StateRefT' IO.RealWorld (Array Lean.Elab.Term.Do.JPDecl) Lean.Elab.TermElabM Lean.Name

full_name: Lean.Elab.Term.Do.insertVars
code: def insertVars (rs : VarSet) (xs : Array Var) : VarSet 
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.eraseVars
code: def eraseVars (rs : VarSet) (xs : Array Var) : VarSet 
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.eraseOptVar
code: def eraseOptVar (rs : VarSet) (x? : Option Var) : VarSet 
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.mkSimpleJmp
code: /-- Create a new jointpoint for `c`, and jump to it with the variables `rs` -/
def mkSimpleJmp (ref : Syntax) (rs : VarSet) (c : Code) : StateRefT (Array JPDecl) TermElabM Code 
goal: StateRefT' IO.RealWorld (Array Lean.Elab.Term.Do.JPDecl) Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.mkJmp
code: /-- Create a new joinpoint that takes `rs` and `val` as arguments. `val` must be syntax representing a pure value.
   The body of the joinpoint is created using `mkJPBody yFresh`, where `yFresh`
   is a fresh variable created by this method. -/
def mkJmp (ref : Syntax) (rs : VarSet) (val : Syntax) (mkJPBody : Syntax → MacroM Code) : StateRefT (Array JPDecl) TermElabM Code 
goal: StateRefT' IO.RealWorld (Array Lean.Elab.Term.Do.JPDecl) Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.pullExitPointsAux
code: /-- `pullExitPointsAux rs c` auxiliary method for `pullExitPoints`, `rs` is the set of update variable in the current path.  -/
partial def pullExitPointsAux (rs : VarSet) (c : Code) : StateRefT (Array JPDecl) TermElabM Code 
goal: StateRefT' IO.RealWorld (Array Lean.Elab.Term.Do.JPDecl) Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.pullExitPoints
code: /--
Auxiliary operation for adding new variables to the collection of updated variables in a CodeBlock.
When a new variable is not already in the collection, but is shadowed by some declaration in `c`,
we create auxiliary join points to make sure we preserve the semantics of the code block.
Example: suppose we have the code block `print x; let x := 10; return x`. And we want to extend it
with the reassignment `x := x + 1`. We first use `pullExitPoints` to create
```
let jp (x!1) :=  return x!1;
print x;
let x := 10;
jmp jp x
```
and then we add the reassignment
```
x := x + 1
let jp (x!1) := return x!1;
print x;
let x := 10;
jmp jp x
```
Note that we created a fresh variable `x!1` to avoid accidental name capture.
As another example, consider
```
print x;
let x := 10
y := y + 1;
return x;
```
We transform it into
```
let jp (y x!1) := return x!1;
print x;
let x := 10
y := y + 1;
jmp jp y x
```
and then we add the reassignment as in the previous example.
We need to include `y` in the jump, because each exit point is implicitly returning the set of
update variables.

We implement the method as follows. Let `us` be `c.uvars`, then
1- for each `return _ y` in `c`, we create a join point
  `let j (us y!1) := return y!1`
   and replace the `return _ y` with `jmp us y`
2- for each `break`, we create a join point
  `let j (us) := break`
   and replace the `break` with `jmp us`.
3- Same as 2 for `continue`.
-/
def pullExitPoints (c : Code) : TermElabM Code 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.extendUpdatedVarsAux
code: partial def extendUpdatedVarsAux (c : Code) (ws : VarSet) : TermElabM Code 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.extendUpdatedVarsAux.update
code: partial def extendUpdatedVarsAux (c : Code) (ws : VarSet) : TermElabM Code 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.Code

full_name: Lean.Elab.Term.Do.extendUpdatedVars
code: /--
Extend the set of updated variables. It assumes `ws` is a super set of `c.uvars`.
We **cannot** simply update the field `c.uvars`, because `c` may have shadowed some variable in `ws`.
See discussion at `pullExitPoints`.
-/
partial def extendUpdatedVars (c : CodeBlock) (ws : VarSet) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.union
code: private def union (s₁ s₂ : VarSet) : VarSet 
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.homogenize
code: /--
Given two code blocks `c₁` and `c₂`, make sure they have the same set of updated variables.
Let `ws` the union of the updated variables in `c₁‵ and ‵c₂`.
We use `extendUpdatedVars c₁ ws` and `extendUpdatedVars c₂ ws`
-/
def homogenize (c₁ c₂ : CodeBlock) : TermElabM (CodeBlock × CodeBlock) 
goal: Lean.Elab.TermElabM (Lean.Elab.Term.Do.CodeBlock × Lean.Elab.Term.Do.CodeBlock)

full_name: Lean.Elab.Term.Do.mkVarDeclCore
code: /--
Extending code blocks with variable declarations: `let x : t := v` and `let x : t ← v`.
We remove `x` from the collection of updated variables.
Remark: `stx` is the syntax for the declaration (e.g., `letDecl`), and `xs` are the variables
declared by it. It is an array because we have let-declarations that declare multiple variables.
Example: `let (x, y) := t`
-/
def mkVarDeclCore (xs : Array Var) (stx : Syntax) (c : CodeBlock) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkReassignCore
code: /--
Extending code blocks with reassignments: `x : t := v` and `x : t ← v`.
Remark: `stx` is the syntax for the declaration (e.g., `letDecl`), and `xs` are the variables
declared by it. It is an array because we have let-declarations that declare multiple variables.
Example: `(x, y) ← t`
-/
def mkReassignCore (xs : Array Var) (stx : Syntax) (c : CodeBlock) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkSeq
code: def mkSeq (action : Syntax) (c : CodeBlock) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkTerminalAction
code: def mkTerminalAction (action : Syntax) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkReturn
code: def mkReturn (ref : Syntax) (val : Syntax) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkBreak
code: def mkBreak (ref : Syntax) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkContinue
code: def mkContinue (ref : Syntax) : CodeBlock 
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkIte
code: def mkIte (ref : Syntax) (optIdent : Syntax) (cond : Syntax) (thenBranch : CodeBlock) (elseBranch : CodeBlock) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.mkUnit
code: private def mkUnit : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.mkPureUnit
code: private def mkPureUnit : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.mkPureUnitAction
code: def mkPureUnitAction : MacroM CodeBlock 
goal: Lean.MacroM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkUnless
code: def mkUnless (cond : Syntax) (c : CodeBlock) : MacroM CodeBlock 
goal: Lean.MacroM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkMatch
code: def mkMatch (ref : Syntax) (genParam : Syntax) (discrs : Syntax) (optMotive : Syntax) (alts : Array (Alt CodeBlock)) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.mkMatchExpr
code: def mkMatchExpr (ref : Syntax) (meta : Bool) (discr : Syntax) (alts : Array (AltExpr CodeBlock)) (elseBranch : CodeBlock) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.concat
code: /-- Return a code block that executes `terminal` and then `k` with the value produced by `terminal`.
   This method assumes `terminal` is a terminal -/
def concat (terminal : CodeBlock) (kRef : Syntax) (y? : Option Var) (k : CodeBlock) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.getLetIdDeclVars
code: def getLetIdDeclVars (letIdDecl : Syntax) : Array Var 
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.getPatternVarsEx
code: def getPatternVarsEx (pattern : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getPatternsVarsEx
code: def getPatternsVarsEx (patterns : Array Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getLetPatDeclVars
code: def getLetPatDeclVars (letPatDecl : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getLetEqnsDeclVars
code: def getLetEqnsDeclVars (letEqnsDecl : Syntax) : Array Var 
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.getLetDeclVars
code: def getLetDeclVars (letDecl : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoLetVars
code: def getDoLetVars (doLet : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoHaveVars
code: def getDoHaveVars : Syntax → TermElabM (Array Var)
  -- NOTE: `hygieneInfo` case should come first as `id` will match anything else
  
goal: Lean.Syntax → Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoLetRecVars
code: def getDoLetRecVars (doLetRec : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoIdDeclVar
code: def getDoIdDeclVar (doIdDecl : Syntax) : Var 
goal: Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.getDoPatDeclVars
code: def getDoPatDeclVars (doPatDecl : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoLetArrowVars
code: def getDoLetArrowVars (doLetArrow : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.getDoReassignVars
code: def getDoReassignVars (doReassign : Syntax) : TermElabM (Array Var) 
goal: Lean.Elab.TermElabM (Array Lean.Elab.Term.Do.Var)

full_name: Lean.Elab.Term.Do.mkDoSeq
code: def mkDoSeq (doElems : Array Syntax) : Syntax 
goal: Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.expandDoIf?
code: /--
  If the given syntax is a `doIf`, return an equivalent `doIf` that has an `else` but no `else if`s or `if let`s.  -/
private def expandDoIf? (stx : Syntax) : MacroM (Option Syntax) 
goal: Lean.MacroM (Option Lean.Syntax)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.expandDoLetExpr?
code: /--
  If the given syntax is a `doLetExpr` or `doLetMetaExpr`, return an equivalent `doIf` that has an `else` but no `else if`s or `if let`s.  -/
private def expandDoLetExpr? (stx : Syntax) (doElems : List Syntax) : MacroM (Option Syntax) 
goal: Lean.MacroM (Option Lean.Syntax)

full_name: Lean.Elab.Term.Do.DoIfView.elseBranch
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.DoIfView.cond
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.DoIfView.ref
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.DoIfView.thenBranch
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.DoIfView
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Type

full_name: Lean.Elab.Term.Do.DoIfView.optIdent
code: structure DoIfView where
  ref        : Syntax
  optIdent   : Syntax
  cond       : Syntax
  thenBranch : Syntax
  elseBranch : Syntax
goal: Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.mkDoIfView
code: /-- This method assumes `expandDoIf?` is not applicable. -/
private def mkDoIfView (doIf : Syntax) : DoIfView 
goal: Lean.Elab.Term.Do.DoIfView

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.mkTuple
code: /--
We use `MProd` instead of `Prod` to group values when expanding the
`do` notation. `MProd` is a universe monomorphic product.
The motivation is to generate simpler universe constraints in code
that was not written by the user.
Note that we are not restricting the macro power since the
`Bind.bind` combinator already forces values computed by monadic
actions to be in the same universe.
-/
private def mkTuple (elems : Array Syntax) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.isDoExpr?
code: /-- Return `some action` if `doElem` is a `doExpr <action>`-/
def isDoExpr? (doElem : Syntax) : Option Syntax 
goal: Option Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.destructTuple
code: /--
  Given `uvars := #[a_1, ..., a_n, a_{n+1}]` construct term
  ```
  let a_1     := x.1
  let x       := x.2
  let a_2     := x.1
  let x       := x.2
  ...
  let a_n     := x.1
  let a_{n+1} := x.2
  body
  ```
  Special cases
  - `uvars := #[]` => `body`
  - `uvars := #[a]` => `let a := x; body`


  We use this method when expanding the `for-in` notation.
-/
private def destructTuple (uvars : Array Var) (x : Syntax) (body : Syntax) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.destructTuple.destruct
code: /--
  Given `uvars := #[a_1, ..., a_n, a_{n+1}]` construct term
  ```
  let a_1     := x.1
  let x       := x.2
  let a_2     := x.1
  let x       := x.2
  ...
  let a_n     := x.1
  let a_{n+1} := x.2
  body
  ```
  Special cases
  - `uvars := #[]` => `body`
  - `uvars := #[a]` => `let a := x; body`


  We use this method when expanding the `for-in` notation.
-/
private def destructTuple (uvars : Array Var) (x : Syntax) (body : Syntax) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.annotate
code: /--
Helper method for annotating `term` with the raw syntax `ref`.
We use this method to implement finer-grained term infos for `do`-blocks.

We use `withRef term` to make sure the synthetic position for the `with_annotate_term` is equal
to the one for `term`. This is important for producing error messages when there is a type mismatch.
Consider the following example:
```
opaque f : IO Nat

def g : IO String := do
  f
```
There is at type mismatch at `f`, but it is detected when elaborating the expanded term
containing the `with_annotate_term .. f`. The current `getRef` when this `annotate` is invoked
is not necessarily `f`. Actually, it is the whole `do`-block. By using `withRef` we ensure
the synthetic position for the `with_annotate_term ..` is equal to `term`.
Recall that synthetic positions are used when generating error messages.
-/
def annotate [Monad m] [MonadRef m] [MonadQuotation m] (ref : Syntax) (term : Syntax) : m Syntax 
goal: m Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.Kind.nestedBC
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.regular
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.forInWithReturn
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.nestedPR
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Type

full_name: Lean.Elab.Term.Do.ToTerm.Kind.forIn
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.nestedPRBC
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.nestedSBC
code: inductive Kind where
  | regular
  | forIn
  | forInWithReturn
  | nestedBC
  | nestedPR
  | nestedSBC
  | nestedPRBC
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.instInhabitedKind
code: instance : Inhabited Kind 
goal: Inhabited Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Kind.isRegular
code: def Kind.isRegular : Kind → Bool
  
goal: Lean.Elab.Term.Do.ToTerm.Kind → Bool

full_name: Lean.Elab.Term.Do.ToTerm.Context.returnType
code: structure Context where
  /-- Syntax to reference the monad associated with the do notation. -/
  m          : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType : Syntax
  uvars      : Array Var
  kind       : Kind
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.Context
code: structure Context where
  /-- Syntax to reference the monad associated with the do notation. -/
  m          : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType : Syntax
  uvars      : Array Var
  kind       : Kind
goal: Type

full_name: Lean.Elab.Term.Do.ToTerm.Context.kind
code: structure Context where
  /-- Syntax to reference the monad associated with the do notation. -/
  m          : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType : Syntax
  uvars      : Array Var
  kind       : Kind
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.Context.uvars
code: structure Context where
  /-- Syntax to reference the monad associated with the do notation. -/
  m          : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType : Syntax
  uvars      : Array Var
  kind       : Kind
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.ToTerm.Context.m
code: structure Context where
  /-- Syntax to reference the monad associated with the do notation. -/
  m          : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType : Syntax
  uvars      : Array Var
  kind       : Kind
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.M
code: abbrev M 
goal: Type

full_name: Lean.Elab.Term.Do.ToTerm.mkUVarTuple
code: def mkUVarTuple : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.returnToTerm
code: def returnToTerm (val : Syntax) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.continueToTerm
code: def continueToTerm : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.breakToTerm
code: def breakToTerm : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.actionTerminalToTerm
code: def actionTerminalToTerm (action : Syntax) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.seqToTerm
code: def seqToTerm (action : Syntax) (k : Syntax) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.declToTerm
code: def declToTerm (decl : Syntax) (k : Syntax) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.reassignToTerm
code: def reassignToTerm (reassign : Syntax) (k : Syntax) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.mkIte
code: def mkIte (optIdent : Syntax) (cond : Syntax) (thenBranch : Syntax) (elseBranch : Syntax) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.mkJoinPoint
code: def mkJoinPoint (j : Name) (ps : Array (Syntax × Bool)) (body : Syntax) (k : Syntax) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.mkJmp
code: def mkJmp (ref : Syntax) (j : Name) (args : Array Syntax) : Syntax 
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.toTerm.go
code: partial def toTerm (c : Code) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.toTerm
code: partial def toTerm (c : Code) : M Syntax 
goal: Lean.Elab.Term.Do.ToTerm.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.run
code: def run (code : Code) (m : Syntax) (returnType : Syntax) (uvars : Array Var := #[]) (kind := Kind.regular) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.mkNestedKind
code: /-- Given
   - `a` is true if the code block has a `Code.action _` exit point
   - `r` is true if the code block has a `Code.return _ _` exit point
   - `bc` is true if the code block has a `Code.break _` or `Code.continue _` exit point

   generate Kind. See comment at the beginning of the `ToTerm` namespace. -/
def mkNestedKind (a r bc : Bool) : Kind 
goal: Lean.Elab.Term.Do.ToTerm.Kind

full_name: Lean.Elab.Term.Do.ToTerm.mkNestedTerm
code: def mkNestedTerm (code : Code) (m : Syntax) (returnType : Syntax) (uvars : Array Var) (a r bc : Bool) : MacroM Syntax 
goal: Lean.MacroM Lean.Syntax

full_name: Lean.Elab.Term.Do.ToTerm.matchNestedTermResult
code: /-- Given a term `term` produced by `ToTerm.run`, pattern match on its result.
   See comment at the beginning of the `ToTerm` namespace.

   - `a` is true if the code block has a `Code.action _` exit point
   - `r` is true if the code block has a `Code.return _ _` exit point
   - `bc` is true if the code block has a `Code.break _` or `Code.continue _` exit point

   The result is a sequence of `doElem` -/
def matchNestedTermResult (term : Syntax) (uvars : Array Var) (a r bc : Bool) : MacroM (List Syntax) 
goal: Lean.MacroM (List Lean.Syntax)

full_name: Lean.Elab.Term.Do.isMutableLet
code: def isMutableLet (doElem : Syntax) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context.insideFor
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Bool

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context.returnType
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context.mutableVars
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context.m
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Type

full_name: Lean.Elab.Term.Do.ToCodeBlock.Context.ref
code: structure Context where
  ref         : Syntax
  /-- Syntax representing the monad associated with the do notation. -/
  m           : Syntax
  /-- Syntax to reference the result of the monadic computation performed by the do notation. -/
  returnType  : Syntax
  mutableVars : VarSet := {}
  insideFor   : Bool := false
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.M
code: abbrev M 
goal: Type

full_name: Lean.Elab.Term.Do.ToCodeBlock.withNewMutableVars
code: def withNewMutableVars {α} (newVars : Array Var) (mutable : Bool) (x : M α) : M α 
goal: Lean.Elab.Term.Do.ToCodeBlock.M α

full_name: Lean.Elab.Term.Do.ToCodeBlock.checkReassignable
code: def checkReassignable (xs : Array Var) : M Unit 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Unit

full_name: Lean.Elab.Term.Do.ToCodeBlock.checkNotShadowingMutable
code: def checkNotShadowingMutable (xs : Array Var) : M Unit 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Unit

full_name: Lean.Elab.Term.Do.ToCodeBlock.withFor
code: def withFor {α} (x : M α) : M α 
goal: Lean.Elab.Term.Do.ToCodeBlock.M α

full_name: Lean.Elab.Term.Do.ToCodeBlock.ToForInTermResult
code: structure ToForInTermResult where
  uvars      : Array Var
  term       : Syntax
goal: Type

full_name: Lean.Elab.Term.Do.ToCodeBlock.ToForInTermResult.uvars
code: structure ToForInTermResult where
  uvars      : Array Var
  term       : Syntax
goal: Array Lean.Elab.Term.Do.Var

full_name: Lean.Elab.Term.Do.ToCodeBlock.ToForInTermResult.term
code: structure ToForInTermResult where
  uvars      : Array Var
  term       : Syntax
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.mkForInBody
code: def mkForInBody  (_ : Syntax) (forInBody : CodeBlock) : M ToForInTermResult 
goal: Lean.Syntax →
  Lean.Elab.Term.Do.CodeBlock → Lean.Elab.Term.Do.ToCodeBlock.M Lean.Elab.Term.Do.ToCodeBlock.ToForInTermResult

full_name: Lean.Elab.Term.Do.ToCodeBlock.ensureInsideFor
code: def ensureInsideFor : M Unit 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Unit

full_name: Lean.Elab.Term.Do.ToCodeBlock.ensureEOS
code: def ensureEOS (doElems : List Syntax) : M Unit 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Unit

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.Do.ToCodeBlock.expandLiftMethodAux
code: private partial def expandLiftMethodAux (inQuot : Bool) (inBinder : Bool) : Syntax → StateT (List Syntax) M Syntax
  
goal: Lean.Syntax → StateT (List Lean.Syntax) Lean.Elab.Term.Do.ToCodeBlock.M Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.expandLiftMethod
code: def expandLiftMethod (doElem : Syntax) : M (List Syntax × Syntax) 
goal: Lean.Elab.Term.Do.ToCodeBlock.M (List Lean.Syntax × Lean.Syntax)

full_name: Lean.Elab.Term.Do.ToCodeBlock.checkLetArrowRHS
code: def checkLetArrowRHS (doElem : Syntax) : M Unit 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Unit

full_name: Lean.Elab.Term.Do.ToCodeBlock.doReturnToCode
code: /-- Generate `CodeBlock` for `doReturn` which is of the form
   ```
   "return " >> optional termParser
   ```
   `doElems` is only used for sanity checking. -/
def doReturnToCode (doReturn : Syntax) (doElems: List Syntax) : M CodeBlock 
goal: Lean.Elab.Term.Do.ToCodeBlock.M Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.ToCodeBlock.Catch.optType
code: structure Catch where
  x         : Syntax
  optType   : Syntax
  codeBlock : CodeBlock
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.Catch
code: structure Catch where
  x         : Syntax
  optType   : Syntax
  codeBlock : CodeBlock
goal: Type

full_name: Lean.Elab.Term.Do.ToCodeBlock.Catch.codeBlock
code: structure Catch where
  x         : Syntax
  optType   : Syntax
  codeBlock : CodeBlock
goal: Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.ToCodeBlock.Catch.x
code: structure Catch where
  x         : Syntax
  optType   : Syntax
  codeBlock : CodeBlock
goal: Lean.Syntax

full_name: Lean.Elab.Term.Do.ToCodeBlock.getTryCatchUpdatedVars
code: def getTryCatchUpdatedVars (tryCode : CodeBlock) (catches : Array Catch) (finallyCode? : Option CodeBlock) : VarSet 
goal: Lean.Elab.Term.Do.VarSet

full_name: Lean.Elab.Term.Do.ToCodeBlock.tryCatchPred
code: def tryCatchPred (tryCode : CodeBlock) (catches : Array Catch) (finallyCode? : Option CodeBlock) (p : Code → Bool) : Bool 
goal: Bool

full_name: Lean.Elab.Term.Do.ToCodeBlock.run
code: def run (doStx : Syntax) (m : Syntax) (returnType : Syntax) : TermElabM CodeBlock 
goal: Lean.Elab.TermElabM Lean.Elab.Term.Do.CodeBlock

full_name: Lean.Elab.Term.Do.elabDo
code: @[builtin_term_elab «do»] def elabDo : TermElab 
goal: Lean.Elab.Term.TermElab

full_name: Lean.Elab.Term.initFn._@..lake.packages.lean4.src.lean.Lean.Elab.Do._hyg.36507
code: builtin_initialize registerTraceClass `Elab.do
goal: IO Unit

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Elab.Do.0.Lean.Elab.Term.toDoElem
code: private def toDoElem (newKind : SyntaxNodeKind) : Macro 
goal: Lean.Macro

full_name: Lean.Elab.Term.expandTermFor
code: @[builtin_macro Lean.Parser.Term.termFor]
def expandTermFor : Macro 
goal: Lean.Macro

full_name: Lean.Elab.Term.expandTermTry
code: @[builtin_macro Lean.Parser.Term.termTry]
def expandTermTry : Macro 
goal: Lean.Macro

full_name: Lean.Elab.Term.expandTermUnless
code: @[builtin_macro Lean.Parser.Term.termUnless]
def expandTermUnless : Macro 
goal: Lean.Macro

full_name: Lean.Elab.Term.expandTermReturn
code: @[builtin_macro Lean.Parser.Term.termReturn]
def expandTermReturn : Macro 
goal: Lean.Macro