VSL - The prelude.record_sigs Structure
# Copyright 2011 Petter Urkedal
#
# This file is part of the Viz Standard Library <http://www.vizlang.org/>.
#
# The Viz Standard Library (VSL) is free software: you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# The VSL is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
# more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with the VSL. If not, see <http://www.gnu.org/licenses/>.
# 0. Describing and Accessing Hierarchical Data
#
# This file defines an abstraction for describing, building, and accessing
# data. It's tailored for native memory, but formulated generically enough to
# work for objects embedded e.g. in an interpreted language like JavaScript,
# or other virtual environments.
#
# Safety Remark. Implementations of these signatures may be unsafe even if not
# indicated by the function names. Issues include uninitialized references,
# unchecked array bounds, and over- and underflow during conversion.
# 0.0. Status
#
# This interface and its implementations are experimental, and have some
# limitations. In particular defining parametric types is currently
# unsupported. This issue may be revisited when we have a compiler which is
# not subject to the value restriction.
# 0.0. Concepts
#
# A record here refers to a layout of data which itself can be embedded in
# other records. A record includes single primitive types and fixed-size
# arrays. Variable-sized arrays are encoded as a "spill".
#
# A spill is a combination of two record descriptions. An instance of a spill
# is an instance of the first record combined with any number of instances of
# the second record, indexed by an integer. A spill encodes the common
# C-idiom of adding variable sized arrays as the last field of a struct. A
# spill is not a record, since its size is unknown.
open prereq
# 0.0. Phantom Types Used Below
#
# Phantom types are used to describe records which do not have a corresponding
# Viz type. Below, type parameters (δ), (ε), and (ζ) run over phantoms
# describing records and (σ) runs over phantoms describing spills.
in phantoms
# 0.0.0. Phantoms for Pointers and Compounds
type ptr_ph δ inj _ptr_ph
type value_ph α inj _value_ph
type array_ph δ inj _array_ph
type spill_ph δ ε inj _spill_ph
# 0.0. Record Architecture
sig a_record_architecture
open phantoms
# 0.0.0. Propositions and Meta-Information about Records
type is_record δ
## A value of type (is_record δ) witness the fact that (δ) is a record,
## and may carry information about the record needed by the
## implementation.
type has_field δ ε
## A value of type (has_field δ ε) witness that (δ) has a field of type
## (ε), and also carries the information to select it.
type has_components δ ε
## A value of type (has_components δ ε) witness the fact that (δ)
## contains a fixed number of components of type (ε), and may carry
## information needed to index them, such as the size of components and
## the number of components if bonds are checked.
type has_elements σ ε
## A value of type (has_elements σ ε) witness that (σ) has a
## variable-sized array of elements of type (ε), and carry details to
## access it. Typical implementations only populate this type where (σ)
## is a spill, as they require records to have fixed size.
# 0.0.0. Axioms and Meta-Information
#
# A record is described by producing evidence that it is a record, and
# evidence for any fields, components, or elements it may have. We use
# the term evidence here as an informal term for an axiom or proof coupled
# with meta-information used by the implementation.
#
# First, two generic facts:
val field_is_transitive : has_field δ ε → has_field ε ζ → has_field δ ζ
## A lookup of a record field followed by a lookup within that record can
## be combined into one operation.
val components_are_elements : has_components δ ε → has_elements δ ε
## Components of an array can be accessed as if they were part of a spill
## where the fixed part is the unit record.
# 0.0.0.0. Pointers
val record_ptr_ev : is_record δ → is_record (ptr_ph δ)
## A pointer to a record is a record.
val spill_ptr_ev :
is_record δ → is_record ε → is_record (ptr_ph (spill_ph δ ε))
## A pointer to a spill is a record.
# 0.0.0.0. Compound Types
val array_ev :
int → is_record δ →
is_record (array_ph δ) × has_components (array_ph δ) δ
val spill_ev :
is_record δ → is_record ε →
has_field (spill_ph δ ε) δ × has_elements (spill_ph δ ε) ε
in! fabric
type ph
val ptr_ev : is_record (ptr_ph ph)
val acquire : is_record δ → io (has_field ph δ)
val realize : io (is_record ph)
# 0.0.0. Lenses
#
# A lens can traverse the representation of an object, and provides
# constant or mutable access.
in lens
type R Ψ δ
type r ψ δ := R (hot ψ) δ
type t δ := R cold δ
val cmp : R Ψ δ → R Ψ δ → torder
val focus_field : has_field δ ε → R Ψ δ → R Ψ ε
val focus_component : has_components δ ε → int → R Ψ δ → R Ψ ε
val focus_element : has_elements σ ε → int → R Ψ σ → R Ψ ε
val unsafe_defocus_field : has_field δ ε → R Ψ ε → R Ψ δ
val get_ptr : t (ptr_ph δ) → t δ
val load_ptr : r ψ (ptr_ph δ) → effect ψ (r ψ δ)
val store_ptr : r ψ δ → r ψ (ptr_ph δ) → effect ψ unit
val get_value : t (value_ph α) → α
val load_value : r ψ (value_ph α) → effect ψ α
val store_value : α → r ψ (value_ph α) → effect ψ unit
val unsafe_null : R Ψ δ
val unsafe_cast : R Ψ δ → R Ψ δ'
val unsafe_freeze : R Ψ δ → t δ
val unsafe_thaw : R Ψ δ → r ψ δ
# 0.0.0. Complete Objects
#
# Safety Remark. Implementations of memory-allocating functions may pass
# uninitialized data to the client. Make sure to initialize all pointers.
in record
type R Ψ δ
type r ψ δ := R (hot ψ) δ
type t δ := R cold δ
val alloc : is_record δ → effect ψ (r ψ δ)
val alloc_finalized : is_record δ → (r ψ δ → effect ψ unit) →
effect ψ (r ψ δ)
val init : is_record δ → (∀ψ. lens.r ψ δ → effect ψ α) → α × R Ψ δ
## (init_record ev f) allocates an instance of (ev) and passes a
## reference to (f) for initialization. The value returned by (f) is
## paired with the object handle as the result.
val alloc_spilled :
is_record δ → int → is_record ε → effect ψ (r ψ (spill_ph δ ε))
val init_spilled :
is_record δ → int → is_record ε →
(∀ψ. lens.r ψ (spill_ph δ ε) → effect ψ α) → α × R Ψ (spill_ph δ ε)
## (init_spill ev n elt_ev f) allocates a spill with an instance of
## (ev) and (n) instances of (elt_ev), initialized by (f), which
## receives a reference lens to the newly allocated object. The
## result of (f) paired with the constructed object is returned.
val focus : R Ψ δ → lens.R Ψ δ
## Acquire read access to a constructed object.
# 0.0.0. Primitive Types
val unit_ev : is_record unit
val value_ev : is_record (value_ph α)
sig a_foreign_type
type ph
type t
val ev : is_record ph
val get : lens.t ph → t
val load : lens.r ψ ph → effect ψ t
val store : t → lens.r ψ ph → effect ψ unit