Overview

Domains are data classifications that tell the MUFL execution environment how to handle data at run time. They are the runtime representation of data in ADAPT packets.

For a description of the difference between compile-time types and runtime domains, refer to Types vs. Domains.

Primitive Domains

NIL

NIL is a single-value domain. The value NIL is used to represent missing data.

TRUE

TRUE is a single-value domain with pre-defined value Boolean true.

INTEGER

MUFL integers are signed 64 bit integers. All arithmetic exceptions such as overflows, underflows, and division by zero result in a transaction abort.

Examples of integer constants: 1, (-14)

Due to grammatical constraints, negative integers must always be enclosed in parentheses.

STRING

A MUFL string is a variable-length string value.

Unicode is not currently supported.

EXAMPLES:

_print "\"Hello world\"\n".

Prints:

"Hello world"

Strings can be subscripted by an integer:

_print ("Hello" 2).

Prints:

l

As with any iterable domain, strings can be sliced.

_print ( "123456" @! (1..3) ) "\n".

Prints:

234

BINARY

The binary domain represents arbitrary binary values.

Binary constants start with 0x followed by a hexadecimal string (case insensitive) with an even number of hex digits.

Binary values can be subscripted and sliced. Slices of binary values are binary values, whereas subscripting a binary value returns an integer in the 0..255 range, representing a single byte.

A is bin = 0x123456AB. 
_print (A 0) "\n". // should be 18
_print (A @! (0..2)) "\n". // should be 0x123456
_print (_typeof 0x1234) "\n".

Prints:

18 
0x123456 
BINARY

HASH_CODE

The hash code domain is a special kind of a binary value that represents a hash code.

Hash = _value_id 1. 
_print << _typeof Hash. // will print "HASH_CODE"

Prints:

HASH_CODE

For information about hashes related to cryptography, refer to Cryptography Hashes.

SAFEREF

Values in this domain represent opaque authorization tokens used to enable a form of capability-based programming.

For more information, refer to ADAPT Safe Reference

TIME

This domain represents date and time values. Because ADAPT evaluation is deterministic, MUFL does not have a function to retrieve current time, however it is possible to retrieve the timestamp associated with the currently invoked transaction, which is always supplied by the ADAPT wrapper.

Complex Domains

DICTIONARY

A dictionary is the main feature of the ADAPT data model. Dictionaries map any adapt value to any other adapt value. Dictionary keys may be of any ordered data domain. Dictionary values may be of any domain.

Dictionaries are immutable. Modifying a dictionary creates a new dictionary composed of the old dictionary and the new modification. Mutations inside MUFL are performed through reference to names or, if a name is bound to a dictionary, you can instead create a reference to an element of the dictionary (to any depth).

For related information, refer to the combinator operator.

Notes:

  • Arrays are represented as dictionaries with integer keys.
  • Sets are represented as dictionaries with boolean (FALSE or TRUE) values.
  • Dictionaries are ordered by their root hash values.
  • When the keys are integers or strings, dictionaries are scanned in the standard order for those values. However, when dictionary keys have values from multiple domains, the ordering is undefined.

BLINDED DICTIONARY

Blinded dictionaries implement partial blinding of a dictionary, replacing some branches with their hash values. Their main use is to reveal some values that are part of a prior hash commitment without revealing other secret values.

FUNCTION

A function or lambda is a domain of values that contain functional code.

fn F (a:int) -> int = (a + 2). 
_print (F 3) "\n". 
fn G (a:int) -> int { _print "Called function G\n". return (a+2). }
_print (G 5) "\n". 
_print (_typeof G) "\n".

Prints:

5 
Called function G 
7 
LAMBDA

In function parameter declarations, you can define the type of the argument and unfold its contents into multiple named values at the same time.

fn F (person: ($first_name->str, $last_name->str, $address->address:($number->int, $street->str, $town->str)))
{ 
   _assert (address $number == person $address $number). 
}

INTEGER SEQUENCE

An integer sequence is a domain that enables users to use the scan statement to simulate for loops. Integer sequences are also used in slicing.

Example:

sc (0..5) -- (->i) { _print i "\n". } // enumerate values 0..5 in sequence
_print ( "121314151617" @! (0..7 ++2) ) "\n". // a substring of the first 7 elements of the given string

Prints:

0 
1 
2 
3 
4 
5 
1111

Example:

sc (10..>1 --3) -- (i->j) { _print i "==>" j "\n". }

Prints:

0==>10 
1==>7 
2==>4

PACKET

Because packets can be nested, there is a MUFL domain to represent them.

Packets are opaque and immutable. Invoking a transaction on a packet state returns a new resulting state (or an error, if encountered during a state transition).

For more information, refer to Nested Packets.

Special Domains

REFERENCE

A reference provides a convenient mechanism to describe state transitions on immutable data. MUFL introduces the concept of references, which serve as search paths to data within packets and dictionaries. By using references, we simulate mutation syntax ->, which says “make this new value be the result of the referenced expression in the resulting state of the packet”.

References are created with a & (reference-to) operator, and dereferenced using the # (dereference) operator. Names of values in MUFL behave as references automatically in the context that requires it.

For example:

A = [1,2,3,4,5]. // construct an array
B = &(A 0).
#B->15. // Set the value of the zeroth element of A via reference B. 
_print (A 0). // will print 15.

Prints:

15

This process is a shortcut to defining the new state of a packet, rather than directly modifying the old state.

For more information, refer to Using References to Mutate Data.

CRYPTO_ELEMENT

Cryptographic data in MUFL is represented as a special domain that ensures that various background tasks on cryptographic data are performed correctly. For example, certain kinds of cryptographic data must be immediately cleared from memory in the process of deallocation. This task is assured by using a special domain for such data.

Additionally, because MUFL implements a flexible set of cryptographic primitives, cryptographic data carries metadata that describes the type of cryptography used. For example, cryptographic signatures contain information about which signing algorithm was used to generate them. Similarly, cryptographic keys contain information about which cryptography scheme they are associated with.

For more information, refer to Cryptography in MUFL.