braket.default_simulator.openqasm.program_context module

class braket.default_simulator.openqasm.program_context.Table(title: str)[source]

Bases: object

Utility class for storing and displaying items.

items() Iterable[tuple[str, Any]][source]
class braket.default_simulator.openqasm.program_context.QubitTable[source]

Bases: Table

get_by_identifier(identifier: Identifier | IndexedIdentifier) tuple[int][source]
get_by_identifier(identifier: IndexedIdentifier) tuple[int]

Convenience method to get an element with a possibly indexed identifier.

get_qubit_size(identifier: Identifier | IndexedIdentifier) int[source]
class braket.default_simulator.openqasm.program_context.ScopedTable(title)[source]

Bases: Table

Scoped version of Table

push_scope() None[source]
pop_scope() None[source]
property in_global_scope
property current_scope: dict[str, Any]
get_scope(key: str) dict[str, Any][source]

Get the smallest scope containing the given key

items() Iterable[tuple[str, Any]][source]
class braket.default_simulator.openqasm.program_context.SymbolTable[source]

Bases: ScopedTable

Scoped table used to map names to types.

class Symbol(symbol_type: ClassicalType | BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral, const: bool = False)[source]

Bases: object

add_symbol(name: str, symbol_type: ClassicalType | BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral | type[Identifier], const: bool = False) None[source]

Add a symbol to the symbol table.

Parameters:
  • name (str) – Name of the symbol.

  • symbol_type (ClassicalType | LiteralType | type[Identifier]) – Type of the symbol. Symbols can have a literal type when they are a numeric argument to a gate or an integer literal loop variable.

  • const (bool) – Whether the variable is immutable.

get_symbol(name: str) Symbol[source]

Get a symbol from the symbol table by name.

Parameters:

name (str) – Name of the symbol.

Returns:

Symbol – The symbol object.

get_type(name: str) ClassicalType | type[BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral][source]

Get the type of a symbol by name.

Parameters:

name (str) – Name of the symbol.

Returns:

ClassicalType | type[LiteralType] – The type of the symbol.

get_const(name: str) bool[source]

Get const status of a symbol by name.

Parameters:

name (str) – Name of the symbol.

Returns:

bool – Whether the symbol is a const symbol.

class braket.default_simulator.openqasm.program_context.VariableTable[source]

Bases: ScopedTable

Scoped table used store values for symbols. This implements the classical memory for the Interpreter.

add_variable(name: str, value: Any) None[source]
get_value(name: str) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]
get_value_by_identifier(identifier: Identifier, type_width: IntegerLiteral | None = None) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]
get_value_by_identifier(identifier: IndexedIdentifier, type_width: IntegerLiteral | None = None) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral

Convenience method to get value with a possibly indexed identifier.

update_value(name: str, value: Any, var_type: ClassicalType, indices: list[DiscreteSet | list[Expression | RangeDefinition]] | None = None) None[source]

Update value of a variable, optionally providing an index

is_initalized(name: str) bool[source]

Determine whether a declared variable is initialized

class braket.default_simulator.openqasm.program_context.GateTable[source]

Bases: ScopedTable

Scoped table to implement gates.

add_gate(name: str, definition: QuantumGateDefinition) None[source]
get_gate_definition(name: str) QuantumGateDefinition[source]
class braket.default_simulator.openqasm.program_context.SubroutineTable[source]

Bases: ScopedTable

Scoped table to implement subroutines.

add_subroutine(name: str, definition: SubroutineDefinition) None[source]
get_subroutine_definition(name: str) SubroutineDefinition[source]
class braket.default_simulator.openqasm.program_context.ScopeManager(context: AbstractProgramContext)[source]

Bases: object

Allows AbstractProgramContext subclasses to manage scope with the with keyword.

class braket.default_simulator.openqasm.program_context.AbstractProgramContext[source]

Bases: ABC

Interpreter state.

Symbol table - symbols in scope Variable table - variable values Gate table - gate definitions Subroutine table - subroutine definitions Qubit mapping - mapping from logical qubits to qubit indices

Circuit - IR build to hand off to the simulator

abstract property circuit

The circuit being built in this context.

property is_branched: bool

Whether mid-circuit measurement branching has occurred.

property supports_midcircuit_measurement: bool

Whether this context supports mid-circuit measurement branching.

property active_paths: list[SimulationPath]

The currently active simulation paths.

load_inputs(inputs: dict[str, Any]) None[source]

Load inputs for the circuit

Parameters:

inputs (dict[str, Any]) – A dictionary containing the inputs to be loaded

parse_pragma(pragma_body: str)[source]

Parse pragma

Parameters:

pragma_body (str) – The body of the pragma statement.

declare_variable(name: str, symbol_type: type[BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral | Identifier] | ClassicalType, value: Any = None, const: bool = False) None[source]

Declare variable in current scope

Parameters:
  • name (str) – The name of the variable

  • symbol_type (ClassicalType | type[LiteralType] | type[Identifier]) – The type of the variable.

  • value (Any) – The initial value of the variable . Defaults to None.

  • const (bool) – Flag indicating if the variable is constant. Defaults to False.

declare_qubit_alias(name: str, value: Identifier) None[source]

Declare qubit alias in current scope

Parameters:
  • name (str) – The name of the qubit alias.

  • value (Identifier) – The identifier representing the qubit

enter_scope() ScopeManager[source]

Allows pushing/popping scope with indentation and the with keyword.

Usage: # inside the original scope … with program_context.enter_scope():

# inside a new scope …

# exited new scope, back in the original scope

push_scope() None[source]

Enter a new scope

pop_scope() None[source]

Exit current scope

property in_global_scope
get_type(name: str) ClassicalType | type[BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral][source]

Get symbol type by name

Parameters:

name (str) – The name of the symbol.

Returns:

ClassicalType | type[LiteralType] – The type of the symbol.

get_const(name: str) bool[source]

Get whether a symbol is const by name”

Parameters:

name (str) – The name of the symbol.

Returns:

bool – True of the symbol os const, False otherwise.

get_value(name: str) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]

Get value of a variable by name

Parameters:

name (str) – The name of the variable.

Returns:

LiteralType – The value of the variable.

Raises:

KeyError – If the variable is not found.

get_value_by_identifier(identifier: Identifier | IndexedIdentifier) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]

Get value of a variable by identifier

Parameters:

identifier (Identifier | IndexedIdentifier) – The identifier of the variable.

Returns:

LiteralType – The value of the variable.

Raises:

KeyError – If the variable is not found.

is_initialized(name: str) bool[source]

Check whether variable is initialized by name

Parameters:

name (str) – The name of the variable.

Returns:

bool – True if the variable is initialized, False otherwise.

update_value(variable: Identifier | IndexedIdentifier, value: Any) None[source]

Update value by identifier, possible only a sub-index of a variable

Parameters:
add_qubits(name: str, num_qubits: int | None = 1) None[source]

Allocate additional qubits for the circuit

Parameters:
  • name (str) – The name of the qubit register

  • num_qubits (int | None) – The number of qubits to allocate. Default is 1.

get_qubits(qubits: Identifier | IndexedIdentifier) tuple[int][source]

Get qubit indices from a qubit identifier, possibly referring to a sub-index of a qubit register

Parameters:

qubits (Identifier | IndexedIdentifier) – The identifier of the qubits.

Returns:

tuple[int] – The indices of the qubits.

Raises:

KeyError – If the qubit identifier is not found.

add_gate(name: str, definition: QuantumGateDefinition) None[source]

Add a gate definition

Parameters:
  • name (str) – The name of the gate.

  • definition (QuantumGateDefinition) – The definition of the gate.

get_gate_definition(name: str) QuantumGateDefinition[source]

Get a gate definition by name

Parameters:

name (str) – The name of the gate.

Returns:

QuantumGateDefinition – The definition of the gate.

Raises:

ValueError – If the gate is not defined.

is_user_defined_gate(name: str) bool[source]

Check whether the gate is user-defined gate

Parameters:

name (str) – The name of the gate.

Returns:

bool – True of the gate is user-defined, False otherwise.

abstractmethod is_builtin_gate(name: str) bool[source]

Abstract method to check if the gate with the given name is currently in scope as a built-in Braket gate. :param name: name of the built-in Braket gate to be checked :type name: str

Returns:

bool – True if the gate is a built-in gate, False otherwise.

add_subroutine(name: str, definition: SubroutineDefinition) None[source]

Add a subroutine definition

Parameters:
  • name (str) – The name of the subroutine.

  • definition (SubroutineDefinition) – The definition of the subroutine.

get_subroutine_definition(name: str) SubroutineDefinition[source]

Get a subroutine definition by name

Parameters:

name (str) – The name of the subroutine.

Returns:

SubroutineDefinition – The definition of the subroutine.

Raises:

NameError – If the subroutine with the give name is not defined.

add_result(result: Amplitude | Expectation | Probability | Sample | StateVector | DensityMatrix | Variance | AdjointGradient) None[source]

Abstract method to add result type to the circuit

Parameters:

result (Results) – The result object representing the measurement results

add_phase(phase: FloatLiteral, qubits: list[Identifier | IndexedIdentifier] | None = None) None[source]

Add quantum phase instruction to the circuit

abstractmethod add_phase_instruction(target, phase_value)[source]

Abstract method to add phase instruction to the circuit

Parameters:
  • target (int or list[int]) – The target qubit or qubits to which the phase instruction is applied

  • phase_value (float) – The phase value to be applied

add_builtin_gate(gate_name: str, parameters: list[FloatLiteral], qubits: list[Identifier | IndexedIdentifier], modifiers: list[QuantumGateModifier] | None = None) None[source]

Add a builtin gate instruction to the circuit

Parameters:
  • gate_name (str) – The name of the built-in gate.

  • parameters (list[FloatLiteral]) – The list of the gate parameters.

  • qubits (list[Identifier | IndexedIdentifier]) – The list of qubits the gate acts on.

  • modifiers (list[QuantumGateModifier] | None) – The list of gate modifiers (optional).

handle_parameter_value(value: float | Expr) Any[source]

Convert parameter value to required format. Default conversion is noop. :param value: Value of the parameter :type value: float | Expr

abstractmethod add_gate_instruction(gate_name: str, target: tuple[int, ...], params, ctrl_modifiers: list[int], power: int)[source]

Abstract method to add Braket gate to the circuit. :param gate_name: name of the built-in Braket gate. :type gate_name: str :param target: control_qubits + target_qubits. :type target: tuple[int] :param ctrl_modifiers: Quantum state on which to control the

operation. Must be a binary sequence of same length as number of qubits in control-qubits in target. For example “0101”, [0, 1, 0, 1], 5 all represent controlling on qubits 0 and 2 being in the |0⟩ state and qubits 1 and 3 being in the |1⟩ state.

Parameters:

power (float) – Integer or fractional power to raise the gate to.

add_custom_unitary(unitary: ndarray, target: tuple[int, ...]) None[source]

Abstract method to add a custom Unitary instruction to the circuit :param unitary: unitary matrix :type unitary: np.ndarray :param target: control_qubits + target_qubits :type target: tuple[int, …]

add_noise_instruction(noise_instruction: str, target: list[int], probabilities: list[float])[source]

Abstract method to add a noise instruction to the circuit

Parameters:
  • noise_instruction (str) – The name of the noise operation

  • target (list[int]) – The target qubit or qubits to which the noise operation is applied.

  • probabilities (list[float]) – The probabilities associated with each possible outcome of the noise operation.

add_kraus_instruction(matrices: list[ndarray], target: list[int])[source]

Abstract method to add a Kraus instruction to the circuit

Parameters:
  • matrices (list[ndarray]) – The matrices defining the Kraus operation

  • target (list[int]) – The target qubit or qubits to which the Kraus operation is applied.

add_measure(target: tuple[int], classical_targets: Iterable[int] | None = None, **kwargs) None[source]

Add a measurement to the circuit.

Parameters:
  • target (tuple[int]) – The qubit indices to measure.

  • classical_targets (Iterable[int] | None) – The classical bit indices to write results into for the circuit’s final output. Used by the simulation infrastructure for bit-level bookkeeping.

add_barrier(target: list[int] | None = None) None[source]

Abstract method to add a barrier instruction to the circuit. By defaul barrier is ignored. Barriers act as no-ops in simulation.

Parameters:

target (list[int] | None) – The target qubits for the barrier. If None, applies to all qubits in the circuit.

add_reset(target: list[int]) None[source]

Add a reset instruction to the circuit.

Resets the specified qubits to the |0⟩ state.

Parameters:

target (list[int]) – The target qubits to reset.

add_verbatim_marker(marker) None[source]

Add verbatim markers

is_mcm_dependent(expression) bool[source]

Whether an expression depends on any mid-circuit measurement result.

An expression is MCM-dependent when any identifier it references resolves (via lexical scoping) to a variable that was produced by a mid-circuit measurement. _mcm_dependent_scopes is populated by mark_mcm_dependent (for measurement destinations) and track_mcm_dependency (for classical assignments that transfer MCM-dependency from the rvalue to the lvalue); this check walks each referenced identifier’s scope stack and stops at the scope where the name is declared.

Used by the Interpreter to decide whether control flow and classical assignments need per-path evaluation. Expressions that are not MCM-dependent are evaluated once and eagerly, matching non-MCM behavior.

Parameters:

expression – The AST expression to check.

Returns:

bool – True if the expression depends on an MCM result.

track_mcm_dependency(lvalue_name: str, rvalue) None[source]

Propagate MCM-dependency through a classical assignment.

If the rvalue references any MCM-dependent variable, the lvalue becomes MCM-dependent (recorded in the scope where the variable was declared). Otherwise, any previous MCM-dependency on the lvalue is cleared from its declaration scope. Subclasses that track per-path state (e.g., branched execution) should override this to extend the criterion.

Parameters:
  • lvalue_name – The name of the variable being assigned.

  • rvalue – The AST expression being evaluated as the rvalue.

mark_mcm_dependent(name: str) None[source]

Unconditionally mark name as MCM-dependent in its declaration scope.

Called by the Interpreter when a variable is assigned a value that is inherently MCM-dependent (e.g. the result of measure).

evaluate_condition(condition)[source]

Evaluate a branching condition for mid-circuit measurement contexts.

Called by the Interpreter when supports_midcircuit_measurement is True. Implementations are generators that yield True (visit the if-block) or False (visit the else-block) for each group of simulation paths. The context manages path state between yields; the Interpreter decides which block to visit based on the yielded boolean.

Parameters:

condition – The AST condition expression.

Yields:

bool

True to visit the if-block, False to visit the

else-block.

evaluate_for_range(set_declaration, loop_var: str, loop_type)[source]

Set up each iteration of a for-loop for mid-circuit measurement.

Called by the Interpreter when supports_midcircuit_measurement is True. Implementations are generators that yield once per loop iteration after setting up the loop variable for the current iteration value. The Interpreter visits the loop body after each yield.

Parameters:
  • set_declaration – The AST range or discrete set expression.

  • loop_var (str) – The loop variable name.

  • loop_type – The loop variable type.

Yields:

None – Signals the Interpreter to visit the loop body.

evaluate_while_condition(condition)[source]

Evaluate a while-loop condition for mid-circuit measurement.

Called by the Interpreter when supports_midcircuit_measurement is True. Implementations are generators that yield True when the loop should continue (at least one path has a true condition). The Interpreter visits the loop body after each True yield. The generator stops when no paths have a true condition.

Parameters:

condition – The AST condition expression.

Yields:

boolTrue to continue looping.

iter_classical_scopes(expression)[source]

Set up iterations for classical expression evaluation in MCM contexts.

Called by the Interpreter when supports_midcircuit_measurement is True around operations that evaluate classical expressions which may depend on mid-circuit measurement results (classical assignments, variable declarations with initializers, etc.). Implementations are generators that yield once for each scope in which the expression should be independently evaluated (e.g., once per active simulation path).

Parameters:

expression – The AST expression being evaluated. Subclasses may use it to flush pending side effects (e.g., mid-circuit measurements) referenced by the expression before iteration.

Yields:

None – Signals the Interpreter to evaluate the expression once.

handle_loop_continue()[source]

Called by the interpreter when a continue statement is encountered in a loop body.

Default behavior: no-op (continue to next iteration naturally). Override to raise NotImplementedError if continue is not supported.

handle_loop_break()[source]

Called by the interpreter when a break statement is encountered in a loop body.

Default behavior: no-op (break out of the loop naturally). Override to raise NotImplementedError if break is not supported.

class braket.default_simulator.openqasm.program_context.ProgramContext(circuit: Circuit | None = None, simulator: BaseLocalSimulator | None = None)[source]

Bases: AbstractProgramContext

Parameters:
  • circuit (Circuit | None) – A partially-built circuit to continue building with this context. Default: None.

  • simulator (BaseLocalSimulator | None) – The BaseLocalSimulator responsible for computing measurement probabilities when branching occurs. Default: None, in which case branching will raise at measurement time.

property circuit

The circuit being built in this context.

property is_branched: bool

Whether mid-circuit measurement branching has occurred.

property supports_midcircuit_measurement: bool

Whether this context supports mid-circuit measurement branching.

property active_paths: list[SimulationPath]

The currently active simulation paths.

declare_variable(name: str, symbol_type: type[BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral | Identifier] | ClassicalType, value: Any = None, const: bool = False) None[source]

Declare variable, storing per-path when branched.

When branched, the symbol table is still updated (for type lookups), but the variable value is stored as a FramedVariable on each active path instead of in the shared variable table.

update_value(variable: Identifier | IndexedIdentifier, value: Any) None[source]

Update variable value, operating per-path when branched.

When branched, updates the variable on all active paths. Indexed updates (e.g., arr[0] = 5) are handled by reading the current value from the path, applying the index update, and writing back.

get_value(name: str) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]

Get variable value, reading from the first active path when branched.

get_value_by_identifier(identifier: Identifier | IndexedIdentifier) BooleanLiteral | IntegerLiteral | FloatLiteral | ArrayLiteral | BitstringLiteral[source]

Get variable value by identifier, reading from the first active path when branched.

is_builtin_gate(name: str) bool[source]

Abstract method to check if the gate with the given name is currently in scope as a built-in Braket gate. :param name: name of the built-in Braket gate to be checked :type name: str

Returns:

bool – True if the gate is a built-in gate, False otherwise.

is_initialized(name: str) bool[source]

Check whether variable is initialized, including per-path variables when branched.

add_phase_instruction(target: tuple[int], phase_value: int)[source]

Abstract method to add phase instruction to the circuit

Parameters:
  • target (int or list[int]) – The target qubit or qubits to which the phase instruction is applied

  • phase_value (float) – The phase value to be applied

add_gate_instruction(gate_name: str, target: tuple[int, ...], params, ctrl_modifiers: list[int], power: int)[source]

Abstract method to add Braket gate to the circuit. :param gate_name: name of the built-in Braket gate. :type gate_name: str :param target: control_qubits + target_qubits. :type target: tuple[int] :param ctrl_modifiers: Quantum state on which to control the

operation. Must be a binary sequence of same length as number of qubits in control-qubits in target. For example “0101”, [0, 1, 0, 1], 5 all represent controlling on qubits 0 and 2 being in the |0⟩ state and qubits 1 and 3 being in the |1⟩ state.

Parameters:

power (float) – Integer or fractional power to raise the gate to.

add_custom_unitary(unitary: ndarray, target: tuple[int, ...]) None[source]

Abstract method to add a custom Unitary instruction to the circuit :param unitary: unitary matrix :type unitary: np.ndarray :param target: control_qubits + target_qubits :type target: tuple[int, …]

add_noise_instruction(noise_instruction: str, target: list[int], probabilities: list[float])[source]

Abstract method to add a noise instruction to the circuit

Parameters:
  • noise_instruction (str) – The name of the noise operation

  • target (list[int]) – The target qubit or qubits to which the noise operation is applied.

  • probabilities (list[float]) – The probabilities associated with each possible outcome of the noise operation.

add_kraus_instruction(matrices: list[ndarray], target: list[int])[source]

Abstract method to add a Kraus instruction to the circuit

Parameters:
  • matrices (list[ndarray]) – The matrices defining the Kraus operation

  • target (list[int]) – The target qubit or qubits to which the Kraus operation is applied.

add_barrier(target: list[int] | None = None) None[source]

Abstract method to add a barrier instruction to the circuit. By defaul barrier is ignored. Barriers act as no-ops in simulation.

Parameters:

target (list[int] | None) – The target qubits for the barrier. If None, applies to all qubits in the circuit.

add_reset(target: list[int]) None[source]

Add a reset instruction to the circuit.

Resets the specified qubits to the |0⟩ state.

Parameters:

target (list[int]) – The target qubits to reset.

add_result(result: Amplitude | Expectation | Probability | Sample | StateVector | DensityMatrix | Variance | AdjointGradient) None[source]

Abstract method to add result type to the circuit

Parameters:

result (Results) – The result object representing the measurement results

add_measure(target: tuple[int], classical_targets: Iterable[int] | None = None, *, classical_destination: Identifier | IndexedIdentifier | None = None) None[source]

Add a measurement, with optional MCM support.

The classical_destination keyword argument is only passed by the Interpreter when supports_midcircuit_measurement is True, so downstream subclasses that override the two-argument base signature are unaffected.

Parameters:
  • target (tuple[int]) – The qubit indices to measure.

  • classical_targets (Iterable[int] | None) – Classical bit indices for the circuit’s final output bookkeeping.

  • classical_destination (Identifier | IndexedIdentifier | None) – The AST node for the classical variable being assigned (e.g. b in b = measure q[0]). When provided, the measurement is treated as a mid-circuit measurement candidate.

track_mcm_dependency(lvalue_name: str, rvalue) None[source]

Extend the base implementation with branched-subset detection.

The lvalue becomes MCM-dependent if the base criterion holds or execution has branched into a subset of paths (making the assignment per-path).

iter_classical_scopes(expression)[source]

Yield once per active path for classical expression evaluation.

Before iteration, flushes any pending mid-circuit measurements referenced by expression so that branching happens before the iteration count is decided. When multiple paths are active, yields once per path after setting it as the sole active path, so that expression evaluation reads from that path’s variable state. Restores all paths after iteration.

Parameters:

expression – The AST expression being evaluated. Any identifiers it references that match pending MCMs will be flushed before iteration.

Yields:

None – Signals the Interpreter to evaluate the expression.

evaluate_condition(condition)[source]

Evaluate a branching condition, yielding per-path branch decisions.

Yields True (visit if-block) or False (visit else-block) for each group of simulation paths. Manages path state and frames between yields.

Only called by the Interpreter when the condition is MCM-dependent, which implies either an active branched state or a pending MCM that will transition to branched on entry.

Parameters:

condition – The AST condition expression.

Yields:

bool – Branch decision for the current path group.

evaluate_for_range(set_declaration, loop_var: str, loop_type)[source]

Set up each for-loop iteration, yielding once per iteration.

Evaluates the range/set per-path (different paths may see different values because MCM results can differ). Yields once per iteration step, with the active-path set narrowed to exactly those paths that still have a value for the current step.

Only called by the Interpreter when the range/set is MCM-dependent, which implies either an active branched state or a pending MCM that will transition to branched on entry.

Parameters:
  • set_declaration – The AST range or discrete set expression.

  • loop_var (str) – The loop variable name.

  • loop_type – The loop variable type.

Yields:

None – Signals the Interpreter to visit the loop body.

evaluate_while_condition(condition)[source]

Evaluate a while-loop condition, yielding True per iteration.

Evaluates the condition per-path each iteration. Yields True when at least one path has a true condition. Stops when no paths remain true.

Only called by the Interpreter when the condition is MCM-dependent, which implies either an active branched state or a pending MCM that will transition to branched on entry.

Parameters:

condition – The AST condition expression.

Yields:

boolTrue to continue looping.