Interpreter

Execution engine for SysML v2 models.

Capabilities

  • Expression evaluation over the AST in longeron.ast (arithmetic, comparison, logic, conditionals, sequences, -> collection operators, invocation of calc definitions and builtin math functions, feature chains, enum literals, instance features).

  • Instantiation of part/item definitions into Instance trees, evaluating attribute values (with inheritance, redefinition overrides and caller-supplied bindings).

  • Constraint / requirement checking against instances.

  • Action execution: parameters, assign, if/while/for, send/accept, perform, terminate, nested actions and calc bindings, in declaration order.

  • State machine simulation: entry transitions, triggers (accept), guards, effects, entry/do/exit actions.

Deliberate simplifications (this is a modeling sandbox, not a full KerML semantic engine): declaration order is execution order for actions (explicit successions are honored as documentation, not reordered), quantities/units evaluate to their numeric value, and control nodes (fork/join/merge/decide) are modeled but not executed.

class longeron.interpreter.Instance(type_name, definition=None)[source]

Bases: object

A runtime instance of a part/item definition (or anonymous usage).

set(path, value)[source]

Assign value at a (possibly dotted) slot path.

Error contract matches Env.assign(): every failure raises EvaluationError, and nothing is mutated on failure. Like Env.assign for simple names, the final slot is created when absent; every intermediate hop must be an existing instance-valued slot.

Return type:

None

class longeron.interpreter.EnumValue(enum, name)[source]

Bases: object

class longeron.interpreter.TypeValue(definition)[source]

Bases: object

A definition used as a value (e.g. in istype or invocations).

class longeron.interpreter.Closure(body, env)[source]

Bases: object

class longeron.interpreter.SentEvent(payload, to=None, via=None)[source]

Bases: object

class longeron.interpreter.ConstraintResult(name, kind, passed, expression, message='')[source]

Bases: object

class longeron.interpreter.RequirementResult(name, assumptions=<factory>, requirements=<factory>)[source]

Bases: object

class longeron.interpreter.ActionResult(outputs, sends, trace, env, terminated=False, time=0.0)[source]

Bases: object

class longeron.interpreter.TransitionFired(source, event, target, time=0.0)[source]

Bases: object

class longeron.interpreter.SimulationResult(final_state, trace, ignored_events, env, sends, time=0.0, active_states=<factory>)[source]

Bases: object

longeron.interpreter.IMPLIED_SPECIALIZATIONS: dict[str, tuple[str | None, str | None]] = {'action': ('Actions::Action', 'Actions::actions'), 'allocation': ('Allocations::Allocation', 'Allocations::allocations'), 'attribute': ('ScalarValues::DataValue', None), 'calc': ('Calculations::Calculation', 'Calculations::calculations'), 'connection': ('Connections::Connection', 'Connections::connections'), 'constraint': ('Constraints::ConstraintCheck', 'Constraints::constraintChecks'), 'enum': ('ScalarValues::DataValue', None), 'interface': ('Interfaces::Interface', 'Interfaces::interfaces'), 'item': ('Items::Item', 'Items::items'), 'occurrence': ('Occurrences::Occurrence', 'Occurrences::occurrences'), 'part': ('Parts::Part', 'Parts::parts'), 'port': ('Ports::Port', 'Ports::ports'), 'requirement': ('Requirements::RequirementCheck', 'Requirements::requirementChecks'), 'state': ('States::StateAction', 'States::stateActions')}

Implied specializations (SysML v2 spec clause 7: every definition/usage kind must directly or indirectly specialize a base element of the Systems Model Library, e.g. checkPartDefinitionSpecialization). A definition or usage that declares no explicit specializations implicitly specializes (definitions) / subsets (usages) these library elements: kind -> (definition base, usage base).

class longeron.interpreter.Resolver(model, library=None)[source]

Bases: object

Qualified-name resolution with memoization.

Resolution follows KerML-style scoping: inner scopes shadow outer ones, and within a scope own members are found before inherited ones, which are found before imported ones. When a library model is supplied, names that fail to resolve in the user model’s root namespace fall back to the library – first to the library’s root packages themselves (so ScalarValues::Real resolves) and then to their contents as if implicitly imported (so a bare Real resolves without an explicit import). That last hop is the KerML global-namespace convenience for standard library packages: a deliberate leniency so existing models that never import ScalarValues stay warning-free. The user model is never mutated.

The caches assume the model is not mutated while this resolver is in use; create a new Interpreter (or call clear_cache()) after structural changes such as add_standard_library.

last_hop: str

how the last successful resolve() found its first segment: "scope" (lexical scoping, incl. imports), "library" (a standard-library root package, i.e. qualified access), or "library-implicit" (a bare name found inside a root library package without any import – the KerML global-namespace convenience; see validate(strict_imports=True))

implied_generals(element)[source]

The implied standard-library base of element.

Implied specializations apply only when the element declares no explicit supers/types/subsets/redefines (see IMPLIED_SPECIALIZATIONS). The base is resolved against the model plus the library fallback; unresolvable bases yield [] silently.

Return type:

list[Namespace]

members_of(element, *, implied=False)[source]

Own + inherited members; redefinitions shadow inherited names.

With implied=True the implied standard-library bases (see implied_generals()) contribute inherited members too.

Return type:

list[Element]

class longeron.interpreter.Env(interpreter, context, frames=None, instance=None)[source]

Bases: object

Layered lookup: local frames -> instance slots -> model namespace.

class longeron.interpreter.Interpreter(model)[source]

Bases: object

Evaluate and execute elements of a Model.

evaluate(expr, context=None, bindings=None, **kwargs)[source]

Evaluate an expression (text or AST) with optional name bindings.

Bindings can be passed as keyword arguments (sugar) or via the bindings mapping – the mapping form covers names that collide with the reserved parameters (expr, context, bindings). Keyword arguments win on overlap.

Return type:

Any

instantiate(definition, bindings=None, **kwargs)[source]

Create an instance of a part/item definition, evaluating attribute values; bindings (keyword arguments, or the bindings mapping for names colliding with reserved parameters) override attribute values by name.

Return type:

Instance

call(calc, *args, **kwargs)[source]

Invoke a calc (or constraint) definition/usage as a function.

Return type:

Any

check(instance)[source]

Evaluate all constraints declared on the instance’s definition.

Return type:

list[ConstraintResult]

snapshot(instance, name=None, kind='part')[source]

Convert a runtime Instance back into a model usage.

The result is a part usage typed by the instance’s definition, with every slot bound to its computed value – suitable for adding to a package and saving (the “full loop”: load, run, write results back).

Return type:

Usage

simulate(state_machine, events=None, inputs=None, max_steps=1000)[source]

Simulate a state machine.

events entries are event names (or (name, payload) tuples); a plain number advances the simulation clock by that amount, firing due accept after/accept at transitions.

Return type:

SimulationResult

class longeron.interpreter.StateMachine(interpreter, definition, inputs)[source]

Bases: object

Hierarchical state machine execution.

Supports nested (composite) states, parallel regions, event triggers, guards, effects, entry/do/exit actions, eventless and when-guarded completion transitions, and after/at time triggers driven by advance().

on_step: Callable[[float, TransitionFired | None], None] | None

observer hook (see longeron.replay): called once after start() completes the initial entry and once after each fired transition, always AFTER the active configuration has been updated

property current: str | None

Dotted path of the first active leaf state (compatibility).

advance(duration)[source]

Advance the simulation clock, firing due time-triggered transitions (accept after d / accept at t) in deadline order.

Return type:

None