# Pattern Matching¶

Felix provides an advanced pattern matching system which includes generic patterns and user defined patterns.

Pattern matching provides a way to decode a data structure by providing an image of the type with “holes” in it which are indicated by variables. Provided pattern matches the value the variables take on the value of the part of the type which is missing.

For products, pattern variables are projections of the value, possibly chained together in reverse order.

For sum types including variants, the argument of the constructor which created the value is extracted, after checking the value was indeed made by the corresponding injection function. If not, the next pattern is tried.

A pattern match over a product type is said to be irrefutable because it cannot fail after static type checking; however a pattern it is included in may fail, and a pattern matching a component may also fail.

## Matches¶

### Syntax¶

syntax patterns {

block = match_stmt;

smatch_head := "chainmatch" sexpr "with" stmt_matching+ =># "(,_2 ,_4)";
smatch_link := "ormatch" sexpr "with" stmt_matching+ =># "(,_2 ,_4)";
smatch_chain := smatch_chain smatch_link =># "(cons _2 _1)"; // revsersed

match_stmt := smatch_head smatch_chain "endmatch" ";" =>#
"(ast_stmt_chainmatch ,_sr ,(cons _1 (reverse _2)))"
;

match_stmt := smatch_head "endmatch" ";" =>#
"(ast_stmt_match (,_sr ,_1))"
;

//$Pattern match statement. //$ At least one branch must match or the program aborts with a match failure.
match_stmt:= "match" sexpr "with" stmt_matching+ "endmatch" ";" =>#
"(ast_stmt_match (,_sr ,_2 ,_4))";

match_stmt:= "match" sexpr "do" stmt_matching+ "done" =>#
"(ast_stmt_match (,_sr ,_2 ,_4))";

//$A single branch of a pattern match statement. //$ The match argument expression is compared to the pattern.
//$If it matches any contained pattern variables are assigned //$ the values in the corresponding possition of the expression,
//$and the statements are executed. private stmt_matching := "|" spattern "=>" stmt+ =># "(,_2 ,_4)"; //$ Pattern match expression with terminator.
satom := pattern_match "endmatch" =># "_1";

//$Pattern match expression without terminator. //$ Match the expression against each of the branches in the matchings.
//$At least one branch must match or the program aborts with a match failure. pattern_match := "match" sexpr "with" smatching+ =># "(ast_match ,_sr (,_2 ,_4))"; //$ The match argument expression is compared to the pattern.
//$If it matches any contained pattern variables are assigned //$ the values in the corresponding possition of the expression,
//$and expression is evaluated and becomes the return value //$ of the whole match.
smatching := "|" spattern "=>" x[let_pri] =># "(,_2 ,_4)";

//$Match nothing. smatching := "|" "=>" sexpr =># "((pat_none ,_sr) ,_3)";  ## Patterns¶ ### Syntax¶ spattern := sguard_pattern ("|" sguard_pattern)* =># "(chain 'pat_alt _1 _2)"; sguard_pattern := swith_pattern "when" sexpr =># "(pat_when ,_sr ,_1 ,_3)"; sguard_pattern := swith_pattern =># "_1";  #### With pattern¶ ### Syntax¶ swith_pattern := sas_pattern "with" spat_avars =># "(pat_with ,_sr ,_1 ,_3)"; spat_avar := sname "=" stypeexpr =># "(,_1 ,_3)"; spat_avars := list::commalist1<spat_avar> =># "_1"; swith_pattern := sas_pattern =># "_1";  #### As pattern¶ ### Syntax¶ sas_pattern := scons_pattern "as" sname =># "(pat_as ,_sr ,_1 ,_3)"; sas_pattern := scons_pattern =># "_1";  #### Cons pattern¶ ### Syntax¶ scons_pattern := stuple_cons_pattern "!" scons_pattern scons_pattern := stuple_cons_pattern scons_pattern :="[" slist_pattern "]" scons_pattern :="[" "]"  #### List pattern¶ ### Syntax¶ slist_pattern := scoercive_pattern "," slist_pattern slist_pattern := scoercive_pattern slist_pattern := scoercive_pattern ",," scoercive_pattern  #### Tuple Cons Pattern¶ ### Syntax¶ stuple_cons_pattern := stuple_pattern ",," stuple_cons_pattern =># stuple_cons_pattern := stuple_pattern "<,,>" stuple_cons_pattern =># stuple_cons_pattern := stuple_pattern =># "_1"  #### Tuple Pattern¶ ### Syntax¶ stuple_pattern := scoercive_pattern ("," scoercive_pattern )* =>#  #### Coercive Pattern¶ ### Syntax¶ scoercive_pattern := sapplicative_pattern "|>" x[sarrow_pri] scoercive_pattern := sapplicative_pattern ":" x[sarrow_pri] scoercive_pattern := sapplicative_pattern scoercive_pattern := stypeexpr ":>>" sname  #### Applicative Pattern¶ ### Syntax¶ sapplicative_pattern := sctor_name sargument_pattern private sapplicative_pattern := sctor_name stypeexpr+ sargument_pattern //$ The sum type constructor can either be a qualified name...
private sctor_name := sname

//$or it can be a case literal. sctor_name := "case" sinteger sctor_name := "" sinteger sapplicative_pattern := "case" sname sargument_pattern sapplicative_pattern := "" sname sargument_pattern sargument_pattern := satomic_pattern sapplicative_pattern := satomic_pattern  #### Atomic Pattern¶ ### Syntax¶  satomic_pattern := sname satomic_pattern := "?" sname satomic_pattern := "val" sname satomic_pattern := "#" sctor_name satomic_pattern := "#" "case" sname satomic_pattern := "" sname satomic_pattern := "case" sinteger satomic_pattern := "" sinteger satomic_pattern := "true" satomic_pattern := "false" satomic_pattern := "_" satomic_pattern := "(" spattern ")" satomic_pattern := "(" ")" satomic_pattern := "(" spat_assign ("," spat_assign )* ")" spat_assign := sname "=" spattern =># "(,_1 ,_3)"; satomic_pattern := "(" spat_assign ("," spat_assign )* "|" sname ")" satomic_pattern := "$" "(" sexpr ")"
satomic_pattern := sliteral
satomic_pattern := sliteral ".." sliteral

}