pub struct Cpp;Expand description
The C++ backend.
Trait Implementations§
Source§impl CodecTarget for Cpp
impl CodecTarget for Cpp
Source§fn scalar(kind: Scalar) -> Self::Type
fn scalar(kind: Scalar) -> Self::Type
The fixed-width types, from the materialiser’s own table.
Index and Size are both std::size_t here: C++ has an
unsigned type for each, so the distinction C needs — a uint32_t
counter against a size_t position — costs nothing to collapse
and a std::vector::size() returns the latter.
Source§fn handle(kind: Handle) -> Self::Type
fn handle(kind: Handle) -> Self::Type
The handles are types of the runtime’s namespace, not nested in
the writer: zerodds::wire::DHeader.
Source§fn runtime_static(method: &str, args: Vec<Self::Expr>) -> Self::Expr
fn runtime_static(method: &str, args: Vec<Self::Expr>) -> Self::Expr
A free function of the runtime’s namespace.
zerodds::wire::no_dheader() and not Writer::no_dheader(),
which is what this used to write. C++ has free functions, so an
operation the walk describes as having no receiver is one; and
the writer’s qualification was wrong the moment a reader asked
for one — Writer::pid_is_user_member names a static member the
writer has no business declaring.
Source§fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
fn call(callee: &str, args: Vec<Self::Expr>) -> Self::Expr
strcmp is the walk’s name for a three-way code-unit
comparison and is not a name this column’s strings answer to:
the key is a std::string, and a.compare(b) is
char_traits<char>::compare — the same unsigned octet order
C11 §7.24.4 gives strcmp, with the same sign convention.
Source§fn carries_hdds_axes() -> bool
fn carries_hdds_axes() -> bool
runtime/cpp carries the three HDDS axes: begin_packed_element
and finish_packed_element on the writer and the reader, the
DHEADER pair for a sequence element’s own length, and
write_wstring_utf8_octets / read_wstring_utf8_octets.
Source§fn wide_int(value: i128) -> Self::Expr
fn wide_int(value: i128) -> Self::Expr
UINT64_C is C’s; C++ writes the suffix.
−2^63 takes no suffix, because it is not a literal:
-9223372036854775808LL is a minus over a literal one past
LLONG_MAX. zerodds_lang_render::cpp::integer_text carries
the clause and the measurement and answers with the subtraction.
The result is a parenthesised expression rather than a literal,
which every site this reaches admits: the walk puts it inside a
static_cast in an if condition and never where C++ requires
a token — the generated union reader is a chain of comparisons
and carries no case label.
Source§fn case_member(base: &str, field: &str) -> Self::Expr
fn case_member(base: &str, field: &str) -> Self::Expr
The storage behind the accessor of a case (adapter::cpp::union_storage):
the codec reads and writes the storage and not the accessor, whose
setter selects the case.
Source§fn count_of(base: &str, _fixed: Option<u64>) -> Self::Expr
fn count_of(base: &str, _fixed: Option<u64>) -> Self::Expr
A std::vector and a std::array both answer .size(), so the
bound the materialiser fixed is not needed and not used.
Source§fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
fn unary(op: &'static str, value: Self::Expr) -> Self::Expr
The tree has no unary node; !a is a == false and -a is
0 - a, which is what both mean.
!a as a == false, and every other operator as itself.
The negation is spelled out because ! on a value the walk
hands over is operator! on whatever type it has, and == false
says the same thing for a bool without depending on that. The
rest go through cpp::Expr::Unary, which is what a complement
needs: the form this used before wrote 0 ~ a, which no
compiler reads.
Source§fn paren(value: Self::Expr) -> Self::Expr
fn paren(value: Self::Expr) -> Self::Expr
The bracket is written, because the walk asked for it.
This returned the expression unchanged, on the reading that “the
renderer brackets by precedence”. It does not — zerodds-lang-cst
says so in as many words, on Expr::Paren: “this tree holds no
operator precedence, so a renderer walking it cannot know where a
bracket is needed. A builder that needs one says so.”
What that cost: a bitmask’s reader asks for
paren(zd_bits & ~UINT64_C(131)) != 0 and got
zd_bits & ~UINT64_C(131) != 0, which C++ groups as
zd_bits & (~131 != 0) — a different number, and one that would
have accepted every undeclared bit. -Wparentheses -Werror made
it a build failure rather than a wrong value, which is the only
reason it was found at the compiler and not in a byte comparison.
Source§fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
fn handoff(value: Self::Expr, _form: Handoff) -> Self::Expr
A reference takes the value either way: there is no address to take and no array to decay.
Source§fn code_point(value: Self::Expr, _narrow: bool) -> Self::Expr
fn code_point(value: Self::Expr, _narrow: bool) -> Self::Expr
write_char takes a char32_t, so the code point is a cast to
it and the runtime keeps what the width allows.
Source§fn bit_pattern(source: BitPatternSource, value: Self::Expr) -> Self::Expr
fn bit_pattern(source: BitPatternSource, value: Self::Expr) -> Self::Expr
The integer form is two static_casts — through the unsigned
type of the source’s width first, which is what masks a negative
value to its two’s-complement octets instead of sign-extending
it — and the float forms are the runtime’s bit_pattern_f32 and
bit_pattern_f64, because C++ has no expression that reads a
float’s bits without std::memcpy.
Source§fn count_up(counter: &str, bound: Self::Expr, body: Self::Block) -> Self::Stmt
fn count_up(counter: &str, bound: Self::Expr, body: Self::Block) -> Self::Stmt
for (std::size_t i = 0; i < bound; i = i + 1), the step written
out for the reason C’s is: the tree has no increment node, and
one spelling across the backends keeps two columns’ generated
source comparable by eye when their octets disagree.
Source§fn present(base: &str, field: &str) -> Self::Expr
fn present(base: &str, field: &str) -> Self::Expr
v.x != nullptr. XTypes 1.3 §7.5.1.2.4.2: “A NULL pointer shall
indicate an omitted value.”
Source§fn set_present(base: &str, field: &str, present: bool) -> Vec<Self::Stmt>
fn set_present(base: &str, field: &str, present: bool) -> Vec<Self::Stmt>
Nothing on the way in — Cpp::make_indirection makes the object
— and zerodds::wire::destroy(v.x); on the way out, which deletes
what the member held and leaves it NULL.
Source§fn optionals_are_pointers() -> bool
fn optionals_are_pointers() -> bool
An @optional member is a plain pointer (§7.5.1.2.4.2).
Source§fn value_is_pointer(_ast: &Ast, _id: Id<TypeNode>) -> bool
fn value_is_pointer(_ast: &Ast, _id: Id<TypeNode>) -> bool
A std::string is a value, so an @optional string is a
std::string * like any other.
Source§fn refuse_unset_external(present: Self::Expr) -> Vec<Self::Stmt>
fn refuse_unset_external(present: Self::Expr) -> Vec<Self::Stmt>
if (!(v.x != nullptr)) { throw zerodds::wire::UnsetExternal(...); }
Source§fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
fn entry_half(entry: Self::Expr, key: bool) -> Self::Expr
The vector is the elements.
.value() and not *: the two are the same inside a guarded
branch and the first says which one it is.
A std::pair, so first and second.
Source§fn optional_value(
_ast: &Ast,
_id: Id<TypeNode>,
base: &str,
field: &str,
) -> Self::Expr
fn optional_value( _ast: &Ast, _id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
The member, the pointer; Cpp::behind_indirection dereferences it.
Source§fn behind_indirection(
_ast: &Ast,
_id: Id<TypeNode>,
place: Self::Expr,
) -> Self::Expr
fn behind_indirection( _ast: &Ast, _id: Id<TypeNode>, place: Self::Expr, ) -> Self::Expr
*place — the object an optional pointer points at.
Source§fn make_indirection(
_ast: &Ast,
_id: Id<TypeNode>,
place: Self::Expr,
) -> (Vec<Self::Stmt>, Self::Expr)
fn make_indirection( _ast: &Ast, _id: Id<TypeNode>, place: Self::Expr, ) -> (Vec<Self::Stmt>, Self::Expr)
zerodds::wire::pointer_slot(place) — the pointer made to point at
a new object when it points nowhere, and the object.
Source§fn holds_a_cycle_externally() -> bool
fn holds_a_cycle_externally() -> bool
true: an @external member is a std::shared_ptr, and a member on a
cycle needs the same: std::optional<T> and a plain T both want
T complete.
crate::adapter::held_externally is the rule the adapter and
the defaulter ask as well.
Source§fn external_value(
_ast: &Ast,
_id: Id<TypeNode>,
base: &str,
field: &str,
_optional: bool,
) -> Self::Expr
fn external_value( _ast: &Ast, _id: Id<TypeNode>, base: &str, field: &str, _optional: bool, ) -> Self::Expr
*v.x — the shared pointer dereferenced, for @external with
and without @optional alike: the member’s codec takes the
value, and crates/lang-rules/src/adapter/cpp.rs gives an
@external member one indirection and no std::optional around
it.
Source§fn external_destination(
base: &str,
field: &str,
_optional: bool,
) -> (Vec<Self::Stmt>, Self::Expr)
fn external_destination( base: &str, field: &str, _optional: bool, ) -> (Vec<Self::Stmt>, Self::Expr)
zerodds::wire::external_slot(v.x) — the slot filled and the
place handed back, in one expression.
The counterpart of Cpp::optional_destination’s emplace: a
pointer member has nothing to write into until it points at
something. A function of the runtime and not
std::make_shared<T>() written here, because this seam is handed
the member and not its type.
Source§fn external_case_value(
_ast: &Ast,
_id: Id<TypeNode>,
base: &str,
field: &str,
) -> Self::Expr
fn external_case_value( _ast: &Ast, _id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
*v.x for a branch too: a union arm’s @external field is the
same std::shared_ptr<T> a structure member is.
Source§fn external_case_destination(
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn external_case_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
The same allocation and the same place as
Cpp::external_destination.
Source§fn external_present(base: &str, field: &str) -> Self::Expr
fn external_present(base: &str, field: &str) -> Self::Expr
v.x != nullptr: the pointer is the absence, with no
std::optional around it to carry a second one.
Source§fn external_set_present(
base: &str,
field: &str,
present: bool,
) -> Vec<Self::Stmt>
fn external_set_present( base: &str, field: &str, present: bool, ) -> Vec<Self::Stmt>
Nothing on the way in — Cpp::external_destination allocates —
and v.x = nullptr; on the way out.
Source§fn sequence_element(
base: &str,
index: Self::Expr,
element: Self::Type,
) -> (Vec<Self::Stmt>, Self::Expr, Vec<Self::Stmt>)
fn sequence_element( base: &str, index: Self::Expr, element: Self::Type, ) -> (Vec<Self::Stmt>, Self::Expr, Vec<Self::Stmt>)
v[i], except for the one container C++ specialises.
std::vector<bool> packs its elements into bits — [vector.bool] —
and operator[] hands back a proxy object rather than a
bool &. A generated decoder takes its destination by reference,
so there is nothing for it to point at, and the call does not
compile. Read into a local and assign it back: one statement
either side, and only where the element really is bool.
Not solved by changing what a sequence<boolean> maps to. The
element codec is named by the IDL kind — zd_dec_p_boolean —
takes a bool &, and is the same function whether the value is a
member, an array element or a map’s value, so a container holding
anything but bool would not match it either. The proxy is the
container’s, so the work-around belongs at the container.
Source§fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>
fn keep_first(base: &str, count: Self::Expr) -> Vec<Self::Stmt>
v.resize(count);, which is make_room again in the shortening
direction. A std::vector owns its elements, so the ones past
the bound are destroyed rather than left where C leaves them.
Source§fn optional_destination(
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn optional_destination( base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
The member: Cpp::make_indirection makes it point somewhere.
Source§fn bulk_octets_write(base: &str, count: Self::Expr) -> Option<Self::Stmt>
fn bulk_octets_write(base: &str, count: Self::Expr) -> Option<Self::Stmt>
w.write_octets(v.data(), n): std::vector<std::uint8_t> and
std::array<std::uint8_t, N> both hold their octets contiguously.
Source§fn bulk_octets_read(base: &str, count: Self::Expr) -> Option<Self::Stmt>
fn bulk_octets_read(base: &str, count: Self::Expr) -> Option<Self::Stmt>
r.read_octets(v.data(), n), after make_room has resized v.
Source§fn make_room(
base: &str,
_element: Self::Type,
count: Self::Expr,
_assigned_whole: bool,
fill: Vec<Self::Stmt>,
) -> Vec<Self::Stmt>
fn make_room( base: &str, _element: Self::Type, count: Self::Expr, _assigned_whole: bool, fill: Vec<Self::Stmt>, ) -> Vec<Self::Stmt>
One statement: resize throws rather than returning nothing, so
there is no guard and the fill follows unconditionally.
Source§fn materialised(_value: Self::Expr) -> Option<Self::Expr>
fn materialised(_value: Self::Expr) -> Option<Self::Expr>
Nothing to check. Every value this column’s reader materialises
is a std::string or a std::vector, which own their storage
and are never absent; the read either produced one or threw.
Source§fn routine(spec: Routine<Self>) -> Option<Self::Decl>
fn routine(spec: Routine<Self>) -> Option<Self::Decl>
static void zd_enc_T(zerodds::wire::Writer &w, const T &v).
A prototype, unlike Java’s, is emitted: C++ resolves a call to a free function by what is declared above it, so a recursive or mutually recursive type needs the declaration ahead of the body exactly as C does.
Source§fn map_entry_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
fn map_entry_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
std::pair<K, V> — the type the materialiser spells the entry
as. The tag map_entry_name answers is a name for generated
identifiers (zd_dec_map_string_long), not a declared type, so
the default’s named(tag) declared the scratch entry with an
identifier no compiler finds.
Source§fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
fn module_prefix(_ast: &Ast, _id: Id<TypeNode>) -> String
C++ has namespaces, so a module needs no prefix in a name.
Source§fn enumerator_constant(ast: &Ast, id: Id<TypeNode>, name: &str) -> Self::Expr
fn enumerator_constant(ast: &Ast, id: Id<TypeNode>, name: &str) -> Self::Expr
::a::b::Colour::red.
The enumeration’s own name is in the middle, which is what makes
this a seam rather than a prefix and a bare identifier:
adapter/cpp.rs declares a scoped enumeration, so an
enumerator is a member of the type. Its reason is written there —
an unscoped enum would put every enumerator of every
enumeration of a module in one namespace, where two IDL-legal
names collide.
Source§fn default_into(
ast: &Ast,
id: Id<TypeNode>,
place: Self::Expr,
) -> Result<Self::Stmt, EncodeError>
fn default_into( ast: &Ast, id: Id<TypeNode>, place: Self::Expr, ) -> Result<Self::Stmt, EncodeError>
A call to the generated defaulter, as the C column does it.
Not place = T{}. Value-initialisation is not Table 9 — an
enumeration whose first literal is not zero, a union’s selected
branch and a member’s own @default are three rows it gets wrong
— and two columns answering the same table by different
mechanisms is a divergence no byte comparison shows, because both
produce a value. crate::default_cpp carries the whole
argument.
§Errors
Never here. The defaulter is a call, and whether the type has one
is settled where the function is built —
crate::default_cpp::cpp_defaulters_called_by reads the calls
this emitted and refuses there, by name.
Source§fn member_default(
ast: &Ast,
node: &MemberNode,
type_: Id<TypeNode>,
place: Self::Expr,
) -> Result<Vec<Self::Stmt>, EncodeError>
fn member_default( ast: &Ast, node: &MemberNode, type_: Id<TypeNode>, place: Self::Expr, ) -> Result<Vec<Self::Stmt>, EncodeError>
§Errors
EncodeError::NoWriter where a @default names a value C++
cannot spell — a long double literal is the one the corpus
reaches.
Source§fn unsigned_holder(bits: u16) -> Self::Type
fn unsigned_holder(bits: u16) -> Self::Type
bits of a bit set. Read moreSource§fn runtime(receiver: &str, method: &str, args: Vec<Self::Expr>) -> Self::Expr
fn runtime(receiver: &str, method: &str, args: Vec<Self::Expr>) -> Self::Expr
Source§fn whole(base: &str) -> Self::Expr
fn whole(base: &str) -> Self::Expr
Source§fn binary(op: &'static str, lhs: Self::Expr, rhs: Self::Expr) -> Self::Expr
fn binary(op: &'static str, lhs: Self::Expr, rhs: Self::Expr) -> Self::Expr
a op b, written as given.Source§fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
fn cast(type_: Self::Type, value: Self::Expr) -> Self::Expr
Source§fn declare(
type_: Self::Type,
name: &str,
value: Option<Self::Expr>,
) -> Self::Stmt
fn declare( type_: Self::Type, name: &str, value: Option<Self::Expr>, ) -> Self::Stmt
Source§fn when(
condition: Self::Expr,
then: Self::Block,
otherwise: Option<Self::Block>,
) -> Self::Stmt
fn when( condition: Self::Expr, then: Self::Block, otherwise: Option<Self::Block>, ) -> Self::Stmt
if (cond) { .. } else { .. }Source§fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
fn until(condition: Self::Expr, body: Self::Block) -> Self::Stmt
Source§fn elements(base: &str) -> Self::Expr
fn elements(base: &str) -> Self::Expr
Source§fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
fn value_type(ast: &Ast, id: Id<TypeNode>) -> Self::Type
id where a codec holds it. Read moreSource§fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
fn type_name(ast: &Ast, id: Id<TypeNode>) -> String
id. Read moreSource§fn escape(name: &str) -> String
fn escape(name: &str) -> String
Source§fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
fn map_entry_name(ast: &Ast, id: Id<TypeNode>) -> String
map’s entry type. Read moreSource§fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
fn bool_less(left: Self::Expr, right: Self::Expr) -> Self::Expr
left is less than right as boolean map keys —
false before true, the ascending-key order’s reading of the
one-octet wire value. Read moreSource§fn unsigned_int(value: i128) -> Self::Expr
fn unsigned_int(value: i128) -> Self::Expr
Source§fn wide_unsigned(value: u64) -> Self::Expr
fn wide_unsigned(value: u64) -> Self::Expr
Source§fn wide_signed(value: i128) -> Self::Expr
fn wide_signed(value: i128) -> Self::Expr
CodecTarget::wide_unsigned.Source§fn drop_value(value: Self::Expr) -> Self::Stmt
fn drop_value(value: Self::Expr) -> Self::Stmt
Source§fn mark_used(name: &str) -> Vec<Self::Stmt>
fn mark_used(name: &str) -> Vec<Self::Stmt>
Source§fn read_call(
callee: &str,
place: Self::Expr,
form: Handoff,
behaviour: Self::Expr,
) -> Self::Stmt
fn read_call( callee: &str, place: Self::Expr, form: Handoff, behaviour: Self::Expr, ) -> Self::Stmt
zd_dec_<T>(r, <destination>, <behaviour>); — one nested
decoder run, with its answer put where place says. Read moreSource§fn read_forward(callee: &str) -> Self::Stmt
fn read_forward(callee: &str) -> Self::Stmt
Source§fn make_room_of(
_ast: &Ast,
_element_id: Id<TypeNode>,
base: &str,
element: Self::Type,
count: Self::Expr,
assigned_whole: bool,
fill: Vec<Self::Stmt>,
) -> Vec<Self::Stmt>
fn make_room_of( _ast: &Ast, _element_id: Id<TypeNode>, base: &str, element: Self::Type, count: Self::Expr, assigned_whole: bool, fill: Vec<Self::Stmt>, ) -> Vec<Self::Stmt>
CodecTarget::make_room for a sequence whose element is
element_id. A target that cannot spell a slot’s start value from
element alone overrides it: Kotlin’s Array(n) { T() } has no
constructor to call where T is a typealias of Int.Source§fn store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt
fn store(place: Self::Expr, type_: Self::Type, value: Self::Expr) -> Self::Stmt
type_. Read moreSource§fn storage(type_: Self::Type, name: &str) -> Self::Stmt
fn storage(type_: Self::Type, name: &str) -> Self::Stmt
Source§fn header_field(value: Self::Expr, field: &str) -> Self::Expr
fn header_field(value: Self::Expr, field: &str) -> Self::Expr
Source§fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
fn clear_union_cases(base: &str, fields: &[String]) -> Vec<Self::Stmt>
Source§fn open_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
fn open_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
lengths are its dimensions,
outermost first. Read moreSource§fn close_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
fn close_array(base: &str, lengths: &[i128]) -> Vec<Self::Stmt>
CodecTarget::open_array.Source§fn enumerator_ordinal(
ast: &Ast,
id: Id<TypeNode>,
value: Self::Expr,
) -> Self::Expr
fn enumerator_ordinal( ast: &Ast, id: Id<TypeNode>, value: Self::Expr, ) -> Self::Expr
Source§fn case_label(ast: &Ast, discriminator: Id<TypeNode>, value: i128) -> Self::Expr
fn case_label(ast: &Ast, discriminator: Id<TypeNode>, value: i128) -> Self::Expr
Source§fn holds_by_reference(
ast: &Ast,
aggregate: Id<TypeNode>,
member_type: Id<TypeNode>,
optional: bool,
external: bool,
) -> bool
fn holds_by_reference( ast: &Ast, aggregate: Id<TypeNode>, member_type: Id<TypeNode>, optional: bool, external: bool, ) -> bool
@optional or @external member of
aggregate, of type member_type, behind a reference of its own
— where the shared walk would reach it through
CodecTarget::present, CodecTarget::optional_value and
their external_ counterparts. A member this answers for goes
through CodecTarget::reference_present,
CodecTarget::reference_value,
CodecTarget::reference_destination and
CodecTarget::reference_absent instead. Read moreSource§fn reference_present(base: &str, field: &str) -> Self::Expr
fn reference_present(base: &str, field: &str) -> Self::Expr
CodecTarget::holds_by_reference answers for
is present. Reached only where that answered true.Source§fn reference_value(
ast: &Ast,
id: Id<TypeNode>,
base: &str,
field: &str,
) -> Self::Expr
fn reference_value( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> Self::Expr
Source§fn reference_destination(
ast: &Ast,
id: Id<TypeNode>,
base: &str,
field: &str,
) -> (Vec<Self::Stmt>, Self::Expr)
fn reference_destination( ast: &Ast, id: Id<TypeNode>, base: &str, field: &str, ) -> (Vec<Self::Stmt>, Self::Expr)
id is the member’s type.Source§fn reference_absent(base: &str, field: &str) -> Vec<Self::Stmt>
fn reference_absent(base: &str, field: &str) -> Vec<Self::Stmt>
Source§fn externals_are_pointers() -> bool
fn externals_are_pointers() -> bool
@external member behind a pointer
of its own, where the member’s value is not a pointer already. Read moreSource§fn published_name(name: String) -> String
fn published_name(name: String) -> String
Source§fn initialized_reader(
_spec: Routine<Self>,
_initializer: Self::Stmt,
) -> Option<Self::Decl>
fn initialized_reader( _spec: Routine<Self>, _initializer: Self::Stmt, ) -> Option<Self::Decl>
Source§fn bitmask_value(ast: &Ast, id: Id<TypeNode>, value: Self::Expr) -> Self::Expr
fn bitmask_value(ast: &Ast, id: Id<TypeNode>, value: Self::Expr) -> Self::Expr
Source§fn inherited_path(depth: usize) -> Option<String>
fn inherited_path(depth: usize) -> Option<String>
depth levels up,
for a column that binds inheritance as a first member parent
(XTypes 1.3 §7.5.1.4.1.3), ending in the separator: parent. for the
base, parent.parent. for its base. None, the default, is a column
that declares the base’s members in the derived structure.