-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overhauls system macro table bootstrapping #872
Conversation
This patch modifies `EncodingContext` to have an empty macro table when constructed for use in v1.0 readers. This allows the Ion 1.0 reader to be used in the process of bootstrapping the Ion 1.1 system macro table, which was previously not possible due to the (not eliminated) circular dependency between macros and readers. System macros that can be expressed in TDL are now constructed from a template definition encoded in Ion 1.0. As a result, the system macro table initialization logic is now substantially easier to read and more straightforward to modify.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #872 +/- ##
==========================================
- Coverage 77.91% 77.62% -0.30%
==========================================
Files 136 136
Lines 34401 34092 -309
Branches 34401 34092 -309
==========================================
- Hits 26805 26465 -340
- Misses 5630 5659 +29
- Partials 1966 1968 +2 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗺️ PR Tour 🧭
let compiled_macro = TemplateCompiler::compile_from_text( | ||
let compiled_macro = TemplateCompiler::compile_from_source( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 The compile_from_text
method previously required Ion 1.1. It now works with any Ion encoding; when used during bootstrapping we only pass it Ion 1.0.
@@ -1317,8 +1317,9 @@ mod tests { | |||
encode_macro_fn: impl FnOnce(MacroAddress) -> Vec<u8>, | |||
test_fn: impl FnOnce(BinaryEExpArgsIterator_1_1<'_>) -> IonResult<()>, | |||
) -> IonResult<()> { | |||
let mut context = EncodingContext::empty(); | |||
let template_macro = TemplateCompiler::compile_from_text(context.get_ref(), macro_source)?; | |||
let mut context = EncodingContext::for_ion_version(IonVersion::v1_1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 At first, Ion 1.0 and 1.1 readers would use the same EncodingContext
. Later, EncodingContext
was modified to be able to take an Ion version, allowing it to initialize the symbol table differently to accommodate Ion 1.1's new symtab. This PR continues that differentiation, causing 1.0 encoding contexts to be initialized with an empty macro table.
@@ -50,6 +54,17 @@ impl ExpansionAnalysis { | |||
} | |||
} | |||
|
|||
/// Returns an expansion analysis for a macro that will produce a single value that may or may | |||
/// not be a system value. | |||
pub const fn possible_system_value() -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 I added a few more named ExpansionAnalysis
constructors so their intent can be expressed at a high level.
@@ -146,7 +174,7 @@ pub struct TemplateCompiler {} | |||
|
|||
impl TemplateCompiler { | |||
/// Takes a TDL expression in the form: | |||
/// ```ion_1_1 | |||
/// ```ion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rustdoc
renderer doesn't differentiate between these two identifiers, but now that the template compiler is Ion-version-agnostic, I wanted this fence to be too.
"$ion" => context | ||
.system_module | ||
.macro_table() | ||
.clone_macro_with_id(macro_id), | ||
"$ion" => ION_1_1_SYSTEM_MACROS.clone_macro_with_id(macro_id), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 System macro resolution now happens in the singleton instance.
Arc::new(Macro::named( | ||
name, | ||
TemplateCompiler::compile_signature(context, signature).unwrap(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 Using the previously defined helper method, we can now compile the signature from source instead of manually instantiating a Vec
of Parameter
s.
template( | ||
r#" | ||
(macro set_symbols (symbols*) | ||
$ion_encoding::( | ||
// Set a new symbol table | ||
(symbol_table [(%symbols)]) | ||
// Include the active encoding module macros | ||
(macro_table $ion_encoding) | ||
) | ||
) | ||
"#, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 My next task is to switch over to the default module syntax, which means redefining these system template macros. That job will now be much easier--I can just revise this Ion 1.0 text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonderful, this is such a nice change.
@@ -827,4 +522,10 @@ impl MacroTable { | |||
} | |||
Ok(()) | |||
} | |||
|
|||
pub(crate) fn reset_to_system_macros(&mut self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 Used (for now) after encountering an Ion 1.1 IVM.
@@ -182,22 +176,14 @@ impl<'top> EncodingContextRef<'top> { | |||
&self.context.macro_table | |||
} | |||
|
|||
pub fn system_symbol_table(&self) -> &'top SymbolTable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 These are no longer needed; we have the singleton.
@@ -287,20 +286,18 @@ mod tests { | |||
fn expand_macro_test( | |||
macro_source: &str, | |||
encode_macro_fn: impl FnOnce(MacroAddress) -> Vec<u8>, | |||
test_fn: impl FnOnce(Reader<AnyEncoding, &[u8]>) -> IonResult<()>, | |||
test_fn: impl FnOnce(Reader<v1_1::Binary, &[u8]>) -> IonResult<()>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🪧 This test was written before encoding directives were implemented. It manually registers a macro definition with the reader instead. Now that 1.0 readers don't have macros, it needs to be limited to working with 1.1 data.
This patch modifies
EncodingContext
to have an empty macro table when constructed for use in Ion 1.0 readers.This allows the Ion 1.0 reader to be used in the process of bootstrapping the Ion 1.1 system macro table, which was previously not possible due to the (now eliminated) circular dependency between macros and readers.
System macros that can be expressed in TDL are now constructed from a template definition encoded in Ion 1.0. As a result, the system macro table initialization logic is now substantially easier to read and more straightforward to modify.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.