Checking¶
Validation and type and effect inference for the reference kernel.
checking
¶
Validation and type/effect inference for the QIEC reference kernel.
NEVER
module-attribute
¶
NEVER = ResumptionUse(0, 0)
A computation that cannot invoke the continuation.
ONCE
module-attribute
¶
ONCE = ResumptionUse(1, 1)
A computation that invokes the continuation exactly once.
KernelError
¶
Bases: TypeError
A static QIEC kernel rejection.
Carries a stable diagnostic code alongside its message. The code is attached where the rejection is raised, because only that site knows which condition fired; classifying by message text afterwards is a guess that silently changes whenever the prose is reworded.
| PARAMETER | DESCRIPTION |
|---|---|
message
|
What was rejected, in prose, for a human reader.
TYPE:
|
code
|
A member of the published code set. Defaults to
TYPE:
|
Source code in src/quivers/qiec/checking.py
StaticScope
dataclass
¶
StaticScope(types: tuple[tuple[str, Kind], ...] = (), indices: tuple[tuple[str, IndexSort], ...] = (), effects: tuple[str, ...] = ())
The three disjoint namespaces visible in a declaration body.
| PARAMETER | DESCRIPTION |
|---|---|
types
|
Type binders in scope, each with its kind.
TYPE:
|
indices
|
Index binders in scope, each with its sort.
TYPE:
|
effects
|
Effect binder names in scope.
TYPE:
|
names
property
¶
Every static name bound here, across all three namespaces.
| RETURNS | DESCRIPTION |
|---|---|
frozenset[str]
|
The union of the type, index, and effect binder names. The namespaces are disjoint by construction, so this is what shadowing is tested against. |
extend
¶
extend(telescope: Telescope, *, subject: str) -> StaticScope
Return this scope widened by a telescope's binders.
| PARAMETER | DESCRIPTION |
|---|---|
telescope
|
Binders to add. Each must be a type, index, or effect binder.
TYPE:
|
subject
|
What is being extended, named in any diagnostic so the error points at the declaration rather than at the scope.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
StaticScope
|
A scope carrying the original binders and the new ones. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If a binder is of an unknown class, or if its name is already bound. Shadowing is rejected rather than resolved so a static name always denotes one thing within a declaration. |
Source code in src/quivers/qiec/checking.py
type_kind
¶
type_kind(name: str) -> Kind | None
The kind of a type binder in scope.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The binder name to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Kind or None
|
The binder's kind, or None when |
Source code in src/quivers/qiec/checking.py
index_sort
¶
index_sort(name: str) -> IndexSort | None
The sort of an index binder in scope.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The binder name to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
IndexSort or None
|
The binder's sort, or None when |
Source code in src/quivers/qiec/checking.py
ComputationSignature
dataclass
¶
ComputationSignature(id: ComputationId, name: str, telescope: Telescope, parameters: tuple[TypeExpr, ...], result: TypeExpr, effects: EffectRow)
What a call needs to know about a computation it invokes.
A signature rather than a declaration, and deliberately so: a call resolves against this, not against the callee's body. That is what lets every signature be collected before any body is checked, which in turn makes a forward call and mutual recursion ordinary rather than requiring a forward declaration.
| PARAMETER | DESCRIPTION |
|---|---|
id
|
The declaration's stable identity, which the call carries.
TYPE:
|
name
|
The authored name, used in diagnostics.
TYPE:
|
telescope
|
Static binders the computation takes.
TYPE:
|
parameters
|
Value parameter types, in order, before instantiation.
TYPE:
|
result
|
The result type before instantiation.
TYPE:
|
effects
|
The row the computation performs, before instantiation.
TYPE:
|
KernelRegistry
dataclass
¶
KernelRegistry(families: dict[FamilyId, FamilyDecl] = dict(), constructors: dict[ConstructorId, ConstructorDecl] = dict(), effects: dict[EffectId, EffectDef] = dict(), operations: dict[OperationId, tuple[EffectDef, OperationDef]] = dict(), handlers: dict[HandlerId, HandlerDef] = dict(), type_constructors: dict[TypeId, TypeConstructorRef] = dict(), computations: dict[ComputationId, ComputationSignature] = dict(), instance_names: dict[EffectInstanceId, str] = dict())
Resolved declarations used by the reference checker.
Every table is keyed by stable identity, so a lookup never depends on a display name.
| PARAMETER | DESCRIPTION |
|---|---|
families
|
Indexed data families by identity.
TYPE:
|
constructors
|
Family constructors by identity.
TYPE:
|
effects
|
Effect interfaces by identity. |
operations
|
Each operation by identity, paired with the interface declaring it.
TYPE:
|
handlers
|
Handler declarations by identity.
TYPE:
|
type_constructors
|
Type constructors by identity, recording the telescope each is known with.
TYPE:
|
computations
|
Named computation signatures by identity.
TYPE:
|
instance_names
|
The source name of each lexical effect instance, for rendering rows in diagnostics.
TYPE:
|
validate_static
¶
validate_static(term: StaticArgument, scope: StaticScope | None = None) -> None
Validate a static term against every declaration known here.
| PARAMETER | DESCRIPTION |
|---|---|
term
|
The static term to check.
TYPE:
|
scope
|
Binders in scope at the term's position. None means the empty scope, so any variable reference is out of scope.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the term is ill-kinded, references an unbound static variable, or applies a known declaration wrongly. |
Source code in src/quivers/qiec/checking.py
validate_type
¶
validate_type(type_: TypeExpr, scope: StaticScope | None = None) -> None
Validate a value type against every declaration known here.
| PARAMETER | DESCRIPTION |
|---|---|
type_
|
The value type to check.
TYPE:
|
scope
|
Binders in scope at the type's position. None means the empty scope.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the type is ill-kinded or references an unbound variable. |
Source code in src/quivers/qiec/checking.py
validate_effect_row
¶
validate_effect_row(row: EffectRow) -> None
Validate all concrete interface applications in an effect row.
| PARAMETER | DESCRIPTION |
|---|---|
row
|
The row whose entries to check. An open tail carries no application and so is not checked here.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If an entry applies its interface wrongly. |
Source code in src/quivers/qiec/checking.py
validate_computation_type
¶
validate_computation_type(type_: ComputationType) -> None
Validate both strata of a computation type.
| PARAMETER | DESCRIPTION |
|---|---|
type_
|
The computation type whose effect row and result type to check.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If either stratum is ill-formed. |
Source code in src/quivers/qiec/checking.py
register_family
¶
register_family(family: FamilyDecl) -> None
Record an indexed family declaration.
| PARAMETER | DESCRIPTION |
|---|---|
family
|
The family to register, with its uniform parameters and its refinable indices.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If a family with this identity is already registered, if two of its binders share a name, or if its type constructor disagrees with one already recorded. |
Source code in src/quivers/qiec/checking.py
register_constructor
¶
register_constructor(constructor: ConstructorDecl) -> None
Record a constructor against the family that declares it.
| PARAMETER | DESCRIPTION |
|---|---|
constructor
|
The constructor to register. Its family must already be registered and must list this constructor.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the constructor is already registered, if its family is unknown or does not declare it, if it returns the wrong number of result indices, if its telescope shadows a family binder, or if a field type or result index is ill-formed. |
Source code in src/quivers/qiec/checking.py
register_effect
¶
register_effect(effect: EffectDef) -> None
Record an effect interface and index its operations.
Each operation's signature is checked in a scope carrying the interface binders and then its own, and may mention the interface being declared.
| PARAMETER | DESCRIPTION |
|---|---|
effect
|
The interface to register.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the interface or one of its operations is already registered, if a binder is shadowed, or if an argument or result type is ill-formed. |
Source code in src/quivers/qiec/checking.py
register_handler
¶
register_handler(handler: HandlerDef) -> None
Record a handler against the interface it handles.
Coverage is checked here rather than at construction, because it is a claim about the interface's operations and only the registry knows those.
| PARAMETER | DESCRIPTION |
|---|---|
handler
|
The handler signature to register.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the handler is already registered, if its telescope shadows a binder, if its input, output, or introduced row is ill-formed, if the interface it names is unknown or wrongly applied, if a clause covers an operation the interface does not declare, or if the handler claims totality while leaving an operation uncovered, or if an authored clause body fails to check, answers the wrong type, or resumes more often than its grade allows. |
Source code in src/quivers/qiec/checking.py
register_computation
¶
register_computation(signature: ComputationSignature) -> None
Record a computation's signature so calls can resolve to it.
Signatures are registered before any body is checked. A call therefore resolves whether the callee is declared above or below it, and mutual recursion needs no forward declaration.
| PARAMETER | DESCRIPTION |
|---|---|
signature
|
The signature to record.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If a computation with this identity is already registered, if its telescope shadows a binder, or if a parameter type, the result type, or the declared row is ill-formed. A duplicate identity is rejected rather than overwritten, since a call carrying that identity would otherwise resolve to whichever declaration happened to register last. |
Source code in src/quivers/qiec/checking.py
computation
¶
computation(computation: ComputationId) -> ComputationSignature
The registered signature with a given identity.
| PARAMETER | DESCRIPTION |
|---|---|
computation
|
The identity to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ComputationSignature
|
The registered signature. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If no computation is registered under that identity, which is how a call to an undeclared name is caught. |
Source code in src/quivers/qiec/checking.py
constructor
¶
constructor(constructor: ConstructorId) -> ConstructorDecl
The registered constructor with a given identity.
| PARAMETER | DESCRIPTION |
|---|---|
constructor
|
The identity to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ConstructorDecl
|
The registered declaration. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If no constructor is registered under that identity. The
underlying |
Source code in src/quivers/qiec/checking.py
handler
¶
handler(handler: HandlerId) -> HandlerDef
The registered handler with a given identity.
| PARAMETER | DESCRIPTION |
|---|---|
handler
|
The identity to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
HandlerDef
|
The registered signature. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If no handler is registered under that identity. |
Source code in src/quivers/qiec/checking.py
operation
¶
operation(operation: OperationId) -> tuple[EffectDef, OperationDef]
The operation with a given identity, and its owning interface.
| PARAMETER | DESCRIPTION |
|---|---|
operation
|
The identity to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[EffectDef, OperationDef]
|
The interface that declares the operation, and the operation itself. The interface comes back too because checking a request needs both. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If no operation is registered under that identity. |
Source code in src/quivers/qiec/checking.py
family_for_type
¶
family_for_type(type_: TypeApplication) -> FamilyDecl
The indexed family a type application is an instance of.
| PARAMETER | DESCRIPTION |
|---|---|
type_
|
The applied type whose family to find.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
FamilyDecl
|
The family whose type constructor the application names. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the application is ill-formed, or names a constructor no registered family declares, which is how a case analysis on a non-family type is rejected. |
Source code in src/quivers/qiec/checking.py
ResumptionType
dataclass
¶
The continuation available inside one handler clause body.
A resumption is not a value and cannot be stored, so it is not a local binding. It is a capability of the position instead: available inside a clause body and nowhere else.
| PARAMETER | DESCRIPTION |
|---|---|
result
|
What the resumed operation supplies, so a
TYPE:
|
answer
|
What resuming produces, which is the clause's own answer type.
TYPE:
|
effects
|
The row resuming performs.
TYPE:
|
CheckContext
dataclass
¶
CheckContext(locals: tuple[Local, ...] = (), givens: tuple[BranchGiven, ...] = (), static_scopes: tuple[StaticScopeId, ...] = (), static_variables: tuple[StaticVariableId, ...] = (), resumption: ResumptionType | None = None)
What is in scope at one point in a term being checked.
| PARAMETER | DESCRIPTION |
|---|---|
locals
|
Value bindings, innermost last.
TYPE:
|
givens
|
Equality evidence introduced by enclosing case branches, which is what makes an index refinement usable in the branch body.
TYPE:
|
static_scopes
|
Static scopes already entered. Tracked so a branch cannot reuse an enclosing scope's identity and silently capture its variables.
TYPE:
|
static_variables
|
Rigid variables currently active, tracked for the same reason.
TYPE:
|
resumption
class-attribute
instance-attribute
¶
resumption: ResumptionType | None = None
The continuation, when checking a handler clause body.
None everywhere else, which is what makes resume outside a
clause a checker error rather than a term with no meaning.
extend
¶
extend(local: Local) -> CheckContext
Return this context with one more value binding.
| PARAMETER | DESCRIPTION |
|---|---|
local
|
The binding to add.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CheckContext
|
A context carrying the new binding innermost. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the name is already bound. Rebinding is rejected rather than shadowed, so a name denotes one value throughout a body. |
Source code in src/quivers/qiec/checking.py
with_givens
¶
with_givens(givens: tuple[BranchGiven, ...]) -> CheckContext
Return this context with further equality evidence in scope.
| PARAMETER | DESCRIPTION |
|---|---|
givens
|
Evidence a case branch introduces by matching a constructor.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CheckContext
|
A context in which that evidence may be appealed to. |
Source code in src/quivers/qiec/checking.py
with_static_scope
¶
with_static_scope(scope: StaticScopeId, variables: tuple[StaticVariableId, ...] = ()) -> CheckContext
Return this context inside a fresh static scope.
| PARAMETER | DESCRIPTION |
|---|---|
scope
|
Identity of the scope being entered.
TYPE:
|
variables
|
Rigid variables the scope introduces.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CheckContext
|
A context recording the scope and its variables as active. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the scope or one of its variables is already active. Reuse would let a branch's rigid variable be confused with an enclosing one, which is what keeps branch refinements from leaking out of the branch. |
Source code in src/quivers/qiec/checking.py
with_resumption
¶
with_resumption(resumption: ResumptionType) -> CheckContext
Return this context inside a handler clause body.
| PARAMETER | DESCRIPTION |
|---|---|
resumption
|
The continuation the clause body may invoke.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
CheckContext
|
A context in which |
Source code in src/quivers/qiec/checking.py
local_type
¶
local_type(name: str) -> TypeExpr | None
The type of a value binding in scope.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The bound name to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TypeExpr or None
|
The binding's type, or None when the name is not bound here.
The innermost binding wins, though |
Source code in src/quivers/qiec/checking.py
given
¶
given(equality: EqualityId) -> BranchGiven | None
The equality evidence with a given identity, if in scope.
| PARAMETER | DESCRIPTION |
|---|---|
equality
|
The identity to resolve.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
BranchGiven or None
|
The evidence, or None when it is not in scope, which is how an appeal to a refinement outside its branch is caught. |
Source code in src/quivers/qiec/checking.py
ResumptionUse
dataclass
¶
How many times a clause body may invoke its continuation.
An interval rather than a count, because a case splits the paths
through a body and different branches may resume different numbers of
times. minimum is what every path does at least, maximum what
some path does at most.
| PARAMETER | DESCRIPTION |
|---|---|
minimum
|
The fewest invocations on any path.
TYPE:
|
maximum
|
The most on any path, or None for unbounded. None is the top of the lattice and is used wherever the analysis cannot bound the count, so an unbounded use is never mistaken for a small one.
TYPE:
|
then
¶
then(other: ResumptionUse) -> ResumptionUse
Sequential composition: both run, so the counts add.
| PARAMETER | DESCRIPTION |
|---|---|
other
|
What runs after this.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ResumptionUse
|
The combined use. Unbounded on either side stays unbounded. |
Source code in src/quivers/qiec/checking.py
join
¶
join(other: ResumptionUse) -> ResumptionUse
Alternation: one path or the other, so the interval widens.
| PARAMETER | DESCRIPTION |
|---|---|
other
|
The alternative path's use.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ResumptionUse
|
The interval covering both. The minimum drops to the smaller because some path now does that few, and the maximum rises to the larger for the same reason. |
Source code in src/quivers/qiec/checking.py
check_static
¶
check_static(term: StaticArgument, scope: StaticScope | None = None, *, registry: KernelRegistry | None = None) -> None
Check the intrinsic kind/sort structure of one static term.
| PARAMETER | DESCRIPTION |
|---|---|
term
|
The static term to check.
TYPE:
|
scope
|
Binders in scope. None checks the term's intrinsic structure alone and permits no variable reference, which is the right mode for a closed declaration.
TYPE:
|
registry
|
Registry to resolve interface applications against. None skips that check, leaving only the structural one.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the term is ill-kinded, references an unbound or wrongly kinded static variable, carries a scoped variable where a declaration is expected, or applies a known interface wrongly. |
Source code in src/quivers/qiec/checking.py
1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 | |
check_type
¶
check_type(type_: TypeExpr, scope: StaticScope | None = None, *, registry: KernelRegistry | None = None) -> None
Check that a type expression is intrinsically well-kinded.
| PARAMETER | DESCRIPTION |
|---|---|
type_
|
The type expression to check.
TYPE:
|
scope
|
Binders in scope, or None for a closed type.
TYPE:
|
registry
|
Registry to resolve interface applications against, or None.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the expression is ill-kinded, or is a well-formed static term that is not a type, such as an index where a type is required. |
Source code in src/quivers/qiec/checking.py
check_evidence
¶
check_evidence(evidence: EqualityEvidence, context: CheckContext) -> EqualityType
Check an appeal to equality evidence and return what it proves.
| PARAMETER | DESCRIPTION |
|---|---|
evidence
|
The appeal being made, either reflexivity or an appeal to a branch given.
TYPE:
|
context
|
Scope the appeal is made in, which decides whether a branch given is still available.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
EqualityType
|
The equality the evidence establishes. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the stated equality is ill-kinded, if reflexivity is claimed between unequal endpoints, if a branch given is appealed to outside its branch or with an equality other than the one it carries, or if the evidence is of an unknown class. |
Source code in src/quivers/qiec/checking.py
infer_value
¶
infer_value(value: Value, registry: KernelRegistry, context: CheckContext = CheckContext()) -> TypeExpr
Infer the type of a pure value term.
| PARAMETER | DESCRIPTION |
|---|---|
value
|
The value to check.
TYPE:
|
registry
|
Declarations the value's types are resolved against.
TYPE:
|
context
|
Bindings and evidence in scope. The default empty context suits a closed value.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TypeExpr
|
The inferred type. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If a local is unbound or carries a type other than the one the term claims, if a literal's value does not inhabit its type, if a constructor is applied wrongly, if equality evidence is forged or out of scope, or if an inferred type mentions a rigid variable that escapes its branch. |
Source code in src/quivers/qiec/checking.py
2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 | |
check_request
¶
check_request(request: EffectRequest, registry: KernelRegistry, context: CheckContext) -> tuple[EffectRef, TypeExpr]
Check one effect request and report what performing it yields.
| PARAMETER | DESCRIPTION |
|---|---|
request
|
The request to check, naming an instance, an interface application, an operation, and the arguments it carries.
TYPE:
|
registry
|
Declarations the request is resolved against.
TYPE:
|
context
|
Scope the request is made in.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
tuple[EffectRef, TypeExpr]
|
The interface application the request performs, and the type resuming it supplies. The interface comes back because the caller needs it to build the row this request adds to. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the operation is unknown, if the named interface does not own it, if the static or value arguments do not match the operation's signature, if the declared result type disagrees with the instantiated one, or if any part mentions a rigid variable out of scope. |
Source code in src/quivers/qiec/checking.py
2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 | |
infer_computation
¶
infer_computation(computation: Computation, registry: KernelRegistry, context: CheckContext = CheckContext()) -> ComputationType
Infer the result type and effect row of a computation.
This is the kernel's entry point for checking effectful code. The
row it returns is what remains unhandled: a Handle discharges its
instance, so a fully handled computation comes back with the empty
row.
| PARAMETER | DESCRIPTION |
|---|---|
computation
|
The term to check.
TYPE:
|
registry
|
Declarations the term is resolved against.
TYPE:
|
context
|
Bindings and evidence in scope. The default empty context suits a closed computation.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ComputationType
|
The result type paired with the effects still outstanding. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If two case branches share a static scope, if a request, value, or branch fails to check, if a handler's interface does not match the instance it discharges, if branch types or rows fail to unify, or if a rigid variable escapes the branch that introduced it. |
Source code in src/quivers/qiec/checking.py
resumption_use
¶
resumption_use(computation: Computation) -> ResumptionUse
Count the continuation invocations along the paths of a body.
A resume is lexical to the clause that encloses it, so a call
contributes nothing: the callee has no access to this clause's
continuation and cannot invoke it however it is written. That is what
keeps the analysis exact rather than conservative across recursion.
| PARAMETER | DESCRIPTION |
|---|---|
computation
|
The clause body to analyse.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ResumptionUse
|
The interval of invocation counts over the body's paths. |
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the term is of an unknown computation class. |
Source code in src/quivers/qiec/checking.py
check_resumption_grade
¶
check_resumption_grade(grade: ResumptionGrade, use: ResumptionUse, *, subject: str) -> None
Hold a clause body to the grade its declaration promises.
| PARAMETER | DESCRIPTION |
|---|---|
grade
|
The declared grade.
TYPE:
|
use
|
What the body actually does, from
TYPE:
|
subject
|
What is being checked, named in any diagnostic.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
KernelError
|
If the body can resume more often than the grade allows, or, for
a linear grade, if some path fails to resume at all. A grade is a
promise other code relies on: a handler declared |