Codegen: Add Raw::getImmediateChild and Synth::getSynthParent

This commit is contained in:
Tom Hvitved
2025-11-06 20:25:01 +01:00
parent 74b774eec5
commit d77b35c5d2
3 changed files with 95 additions and 1 deletions

View File

@@ -29,9 +29,79 @@ module Raw {
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}}) {{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
} }
{{#is_indexed}}
/**
* Gets the number of {{doc_plural}}.
{{#internal}}
* INTERNAL: Do not use.
{{/internal}}
*/
int getNumberOf{{plural}}() {
result = count(int i | {{tablename}}(this, i, _))
}
{{/is_indexed}}
{{/synth}} {{/synth}}
{{/properties}} {{/properties}}
} }
{{#final}}
private Element getImmediateChildOf{{name}}({{name}} e, int index) {
{{^has_children}}none(){{/has_children}}
{{#has_children}}
{{! n is the base offset 0, for ease of generation }}
{{! n<child> is constructed to be strictly greater than the indexes for <child> children }}
exists(int n{{#all_children}}, int n{{property.singular}}{{/all_children}} |
n = 0
{{#all_children}}
{{#property}}
{{#synth}}
and
n{{singular}} = n{{prev}}
{{/synth}}
{{^synth}}
{{! n<child> is defined on top of the previous definition }}
{{! for single and optional properties it adds 1 (regardless of whether the optional property exists) }}
{{! for repeated it adds 1 + the maximum index (which works for repeated optional as well) }}
and
n{{singular}} = n{{prev}} {{^is_repeated}}+ 1{{/is_repeated}}{{#is_repeated}}+ e.getNumberOf{{plural}}(){{/is_repeated}}
{{/synth}}
{{/property}}
{{/all_children}} and (
none()
{{#all_children}}
{{#property}}
{{^synth}}
or
{{#is_repeated}}
result = e.get{{singular}}(index - n{{prev}})
{{/is_repeated}}
{{^is_repeated}}
index = n{{prev}} and result = e.get{{singular}}()
{{/is_repeated}}
{{/synth}}
{{/property}}
{{/all_children}}
))
{{/has_children}}
}
{{/final}}
{{/classes}} {{/classes}}
/**
* Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct.
*/
pragma[nomagic]
Element getImmediateChild(Element e, int index) {
// why does this look more complicated than it should?
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
none()
{{#classes}}
{{#final}}
or
result = getImmediateChildOf{{name}}(e, index)
{{/final}}
{{/classes}}
}
} }

View File

@@ -23,7 +23,12 @@ private module Impl {
{{! for single and optional properties it adds 1 (regardless of whether the optional property exists) }} {{! for single and optional properties it adds 1 (regardless of whether the optional property exists) }}
{{! for repeated it adds 1 + the maximum index (which works for repeated optional as well) }} {{! for repeated it adds 1 + the maximum index (which works for repeated optional as well) }}
and and
n{{singular}} = n{{prev}} + 1{{#is_repeated}}+ max(int i | i = -1 or exists(e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}(i)) | i){{/is_repeated}} {{#type_is_hideable}}
n{{singular}} = n{{prev}} + 1{{#is_repeated}}+ max(int i | i = -1 or exists(e.getImmediate{{singular}}(i)) | i){{/is_repeated}}
{{/type_is_hideable}}
{{^type_is_hideable}}
n{{singular}} = n{{prev}} {{^is_repeated}}+ 1{{/is_repeated}}{{#is_repeated}}+ e.getNumberOf{{plural}}(){{/is_repeated}}
{{/type_is_hideable}}
{{/property}} {{/property}}
{{/all_children}} and ( {{/all_children}} and (
none() none()

View File

@@ -32,9 +32,28 @@ module Synth {
{{/root}} {{/root}}
{{/non_final_classes}} {{/non_final_classes}}
/**
* INTERNAL: Do not use.
*
* Gets the parent of synthetic element `e`.
*/
Raw::{{root}} getSynthParent(T{{root}} e) {
none()
{{#final_classes}}
{{#is_fresh_synth}}
{{#has_params}}
or
e = T{{name}}({{#params}}{{#first}}result{{/first}}{{^first}}, _{{/first}}{{/params}})
{{/has_params}}
{{/is_fresh_synth}}
{{/final_classes}}
}
{{#final_classes}} {{#final_classes}}
/** /**
* INTERNAL: Do not use. * INTERNAL: Do not use.
*
* Converts a raw element to a synthesized `T{{name}}`, if possible. * Converts a raw element to a synthesized `T{{name}}`, if possible.
*/ */
T{{name}} convert{{name}}FromRaw(Raw::Element e) { T{{name}} convert{{name}}FromRaw(Raw::Element e) {