Add support for abstract/free types #594
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi,
This PR adds support for abstract or free types, written as types with no right-hand side equation. These abstract types can be given a semantics by defining operations on them as imported functions or nodes with no definitions, and giving these operations a contract.
I chose to represent abstract types as roughly equivalent to a struct with one
integer field. The integer describes a unique reference to an object of the
abstract type -- like a pointer. This field is implemented as a
different index type to regular record fields to ensure type safety.
In implementing this new index type, I have erred on the side of emulating
regular struct behaviour.
I chose this struct-like representation over the Abstr type in terms/types.ml
because it gives counterexamples, while Abstr did not when I tried it.
As an example, the test in tests/regression/falsifiable/abstract_type.lus
defines an abstract type
COUNTER
. It also defines imported (FFI) operationsfor retrieving the count and incrementing the counter, which returns a
new counter with a one-higher count. For properties that fail, the
counterexamples for the abstract type look like arbitrary numbers, but
the important thing is that each number uniquely maps to an abstract
state describing the counter's internals.
For this test, I get the following counterexample. The initial counter is given a reference of 2, but the operation
get_counter
maps reference 2 to the actual count of 0. Then, incrementing counter referenced by 2 returns a new counter reference of 8. Asking this new counter for its count returns the actual incremented count of 1.