@informalsystems/quint
Version:
Core tool for the Quint specification language
355 lines (354 loc) • 13.6 kB
TypeScript
import { Map as ImmutableMap, List, OrderedMap, Set, ValueObject } from 'immutable';
import { Maybe } from '@sweet-monads/maybe';
import { IdGenerator } from '../../idGenerator';
import { QuintEx, QuintLambdaParameter } from '../../ir/quintIr';
import { QuintError } from '../../quintError';
import { Either } from '@sweet-monads/either';
import { EvalFunction } from './builder';
import { Context, Register } from './Context';
/**
* A factory of runtime values that should be used to instantiate new values.
*/
export declare const rv: {
/**
* Make a runtime value that represents a Boolean.
*
* @param value a Boolean value
* @return a new runtime value that carries the Boolean value
*/
mkBool: (value: boolean) => RuntimeValue;
/**
* Make a runtime value that represents an integer.
*
* @param value an integer value
* @return a new runtime value that carries the integer value
*/
mkInt: (value: bigint | number) => RuntimeValue;
/**
* Make a runtime value that represents a string.
*
* @param value a string
* @return a new runtime value that carries the string
*/
mkStr: (value: string) => RuntimeValue;
/**
* Make a runtime value that represents a tuple.
*
* @param value an iterable collection of runtime values
* @return a new runtime value that carries the tuple
*/
mkTuple: (elems: Iterable<RuntimeValue>) => RuntimeValue;
/**
* Make a runtime value that represents a list.
*
* @param value an iterable collection of runtime values
* @return a new runtime value that carries the list
*/
mkList: (elems: Iterable<RuntimeValue>) => RuntimeValue;
/**
* Make a runtime value that represents a record.
*
* @param value an iterable collection of pairs of strings and runtime values
* @return a new runtime value that carries the record
*/
mkRecord: (elems: Iterable<[string, RuntimeValue]>) => RuntimeValue;
/**
* Make a runtime value that represents a variant value of a sum type.
*
* @param label a string reperenting the variant's label
* @param value the value held by the variant
* @return a new runtime value that represents the variant
*/
mkVariant: (label: string, value: RuntimeValue) => RuntimeValue;
/**
* Make a runtime value that represents a map.
*
* @param value an iterable collection of pairs of runtime values
* @return a new runtime value that carries the map
*/
mkMap: (elems: Iterable<[RuntimeValue, RuntimeValue]>) => RuntimeValue;
/**
* Make a runtime value that represents a map, using a Map.
*
* @param value an iterable collection of pairs of runtime values
* @return a new runtime value that carries the map
*/
fromMap: (map: ImmutableMap<RuntimeValue, RuntimeValue>) => RuntimeValue;
/**
* Make a runtime value that represents a set via an immutable set.
*
* @param elems an iterable collection of runtime values
* @return a new runtime value that represents
* the immutable set of normalized elements
*/
mkSet: (elems: Iterable<RuntimeValue>) => RuntimeValue;
/**
* Make a runtime value that represents either Nat or Int.
*
* @param set kind (Nat or Int)
* @return a new runtime value that carries the infinite set
*/
mkInfSet: (kind: 'Nat' | 'Int') => RuntimeValue;
/**
* Make a runtime value that represents an integer interval as a pair
* of big integers. This interval may be converted to an immutable set
* via `this#toSet()`.
*
* @param first the minimal point of the interval (inclusive)
* @param last the maximal poitn of the interval (inclusive)
* @return a new runtime value that the interval
*/
mkInterval: (first: bigint | number, last: bigint | number) => RuntimeValue;
/**
* Make a runtime value that represents a cross product of sets.
*
* @param value an iterable collection of runtime values
* @return a new runtime value that carries the tuple
*/
mkCrossProd: (sets: RuntimeValue[]) => RuntimeValue;
/**
* Make a runtime value that represents a set of maps.
*
* @param domainSet the set that stores the map domain
* @param rangeSet the set that stores the map range
* @return a new runtime value that carries the set of maps
*/
mkMapSet: (domainSet: RuntimeValue, rangeSet: RuntimeValue) => RuntimeValue;
/**
* Make a runtime value that represents a powerset.
*
* @param the baseset
* @return a new runtime value that represents the powerset of the baseset
*/
mkPowerset: (baseSet: RuntimeValue) => RuntimeValue;
/**
* Make a runtime value that represents a lambda.
*
* @param params the lambda parameters
* @param body the lambda body expression
* @returns a runtime value of lambda
*/
mkLambda: (params: QuintLambdaParameter[], body: EvalFunction, paramRegistry: Map<bigint, Register>) => RuntimeValueLambda;
/**
* Make a runtime value from a quint expression.
* @param ex - the Quint expression
* @returns a runtime value for the expression
*/
fromQuintEx: (ex: QuintEx) => RuntimeValue;
/**
* Convert a runtime value to a Quint expression.
* @param value - the runtime value to convert
* @returns a Quint expression for the runtime value
*/
toQuintEx: (value: RuntimeValue) => QuintEx;
};
/** The default entry point of this module */
export default rv;
/**
* Get a ground expression, that is, an expression
* that contains only literals and constructors, and
* convert it to a runtime value.
*
* @param ex the expression to convert
* @returns the runtime value that encodes the expression
*/
export declare function fromQuintEx(ex: QuintEx): Maybe<RuntimeValue>;
/**
* A runtime value produced and consumed by the simulator. The structure of
* the runtime values is not exposed to the users.
*
* Since runtime values are internal to the simulator, we implement the
* set-like operations over all runtime values. This simplifies the simulator
* code, as it does not have to distinguish between iterable values and
* non-iterable ones. Of course, this may lead to ill-typed operations. Type
* correctness of the input must be checked by the type checker.
*/
export interface RuntimeValue extends ValueObject, Iterable<RuntimeValue> {
/**
* Can the runtime value behave like a set? Effectively, this means that the
* value returns a sequence of elements, when it is iterated over.
*/
isSetLike: boolean;
/**
* Transform this runtime value into the normal form, so it can be
* added to an immutable set:
*
* - integers and literals are already in the normal form,
* - immutable sets are in the normal form,
* - intervals and powersets are converted to immutable sets.
*/
normalForm(): RuntimeValue;
/**
* If the result is set-like, transform it to an immutable
* set via iteration. Otherwise, return an empty set.
* This is useful for special sets such as intervals.
*
* @return an immutable set of results
* (probably much larger than the original object)
*/
toSet(): Set<RuntimeValue>;
/**
* If the result is a tuple or a list, transform it to an immutable list of
* values. Otherwise, return an empty list.
*
* @return an immutable list of results
*/
toList(): List<RuntimeValue>;
/**
* If the result is a map, transform it to a map of values.
* Otherwise, return an empty map.
*
* @return an immutable map of key-values
*/
toMap(): ImmutableMap<RuntimeValue, RuntimeValue>;
/**
* If the result is a record, transform it to a map of values.
* Otherwise, return an empty map.
*
* @return an immutable map of key-values
*/
toOrderedMap(): OrderedMap<string, RuntimeValue>;
/**
* If the result contains a Boolean value, return it. Otherwise, return false.
*
* @return the stored Boolean value (if it's Boolean), or false.
*/
toBool(): boolean;
/**
* If the result contains an integer value, return it. Otherwise, return 0n.
*
* @return the stored integer value (if it's integer) or 0n.
*/
toInt(): bigint;
/**
* If the result contains a string value, return it.
*
* @return the stored string value.
*/
toStr(): string;
/**
* If the result is a 2-tuple, return it. Otherwise, throw an error.
*
* @return the stored 2-tuple value.
*/
toTuple2(): [RuntimeValue, RuntimeValue];
/**
* If the result is a lambda, use the context to build an arrow function and return it. Otherwise, throw an error.
*
* @return the arrow function that represents the lambda.
*/
toArrow(): (ctx: Context, args: RuntimeValue[]) => Either<QuintError, RuntimeValue>;
/**
* If the result is a variant, return the label and the value.
*
* @return the label and the value of the variant.
*/
toVariant(): [string, RuntimeValue];
/**
* If the result is set-like, does it contain contain a value?
* If the result is not set-like, return false.
*
* @param elem evaluation result to check for membership
* @return true, if `value` appears in the result
*/
contains(_value: RuntimeValue): boolean;
/**
* If this runtime value is set-like, does it contain all elements of
* another set-like runtime value?
*
* @param superset set-like collection of runtime values
* @result true if all elements of this are included
* or equal to the elements of `superset`
*/
isSubset(_superset: RuntimeValue): boolean;
/**
* If this runtime value is set-like, pick one of its elements using the
* position as returned by the `positions` iterator. Importantly,
* `pick` may use the iterator for picking from element sets,
* e.g., think of `Set(Set(2, 3, 4))`. Hence, the iterator is modified
* by pick in place. Also, see #bounds().
*/
pick(positions: Iterator<bigint>): Either<QuintError, RuntimeValue>;
/**
* If this runtime value is set-line, compute the bounds for all subsets,
* as a flat array. A none() value indicates infinity, whereas
* just(n) indicates set cardinality. For example:
*
* - bounds for Set(1, 2) is [just(2)],
* - bounds for Int is [none()]
* - bounds for 1.to(3).setOfMaps(3.to(6)) is [just(4), just(4), just(4)],
* - bounds for 1.to(3).setOfMaps(Int) is [none(), none(), none()].
*/
bounds(): Maybe<bigint>[];
/**
* If this runtime value is set-like, return the number of its elements,
* unless its infinite. If the set is infinite, throw an exception,
* as there is no way to efficiently deal with infinite cardinalities.
*
* @return just the number of set elements, if the set is finite,
* or none(), if the set is infinite
*/
cardinality(): Either<QuintError, bigint>;
/**
* Convert a runtime value to a Quint expression.
*
* This function always returns sets in the normalized representation,
* that is, in `set(elements)`, the elements are ordered according to their
* string representation. As sorting via strings may be slow, we do not
* recommend using `toQuintEx` in computation-intensive code.
*
* @param gen a generator that produces unique ids
* @return this evaluation result converted to Quint expression.
*/
toQuintEx(gen: IdGenerator): QuintEx;
}
/**
* The default implementation of the common methods.
* This implementation is internal to the module.
*/
declare abstract class RuntimeValueBase implements RuntimeValue {
isSetLike: boolean;
constructor(isSetLike: boolean);
[Symbol.iterator](): {
next(): IteratorResult<RuntimeValue>;
};
normalForm(): RuntimeValue;
toSet(): Set<RuntimeValue>;
toList(): List<RuntimeValue>;
toOrderedMap(): OrderedMap<string, RuntimeValue>;
toMap(): ImmutableMap<RuntimeValue, RuntimeValue>;
toBool(): boolean;
toInt(): bigint;
toStr(): string;
toTuple2(): [RuntimeValue, RuntimeValue];
toArrow(): (ctx: Context, args: RuntimeValue[]) => Either<QuintError, RuntimeValue>;
toVariant(): [string, RuntimeValue];
contains(elem: RuntimeValue): boolean;
isSubset(superset: RuntimeValue): boolean;
equals(other: unknown): boolean;
hashCode(): number;
pick(_positions: Iterator<bigint>): Either<QuintError, RuntimeValue>;
bounds(): Maybe<bigint>[];
cardinality(): Either<QuintError, bigint>;
toQuintEx(gen: IdGenerator): QuintEx;
}
export declare class RuntimeValueVariant extends RuntimeValueBase implements RuntimeValue {
label: string;
value: RuntimeValue;
constructor(label: string, value: RuntimeValue);
hashCode(): number;
toQuintEx(gen: IdGenerator): QuintEx;
}
/**
* A lambda operator as a runtime value. Technically, it should not be a value
* in Quint/TLA+. However, we have to carry lambdas when evaluating higher-order
* operators.
*
* RuntimeValueLambda cannot be compared with other values.
*/
export declare class RuntimeValueLambda extends RuntimeValueBase implements RuntimeValue {
body: EvalFunction;
registers: Register[];
constructor(body: EvalFunction, registers: Register[]);
toQuintEx(gen: IdGenerator): QuintEx;
}