Documentation

Elaborator.PlusCal

Statement/showable/process/algorithm checking: checkStatement/checkBlock/checkBranches/ checkPlusCalDeclarations/checkProcess/checkAlgorithm, turning a CorePlusCal.Algorithm (Option Typ) (CoreTLAPlus.Expression (Option Typ)) (α still the optional, user-written @type annotation) into a TypedPlusCal.Algorithm.

A few notable points:

@[reducible, inline]
abbrev SrcRef :

The checker's actual PlusCal input: CorePlusCal.* at α := Option Typ (a with-bound variable's/variables entry's optional @type) and β := SrcExpr.

Equations
Instances For
    @[reducible, inline]
    abbrev SrcStatement (b : Bool) :
    Equations
    Instances For
      @[reducible, inline]
      abbrev SrcBlock (b : Bool) :
      Equations
      Instances For
        @[reducible, inline]
        abbrev SrcBranches (b : Bool) :
        Equations
        Instances For
          @[reducible, inline]
          Equations
          Instances For
            @[reducible, inline]
            Equations
            Instances For
              @[reducible, inline]
              Equations
              Instances For
                partial def showable :

                The showable predicate, used by print: Int/Bool/Str/Address atomic; Function/Set/Seq/Tuple/Record recursively (a Function is showable when both its domain and range are). Operator/Channel/Const/rigid type variables, and anything containing them, are not showable. Pure and non-monadic — callers must resolve τ's metavariables first (instantiateMVars, at the point of use) so .mvar _ => false only fires on a genuinely unresolved metavariable, not one already pinned to something showable. partial: nested List recursion over Tuple/Record's fields isn't visibly structurally decreasing to Lean.

                partial def sendable :

                The sendable predicate, used by a channel's own declared element type (checkChannelDecl): the same restriction as showable (a CONSTANT isn't sendable either — it gets substituted by the user only after code generation, and an unsendable instantiation would silently break this invariant once compiled). Identical in shape to showable but defined separately since the two restrictions only happen to coincide today, not the same rule reused. Same non-monadic, resolve-first contract as showable.

                @[implicit_reducible]

                Needed for the partial defs below to type-check at all (an arbitrary m isn't otherwise known nonempty).

                Equations
                Instances For
                  @[implicit_reducible]
                  Equations
                  Instances For
                    @[implicit_reducible]
                    Equations
                    Instances For

                      Declarations checking, shared by both Algorithm.globalState and a Process's own localState: variables first, then channels/fifos, each stage's bindings in scope for the next.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For

                        Γ|Ξ⊩S ok — a transform, not a pure ok-judgment: every embedded CoreTLAPlus.Expression/Ref becomes a checked TypedPlusCal.Expression/Ref, and receive additionally gains its Coercion.

                        partial: no structurally-decreasing measure across the mutual group visible to Lean (Block's begin : List (Statement _ _ false) field).

                        partial def checkBlock {m : TypeType} [Monad m] [MonadElaborator m] [MonadPendingBounds m] {b : Bool} (blk : SrcBlock b) :

                        Γ|Ξ⊩B ok for atomic blocks — check every non-terminal statement, then the terminal one.

                        either's own branch list, checked pointwise — no dedicated rule beyond [Either] reusing Γ|Ξ⊩B ok per branch.

                        Γ|Ξ⊩ p∈S ⋆ x1=e1;...;xm=em ⋆ T1...Tn ok: S must be Set(Address), checked without self in scope; everything else about a process — mailbox, local variables, every thread — is checked with self:Address already in scope. mailbox's filter/index expressions are inferred, unconstrained, but still need self in scope (@mailbox: agt[self]; is the standard idiom).

                        process (p = e) checks e against Address directly, not Set(Address) (dispatches on proc.«=|∈» rather than constructing a singleton set {e} and checking that).

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For

                          Γ|Ξ⊩ fifos c1:τ1,...,cm:τm; P1∥...∥Pn ok: every channel declaration checked (also covers globalState.variables), then every process checked against Γ extended by those bindings. Those bindings stay scoped to the algorithm itself — PlusCal declarations don't leak into the surrounding TLA⁺ module's own Γ.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For