pub struct Ast { /* private fields */ }Expand description
The common AST.
Nodes live in per-kind generational arenas; handles are the fast
access path, NodeId the stable one. Spec §1, §3.
Implementations§
Source§impl Ast
impl Ast
Sourcepub fn begin(&mut self) -> AstTransaction<'_>
pub fn begin(&mut self) -> AstTransaction<'_>
Open a transaction.
Mutations made through it are published as one changeset when it commits, and reversed entirely if it does not. Spec §5.1.
Sourcepub fn remove(&mut self, any: AnyId) -> Result<(), AstError>
pub fn remove(&mut self, any: AnyId) -> Result<(), AstError>
Remove a node, cascading to the parts it owns and breaking every reference that pointed at it.
A dangling resolved handle must not survive a delete; incoming
references become Broken(NotFound) so the loss is visible
rather than silent. Spec §5.2.
§Errors
AstError::NotFound when the identity is not in the model,
AstError::Invariant when the resulting model breaks a
structural rule, in which case nothing was removed.
Source§impl Ast
impl Ast
Sourcepub fn new() -> Self
pub fn new() -> Self
A model containing the root module and the built-in declarations.
Built-in identities come from IdSpace::BUILTIN and are
allocated in a fixed order, so they are identical in every model
and snapshots from different processes compare. Spec §3.6, §9.
Sourcepub const fn root_module(&self) -> Id<ModuleNode>
pub const fn root_module(&self) -> Id<ModuleNode>
The anonymous global scope.
Sourcepub const fn builtin_module(&self) -> Id<ModuleNode>
pub const fn builtin_module(&self) -> Id<ModuleNode>
The module holding the built-in declarations.
Sourcepub fn builtin_annotation(&self, name: &str) -> Option<Id<AnnotationDefNode>>
pub fn builtin_annotation(&self, name: &str) -> Option<Id<AnnotationDefNode>>
A built-in annotation by name, without the @.
Sourcepub fn resolve_node_id(&self, node: NodeId) -> Option<AnyId>
pub fn resolve_node_id(&self, node: NodeId) -> Option<AnyId>
Map a stable identity back to its handle and kind.
Sourcepub fn observers_mut(&mut self) -> &mut ObserverRegistry
pub fn observers_mut(&mut self) -> &mut ObserverRegistry
The observer registry, for registering change consumers.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Total number of live nodes across every arena.
Sourcepub const fn commit_sequence(&self) -> u64
pub const fn commit_sequence(&self) -> u64
The sequence number of the last committed changeset.
Zero on a fresh model; every commit increments it, so a consumer can tell whether it has seen every changeset. Spec §5.2.
Sourcepub fn allocate_synthetic_id(&mut self) -> Result<NodeId, AstError>
pub fn allocate_synthetic_id(&mut self) -> Result<NodeId, AstError>
Allocate an identity in IdSpace::SYNTHETIC.
For nodes a tool fabricates that correspond to nothing in any source — an implicit wrapper, a generated helper type. Keeping them in their own namespace means a diff between a parsed model and a fabricated one never confuses the two. Spec §1.2.
§Errors
AstError::Core when the synthetic counter is exhausted.
Sourcepub fn take_commit_error(&mut self) -> Option<AstError>
pub fn take_commit_error(&mut self) -> Option<AstError>
The error of the most recent auto-committed mutation, if it was rejected.
A mutation made outside an explicit transaction validates on the spot; when it fails, the model is rolled back and the failure is recorded here rather than lost. Taking it clears it.
Sourcepub fn module(&self, id: Id<ModuleNode>) -> Result<&ModuleNode, AstError>
pub fn module(&self, id: Id<ModuleNode>) -> Result<&ModuleNode, AstError>
Sourcepub fn ensure_module(
&mut self,
parent: Id<ModuleNode>,
name: &str,
) -> Result<Id<ModuleNode>, AstError>
pub fn ensure_module( &mut self, parent: Id<ModuleNode>, name: &str, ) -> Result<Id<ModuleNode>, AstError>
Create the named child module, or return the existing one.
This is what makes reopening a module across translation units converge on one node. Spec §3.1.
§Errors
AstError::Core if the parent handle is stale or identity
space is exhausted.
Sourcepub fn modules(&self) -> impl Iterator<Item = (Id<ModuleNode>, &ModuleNode)>
pub fn modules(&self) -> impl Iterator<Item = (Id<ModuleNode>, &ModuleNode)>
Iterate every module in the model, in arena order.
Sourcepub fn module_by_path(&self, path: &ScopedName) -> Option<Id<ModuleNode>>
pub fn module_by_path(&self, path: &ScopedName) -> Option<Id<ModuleNode>>
Look a module up by its path from the root.
Sourcepub fn add_type(
&mut self,
module: Id<ModuleNode>,
name: &str,
kind: TypeKind,
) -> Result<Id<TypeNode>, AstError>
pub fn add_type( &mut self, module: Id<ModuleNode>, name: &str, kind: TypeKind, ) -> Result<Id<TypeNode>, AstError>
Declare a type in a module.
§Errors
AstError::Core if the module handle is stale or identity
space is exhausted.
Sourcepub fn add_forward_type(
&mut self,
module: Id<ModuleNode>,
name: &str,
kind: TypeKind,
) -> Result<Id<TypeNode>, AstError>
pub fn add_forward_type( &mut self, module: Id<ModuleNode>, name: &str, kind: TypeKind, ) -> Result<Id<TypeNode>, AstError>
Declare a type whose body has not arrived yet.
Not a separate node kind: completing it later is an update, so handles taken now stay valid. Spec §3.2.
§Errors
As Ast::add_type.
Sourcepub fn complete_type(
&mut self,
id: Id<TypeNode>,
kind: TypeKind,
) -> Result<(), AstError>
pub fn complete_type( &mut self, id: Id<TypeNode>, kind: TypeKind, ) -> Result<(), AstError>
Give a forward-declared type its body.
An update of the existing node, not a second one: every reference taken while only the forward declaration existed stays valid, which is why forwardness is a state rather than a kind. Spec §3.2.
§Errors
AstError::AlreadyComplete if the type already has a body —
two definitions of one name are a duplicate, not a completion.
AstError::Core on a stale handle.
Sourcepub fn types(&self) -> impl Iterator<Item = (Id<TypeNode>, &TypeNode)>
pub fn types(&self) -> impl Iterator<Item = (Id<TypeNode>, &TypeNode)>
Iterate every type in the model, in arena order.
Sourcepub fn member(&self, id: Id<MemberNode>) -> Result<&MemberNode, AstError>
pub fn member(&self, id: Id<MemberNode>) -> Result<&MemberNode, AstError>
Sourcepub fn members(&self) -> impl Iterator<Item = (Id<MemberNode>, &MemberNode)>
pub fn members(&self) -> impl Iterator<Item = (Id<MemberNode>, &MemberNode)>
Iterate every member in the model, in arena order.
Sourcepub fn add_member(
&mut self,
aggregate: Id<TypeNode>,
spec: MemberSpec,
) -> Result<Id<MemberNode>, AstError>
pub fn add_member( &mut self, aggregate: Id<TypeNode>, spec: MemberSpec, ) -> Result<Id<MemberNode>, AstError>
Add a member to a struct or valuetype.
§Errors
AstError::WrongKind if the target is not an aggregate that
holds members, AstError::Core on a stale handle.
Sourcepub fn add_member_at(
&mut self,
aggregate: Id<TypeNode>,
spec: MemberSpec,
index: usize,
) -> Result<Id<MemberNode>, AstError>
pub fn add_member_at( &mut self, aggregate: Id<TypeNode>, spec: MemberSpec, index: usize, ) -> Result<Id<MemberNode>, AstError>
Self::add_member at a position among the aggregate’s members.
DDS-XTypes 1.3 §7.5.2.7.6: “any value greater than the current
largest index value in the type shall be taken to indicate that the
new member will become the last member”; a member at index and
those after it “shall be shifted up by a single index value”.
§Errors
As Self::add_member.
Sourcepub fn add_case_at(
&mut self,
union: Id<TypeNode>,
labels: Vec<CaseLabel>,
spec: MemberSpec,
index: usize,
) -> Result<Id<CaseNode>, AstError>
pub fn add_case_at( &mut self, union: Id<TypeNode>, labels: Vec<CaseLabel>, spec: MemberSpec, index: usize, ) -> Result<Id<CaseNode>, AstError>
Self::add_case at a position among the union’s cases, with the
rule of Self::add_member_at.
§Errors
As Self::add_case.
Sourcepub fn add_exception_member(
&mut self,
exception: Id<ExceptionNode>,
spec: MemberSpec,
) -> Result<Id<MemberNode>, AstError>
pub fn add_exception_member( &mut self, exception: Id<ExceptionNode>, spec: MemberSpec, ) -> Result<Id<MemberNode>, AstError>
Sourcepub fn cases(&self) -> impl Iterator<Item = (Id<CaseNode>, &CaseNode)>
pub fn cases(&self) -> impl Iterator<Item = (Id<CaseNode>, &CaseNode)>
Iterate every cases node in the model, in arena order.
Sourcepub fn add_case(
&mut self,
union: Id<TypeNode>,
labels: Vec<CaseLabel>,
spec: MemberSpec,
) -> Result<Id<CaseNode>, AstError>
pub fn add_case( &mut self, union: Id<TypeNode>, labels: Vec<CaseLabel>, spec: MemberSpec, ) -> Result<Id<CaseNode>, AstError>
Add a case to a union.
A case carrying CaseLabel::Default is also recorded as the
union’s default case.
§Errors
AstError::NotAnAggregate if the target is not a union.
Sourcepub fn enumerator(
&self,
id: Id<EnumeratorNode>,
) -> Result<&EnumeratorNode, AstError>
pub fn enumerator( &self, id: Id<EnumeratorNode>, ) -> Result<&EnumeratorNode, AstError>
Sourcepub fn enumerators(
&self,
) -> impl Iterator<Item = (Id<EnumeratorNode>, &EnumeratorNode)>
pub fn enumerators( &self, ) -> impl Iterator<Item = (Id<EnumeratorNode>, &EnumeratorNode)>
Iterate every enumerator in the model, in arena order.
Sourcepub fn enumerator_mut(
&mut self,
id: Id<EnumeratorNode>,
) -> Result<&mut EnumeratorNode, AstError>
pub fn enumerator_mut( &mut self, id: Id<EnumeratorNode>, ) -> Result<&mut EnumeratorNode, AstError>
Borrow an enumerator mutably.
For @value(n), which a frontend applies after the enumerator
exists.
§Errors
AstError::Core with a stale or unknown handle.
Sourcepub fn add_enumerator(
&mut self,
enumeration: Id<TypeNode>,
name: &str,
value: Option<Id<ConstExprNode>>,
) -> Result<Id<EnumeratorNode>, AstError>
pub fn add_enumerator( &mut self, enumeration: Id<TypeNode>, name: &str, value: Option<Id<ConstExprNode>>, ) -> Result<Id<EnumeratorNode>, AstError>
Add an enumerator to an enumeration.
value is None for a positional enumerator and Some for an
explicit @value(n); the two encode differently. Spec §3.3.
§Errors
AstError::NotAnAggregate if the target is not an enumeration.
Sourcepub fn bit_value(&self, id: Id<BitValueNode>) -> Result<&BitValueNode, AstError>
pub fn bit_value(&self, id: Id<BitValueNode>) -> Result<&BitValueNode, AstError>
Sourcepub fn bit_value_mut(
&mut self,
id: Id<BitValueNode>,
) -> Result<&mut BitValueNode, AstError>
pub fn bit_value_mut( &mut self, id: Id<BitValueNode>, ) -> Result<&mut BitValueNode, AstError>
Borrow a bitmask bit mutably.
For @position(k), which a frontend applies after the bit exists.
§Errors
AstError::Core with a stale or unknown handle.
Sourcepub fn bit_values(
&self,
) -> impl Iterator<Item = (Id<BitValueNode>, &BitValueNode)>
pub fn bit_values( &self, ) -> impl Iterator<Item = (Id<BitValueNode>, &BitValueNode)>
Iterate every bit values node in the model, in arena order.
Sourcepub fn add_bit_value(
&mut self,
bitmask: Id<TypeNode>,
name: &str,
position: Option<u16>,
) -> Result<Id<BitValueNode>, AstError>
pub fn add_bit_value( &mut self, bitmask: Id<TypeNode>, name: &str, position: Option<u16>, ) -> Result<Id<BitValueNode>, AstError>
Add a bit to a bitmask.
position is None for a positional bit and Some for an
explicit @position(k). Spec §3.3.
§Errors
AstError::NotAnAggregate if the target is not a bitmask.
Sourcepub fn bitfield(&self, id: Id<BitfieldNode>) -> Result<&BitfieldNode, AstError>
pub fn bitfield(&self, id: Id<BitfieldNode>) -> Result<&BitfieldNode, AstError>
Sourcepub fn add_bitfield(
&mut self,
bitset: Id<TypeNode>,
name: Option<&str>,
bits: u16,
holder_type: Option<Ref<TypeNode>>,
) -> Result<Id<BitfieldNode>, AstError>
pub fn add_bitfield( &mut self, bitset: Id<TypeNode>, name: Option<&str>, bits: u16, holder_type: Option<Ref<TypeNode>>, ) -> Result<Id<BitfieldNode>, AstError>
Add a field to a bitset. name is None for anonymous padding.
§Errors
AstError::NotAnAggregate if the target is not a bitset.
Sourcepub fn expr(&self, id: Id<ConstExprNode>) -> Result<&ConstExprNode, AstError>
pub fn expr(&self, id: Id<ConstExprNode>) -> Result<&ConstExprNode, AstError>
Sourcepub fn add_int_expr(
&mut self,
value: i128,
) -> Result<Id<ConstExprNode>, AstError>
pub fn add_int_expr( &mut self, value: i128, ) -> Result<Id<ConstExprNode>, AstError>
Sourcepub fn constants(&self) -> impl Iterator<Item = (Id<ConstNode>, &ConstNode)>
pub fn constants(&self) -> impl Iterator<Item = (Id<ConstNode>, &ConstNode)>
Iterate every constants node in the model, in arena order.
Sourcepub fn add_const(
&mut self,
module: Id<ModuleNode>,
name: &str,
type_: Ref<TypeNode>,
expr: Id<ConstExprNode>,
) -> Result<Id<ConstNode>, AstError>
pub fn add_const( &mut self, module: Id<ModuleNode>, name: &str, type_: Ref<TypeNode>, expr: Id<ConstExprNode>, ) -> Result<Id<ConstNode>, AstError>
Sourcepub fn eval_integral(&self, expr: Id<ConstExprNode>) -> Result<i128, EvalError>
pub fn eval_integral(&self, expr: Id<ConstExprNode>) -> Result<i128, EvalError>
Evaluate an expression to an integral value.
The tree is not mutated: evaluation is a query, so the written form stays available to the formatter and the linter. Spec §3.5.
§Errors
EvalError::Unresolved when the tree reaches a reference that
is not resolved — a partially discovered model fails loudly
rather than substituting a default. Also
EvalError::DivisionByZero, EvalError::Overflow,
EvalError::InvalidShift, EvalError::NotIntegral,
EvalError::DanglingExpr and EvalError::TooDeep.
Sourcepub fn eval_const(
&self,
expr: Id<ConstExprNode>,
) -> Result<ConstValue, EvalError>
pub fn eval_const( &self, expr: Id<ConstExprNode>, ) -> Result<ConstValue, EvalError>
Evaluate an expression to its value, whatever kind that is.
Self::eval_integral is the right question wherever the wire
needs a number, and the wrong one wherever a backend only needs to
know what a constant says. const string MODULE_ID = "…"; is
evaluated and has no integer, so an integral evaluator reports
NotIntegral and a caller that has nothing else to ask cannot emit
the constant at all.
An expression with an operator in it is integral and comes back as
ConstValue::Integer, unless a floating-point operand stands in
it: then it is evaluated in double as IDL 4.2 §7.4.1.4.2 says and
comes back as ConstValue::Float; a fixed-point operand makes it
exact decimal arithmetic after Table 7-11, back as
ConstValue::Fixed.
§Errors
As Self::eval_integral; for floating arithmetic also
EvalError::MixedOperands, EvalError::NotFloatingOperator
and EvalError::LongDouble, for fixed-point arithmetic
EvalError::NotFixedOperator. A literal alone always has a value.
Sourcepub fn interface(
&self,
id: Id<InterfaceNode>,
) -> Result<&InterfaceNode, AstError>
pub fn interface( &self, id: Id<InterfaceNode>, ) -> Result<&InterfaceNode, AstError>
Sourcepub fn add_interface(
&mut self,
module: Id<ModuleNode>,
name: &str,
kind: InterfaceKind,
bases: Vec<Ref<InterfaceNode>>,
) -> Result<Id<InterfaceNode>, AstError>
pub fn add_interface( &mut self, module: Id<ModuleNode>, name: &str, kind: InterfaceKind, bases: Vec<Ref<InterfaceNode>>, ) -> Result<Id<InterfaceNode>, AstError>
Sourcepub fn add_forward_interface(
&mut self,
module: Id<ModuleNode>,
name: &str,
kind: InterfaceKind,
) -> Result<Id<InterfaceNode>, AstError>
pub fn add_forward_interface( &mut self, module: Id<ModuleNode>, name: &str, kind: InterfaceKind, ) -> Result<Id<InterfaceNode>, AstError>
Declare an interface whose body has not arrived.
interface I; — IDL 4.2 §7.4.3, rule (75). The same shape
Self::add_forward_type gives a struct or a union, and for the
same reason: forwardness is a state of one node, so a reference
taken against the declaration stays valid when the definition
completes it.
§Errors
Sourcepub fn complete_interface(
&mut self,
id: Id<InterfaceNode>,
kind: InterfaceKind,
bases: Vec<Ref<InterfaceNode>>,
) -> Result<(), AstError>
pub fn complete_interface( &mut self, id: Id<InterfaceNode>, kind: InterfaceKind, bases: Vec<Ref<InterfaceNode>>, ) -> Result<(), AstError>
Give a forward-declared interface its body.
An update of the existing node, not a second one — the reason
Self::complete_type gives.
§Errors
AstError::AlreadyComplete if the interface already has a body:
two definitions of one name are a duplicate, not a completion.
AstError::Core on a stale handle.
Sourcepub fn interfaces(
&self,
) -> impl Iterator<Item = (Id<InterfaceNode>, &InterfaceNode)>
pub fn interfaces( &self, ) -> impl Iterator<Item = (Id<InterfaceNode>, &InterfaceNode)>
Iterate every interface in the model, in arena order.
Sourcepub fn operations(
&self,
) -> impl Iterator<Item = (Id<OperationNode>, &OperationNode)>
pub fn operations( &self, ) -> impl Iterator<Item = (Id<OperationNode>, &OperationNode)>
Iterate every operation in the model, in arena order.
An operation’s owner is OperationNode::parent, which is an
AnyId because a valuetype declares operations too. There is
no list on the valuetype for the exported ones — only for its
initialisers, which is what rule (105) distinguishes — so this
is how a consumer finds them.
Sourcepub fn set_interface_form(
&mut self,
id: Id<InterfaceNode>,
kind: InterfaceKind,
bases: Vec<Ref<InterfaceNode>>,
) -> Result<(), AstError>
pub fn set_interface_form( &mut self, id: Id<InterfaceNode>, kind: InterfaceKind, bases: Vec<Ref<InterfaceNode>>, ) -> Result<(), AstError>
Rewrite an interface’s form and base list.
Distinct from Self::complete_interface, which gives a forward
declaration the body it was still waiting for. This restates a
declaration that already has one: CCM 4.0 §6.2’s equivalent
interface is the component declaration with a different form and
a different base list, and the identity has to survive the change
so that references taken against the component keep pointing at
it.
The waiter index is rebuilt, because the old bases’ pending keys have to go and the new ones have to be seen.
§Errors
AstError::Core on a stale handle.
Sourcepub fn add_valuetype_base(
&mut self,
id: Id<TypeNode>,
base: Ref<TypeNode>,
) -> Result<(), AstError>
pub fn add_valuetype_base( &mut self, id: Id<TypeNode>, base: Ref<TypeNode>, ) -> Result<(), AstError>
Add a base to a valuetype.
A method rather than mutable access to the list, for the reason
Self::add_raises gives: a reference added behind the model’s
back is never indexed, and an unindexed pending reference is one
that never resolves.
§Errors
AstError::NotAnAggregate when the type is not a valuetype,
AstError::Core on a stale handle.
Sourcepub fn object_reference_to(
&mut self,
interface: Id<InterfaceNode>,
) -> Result<Id<TypeNode>, AstError>
pub fn object_reference_to( &mut self, interface: Id<InterfaceNode>, ) -> Result<Id<TypeNode>, AstError>
The type that is an object reference to interface.
An interface name written where a type is expected is an object
reference — OMG IDL 4.2 §7.4.6 — and struct S { I x; } is the
ordinary way to write one. The reference in S::x is a
Ref<TypeNode> and an interface is not a type, so the model needs
a type node standing for “a reference to I”; this returns it,
creating it the first time and returning the same one after.
It carries the interface’s own name so a backend renders I, and
it is deliberately left out of the name index: the name in the
scope belongs to the interface, and indexing both would make every
use of it ambiguous.
§Errors
AstError::Core on a stale interface handle.
Sourcepub fn operation(
&self,
id: Id<OperationNode>,
) -> Result<&OperationNode, AstError>
pub fn operation( &self, id: Id<OperationNode>, ) -> Result<&OperationNode, AstError>
Sourcepub fn add_operation(
&mut self,
interface: Id<InterfaceNode>,
name: &str,
return_type: Option<Ref<TypeNode>>,
oneway: bool,
) -> Result<Id<OperationNode>, AstError>
pub fn add_operation( &mut self, interface: Id<InterfaceNode>, name: &str, return_type: Option<Ref<TypeNode>>, oneway: bool, ) -> Result<Id<OperationNode>, AstError>
Sourcepub fn add_valuetype_operation(
&mut self,
valuetype: Id<TypeNode>,
name: &str,
return_type: Option<Ref<TypeNode>>,
initializer: bool,
) -> Result<Id<OperationNode>, AstError>
pub fn add_valuetype_operation( &mut self, valuetype: Id<TypeNode>, name: &str, return_type: Option<Ref<TypeNode>>, initializer: bool, ) -> Result<Id<OperationNode>, AstError>
Add an initialiser or an exported operation to a valuetype.
OMG IDL 4.2 rule (105): a valuetype body holds factory
initialisers and ordinary operations alongside its state.
TypeKind::Valuetype::initializers was in the model from the
start and nothing could fill it — Self::add_operation takes
an Id<InterfaceNode>, so every factory in every IDL file
this tree read was parsed, kept in the CST and dropped at the
model boundary with no diagnostic.
initializer decides which list the operation joins: an
initialiser goes into initializers, an exported operation is
reachable through its parent and is not one.
§Errors
AstError::Core on a stale handle, and
AstError::Core when the type is not a valuetype.
Sourcepub fn set_oneway(
&mut self,
id: Id<OperationNode>,
oneway: bool,
) -> Result<(), AstError>
pub fn set_oneway( &mut self, id: Id<OperationNode>, oneway: bool, ) -> Result<(), AstError>
Mark an operation oneway.
@oneway writes the same flag as the keyword form; both reach
the operation through here.
§Errors
AstError::Core with a stale or unknown handle.
Sourcepub fn add_raises(
&mut self,
id: Id<OperationNode>,
exception: Ref<ExceptionNode>,
) -> Result<(), AstError>
pub fn add_raises( &mut self, id: Id<OperationNode>, exception: Ref<ExceptionNode>, ) -> Result<(), AstError>
Add an exception to an operation’s raises clause.
A method rather than mutable access to the list: a reference added behind the model’s back is never indexed, and an unindexed pending reference is one that never resolves.
§Errors
AstError::Core with a stale or unknown handle.
Sourcepub fn add_context(
&mut self,
id: Id<OperationNode>,
context: &str,
) -> Result<(), AstError>
pub fn add_context( &mut self, id: Id<OperationNode>, context: &str, ) -> Result<(), AstError>
Sourcepub fn add_param(
&mut self,
operation: Id<OperationNode>,
name: &str,
direction: ParamDirection,
type_: Ref<TypeNode>,
) -> Result<Id<ParamNode>, AstError>
pub fn add_param( &mut self, operation: Id<OperationNode>, name: &str, direction: ParamDirection, type_: Ref<TypeNode>, ) -> Result<Id<ParamNode>, AstError>
Sourcepub fn attribute(
&self,
id: Id<AttributeNode>,
) -> Result<&AttributeNode, AstError>
pub fn attribute( &self, id: Id<AttributeNode>, ) -> Result<&AttributeNode, AstError>
Sourcepub fn add_attribute_raises(
&mut self,
id: Id<AttributeNode>,
exception: Ref<ExceptionNode>,
on_set: bool,
) -> Result<(), AstError>
pub fn add_attribute_raises( &mut self, id: Id<AttributeNode>, exception: Ref<ExceptionNode>, on_set: bool, ) -> Result<(), AstError>
Add an exception to an attribute’s getraises or setraises
clause.
§Errors
AstError::Core with a stale or unknown handle.
Sourcepub fn add_attribute(
&mut self,
interface: Id<InterfaceNode>,
name: &str,
type_: Ref<TypeNode>,
readonly: bool,
) -> Result<Id<AttributeNode>, AstError>
pub fn add_attribute( &mut self, interface: Id<InterfaceNode>, name: &str, type_: Ref<TypeNode>, readonly: bool, ) -> Result<Id<AttributeNode>, AstError>
Sourcepub fn exception(
&self,
id: Id<ExceptionNode>,
) -> Result<&ExceptionNode, AstError>
pub fn exception( &self, id: Id<ExceptionNode>, ) -> Result<&ExceptionNode, AstError>
Sourcepub fn exceptions(
&self,
) -> impl Iterator<Item = (Id<ExceptionNode>, &ExceptionNode)>
pub fn exceptions( &self, ) -> impl Iterator<Item = (Id<ExceptionNode>, &ExceptionNode)>
Iterate every exceptions node in the model, in arena order.
Sourcepub fn set_declaration_scope(
&mut self,
any: AnyId,
scope: &str,
) -> Result<(), AstError>
pub fn set_declaration_scope( &mut self, any: AnyId, scope: &str, ) -> Result<(), AstError>
Record that a type, constant or exception is declared inside the
interface or value type scope rather than directly in its module.
§Errors
AstError::Core on a stale handle; AstError::WrongKind for a
node of another kind, which no interface body declares.
Sourcepub fn add_exception(
&mut self,
module: Id<ModuleNode>,
name: &str,
) -> Result<Id<ExceptionNode>, AstError>
pub fn add_exception( &mut self, module: Id<ModuleNode>, name: &str, ) -> Result<Id<ExceptionNode>, AstError>
Sourcepub fn annotation_defs(
&self,
) -> impl Iterator<Item = (Id<AnnotationDefNode>, &AnnotationDefNode)>
pub fn annotation_defs( &self, ) -> impl Iterator<Item = (Id<AnnotationDefNode>, &AnnotationDefNode)>
Every annotation declaration in the model, in arena order.
The counterpart of Ast::types for the other declaration kind
that has a TypeObject: Annex B gives MinimalTypeObject a
case TK_ANNOTATION: MinimalAnnotationType annotation_type;, and
an @annotation declaration is not a TypeNode in this model,
so a caller that wants to build one had no way to reach it.
Sourcepub fn annotation_def(
&self,
id: Id<AnnotationDefNode>,
) -> Result<&AnnotationDefNode, AstError>
pub fn annotation_def( &self, id: Id<AnnotationDefNode>, ) -> Result<&AnnotationDefNode, AstError>
Sourcepub fn add_annotation_def(
&mut self,
module: Id<ModuleNode>,
name: &str,
) -> Result<Id<AnnotationDefNode>, AstError>
pub fn add_annotation_def( &mut self, module: Id<ModuleNode>, name: &str, ) -> Result<Id<AnnotationDefNode>, AstError>
Sourcepub fn annotation_member(
&self,
id: Id<AnnotationMemberNode>,
) -> Result<&AnnotationMemberNode, AstError>
pub fn annotation_member( &self, id: Id<AnnotationMemberNode>, ) -> Result<&AnnotationMemberNode, AstError>
Sourcepub fn add_annotation_member(
&mut self,
annotation: Id<AnnotationDefNode>,
name: &str,
type_: Ref<TypeNode>,
default: Option<Id<ConstExprNode>>,
) -> Result<Id<AnnotationMemberNode>, AstError>
pub fn add_annotation_member( &mut self, annotation: Id<AnnotationDefNode>, name: &str, type_: Ref<TypeNode>, default: Option<Id<ConstExprNode>>, ) -> Result<Id<AnnotationMemberNode>, AstError>
Sourcepub fn library(&self, id: Id<LibraryNode>) -> Result<&LibraryNode, AstError>
pub fn library(&self, id: Id<LibraryNode>) -> Result<&LibraryNode, AstError>
Sourcepub fn add_library(&mut self, name: &str) -> Result<Id<LibraryNode>, AstError>
pub fn add_library(&mut self, name: &str) -> Result<Id<LibraryNode>, AstError>
Sourcepub fn domain(&self, id: Id<DomainNode>) -> Result<&DomainNode, AstError>
pub fn domain(&self, id: Id<DomainNode>) -> Result<&DomainNode, AstError>
Sourcepub fn add_domain(
&mut self,
library: Id<LibraryNode>,
name: &str,
domain_id: u32,
) -> Result<Id<DomainNode>, AstError>
pub fn add_domain( &mut self, library: Id<LibraryNode>, name: &str, domain_id: u32, ) -> Result<Id<DomainNode>, AstError>
Sourcepub fn add_topic(
&mut self,
domain: Id<DomainNode>,
name: &str,
type_: Ref<TypeNode>,
qos: Option<Ref<QosProfileNode>>,
) -> Result<Id<TopicNode>, AstError>
pub fn add_topic( &mut self, domain: Id<DomainNode>, name: &str, type_: Ref<TypeNode>, qos: Option<Ref<QosProfileNode>>, ) -> Result<Id<TopicNode>, AstError>
Sourcepub fn qos_profile(
&self,
id: Id<QosProfileNode>,
) -> Result<&QosProfileNode, AstError>
pub fn qos_profile( &self, id: Id<QosProfileNode>, ) -> Result<&QosProfileNode, AstError>
Sourcepub fn add_qos_profile(
&mut self,
library: Id<LibraryNode>,
name: &str,
base: Option<Ref<QosProfileNode>>,
policies: Vec<QosPolicy>,
) -> Result<Id<QosProfileNode>, AstError>
pub fn add_qos_profile( &mut self, library: Id<LibraryNode>, name: &str, base: Option<Ref<QosProfileNode>>, policies: Vec<QosPolicy>, ) -> Result<Id<QosProfileNode>, AstError>
Sourcepub fn participant(
&self,
id: Id<ParticipantNode>,
) -> Result<&ParticipantNode, AstError>
pub fn participant( &self, id: Id<ParticipantNode>, ) -> Result<&ParticipantNode, AstError>
Sourcepub fn add_participant(
&mut self,
library: Id<LibraryNode>,
name: &str,
domain: Ref<DomainNode>,
qos: Option<Ref<QosProfileNode>>,
) -> Result<Id<ParticipantNode>, AstError>
pub fn add_participant( &mut self, library: Id<LibraryNode>, name: &str, domain: Ref<DomainNode>, qos: Option<Ref<QosProfileNode>>, ) -> Result<Id<ParticipantNode>, AstError>
Sourcepub fn endpoint(&self, id: Id<EndpointNode>) -> Result<&EndpointNode, AstError>
pub fn endpoint(&self, id: Id<EndpointNode>) -> Result<&EndpointNode, AstError>
Sourcepub fn add_endpoint(
&mut self,
participant: Id<ParticipantNode>,
name: &str,
role: EndpointRole,
topic: Ref<TopicNode>,
qos: Option<Ref<QosProfileNode>>,
) -> Result<Id<EndpointNode>, AstError>
pub fn add_endpoint( &mut self, participant: Id<ParticipantNode>, name: &str, role: EndpointRole, topic: Ref<TopicNode>, qos: Option<Ref<QosProfileNode>>, ) -> Result<Id<EndpointNode>, AstError>
Sourcepub fn facets_mut(&mut self, any: AnyId) -> Option<&mut Facets>
pub fn facets_mut(&mut self, any: AnyId) -> Option<&mut Facets>
The facets of any node, mutably.
Sourcepub fn any_of_member(&self, id: Id<MemberNode>) -> Result<AnyId, AstError>
pub fn any_of_member(&self, id: Id<MemberNode>) -> Result<AnyId, AstError>
Source§impl Ast
impl Ast
Sourcepub fn drop_outside_profile(
&mut self,
profile: Profile,
) -> Result<Vec<Dropped>, AstError>
pub fn drop_outside_profile( &mut self, profile: Profile, ) -> Result<Vec<Dropped>, AstError>
Remove the data types that reach a construct profile has no type
for, and return what was removed.
A type is removed when it is, or reaches through members, cases,
aliases, collection elements, map keys and values, bases or a
discriminator, a construct construct_verdict(profile, …)
rejects among any, ValueBase, native and an object
reference. The construct’s own node stays in the model (it is the
shared node every any points at).
A type that a constant, an operation, a parameter, an attribute, an annotation member or a topic names is kept: removing it would leave that declaration with a reference to nothing, and the caller would then be told about a broken reference instead of the construct. Such a type stays in the model and a code generator reports the construct by name, as before.
Nothing is removed under a profile that admits all four.
§Errors
AstError when a removal breaks a structural rule of the model;
the types removed before it stay removed, so a caller treats the
model as spoilt.
Source§impl Ast
impl Ast
Sourcepub fn validate(&self, profile: Profile) -> Result<(), Vec<ProfileViolation>>
pub fn validate(&self, profile: Profile) -> Result<(), Vec<ProfileViolation>>
Measure the model against a profile.
Drives the construct table in verdict, so every type kind and
every facet property has an explicit ruling. Profile-specific
checks that are not a simple yes/no on a construct — bit bounds,
topic resolvability, plain-type reachability — run alongside it.
§Errors
Every violation found, never only the first.
Sourcepub fn validate_complete(&self) -> Result<(), Vec<ProfileViolation>>
pub fn validate_complete(&self) -> Result<(), Vec<ProfileViolation>>
Check the completeness rules: nothing left pending, nothing broken, every forward declaration given a body.
Deliberately separate from the commit gate: a partially discovered model passes every structural invariant and fails this. Spec §8.2.
§Errors
Every incompleteness found.
Source§impl Ast
impl Ast
Sourcepub fn find_by_scoped_name(
&self,
name: &ScopedName,
) -> Result<AnyId, IndexLookup>
pub fn find_by_scoped_name( &self, name: &ScopedName, ) -> Result<AnyId, IndexLookup>
Find any node by its full scoped name.
§Errors
IndexLookup::Missing when nothing carries the name,
IndexLookup::Ambiguous with every candidate when several do.
Sourcepub fn find_by_type_identifier(
&self,
key: &TypeIdentifierKey,
) -> Result<Id<TypeNode>, IndexLookup>
pub fn find_by_type_identifier( &self, key: &TypeIdentifierKey, ) -> Result<Id<TypeNode>, IndexLookup>
Sourcepub fn find_by_ros_name(
&self,
name: &RosTypeName,
) -> Result<Id<TypeNode>, IndexLookup>
pub fn find_by_ros_name( &self, name: &RosTypeName, ) -> Result<Id<TypeNode>, IndexLookup>
Sourcepub fn find_by_repository_id(
&self,
id: &RepositoryId,
) -> Result<AnyId, IndexLookup>
pub fn find_by_repository_id( &self, id: &RepositoryId, ) -> Result<AnyId, IndexLookup>
Sourcepub fn scoped_name_of(&self, any: AnyId) -> Option<ScopedName>
pub fn scoped_name_of(&self, any: AnyId) -> Option<ScopedName>
The full scoped name of a node, if it has one.
Nodes that live inside a type rather than a module — members, cases, parameters — have no scoped name of their own.
Sourcepub fn members_of(&self, type_: Id<TypeNode>) -> &[Id<MemberNode>]
pub fn members_of(&self, type_: Id<TypeNode>) -> &[Id<MemberNode>]
The members of an aggregate, empty for every other kind.
Sourcepub fn all_members_of(&self, type_: Id<TypeNode>) -> Vec<Id<MemberNode>>
pub fn all_members_of(&self, type_: Id<TypeNode>) -> Vec<Id<MemberNode>>
The members of an aggregate, its bases’ members first.
Ast::members_of answers what a type declares; this answers
what it has, which is what every wire consumer needs.
DDS-XTypes 1.3 §7.4.1.1.5.1: “The members defined by the base
type, if any, shall be serialized before the members of their
derived types. The representation shall be exactly as if all of
the members had been defined, in the same order, in the
most-derived type.”
The chain is walked to a fixed depth and a base already seen is not walked again: an inheritance cycle is invalid IDL, and looping here would hang instead of reporting it.
Sourcepub fn base_of(&self, type_: Id<TypeNode>) -> Option<Id<TypeNode>>
pub fn base_of(&self, type_: Id<TypeNode>) -> Option<Id<TypeNode>>
The base an aggregate extends, if it has one.
A valuetype may name several; only a single base is a structure on the wire, so the first is what the layout follows.
A bitset counts: IDL 4.2 §7.4.13.4.3.2 gives bitset “an
optional single inheritance specification”, and the inherited
bitfields are part of what the derived bitset packs.
Ast::members_of is empty for a bitset either way, so
Ast::all_members_of is unaffected by the extra arm.
Sourcepub fn bitfields_of(&self, type_: Id<TypeNode>) -> &[Id<BitfieldNode>]
pub fn bitfields_of(&self, type_: Id<TypeNode>) -> &[Id<BitfieldNode>]
The bitfields a bitset declares, empty for every other kind.
Sourcepub fn all_bitfields_of(&self, type_: Id<TypeNode>) -> Vec<Id<BitfieldNode>>
pub fn all_bitfields_of(&self, type_: Id<TypeNode>) -> Vec<Id<BitfieldNode>>
The bitfields a bitset has, its bases’ bitfields first.
The bitset counterpart of Ast::all_members_of, and needed for
the same reason: a plan that leaves the inherited bitfields out
sizes the anchor as if they did not exist, and every emitter
behind it writes short.
§Why base-first, when no specification says so
DDS-XTypes 1.3 has no serialisation rule for a bitset — see the
note above wire_probe::encode::write_bitset. The order is
therefore taken from the one implementation that serialises the
construct at all. Measured on 2026-08-09, eProsima Fast DDS
3.6.1 flattens bitset B3 : B2 : B1 with bitfield<8> a,
bitfield<8> b, bitfield<4> c into a std::bitset<20> and
packs a at bits 0..8, b at 8..16 and c at 16..20 — the
base’s bitfields at the least significant end, in declaration
order. Cyclone’s idlc and RTI’s rtiddsgen do not parse
bitset at all, so Fast DDS is the only oracle there is.
The chain is walked to the same fixed depth as
Ast::all_members_of, and a base already seen is not walked
again: an inheritance cycle is invalid IDL, and looping here
would hang instead of reporting it.
Sourcepub fn enumerators_of(&self, type_: Id<TypeNode>) -> &[Id<EnumeratorNode>]
pub fn enumerators_of(&self, type_: Id<TypeNode>) -> &[Id<EnumeratorNode>]
The enumerators of an enumeration, empty for every other kind.
Sourcepub fn bits_of(&self, type_: Id<TypeNode>) -> &[Id<BitValueNode>]
pub fn bits_of(&self, type_: Id<TypeNode>) -> &[Id<BitValueNode>]
The bits of a bitmask, empty for every other kind.
Sourcepub fn attributes_of(
&self,
interface: Id<InterfaceNode>,
) -> &[Id<AttributeNode>]
pub fn attributes_of( &self, interface: Id<InterfaceNode>, ) -> &[Id<AttributeNode>]
The attributes an interface declares directly.
Sourcepub fn effective_extensibility(&self, type_: Id<TypeNode>) -> Extensibility
pub fn effective_extensibility(&self, type_: Id<TypeNode>) -> Extensibility
The extensibility a type has, written or defaulted.
The facet keeps None for a type whose source said nothing, so
what was written stays distinguishable from what the rule gives.
This is the rule: @final/@appendable/@mutable, else
@extensibility(...), else — for a structure that derives from
another — its base’s, else appendable. DDS-XTypes 1.3 §7.2.4.4,
§7.2.2.4.5.
Appendable, not final: a consumer that assumed final would emit types that cannot evolve, and no DHEADER where one belongs.
The base’s, not appendable: §7.2.2.4.5 lets a derived structure
leave its extensibility unspecified or give the base’s, so an
unspecified one has the base’s. Cyclone DDS 11.0.1 frames
struct Derived : Base of a @mutable base as mutable
(DDS_OP_PLC, measured); falling back to appendable here framed it
with a DHEADER and no EMHEADERs.
Sourcepub fn effective_autoid(&self, type_: Id<TypeNode>) -> Option<AutoId>
pub fn effective_autoid(&self, type_: Id<TypeNode>) -> Option<AutoId>
The @autoid policy of a type: its own, else the nearest enclosing
module’s.
DDS-XTypes 1.3 §7.3.1.2.1.1 and Table 21 apply @autoid to
“Module declarations, Structure declarations, Union declarations”;
on a module it governs every aggregated type declared in it that
does not carry its own. None is “nothing said”, which numbers
the members sequentially.
Sourcepub fn effective_data_representation(
&self,
type_: Id<TypeNode>,
) -> Option<DataRepresentationMask>
pub fn effective_data_representation( &self, type_: Id<TypeNode>, ) -> Option<DataRepresentationMask>
The @data_representation mask of a type: its own, else the
nearest enclosing module’s.
DDS-XTypes 1.3 §7.3.1.2.1.15: the annotation “may be applied to
modules and to types”; a module’s value is the default for the
types in it. None is “nothing said”, which §7.6.3.1.1 reads as
every representation the implementation supports.
Sourcepub fn data_representation_mask(
&self,
type_: Id<TypeNode>,
) -> DataRepresentationMask
pub fn data_representation_mask( &self, type_: Id<TypeNode>, ) -> DataRepresentationMask
The DataRepresentationMask a type has, with the annotation-less
case resolved: a type and its modules that carry no
@data_representation are “interpreted as if the
DataRepresentationMask value was set to 0xffffffff” (DDS-XTypes
1.3 §7.3.1.2.1.15), which is crate::DataRepresentationMask::ALL.
Sourcepub fn effective_bit_bound(&self, type_: Id<TypeNode>) -> u16
pub fn effective_bit_bound(&self, type_: Id<TypeNode>) -> u16
The bit bound an enum or bitmask has, written or defaulted. DDS-XTypes 1.3 §7.3.1.2.1.9.
Sourcepub fn effective_try_construct(
&self,
written: Option<TryConstruct>,
used: Option<Id<TypeNode>>,
) -> TryConstruct
pub fn effective_try_construct( &self, written: Option<TryConstruct>, used: Option<Id<TypeNode>>, ) -> TryConstruct
The try_construct behaviour that governs one use of a type.
written is the annotation at the use site — a member’s own
@try_construct, or the collection’s element_try_construct /
key_try_construct, or the union’s
discriminator_try_construct. used is the type being used
there.
The order is: what the use site wrote, else what the alias chain
of the used type declares nearest-first, else
TryConstruct::ABSENT — DISCARD, which §7.2.2.7 names as
the default when the annotation is not used.
§Why an alias may carry one
The clause does not list aliases among the positions
(§7.3.1.2.1.12 names members, the discriminator, array and
sequence elements, and map keys and values), and both Cyclone and
RTI refuse @try_construct on a typedef by name. Neither of
those is a statement about what an alias-borne annotation would
mean; they are front ends declining to accept it, and the two
implementations that do accept it — Fast DDS and OpenDDS — say
nothing about it either. With the specification silent, the
reading here is the broader one: an alias states the behaviour
that uses of it take by default, and any use site that writes its
own overrides it. Nothing an author wrote can be lost that way,
and typedef string<5> String5 — the very declaration
§7.3.1.2.1.12.4 builds its example on — becomes able to carry the
behaviour it exists to give its uses.
A peer built by Cyclone or RTI will not compile such a
declaration at all;
crates/ast-layout/tests/fixtures/try_construct_behaviour.md
records that.
Sourcepub fn element_try_construct(
&self,
collection: Id<TypeNode>,
member_wrote: Option<TryConstruct>,
) -> TryConstruct
pub fn element_try_construct( &self, collection: Id<TypeNode>, member_wrote: Option<TryConstruct>, ) -> TryConstruct
The behaviour that governs the elements of one collection.
collection is a sequence, an array or a map — for a map this is
the value slot. member_wrote is the @try_construct on the
member whose type this collection is, if any.
§Why a member’s annotation can reach an array’s elements
An array cannot be trimmed and cannot overflow: Table 17 requires
T1.bounds[] == T2.bounds[], so the only way an array fails to
construct is that one of its elements does. Its row accordingly
speaks of nothing but “the TryConstruct behavior associated with
T1 element type” — an array has no member-level behaviour to
carry. There is also no template syntax to annotate an array’s
element with: @try_construct(TRIM) String5 m[3] writes the
annotation in front of the member, which is where OpenDDS reads
its array_element_try_construct from as well.
A sequence or a map has both, and they are different questions — the member’s governs a length the receiver’s bound cannot hold (§7.3.1.2.1.12.3), the element’s governs one element that will not construct (§7.3.1.2.1.12.4) — so a member’s annotation never reaches their elements.
Sourcepub fn key_try_construct(&self, map: Id<TypeNode>) -> TryConstruct
pub fn key_try_construct(&self, map: Id<TypeNode>) -> TryConstruct
The behaviour that governs a map’s keys.
Table 17 gives a key no escape — a key that cannot construct
fails the whole map — so this is DISCARD unless a declaration
wrote DISCARD explicitly, which the front end is the only thing
that admits. It reads the slot rather than returning a constant
so that a future revision of the clause has one place to change.
Sourcepub fn effective_nested(&self, type_: Id<TypeNode>) -> bool
pub fn effective_nested(&self, type_: Id<TypeNode>) -> bool
Whether a type is @nested — its own annotation, else the
@default_nested of the nearest enclosing module that carries
one.
DDS-XTypes 1.3 §7.3.1.2.1.7: “@default_nested … applied to a module … indicates whether the types defined within it are nested by default … value defaults to that of the enclosing module. If a top-level module is not annotated, the default is FALSE.”
A type’s own @nested wins over the module’s. @default_nested
used to reach nothing at all: the annotation parsed, the model
dropped it, and a whole module declared nested emitted
IS_NESTED-free TypeObjects — which is a topic type per
endpoint that the author said should be none.
The walk is bounded by the module chain, which the model builds acyclically; the counter is there so a handle that somehow points at its own ancestor ends the loop rather than the process.
Sourcepub fn element_is_external(&self, collection: Id<TypeNode>) -> bool
pub fn element_is_external(&self, collection: Id<TypeNode>) -> bool
Whether the elements of a collection are @external — the
sequence or array element, or the value of a map
(DDS-XTypes 1.3 §7.3.1.2.1.4).
Sourcepub fn element_annotations(
&self,
collection: Id<TypeNode>,
) -> &[AppliedAnnotation]
pub fn element_annotations( &self, collection: Id<TypeNode>, ) -> &[AppliedAnnotation]
The user-declared annotations written on the element type of a collection (DDS-XTypes 1.3 §7.2.2.6), in the order they were written. For a map, the value’s.
Sourcepub fn key_annotations(&self, map: Id<TypeNode>) -> &[AppliedAnnotation]
pub fn key_annotations(&self, map: Id<TypeNode>) -> &[AppliedAnnotation]
The user-declared annotations written on the key type of a map.
Sourcepub fn discriminator_annotations(
&self,
union_: Id<TypeNode>,
) -> &[AppliedAnnotation]
pub fn discriminator_annotations( &self, union_: Id<TypeNode>, ) -> &[AppliedAnnotation]
The user-declared annotations written on the discriminator type of a union (DDS-XTypes 1.3 §7.3.1.2.5).
Sourcepub fn key_is_external(&self, map: Id<TypeNode>) -> bool
pub fn key_is_external(&self, map: Id<TypeNode>) -> bool
Whether the key of a map is @external.
Sourcepub fn discriminator_try_construct(&self, union: Id<TypeNode>) -> TryConstruct
pub fn discriminator_try_construct(&self, union: Id<TypeNode>) -> TryConstruct
The behaviour that governs a union’s discriminator. DDS-XTypes 1.3 §7.3.1.2.1.12.5, Table 19.
Sourcepub fn discriminator_is_key(&self, union: Id<TypeNode>) -> bool
pub fn discriminator_is_key(&self, union: Id<TypeNode>) -> bool
Whether a union’s discriminator carries @key.
DDS-XTypes 1.3 Table 21 lists @key against “Structure Members,
Union discriminator” and §7.2.2.4.4.4.8’s example is union MyCommand switch (@key CommandKind). A union that answers true
here is a keyed topic type whose key holder is the discriminator
alone, and §7.2.4.4.4.5 — Table 19’s UNION_TYPE row, “Either
the discriminators of both T1 and T2 are keys or neither are
keys” — makes it unassignable to a union that answers false.
False for anything that is not a union, and false for a union
whose front end was not asked to carry the annotation — see
zerodds_idl_lower::KeyOnUnionDiscriminator.
Sourcepub fn effective_enumerator_value(&self, id: Id<EnumeratorNode>) -> Option<i128>
pub fn effective_enumerator_value(&self, id: Id<EnumeratorNode>) -> Option<i128>
The value an enumerator has, written or positional.
@value(n), else the previous enumerator’s value plus one,
starting at 0. OMG IDL 4.2 §7.4.13.
Returns None only when the handle is stale or an explicit
expression does not evaluate — never a substituted 0, which would
give two enumerators the same value without saying so.
Sourcepub fn effective_bit_position(&self, id: Id<BitValueNode>) -> Option<u16>
pub fn effective_bit_position(&self, id: Id<BitValueNode>) -> Option<u16>
The position a bitmask bit has, written or positional. DDS-XTypes 1.3 §7.3.1.2.1.10.
Sourcepub fn cases_of(&self, type_: Id<TypeNode>) -> &[Id<CaseNode>]
pub fn cases_of(&self, type_: Id<TypeNode>) -> &[Id<CaseNode>]
The cases of a union, empty for every other kind.
Sourcepub fn operations_of(
&self,
interface: Id<InterfaceNode>,
) -> &[Id<OperationNode>]
pub fn operations_of( &self, interface: Id<InterfaceNode>, ) -> &[Id<OperationNode>]
The operations an interface declares directly.
Not the whole answer. InterfaceNode.bases exists and OMG
IDL 4.2 §7.4.3 gives a derived interface every operation of its
bases, so this list is short by exactly those. Only a caller that
writes the base into the target language — a Java extends, a
C++ base clause, a TypeScript extends — wants it; every caller
that emits a flat declaration wants Ast::all_operations_of,
and one that took this instead emitted a type the source did not
describe with nothing to report it.
Sourcepub fn all_operations_of(
&self,
interface: Id<InterfaceNode>,
) -> Vec<Id<OperationNode>>
pub fn all_operations_of( &self, interface: Id<InterfaceNode>, ) -> Vec<Id<OperationNode>>
Every operation an interface has, its bases’ before its own.
Ast::operations_of answers what an interface declares;
this answers what it has. OMG IDL 4.2 §7.4.3: a derived
interface “inherits all the operations and attributes of its
base interfaces”, and a client holding a Derived may call
every one of them. A generated binding that carries only the
declared ones is a type the source did not describe, and nothing
reports it — the operation is simply not there.
Multiple inheritance is a graph and not a chain, so bases are
walked in declaration order — the order §7.4.3 resolves an
operation lookup along — and an interface reached twice through
a diamond contributes its operations once. The depth bound and
the seen list are Ast::all_members_of’s, for the same reason:
an inheritance cycle is invalid IDL and looping here would hang
instead of reporting it.
Sourcepub fn descendants(&self, root: AnyId) -> Vec<AnyId>
pub fn descendants(&self, root: AnyId) -> Vec<AnyId>
Every node reachable from root, itself included, in pre-order.
Terminates on recursive types: a struct containing
sequence<Self> appears once. Spec §6.
Sourcepub fn all_nodes(&self) -> impl Iterator<Item = AnyId> + '_
pub fn all_nodes(&self) -> impl Iterator<Item = AnyId> + '_
Every node the model holds, in identity order.
Sourcepub fn reachable_types(&self, type_: Id<TypeNode>) -> VisitSet
pub fn reachable_types(&self, type_: Id<TypeNode>) -> VisitSet
Every type reachable from type_, itself included.
The layout cache uses this to know which cached plans a change invalidates. Spec §7.
Sourcepub fn reindex(&mut self)
pub fn reindex(&mut self)
Rebuild every index from the model’s current content.
Called after loading a snapshot; ordinary editing maintains the indices from the changeset instead. Spec §6, §9.
Sourcepub fn set_type_identifier(
&mut self,
type_: Id<TypeNode>,
key: TypeIdentifierKey,
) -> Result<(), AstError>
pub fn set_type_identifier( &mut self, type_: Id<TypeNode>, key: TypeIdentifierKey, ) -> Result<(), AstError>
Register a type identifier for a type.
The identifier is computed by the XTypes runtime, not here; the model only indexes it. Spec §1.2.
§Errors
crate::AstError::Core with a stale handle.
Source§impl Ast
impl Ast
Sourcepub fn pending_slots(&self, any: AnyId) -> Vec<PendingSlot>
pub fn pending_slots(&self, any: AnyId) -> Vec<PendingSlot>
Every pending reference a node holds.
The one place that knows where references live, so adding a reference to a node kind is one edit rather than four.
Source§impl Ast
impl Ast
Sourcepub fn pending_waiters(&self, key: &PendingRef) -> &[NodeId]
pub fn pending_waiters(&self, key: &PendingRef) -> &[NodeId]
Every node waiting on a given lookup key.
Sourcepub fn pending_count(&self) -> usize
pub fn pending_count(&self) -> usize
How many references are still pending.
Sourcepub fn resolve_pending(
&mut self,
key: &PendingRef,
target: Id<TypeNode>,
) -> Result<usize, AstError>
pub fn resolve_pending( &mut self, key: &PendingRef, target: Id<TypeNode>, ) -> Result<usize, AstError>
Resolve every waiter on key to target.
Returns how many references changed. Each one emits an Updated
change carrying both the old and the new reference state.
§Errors
AstError::WrongKind when the target cannot satisfy the
waiters — a member’s type reference pointing at an interface, for
instance.
Sourcepub fn resolve_pending_to(
&mut self,
key: &PendingRef,
target: AnyId,
) -> Result<usize, AstError>
pub fn resolve_pending_to( &mut self, key: &PendingRef, target: AnyId, ) -> Result<usize, AstError>
Resolve every waiter on key to any kind of node.
The general form of Ast::resolve_pending: a constant named in
an array dimension, an exception in a raises clause and a base
interface all resolve through here.
§Errors
AstError::Core on an arena failure while rewriting.
Sourcepub fn break_pending(
&mut self,
key: &PendingRef,
cause: BreakCause,
) -> Result<usize, AstError>
pub fn break_pending( &mut self, key: &PendingRef, cause: BreakCause, ) -> Result<usize, AstError>
Mark every waiter on key broken, with a cause.
§Errors
Never fails today; the signature matches Ast::resolve_pending
so callers can treat both the same way.
Sourcepub fn resolve_all_by_name(&mut self) -> Result<ResolveReport, AstError>
pub fn resolve_all_by_name(&mut self) -> Result<ResolveReport, AstError>
§Errors
AstError::Core on an arena failure while rewriting.
Sourcepub fn reindex_pending(&mut self, any: AnyId)
pub fn reindex_pending(&mut self, any: AnyId)
Rebuild a node’s entries in the waiter index.
For a mutation that replaced or added references: the old keys go and the current ones are indexed. An unindexed pending reference never resolves.
Source§impl Ast
impl Ast
Sourcepub fn to_snapshot(&self) -> Result<Vec<u8>, AstError>
pub fn to_snapshot(&self) -> Result<Vec<u8>, AstError>
Serialise the model.
§Errors
AstError::Core when a name or payload exceeds what the length
prefix can express.
Sourcepub fn from_snapshot(bytes: &[u8]) -> Result<Self, AstError>
pub fn from_snapshot(bytes: &[u8]) -> Result<Self, AstError>
Load a model from a snapshot.
Every NodeId is preserved and the indices are rebuilt, so the
loaded model is usable immediately.
§Errors
AstError::Core with AstCoreError::MalformedSnapshot on a
wrong magic, an unknown version, truncation or an out-of-range
handle. Never panics; this is a fuzz target.