UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

355 lines (354 loc) 13.6 kB
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; }