Skip to content

Simplify Capture and DynamicCaptures storage #177

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

Merged
merged 3 commits into from
Feb 24, 2022

Conversation

milseman
Copy link
Member

Change to an array of structs instead of recursive indirect enums.

Change to an array of structs instead of recursive indirect enums.
@milseman
Copy link
Member Author

@swift-ci please test

/// A structured capture
struct StructuredCapture {
/// The `.optional` height of the result
var numOptionals = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

It's more common to use a "Count" suffix. Can I suggest

Suggested change
var numOptionals = 0
var optionalCount = 0


static func array(_ children: [Capture], childType: Any.Type) -> Capture {
.array(children, childType: AnyType(childType))
var numSomes: Int {
Copy link
Contributor

Choose a reason for hiding this comment

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

someCount

extension Sequence where Element == StructuredCapture {
// FIXME: This is a stop gap where we still slice the input
// and traffic through existentials
func extractExistentialMatch(
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Since the is not side-effecting, it might read better as a noun phrase.

Suggested change
func extractExistentialMatch(
func existentialMatch(

var caps = Array<Any>()
caps.append(input)
caps.append(contentsOf: self.map {
$0.extractExistentialMatchComponent(from: input)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same nit suggestion here, existentialMatchComponent(from:)

public static var empty: Self {
.tuple([])
public struct DynamicCapture: Hashable {
var numOptionals = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

optionalCount


public static var empty: Self {
.tuple([])
public struct DynamicCapture: Hashable {
Copy link
Contributor

Choose a reason for hiding this comment

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

  • This is a user-facing type but it does not have any public API. How would a user access it?
  • Since it now represents a single capture rather than a tree, should we name it AnyCapture instead?
  • We can have properties public var base: Any and public var range: Range<String.Index>.

Copy link
Member Author

@milseman milseman Feb 23, 2022

Choose a reason for hiding this comment

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

  1. Is there any reason for DynamicCaptures to be public other than for the initializer taking one?
  2. SGTM edit: It would be AnySubstringCapture
  3. Err, are back to exposing this to users?

Copy link
Contributor

@rxwei rxwei Feb 23, 2022

Choose a reason for hiding this comment

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

Is there any reason for DynamicCaptures to be public other than for the initializer taking one?

The user would need to access the captured range and substring. How else would the user do it?

It would be AnySubstringCapture

Sure.

Copy link
Member Author

Choose a reason for hiding this comment

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

The user would need to access the captured range and substring. How else would the user do it?

We want API to get the number of captures, and for a given capture to get the slice/range/etc. I was thinking this would be more like static captures, where the more common approach API is on RegexMatch rather than Match. That is, enum DynamicCaptures {} would suffice as just a marker.

Or, we can have a dynamic capture type which holds the API. I'm not too particular on one approach over the other, just wondering what the rationale was or the tradeoffs.

@milseman
Copy link
Member Author

@rxwei updated. I think some of the remaining questions are what API are we exposing in the dynamic case. I'm trying to work towards a world where we have the freedom to have a different storage representation than literally storing Match, but I'm not sure how this applies to DynamicCaptures and/or whether AnyCapture could include values.

@milseman
Copy link
Member Author

@rxwei I pushed a simple mock API for dynamic captures. I feel like at this point, designing the API is a separate discussion/PR than designing the storage representation, but I'm providing some basic API for future prototyping purposes.

@milseman
Copy link
Member Author

@swift-ci please test

@milseman milseman merged commit 0d65e2e into swiftlang:main Feb 24, 2022
@milseman milseman deleted the deforestation_trap branch February 24, 2022 20:04
Comment on lines 56 to 58
for _ in 0..<someCount {
underlying = Optional(underlying) as Any
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The recursive type erasure is unfortunate and will make the final conversion (i.e. as! Match) slower. This could've opened the existentials so that only the outer result is type-erased.

  for _ in 0..<someCount {
    func wrap<T>(_ x: T) {
      underlying = Optional(x) as Any
    }
    _openExistential(underlying, do: wrap)
  }

I've applied this in #182.

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