Skip to content
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

Adds macro evaluator implementation #924

Merged
merged 2 commits into from
Aug 20, 2024

Conversation

popematt
Copy link
Contributor

Issue #, if available:

#730, #731

Description of changes:

An initial macro evaluator implementation.

There are a few things that should be improved, but I haven't done them yet.

  • I want to move the Expander interface and implementations out of MacroEvaluator before adding more system macros so that MacroEvaluator.kt doesn't get ridiculously large.
  • Testing only covers happy cases right now.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@popematt popematt requested review from zslayton and tgregg August 16, 2024 20:14
Copy link

codecov bot commented Aug 16, 2024

Codecov Report

Attention: Patch coverage is 77.77778% with 32 lines in your changes missing coverage. Please review.

Please upload report for BASE (ion-11-encoding@b235531). Learn more about missing BASE report.

Files Patch % Lines
...n/java/com/amazon/ion/impl/macro/MacroEvaluator.kt 76.86% 15 Missing and 16 partials ⚠️
...main/java/com/amazon/ion/impl/macro/Environment.kt 85.71% 1 Missing ⚠️
Additional details and impacted files
@@                Coverage Diff                 @@
##             ion-11-encoding     #924   +/-   ##
==================================================
  Coverage                   ?   69.63%           
  Complexity                 ?     6628           
==================================================
  Files                      ?      190           
  Lines                      ?    26195           
  Branches                   ?     4724           
==================================================
  Hits                       ?    18240           
  Misses                     ?     6535           
  Partials                   ?     1420           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

// SPDX-License-Identifier: Apache-2.0
package com.amazon.ion.impl.macro

data class Environment private constructor(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here.

Comment on lines +176 to +178
assertEquals(StringValue(value = "c"), evaluator.expandNext())
assertEquals(null, evaluator.expandNext())
evaluator.stepOut()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is early step out supported? If so, let's add a test for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is supported. I'll add that.

// Given:
// (macro foo_struct (x*) {foo: x})
// When:
// (:foo_struct (: bar baz))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not relevant to this PR, but the more I look at this syntax for an argument group, the less I like it... we've been trained that whitespace after a colon doesn't matter, except here it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why I tried to propose [:

Comment on lines +475 to +476
// Yes, the field name should be here only once. The Ion reader that wraps the evaluator
// is responsible for carrying the field name over to any values that follow.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the API that I came up with. 🤷‍♂️

To make it easier for me to ensure correctness, I started by having very segregated concerns. The MacroEvaluator class is only concerned with combining Expressions. The MacroEvaluatorAsIonReader class is responsible for taking the MacroEvaluator output and making it fit the IonReader expectations. It doesn't have to be this way, and if we merge the MacroEvaluatorAsIonReader class with MacroEvaluator, then this will no longer be relevant.

Comment on lines +505 to +506
// Yes, the field name should be here. The Ion reader that wraps the evaluator
// is responsible for discarding the field name if no values follow.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above—same reason.

macroEvaluator.expansionStack.peek().expansionKind = ExpansionKind.Values
val minDepth = macroEvaluator.expansionStack.size()
// ...But capture the output and turn it into a String
val sb = StringBuilder()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking forward to performance tuning, maybe we could have a reusable StringBuilder that is used for all make_string expansions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could run into some problems with macros that are composed of other macros when the is a nested make_string in the arguments for a make_string, but we could certainly see about a StringBuilder pool.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or one StringBuilder for each nesting depth?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that might work.

Placeholder -> TODO("unreachable")
is MacroInvocation -> pushTdlMacroExpansion(currentExpr)
is EExpression -> pushEExpressionExpansion(currentExpr)
is VariableRef -> pushVariableExpansion(currentExpr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When/where is the variable substituted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In pushVariableExpansion, it gets the argument expressions from the environment and pushes them into the expansion stack.

@popematt popematt merged commit f6a9c61 into amazon-ion:ion-11-encoding Aug 20, 2024
18 of 36 checks passed
@popematt popematt deleted the macro-evaluator-impl branch August 20, 2024 20:44
tgregg pushed a commit that referenced this pull request Sep 9, 2024
tgregg pushed a commit that referenced this pull request Dec 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants