mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 16:51:14 +00:00
ifcparse: keep unresolved references in the attribute slots
The parser could not resolve a #name when it read it, because the instance may be defined further down the file, so it left the slot empty and appended (owner, attribute, name) to a side table that a second pass walked. The table held one entry per reference for the whole read: 64 MB on a 58 MB model, the high-water mark of opening. Now the reference stays where the tokenizer put it: the attribute slot holds the instance_reference, or the reference_or_simple_type aggregate for a list (mixed with inline typed values or not), until every instance has been read, and resolve_instance_references() walks each instance's slots and swaps names for instances. Ordering is what the tokenizer produced; nothing is re-derived. A missing name becomes null in a scalar and is dropped from an aggregate, as before; the error keeps its offset. The three transient alternatives are appended to the attribute pack and to argument_type in lock step and are never visible once a file is loaded. Simple type instances read inline (IfcPropertySetDefinitionSet) have their own slots, so their references need no diversion. The table remains for the header entities and for streaming consumers of instance_streamer::references(), which leave resolve_references_in_place off. TXG 58 MB / 210_King 147 MB / OKgate22 231 MB, single thread: time unchanged (1.05 / 2.69 / 4.99 s), memory after the parse 287 -> 274, 698 -> 654, 1086 -> 1036 MB, peak 400 -> 365, 965 -> 871, 1471 -> 1347 MB. This commit was written by an AI coding tool and has not been verified by a human. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013wcN7XquTfUi4vsKQ4KchL
This commit is contained in:
@@ -89,6 +89,21 @@ namespace impl {
|
||||
static std::string get() { return "derived"; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variant_type_name<ifcopenshell::instance_reference> {
|
||||
static std::string get() { return "unresolved reference"; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variant_type_name<std::vector<ifcopenshell::reference_or_simple_type>> {
|
||||
static std::string get() { return "unresolved reference aggregate"; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variant_type_name<std::vector<std::vector<ifcopenshell::reference_or_simple_type>>> {
|
||||
static std::string get() { return "unresolved reference aggregate of aggregates"; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variant_type_name<int> {
|
||||
static std::string get() { return "int"; }
|
||||
@@ -214,7 +229,15 @@ typedef parameter_pack <
|
||||
// An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.))
|
||||
std::vector<std::vector<double>>,
|
||||
// An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3))
|
||||
std::vector<std::vector<express::base>>>
|
||||
std::vector<std::vector<express::base>>,
|
||||
// PARSE-TIME ONLY: a reference, or an aggregate mixing references and
|
||||
// inline typed values, exactly as the tokenizer produced it, held in
|
||||
// the slot until every instance has been read and then replaced by the
|
||||
// three forms above. Never present once a file is loaded. Their indices
|
||||
// match the Argument_UNRESOLVED_* members of argument_type.
|
||||
instance_reference,
|
||||
std::vector<reference_or_simple_type>,
|
||||
std::vector<std::vector<reference_or_simple_type>>>
|
||||
type_variant_parameter_pack;
|
||||
|
||||
template<typename Pack>
|
||||
|
||||
Reference in New Issue
Block a user