Analyze a declaration without executing its body¶
Declare a Digital block, bind a symbol and inspect the semantic representation produced by the frontend. Complete Digital parameters, then use the installed environment. This lesson performs no numerical simulation.
The decorated function has a deliberately observable body: it appends its argument to body_calls. Predict that the list stays empty throughout declaration and analysis. The default decorator reads the signature and declared requirements; invoking the decorated object constructs an invocation record rather than calling the Python body.
Follow syntax into meaning¶
"""Lower a source-aware Hybrid declaration from Syntax AST to Semantic HIR.
The compiler-facing path starts with declarations, not execution. This lesson
shows stable node identity, symbol binding, source-aware analysis, and explicit
diagnostics while keeping all numerical kernels out of scope.
"""
from __future__ import annotations
import json
from cascaqit.syntax import (
ParameterSpec,
SymbolBinding,
SymbolRef,
analyze,
digital_block,
program_syntax,
)
body_calls: list[float] = []
@digital_block(
qubits=("q0",),
parameters={"theta": ParameterSpec(unit="rad")},
capabilities=("gate.rx",),
)
def rotate(theta: float) -> None:
"""Declare one typed Digital block without executing its function body."""
body_calls.append(theta)
def main() -> None:
"""Build Syntax AST, bind a symbol, and inspect Semantic HIR."""
syntax = program_syntax(
"lesson.compiler.beginner",
blocks=(rotate,),
invocations=(rotate(SymbolRef("theta"), mapping={"q0": "logical.0"}),),
)
analysis = analyze(
syntax,
symbols={
"theta": SymbolBinding(name="theta", dtype="float", unit="rad", value=0.25)
},
available_capabilities=("gate.rx",),
)
if analysis.hir is None:
raise RuntimeError([item.to_dict() for item in analysis.diagnostics])
payload = {
"track": "compiler_engineer",
"level": "beginner",
"lesson": "syntax_hir",
"facts": {
"syntax_block_count": len(syntax.blocks),
"hir_block_kinds": [block.block_kind for block in analysis.hir.blocks],
"diagnostic_codes": [item.code for item in analysis.diagnostics],
"syntax_hash_present": len(syntax.stable_hash()) == 64,
"hir_hash_present": len(analysis.hir.stable_hash()) == 64,
"function_body_executed": bool(body_calls),
},
"boundaries": {
"hardware_execution": False,
"cloud_execution": False,
"network_accessed": False,
"credentials_loaded": False,
},
}
print(json.dumps(payload, sort_keys=True))
if __name__ == "__main__":
main()
python3 examples/user/tracks/compiler_engineer/01_beginner_syntax_hir_en.py
| Representation | Information used here |
|---|---|
| Syntax AST | A block named rotate, an invocation, a symbolic argument and logical mapping. |
| Semantic HIR | The resolved argument type, unit, value, capability requirements and source-linked block information. |
| Executable program | Not produced by this signature-only declaration. |
SymbolRef('theta') names a value to resolve. SymbolBinding supplies a float with unit rad and value 0.25. The mapping connects the block's local q0 to the enclosing logical identity logical.0. The capability list declares that the analysis context permits gate.rx.
{
"boundaries": {
"cloud_execution": false,
"credentials_loaded": false,
"hardware_execution": false,
"network_accessed": false
},
"facts": {
"diagnostic_codes": [],
"function_body_executed": false,
"hir_block_kinds": [
"digital"
],
"hir_hash_present": true,
"syntax_block_count": 1,
"syntax_hash_present": true
},
"lesson": "syntax_hir",
"level": "beginner",
"track": "compiler_engineer"
}
A successful result contains one Digital HIR block and no diagnostic codes. function_body_executed is calculated from the observable list, and should be false. Hashes identify the recorded representations; a hash does not mean that a rotation was simulated.
The name rotate and capability gate.rx do not by themselves implement RX. The function body here contains bookkeeping, not a gate declaration, and is not run. This distinction matters when writing tools that display or transform declarations before they become executable programs.
Break one semantic requirement¶
- Remove the
thetaentry from thesymbolsmapping supplied toanalyze. - Restore it but set the binding unit to
uswhile the parameter still requiresrad. - Restore the unit but pass an empty
available_capabilitiestuple.
The corresponding diagnostics are SEMANTIC_SYMBOL_UNBOUND, SEMANTIC_PARAMETER_UNIT_MISMATCH and SEMANTIC_CAPABILITY_UNSUPPORTED. Failed analysis returns no HIR; do not continue with a guessed partial representation. The body-call list stays empty in all three cases. In an editor, display the code together with its object path and available source span so the user can locate the declaration.
The separate lower_body=True option supports static parsing of a restricted gate/control declaration language. It still does not execute arbitrary Python. This example's list append is outside that supported subset, so do not enable body lowering here expecting bookkeeping code to run. See Hybrid syntax for supported declarations and source-capture limits. Continue with graphs and execution plans.