Python runtime library for Dafny, providing essential data structures, type representations, and utility functions for executing Dafny-compiled Python code
—
Exception-driven control flow constructs for implementing Dafny's labeled break/continue statements, tail call optimization, and program halting. These exceptions and context managers enable precise control flow that matches Dafny's semantics.
Exception classes that implement Dafny's control flow constructs through Python's exception mechanism.
@dataclass
class Break(Exception):
target: str
"""
Exception for implementing labeled break statements.
Attributes:
- target: str - The label name to break to
"""
@dataclass
class Continue(Exception):
target: str
"""
Exception for implementing labeled continue statements.
Attributes:
- target: str - The label name to continue to
"""
class TailCall(Exception):
"""
Exception for implementing tail call optimization.
Used to implement tail recursive calls efficiently.
"""
@dataclass
class HaltException(Exception):
message: str
"""
Exception thrown when a Dafny program halts with an error.
Attributes:
- message: str - The halt message describing the error
"""Context managers that properly handle labeled break/continue exceptions and tail calls.
def label(name: str = None):
"""
Context manager for handling labeled breaks and tail calls.
Parameters:
- name: str, optional - Label name for targeted breaks
Usage:
with label("outer_loop"):
# code that may raise Break("outer_loop") or TailCall
pass
"""
def c_label(name: str = None):
"""
Context manager for handling labeled continues.
Parameters:
- name: str, optional - Label name for targeted continues
Usage:
with c_label("inner_loop"):
# code that may raise Continue("inner_loop")
pass
"""from _dafny import Break, Continue, TailCall, HaltException
# Create control flow exceptions
break_exc = Break("outer_loop")
continue_exc = Continue("inner_loop")
halt_exc = HaltException("Division by zero")
# These would typically be raised within Dafny-generated code
# raise break_exc # Would break to "outer_loop" label
# raise continue_exc # Would continue at "inner_loop" label
# raise halt_exc # Would halt program with error messagefrom _dafny import Break, Continue, label, c_label
# Simulating nested loops with labeled break
try:
with label("outer"):
for i in range(10):
with label("inner"):
for j in range(10):
if i * j > 20:
raise Break("outer") # Break out of both loops
if j == 5:
raise Break("inner") # Break only inner loop
print(f"i={i}, j={j}")
except Break:
pass # Break was handled by appropriate label context
# Labeled continue example
try:
with c_label("outer"):
for i in range(5):
with c_label("inner"):
for j in range(5):
if j == 2:
raise Continue("inner") # Continue inner loop
if i == 3:
raise Continue("outer") # Continue outer loop
print(f"Processing i={i}, j={j}")
except Continue:
pass # Continue was handled by appropriate label contextfrom _dafny import TailCall, label
def factorial_helper(n, acc):
"""Tail-recursive factorial implementation."""
if n <= 1:
return acc
else:
# In Dafny, this would be a tail call
# The TailCall exception enables optimization
raise TailCall() # Signal tail call optimization needed
def factorial(n):
"""Factorial with tail call optimization."""
acc = 1
while True:
try:
with label(): # Unnamed label catches TailCall
if n <= 1:
return acc
acc = acc * n
n = n - 1
raise TailCall() # Tail call optimization
except TailCall:
continue # Loop continues for tail callfrom _dafny import HaltException
def safe_divide(a, b):
"""Division with Dafny-style halting on error."""
if b == 0:
raise HaltException("Division by zero is not allowed")
return a / b
# Usage that might halt
try:
result = safe_divide(10, 0)
except HaltException as e:
print(f"Program halted: {e.message}")
# In Dafny runtime, this would terminate the programfrom _dafny import Break, Continue, HaltException, label, c_label
def complex_search(matrix, target):
"""
Complex search with multiple control flow constructs.
Demonstrates nested labels and different exception types.
"""
try:
with label("search_complete"):
for row_idx in range(len(matrix)):
with c_label("next_row"):
with label("row_complete"):
for col_idx in range(len(matrix[row_idx])):
with c_label("next_col"):
value = matrix[row_idx][col_idx]
if value is None:
raise HaltException("Null value encountered in matrix")
if value == target:
print(f"Found {target} at ({row_idx}, {col_idx})")
raise Break("search_complete")
if value < 0:
print(f"Skipping negative value at ({row_idx}, {col_idx})")
raise Continue("next_col")
if value > 100:
print(f"Large value at ({row_idx}, {col_idx}), skipping row")
raise Continue("next_row")
print(f"Checking ({row_idx}, {col_idx}): {value}")
print(f"Completed row {row_idx}")
print("Search completed - target not found")
except HaltException as e:
print(f"Search halted: {e.message}")
return None
except (Break, Continue):
# These should have been caught by their respective labels
print("Uncaught control flow exception")
return None
# Example usage
test_matrix = [
[1, 2, 3, 4],
[5, -1, 7, 8],
[9, 10, 50, 12]
]
complex_search(test_matrix, 50) # Will find target
complex_search(test_matrix, 999) # Will complete search without findingThese control flow constructs are primarily used by Dafny-generated Python code rather than being called directly. They enable:
The exception-based approach allows Dafny's control flow semantics to be preserved in Python while maintaining performance and clarity in the generated code.
Install with Tessl CLI
npx tessl i tessl/pypi-dafnyruntimepython