This change adds support for named record types. It augments the state of a RecordType instance by
QNm recordName (which is null in case of an anonymous record type), and
InputInfo info (which is not null only for unresolved references as explained below).
While parsing,
the declaration of a named record type adds a fully populated RecordType instance to QueryParser.namedRecordTypes, a QNmMap<RecordType>.
a reference to a (yet) unknown type collects a preliminary populated RecordType instance in QueryParser.recordTypeRefs, a QNmMap<RecordType>, as an "unresolved reference". Later, the state of those instances is replaced by the state of the instance provided by the corresponding declaration, by calling RecordType.resolveRefs. This is necessary because references may occur ahead of the declaration. Note that in this step even the members of RecordType's base class, MapType, are modified. A reference that cannot be matched to a named record declaration results in a "missing type" error, this is where RecordType.info comes into play.
As a named record type may be recursive, measures must be taken to prevent stack overflows while executing eq, instanceOf, union, and intersect. This is accomplished by keeping track of the pairs of objects that are being compared or combined when entering recursive calls, and stopping further processing when a thus known pair is detected. Unfortunatedly some SeqType methods, that used to be involved, had to be inlined in RecordType, in order to pass down the pairs.
The generation of named record type constructor functions as a StaticFunc is fairly straightforward, the actual work however is done in RecordType.RecordConstructor.
This change adds support for named record types. It augments the state of a
RecordType
instance byQNm recordName
(which isnull
in case of an anonymous record type), andInputInfo info
(which is notnull
only for unresolved references as explained below).While parsing,
the declaration of a named record type adds a fully populated
RecordType
instance toQueryParser.namedRecordTypes
, aQNmMap<RecordType>
.a reference to a (yet) unknown type collects a preliminary populated
RecordType
instance inQueryParser.recordTypeRefs
, aQNmMap<RecordType>
, as an "unresolved reference". Later, the state of those instances is replaced by the state of the instance provided by the corresponding declaration, by callingRecordType.resolveRefs
. This is necessary because references may occur ahead of the declaration. Note that in this step even the members ofRecordType
's base class,MapType
, are modified. A reference that cannot be matched to a named record declaration results in a "missing type" error, this is whereRecordType.info
comes into play.As a named record type may be recursive, measures must be taken to prevent stack overflows while executing
eq
,instanceOf
,union
, andintersect
. This is accomplished by keeping track of the pairs of objects that are being compared or combined when entering recursive calls, and stopping further processing when a thus known pair is detected. Unfortunatedly someSeqType
methods, that used to be involved, had to be inlined inRecordType
, in order to pass down the pairs.The generation of named record type constructor functions as a
StaticFunc
is fairly straightforward, the actual work however is done inRecordType.RecordConstructor
.