Funcons-beta : Binding.cbs | PRETTY | PDF
Outline
Binding
[
  Type     environments       Alias envs
  Datatype identifiers        Alias ids
  Funcon   identifier-tagged  Alias id-tagged
  Funcon   fresh-identifier
  Entity   environment        Alias env
  Funcon   initialise-binding
  Funcon   bind-value         Alias bind
  Funcon   unbind
  Funcon   bound-directly
  Funcon   bound-value        Alias bound
  Funcon   closed
  Funcon   scope
  Funcon   accumulate
  Funcon   collateral
  Funcon   bind-recursively
  Funcon   recursive
]Meta-variables
  T <: valuesEnvironments
Type
  environments ~> maps(identifiers, values?)
Alias
  envs = environmentsAn environment represents bindings of identifiers to values.
  Mapping an identifier to ( ) represents that its binding is hidden.
Circularity in environments (due to recursive bindings) is represented using
  bindings to cut-points called links. Funcons are provided for making
  declarations recursive and for referring to bound values without explicit
  mention of links, so their existence can generally be ignored.
Datatype
  identifiers ::= {_:strings} | identifier-tagged(_:identifiers, _:values)
Alias
  ids = identifiersAlias
  id-tagged = identifier-taggedAn identifier is either a string of characters, or an identifier tagged with some value (e.g., with the identifier of a namespace).
Funcon
  fresh-identifier : =>identifiersfresh-identifier computes an identifier distinct from all previously
  computed identifiers.
Rule
  fresh-identifier ~> identifier-tagged("generated", fresh-atom)Current bindings
Entity
  environment(_:environments) |- _ ---> _Alias
  env = environmentThe environment entity allows a computation to refer to the current bindings of identifiers to values.
Funcon
  initialise-binding(X:=>T) : =>T
   ~> initialise-linking(initialise-generating(closed(X)))initialise-binding(X) ensures that X does not depend on non-local bindings.
  It also ensures that the linking entity (used to represent potentially cyclic
  bindings) and the generating entity (for creating fresh identifiers) are 
  initialised.
Funcon
  bind-value(I:identifiers, V:values) : =>environments
    ~> { I |-> V }
Alias
  bind = bind-valuebind-value(I, X) computes the environment that binds only I to the value
  computed by X.
Funcon
  unbind(I:identifiers) : =>environments
    ~> { I |-> ( ) }unbind(I) computes the environment that hides the binding of I.
Funcon
  bound-directly(_:identifiers) : =>valuesbound-directly(I) returns the value to which I is currently bound, if any,
  and otherwise fails.
bound-directly(I) does not follow links. It is used only in connection with
  recursively-bound values when references are not encapsulated in abstractions.
Rule 
  lookup(Rho, I) ~> (V:values)
  --------------------------------------------------------
  environment(Rho) |- bound-directly(I:identifiers) ---> V
Rule 
  lookup(Rho, I) ~> ( )
  -----------------------------------------------------------
  environment(Rho) |- bound-directly(I:identifiers) ---> failFuncon
  bound-value(I:identifiers) : =>values
   ~> follow-if-link(bound-directly(I))
Alias
  bound = bound-valuebound-value(I) inspects the value to which I is currently bound, if any,
   and otherwise fails. If the value is a link, bound-value(I) returns the
   value obtained by following the link, if any, and otherwise fails. If the 
   inspected value is not a link, bound-value(I) returns it.
bound-value(I) is used for references to non-recursive bindings and to
   recursively-bound values when references are encapsulated in abstractions.
Scope
Funcon
  closed(X:=>T) : =>Tclosed(X) ensures that X does not depend on non-local bindings.
Rule
  environment(map( )) |- X ---> X′
  -------------------------------------------
  environment(_) |- closed(X) ---> closed(X′)
Rule
  closed(V:T) ~> VFuncon
  scope(_:environments, _:=>T) : =>Tscope(D,X) executes D with the current bindings, to compute an environment
  Rho representing local bindings. It then executes X to compute the result,
  with the current bindings extended by Rho, which may shadow or hide previous
  bindings.
closed(scope(Rho, X)) ensures that X can reference only the bindings
  provided by Rho.
Rule
  environment(map-override(Rho1, Rho0)) |- X ---> X′
  ---------------------------------------------------------------------
  environment(Rho0) |- scope(Rho1:environments, X) ---> scope(Rho1, X′)
Rule
  scope(_:environments, V:T) ~> VFuncon
  accumulate(_:(=>environments)*) : =>environmentsaccumulate(D1, D2) executes D1 with the current bindings, to compute an
  environment Rho1 representing some local bindings. It then executes D2 to
  compute an environment Rho2 representing further local bindings, with the
  current bindings extended by Rho1, which may shadow or hide previous
  current bindings. The result is Rho1 extended by Rho2, which may shadow
  or hide the bindings of Rho1.
accumulate(_, _) is associative, with map( ) as unit, and extends to any
  number of arguments.
Rule
                  D1 ---> D1′
  -------------------------------------------
  accumulate(D1, D2) ---> accumulate(D1′, D2)
Rule
  accumulate(Rho1:environments, D2) ~> scope(Rho1, map-override(D2, Rho1))
Rule
  accumulate( ) ~> map( )
Rule
  accumulate(D1) ~> D1
Rule
  accumulate(D1, D2, D+) ~> accumulate(D1, accumulate(D2, D+))Funcon
  collateral(Rho*:environments*) : =>environments
   ~> checked map-unite(Rho*)collateral(D1, ...) pre-evaluates its arguments with the current bindings,
  and unites the resulting maps, which fails if the domains are not pairwise
  disjoint.
collateral(D1, D2) is associative and commutative with map( ) as unit, 
  and extends to any number of arguments.
Recurse
Funcon
  bind-recursively(I:identifiers, E:=>values) : =>environments
    ~> recursive({I}, bind-value(I, E))bind-recursively(I, E) binds I to a link that refers to the value of E, 
  representing a recursive binding of I to the value of E.
  Since bound-value(I) follows links, it should not be executed during the
  evaluation of E.
Funcon
  recursive(SI:sets(identifiers), D:=>environments) : =>environments
    ~> re-close(bind-to-forward-links(SI), D)recursive(SI, D) executes D with potential recursion on the bindings of 
  the identifiers in the set SI (which need not be the same as the set of
  identifiers bound by D).
Auxiliary Funcon
  re-close(M:maps(identifiers, links), D:=>environments) : =>environments
    ~> accumulate(scope(M, D), sequential(set-forward-links(M), map( )))re-close(M, D) first executes D in the scope M, which maps identifiers
  to freshly allocated links. This computes an environment Rho where the bound
  values may contain links, or implicit references to links in abstraction
  values. It then sets the link for each identifier in the domain of M to
  refer to its bound value in Rho, and returns Rho as the result.
Auxiliary Funcon
  bind-to-forward-links(SI:sets(identifiers)) : =>maps(identifiers, links)
    ~> map-unite(interleave-map(bind-value(given, fresh-link(values)), 
                                set-elements(SI)))bind-to-forward-links(SI) binds each identifier in the set SI to a
  freshly allocated link.
Auxiliary Funcon
  set-forward-links(M:maps(identifiers, links)) : =>null-type
    ~> effect(interleave-map(set-link(map-lookup(M, given), bound-value(given)),
                             set-elements(map-domain(M))))For each identifier I in the domain of M, set-forward-links(M) sets the 
  link to which I is mapped by M to the current bound value of I.