Just-in-Time (JIT) Parsing#
By default, MontePy defers the full parse of each input until the data are actually
needed.
On first read only a lightweight “JIT” parse is performed: enough to categorize
the input and extract its number (for
Numbered_MCNP_Object subclasses).
The raw Input object is stored and the full
parse is triggered on-demand.
How it Works#
MCNP_Object.__init__is called withjit_parse=True(the default)._jit_light_initinstantiatesself._JitParser(), parses only the first few tokens, and stores the results as instance attributes. The attribute_not_parsed = Trueis set as a marker.If the JIT parse raises any exception (including
AttributeErrorwhen_JitParseris not defined), the exception is caught and a full parse is performed automatically as a fallback. JIT parsing is explicitly “fast and dirty” — correctness is guaranteed by this fallback, not by the JIT parser itself.When the full data are required,
full_parse()is called. This re-runs__init__withjit_parse=False, triggering a full parse via_parse_tree. Any attributes listed in_KEYS_TO_PRESERVEare carried over from the JIT state.
Warning
JIT parsers must be context-free (no state, no look-back).
Do not add context-sensitive logic to a _JitParser.
Keep it minimal: parse only what is needed to categorize the input and read its
number.
Anything that could fail gracefully will be handled by the automatic fallback to
full parsing.
needs_full_ast vs needs_full_cst#
Two decorators are provided to trigger a full parse on demand. They differ in what kind of parsed data they signal is needed:
needs_full_ast()Use on getters (reading data). Signals that an Abstract Syntax Tree (AST) — the semantic values — is sufficient.
needs_full_cst()Use on setters and deleters (modifying data). Signals that a Concrete Syntax Tree (CST) — which preserves whitespace and comment formatting — is required so that the modified input can be written back faithfully.
Both decorators currently call self.full_parse() and are therefore functionally
identical.
The distinction is preserved as infrastructure for a possible future where JIT parsing
can provide a partial AST (enough for reads) without yet building the full CST (needed
for writes).
Using the correct decorator now ensures that future optimization can be applied without
changing call sites.
from montepy.utilities import needs_full_ast, needs_full_cst
@property
@needs_full_ast # reading: AST is sufficient
def density(self):
return self._density_node.value
@density.setter
@needs_full_cst # writing: CST required for faithful round-trip output
def density(self, value):
self._density_node.value = value
Supporting JIT Parsing in a New Class#
To add JIT support to a new class:
Set
_JitParserto the lightweight, context-free parser class that parses only the minimum needed tokens (number, classifier, etc.):class MyInput(MCNP_Object): @staticmethod def _parser(): return MyFullParser() _JitParser = MyJitParser
If any data must survive the JIT → full-parse transition (e.g., problem links established between the two steps), add those attribute names to
_KEYS_TO_PRESERVE:_KEYS_TO_PRESERVE = {"_some_attr"}
Decorate getters with
@needs_full_astand setters/deleters with@needs_full_cst.