Skip to content

Syntax feature layering #306

Open
Open

Description

Note

I'd like to continue to update this if it is necessary. This issue currently reflects what we have (in #293).

I'm trying to refactor what ideas we have based on the layering idea. This is also an answer to #305, #281

By layering, I do not mean we must have all features in layer 1 or must defer all features in layer 2.

This layering mostly focused on syntax, not runtime semantics.

I'll analyze this based on whether we can desugar a pattern into the composition of other patterns. (So you'll find the Primitive pattern (1 in { x: 1 }) is in Layer 2.)

This means we can pick all features from Layer 0 and some features from Layer 1 and 2, then the results become a somewhat usable pattern-matching proposal. (You may want to take a look at https://github.com/codehag/pattern-matching-epic).

I include:

  • all "future extensions" (= do not expect it will be in the final proposal, marked by 🤔)
  • features without consensus (might be incorrect!) (also marked by 🤔)

Non-pattern structures

Level 0: Basic feature

We should have at least one of them to enter the pattern world.

  • match expression (match (expr) { ... })
    • basic clause (when, or no keyword at all) (when <pattern>: <expr>, or <pattern>: <expr>)
    • basic clause with guard (when <pattern> if (<expr>): <expr>, or <pattern> if (<expr>): <expr>)
      • 🍬 desugar: can be removed if we have the if pattern
    • default clause (default: <expr>)
    • if clause (if (<expr>): <expr>)
      • 🍬 desugar: can be removed if we have the if pattern
  • is expression
    • 🍬 desugar: impossible if the is expression enables the possibility to declare a new variable inside an expression
    • ⚠️ concern: block scoped declaration { if (!(x is [let a, let b])) return; f(a, b) }

Level 1: Good to have

Maybe future extensions.

  • if-let (and also for, while, do-while)
    • based on the is expression
    • or something else like if match <pattern> (expr) {}
  • 🤔 try-catch integration
  • 🤔 async match
  • 🤔 match on function parameter
    • 🤔 function overload based on parameter matching

Pattern

Level 0: Basic features, impossible to desugar

  • Variable pattern (expected_value)
    • 🍬 desugar with custom matcher: write a function to match the value
  • Object pattern ({ a: expected_value })
    • 🍬 desugar with custom matcher: write a function to match the shape and return value as an array
    • ⚠️ concern: { __proto__: f } means property __proto__ (owned or on the prototype) or [[Prototype]] or early errors?
    • ⚠️ concern: Computed property ({ [Symbol.iterator]: f }) adds arbitrary expression interpolation
    • ⚠️ concern: Shorthand property ({ x }) means { x: x } or { x: let x }?
    • ⚠️ concern: Rest property without matcher ({ ...x }) means { ...x: x } or { ...x: let x }?
  • Binding pattern ({ a: let x })

Level 1: Advance features, impossible to desugar

Level 2: Ergonomic features

  • Simple literal pattern (null, true, 1, 2n, "str", NaN, `abc`)
    • 🍬 desugar: extract let x = ...; somewhere then match against x
  • Near literal pattern (undefined +1 -1 +1n -1n, 🤔 +Infinity, 🤔 -Infinity)
  • 🤔 Unary algebraic pattern (+0, -x)
  • RegEx literal pattern (/a/)
    • 🍬 desugar (with custom matcher): extract let x = ...; somewhere then match against x({ groups: { ... } })
  • 🤔 RegEx named capture group bindings (/a(?<let name>)/)
  • Extended variable pattern ({ value: Number.POSITIVE_INFINITY }, 🤔 { x: Array[Symbol.iterator] })
    • 🍬 desugar: extract let x = ...; somewhere then match against x
    • ⚠️ concern: cache [[Get]] of "POSITIVE_INFINITY" on Number?
    • ⚠️ concern: arbitrary expression interpolation (for ident[expr] syntax)
  • Shorthand property binding ({ let x })
    • 🍬 desugar: { x: let x }
  • 🤔 Shorthand object pattern (let { x, y })
  • 🤔 Relation pattern (>= 2)
    • 🍬 desugar with if pattern and and pattern: let x and if (x > 20 && x < 30)
    • ⚠️ concern: what RHS should be? number literal and (dotted) identifier?
    • > 2, < 2
    • 🤔🤔 instanceof x
    • 🤔🤔 === x
      • ⚠️ concern: looks strange { constructor: === Point }
    • 🤔🤔 "x" in
      • ⚠️ concern: looks strange { x: "a" in }
    • 🤔🤔 typeof "x"
      • ⚠️ concern: we already choose custom matchers to match like { x: Number }, not { x: typeof "number" }
  • 🤔 Void pattern ({ a: 1, b: void })
    • 🍬 desugar: create a new unused binding { a: 1, b: let _ }
    • Note: because we need to also add it into destructing and using.
  • 🤔 Optional property pattern ({ a: 1, b?: 2 })
    • 🍬 desugar (with or): { a: 1 } or { a: 1, b: 2 }
    • 🍬 desugar (with default value): { a: 1, b = undefined }
  • 🤔 Binding-while-matching property pattern ({ let a: Number })
    • 🍬 desugar (with and): { a: Number and let a }
  • 🤔 Chaining guards
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions