UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

144 lines (143 loc) 5.38 kB
import { QuintApp } from '../ir/quintIr'; import { Rng } from './../rng'; import { Either } from '@sweet-monads/either'; import { QuintError } from '../quintError'; import { RuntimeValue } from './impl/runtimeValue'; /** * A snapshot of how a single operator (e.g., an action) was executed. * In stack-based languages, this usually corresponds to a stack frame. * In Quint, it is simply the applied operator and the arguments. * * In addition to that, we use a top-level execution frame to represent * the execution history: * * - `subframes` stores the executed actions, e.g., `init` and `step` * - `result` stores the result of the overall computation: * just(false), just(true), or none(). * - `args` stores the visited states. Note that |subframes| = |args|. * - `app` is a dummy operator, e.g., an empty record. */ export interface ExecutionFrame { /** * The operator that was applied in this frame. */ app: QuintApp; /** * The actual runtime values that were used in the call. */ args: RuntimeValue[]; /** * An optional result of the execution. */ result: Either<QuintError, RuntimeValue>; /** * The frames of the operators that were called by this operator. */ subframes: ExecutionFrame[]; } export interface Trace { frame: ExecutionFrame; seed: bigint; } /** * A listener that receives events in the course of Quint evaluation. * This listener may be used to collect a trace, or to record profiling data. */ export interface ExecutionListener { /** * This callback is called whenever a user-defined operator is called. * * @param app operator application in Quint IR */ onUserOperatorCall(app: QuintApp): void; /** * This callback is called whenever a user-defined operator returns * from its evaluation. Note that it is the runtime's obligation to * balance the Call and Return events. * * @param app operator application in Quint IR * @param args the actual arguments obtained in evaluation * @param result optional result of the evaluation */ onUserOperatorReturn(app: QuintApp, args: RuntimeValue[], result: Either<QuintError, RuntimeValue>): void; /** * This callback is called *before* one of the arguments of `any {...}` * is evaluated. This is a very important call, as it introduces a * branching point in the execution. * * @param anyExpr the expression `any { ... }` that contains the option * @param position the position of the option in `anyExpr.args` */ onAnyOptionCall(anyExpr: QuintApp, position: number): void; /** * This callback is called *after* one of the arguments of `any {...}` * is evaluated. Note that it is the runtime's * obligation to balance the Call and Return events. * * @param anyExpr the expression `any { ... }` that contains the option * @param position the position of the option in `anyExpr.args` */ onAnyOptionReturn(anyExpr: QuintApp, position: number): void; /** * This callback is called when leaving `any { A_1, ..., A_n }`. * It instructs the listener to discard the top `noptions` records * except the one in the `choice` position. * * @param noptions the number of translated options, that is, `n`. * @param choice is a number between -1 and n (exclusive), * where -1 means that no option was chosen (discard all). */ onAnyReturn(noptions: number, choice: number): void; /** * This callback is called whenever an execution proceeds to the next state, * e.g., once A has been evaluated in A.then(B). * @param oldState the old state that is about to be discarded * @param newState the new state, from which the execution continues */ onNextState(oldState: RuntimeValue, newState: RuntimeValue): void; /** * This callback is called when a new run is executed, * e.g., when multiple runs are executed in the simulator. */ onRunCall(): void; /** * This callback is called when the previous run has finished. * * @param outcome whether the run has: * - failed, that is, `none()`, * - finished after finding no violation, `just(mkBool(true))`, * - finished after finding a violation, `just(mkBool(false))` * @param trace the array of produced states (each state is a record) */ onRunReturn(outcome: Either<QuintError, RuntimeValue>, trace: RuntimeValue[]): void; } /** * An implementation of ExecutionListener that does nothing. */ export declare const noExecutionListener: ExecutionListener; /** * The interface of a trace recorder that records the best trace. */ export interface TraceRecorder extends ExecutionListener { /** * The verbosity level used by the recorder (mutable). */ verbosityLevel: number; /** * The random number generator used by the recorder (mutable). */ rng: Rng; /** * The current frame that is being recorded. */ currentFrame: ExecutionFrame; /** * Clear the recorded trace */ clear: () => void; /** * The best recorded traces. */ bestTraces: Trace[]; } export declare const newTraceRecorder: (verbosityLevel: number, rng: Rng, tracesToRecord?: number) => TraceRecorder;