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

UPW[WIP]: faster, lightweight, more flexible and concisely implemented pattern matching #83

Merged
merged 17 commits into from
May 4, 2020

Conversation

thautwarm
Copy link
Owner

@thautwarm thautwarm commented May 2, 2020

  1. generating more stably typed code, hence sometimes can be ~x2 faster than the the previous

    • bottom-up type info propagation via tagless final
    • top-down propagation
  2. MLStyle as a dev-only dep

    • generating quite readable and concise code
    • generating julia code requring no runtime support(any Expr to julia code library?)
  3. more intuitive pattern objects(top-level first-class patterns)

    • pattern_compile(::Type{P}, self::Function, type_params, type_args, args) pattern_uncall(::Type{P}, self::Function, type_params, type_args, args)

      Defining pattern_compile pattern_uncall for type P will control the code generation when P is used as a pattern.

      self is given by our compiler, and self(::Expr) will return a pattern.

      Within the following code, pattern syntax (a, b, c) will be equivalent to MyTuplePat(a, b, c).

      struct MyTuplePat end
      MLStyle.pattern_uncall(::Type{MyTuplePat}, self, _, _, args) =
          Expr(:tuple, args...) |> self
      
      @match (1, 2, 3) begin
          MyTuplePat(a, b, c) => a + c + b
          _ => error("anyway")
      end # => 6
    • is_enum

      In the following code, pattern S is equivalent to S():

      struct S end
      MLStyle.is_enum(::Type{S}) = true
      
      pattern_uncall(::Type{S}, self, _, _, _) =
          :(::$S) |> self
      
      @match S() begin
          S => 1
      end # => 1

    Above designs deprecate some redundant/non-intuitive things, e.g., MLStyle Extension List

  4. new features
    - [x] according to real world practice, things like @switch can be productive:

      @switch val begin
           @case pat1
                stmt1
                stmt2
           @case pat2
                ...
      end

Breakage&Deprecation

Before merging this, we shall make sure all of the downstream uses of MLStyle are concerned and well compatible. If not, workaround PRs should be created for fixing the corresponding issues.

Most stuffs can be compatible, except the following ones need attentions:

  1. the internal APIs def_pattern, def_app_pattern, etc., will be removed.
  2. scoping specifiers for data type definitions: @data public, @data internal, etc., will be deprecated as they now just do nothing.
    The new visibility is the same as julia scopes, i.e, an object implements pattern_compile is visible in current module, you can use it as a pattern when matching.
  3. defining view patterns(active patterns) doesn't need @active macro. Using @active to define view patterns will be deprecated, and note that the view patterns defined by @active cannot be statically generated, i.e., if you use @active, you cannot use MLStyle as a dev-only dependency.

@thautwarm
Copy link
Owner Author

add pattern_unref, which provides the capability to overload code generation for patterns like A[...]

@thautwarm
Copy link
Owner Author

uncomprehension patterns [pat for value in seq] => seq becomes orders of magnitude faster due to the better use of type information.

* support 'MLStyle.Modules.*'
* all tests passing
  - add '@testcase' macro and '@lift' marker in "runtests.jl". works perfectly for our cases.
* restore MLStyle.Render but deprecate it
* no need of 'MLStyle.Modules.AST.Compat' as now our pattern totally can somehow understand the scope info.
* fix duplicate @Label issues in when patterns('@when' from 'MLStyle.StandardPatterns.WhenCases'):
    - add 'CFGItem' and 'CFGSpec' types to MLStyle.AbstractPattern.
    - use CFGJump(CFGJump(:x) = CFGItem(:symbolicgoto, :x)) and CFGLabel(works the same way as CFGJump)
    - 'MLStyle.AbstractPattern.init_cfg':
      every time, when using generator functions from MLStyle APIs, such as 'gen_match', 'gen_switch',
      you should invoke 'MLStyle.AbstractPattern.init_cfg' before splicing it into your code.
* record matching:
   support 4 kinds of matching for records:
   1. positional:  S(a, b, c)
   2. field punning: S(; a, b=b_, c=c_), 'a, b, c' are names,  'b_, c_' are patterns
   3. wildcard constructor: S(_), if type of S matches. for compatibility, and consistency with active patterns
   4. just type check(same as 3): S()
* active pattern clarification:
   - S()  : if '@Active S(x)' returns true, otherwise(fail) returns false
   - S(v) : if '@Active S(x)' returns Some(v), otherwise(fail) returns nothing
   - S(a, b): more than 2 arguments, '@Active S(x)' returns a tuple
* fix some typos in documentations(cuture->cultural, etc)
@codecov
Copy link

codecov bot commented May 4, 2020

Codecov Report

Merging #83 into master will increase coverage by 7.00%.
The diff coverage is 85.09%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #83      +/-   ##
==========================================
+ Coverage   78.57%   85.57%   +7.00%     
==========================================
  Files          20       31      +11     
  Lines         658     1442     +784     
==========================================
+ Hits          517     1234     +717     
- Misses        141      208      +67     
Impacted Files Coverage Δ
src/AbstractPatterns/Print.jl 0.00% <0.00%> (ø)
src/AbstractPatterns/structures/Print.jl 0.00% <0.00%> (ø)
src/MLStyle.jl 100.00% <ø> (ø)
src/MatchCore.jl 86.23% <ø> (ø)
src/Render.jl 3.12% <3.12%> (-68.75%) ⬇️
src/Extension.jl 50.00% <50.00%> (-32.36%) ⬇️
src/Sugars.jl 66.66% <66.66%> (ø)
src/AbstractPatterns/impl/BasicPatterns.jl 68.23% <68.23%> (ø)
src/AbstractPatterns/DataStructure.jl 70.00% <70.00%> (ø)
...c/AbstractPatterns/structures/TypeTagExtraction.jl 74.07% <74.07%> (ø)
... and 40 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 536566c...808804b. Read the comment docs.

@thautwarm
Copy link
Owner Author

I'd merge it to master to show the dev status.

@thautwarm thautwarm merged commit 9202014 into master May 4, 2020
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.

1 participant