Stand-In-Language / stand-in-language

A simple but robust virtual machine
https://stand-in-language.github.io/
Apache License 2.0
10 stars 6 forks source link

implement pattern matching in parser #49

Open sfultong opened 3 years ago

sfultong commented 3 years ago

The first part of this should be pretty easy: all we need to do is be able to match on pairs and zero.

The second part is matching user-defined types and is blocked by #47

sfultong commented 3 years ago

A long term goal is to have incomplete pattern matching sections compile to a refinement check

hhefesto commented 3 years ago

As agreed in gitter dm, also pattern matching on all these:

main = \input -> case input of
                  (a, (b, c)) -> foo a b c
                  "string" -> bar
                  [a, b, c] -> foo a b c
                  2 -> bar
                  [(a,b), c, 2] -> foo' a b c

Just leaving this here for record keeping.

hhefesto commented 3 years ago
case patternn of
  (a,a) -> match1Out

matches like the above aren't allowed (i.e. can't have multiple of the same variable in a match)

hhefesto commented 3 years ago

checkout "_" (i.e. ignore) pattern matching

hhefesto commented 3 years ago
let myConst = (left MyInt0) 8
in case myConst of
     ((left MyInt0) 8) -> ("Success!", 1)
     x             -> ("default case", 0)

This breaks becuase ((left MyInt0) 8) is an application of a function and this is still disallowed because it's not implemented in generateCondition

sfultong commented 3 years ago

note that #71 should help with pattern matching on smart constructors and other functions

sfultong commented 1 year ago

Let's take the simplest pattern matching case, with no variables first:

let a = (0,0)
in case a of
  (0,0) -> "pair"
  _       -> "not pair"

this is equivalent to

let a = (0,0)
in if a
    then -- match outer pair
      if not (left a)
      then -- match first 0
        if not (right a)
        then -- match second 0
           "pair"
        else "not pair"
      else "not pair"
    else "not pair"
sfultong commented 1 year ago

Let's add in a variable:

let a = (0,0)
in case a of
   (x,0) -> (0,x)
   _      -> 2

Then we can do something like

let a = (0,0)
in if a
    then -- match outer pair
      if not (right a)
      then -- match second 0
        (\x -> (0,x)) -- expression after case match
           (left a)     -- apply variable from case match
      else 2
    else 2
hhefesto commented 1 year ago

How about these cases?:

let a = 0
in case a of
   (x,y) -> 0
   _     -> 1
let a = (0,0)
in case a of
   (x,y) -> 0
   _     -> 1

knowing that:

telomare> left 0
0
telomare> left (left 0)
0
sfultong commented 1 year ago
let a = (0,0)
in if a -- notice this if statement, which checks for matching a pair
  then (\x y -> 0) (left a) (right a)
  else 1

This seems like it works for implementing your second case, and you can just do the inverse for case 1