github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optgen/lang/testdata/compiler (about)

     1  #
     2  # Simple case.
     3  #
     4  compile
     5  # Join comment.
     6  define Join {
     7      # Left comment.
     8      Left  Expr
     9  
    10      # Right comment.
    11      Right Expr
    12  }
    13  
    14  # CommuteJoin comment.
    15  [CommuteJoin]
    16  (Join $left:* $right:*) => (Join $right $left)
    17  ----
    18  (Compiled
    19  	(Defines
    20  		(Define
    21  			Comments=(Comments # Join comment.)
    22  			Tags=(Tags)
    23  			Name="Join"
    24  			Fields=(DefineFields
    25  				(DefineField
    26  					Comments=(Comments # Left comment.)
    27  					Name="Left"
    28  					Type="Expr"
    29  					Src=<test.opt:4:5>
    30  				)
    31  				(DefineField
    32  					Comments=(Comments # Right comment.)
    33  					Name="Right"
    34  					Type="Expr"
    35  					Src=<test.opt:7:5>
    36  				)
    37  			)
    38  			Src=<test.opt:2:1>
    39  		)
    40  	)
    41  	(Rules
    42  		(Rule
    43  			Comments=(Comments # CommuteJoin comment.)
    44  			Name="CommuteJoin"
    45  			Tags=(Tags)
    46  			Match=(Func
    47  				Name=Join
    48  				Args=(Slice
    49  					(Bind Label="left" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:12:7>)
    50  					(Bind Label="right" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:12:15>)
    51  				)
    52  				Typ=Join
    53  				Src=<test.opt:12:1>
    54  			)
    55  			Replace=(Func
    56  				Name=Join
    57  				Args=(Slice
    58  					(Ref Label="right" Typ=Expr Src=<test.opt:12:34>)
    59  					(Ref Label="left" Typ=Expr Src=<test.opt:12:41>)
    60  				)
    61  				Typ=Join
    62  				Src=<test.opt:12:28>
    63  			)
    64  			Src=<test.opt:11:1>
    65  		)
    66  	)
    67  )
    68  
    69  #
    70  # Expand multiple match names into multiple rules and use OpName function with
    71  # no arguments.
    72  #
    73  compile
    74  [Join]
    75  define InnerJoin {
    76      Left  Expr
    77      Right Expr
    78  }
    79  [Join]
    80  define LeftJoin {
    81      Left  Expr
    82      Right Expr
    83  }
    84  define Project {
    85      Input Expr
    86  }
    87  
    88  # Name rule comment.
    89  [Name]
    90  (Join | Project * & (Func (OpName))) => ((OpName) (OpName))
    91  ----
    92  (Compiled
    93  	(Defines
    94  		(Define
    95  			Comments=(Comments)
    96  			Tags=(Tags Join)
    97  			Name="InnerJoin"
    98  			Fields=(DefineFields
    99  				(DefineField Comments=(Comments) Name="Left" Type="Expr" Src=<test.opt:3:5>)
   100  				(DefineField Comments=(Comments) Name="Right" Type="Expr" Src=<test.opt:4:5>)
   101  			)
   102  			Src=<test.opt:1:1>
   103  		)
   104  		(Define
   105  			Comments=(Comments)
   106  			Tags=(Tags Join)
   107  			Name="LeftJoin"
   108  			Fields=(DefineFields
   109  				(DefineField Comments=(Comments) Name="Left" Type="Expr" Src=<test.opt:8:5>)
   110  				(DefineField Comments=(Comments) Name="Right" Type="Expr" Src=<test.opt:9:5>)
   111  			)
   112  			Src=<test.opt:6:1>
   113  		)
   114  		(Define
   115  			Comments=(Comments)
   116  			Tags=(Tags)
   117  			Name="Project"
   118  			Fields=(DefineFields
   119  				(DefineField Comments=(Comments) Name="Input" Type="Expr" Src=<test.opt:12:5>)
   120  			)
   121  			Src=<test.opt:11:1>
   122  		)
   123  	)
   124  	(Rules
   125  		(Rule
   126  			Comments=(Comments # Name rule comment.)
   127  			Name="Name"
   128  			Tags=(Tags)
   129  			Match=(Func
   130  				Name=InnerJoin
   131  				Args=(Slice
   132  					(And
   133  						Left=(Any Typ=Expr)
   134  						Right=(CustomFunc
   135  							Name=Func
   136  							Args=(Slice InnerJoin)
   137  							Typ=Expr
   138  							Src=<test.opt:17:21>
   139  						)
   140  						Typ=Expr
   141  						Src=<test.opt:17:17>
   142  					)
   143  				)
   144  				Typ=InnerJoin
   145  				Src=<test.opt:17:1>
   146  			)
   147  			Replace=(Func
   148  				Name=InnerJoin
   149  				Args=(Slice InnerJoin)
   150  				Typ=InnerJoin
   151  				Src=<test.opt:17:41>
   152  			)
   153  			Src=<test.opt:16:1>
   154  		)
   155  		(Rule
   156  			Comments=(Comments # Name rule comment.)
   157  			Name="Name"
   158  			Tags=(Tags)
   159  			Match=(Func
   160  				Name=LeftJoin
   161  				Args=(Slice
   162  					(And
   163  						Left=(Any Typ=Expr)
   164  						Right=(CustomFunc
   165  							Name=Func
   166  							Args=(Slice LeftJoin)
   167  							Typ=Expr
   168  							Src=<test.opt:17:21>
   169  						)
   170  						Typ=Expr
   171  						Src=<test.opt:17:17>
   172  					)
   173  				)
   174  				Typ=LeftJoin
   175  				Src=<test.opt:17:1>
   176  			)
   177  			Replace=(Func
   178  				Name=LeftJoin
   179  				Args=(Slice LeftJoin)
   180  				Typ=LeftJoin
   181  				Src=<test.opt:17:41>
   182  			)
   183  			Src=<test.opt:16:1>
   184  		)
   185  		(Rule
   186  			Comments=(Comments # Name rule comment.)
   187  			Name="Name"
   188  			Tags=(Tags)
   189  			Match=(Func
   190  				Name=Project
   191  				Args=(Slice
   192  					(And
   193  						Left=(Any Typ=Expr)
   194  						Right=(CustomFunc
   195  							Name=Func
   196  							Args=(Slice Project)
   197  							Typ=Expr
   198  							Src=<test.opt:17:21>
   199  						)
   200  						Typ=Expr
   201  						Src=<test.opt:17:17>
   202  					)
   203  				)
   204  				Typ=Project
   205  				Src=<test.opt:17:1>
   206  			)
   207  			Replace=(Func
   208  				Name=Project
   209  				Args=(Slice Project)
   210  				Typ=Project
   211  				Src=<test.opt:17:41>
   212  			)
   213  			Src=<test.opt:16:1>
   214  		)
   215  	)
   216  )
   217  
   218  #
   219  # Compile OpName functions with arguments.
   220  #
   221  compile
   222  define Op {
   223      Input Expr
   224  }
   225  define SubOp1 {}
   226  define SubOp2 {}
   227  
   228  [SingleName]
   229  (Op $input:(SubOp1) & ^(Func (OpName $input))) => ((OpName $input))
   230  
   231  [MultipleNames]
   232  (Op $input:(SubOp1 | SubOp2) & (Func (OpName $input))) => ((OpName $input))
   233  ----
   234  (Compiled
   235  	(Defines
   236  		(Define
   237  			Comments=(Comments)
   238  			Tags=(Tags)
   239  			Name="Op"
   240  			Fields=(DefineFields
   241  				(DefineField Comments=(Comments) Name="Input" Type="Expr" Src=<test.opt:2:5>)
   242  			)
   243  			Src=<test.opt:1:1>
   244  		)
   245  		(Define Comments=(Comments) Tags=(Tags) Name="SubOp1" Fields=(DefineFields) Src=<test.opt:4:1>)
   246  		(Define Comments=(Comments) Tags=(Tags) Name="SubOp2" Fields=(DefineFields) Src=<test.opt:5:1>)
   247  	)
   248  	(Rules
   249  		(Rule
   250  			Comments=(Comments)
   251  			Name="SingleName"
   252  			Tags=(Tags)
   253  			Match=(Func
   254  				Name=Op
   255  				Args=(Slice
   256  					(Bind
   257  						Label="input"
   258  						Target=(And
   259  							Left=(Func Name=SubOp1 Args=(Slice) Typ=SubOp1 Src=<test.opt:8:12>)
   260  							Right=(Not
   261  								Input=(CustomFunc
   262  									Name=Func
   263  									Args=(Slice
   264  										(CustomFunc
   265  											Name=OpName
   266  											Args=(Slice
   267  												(Ref Label="input" Src=<test.opt:8:38>)
   268  											)
   269  											Src=<test.opt:8:30>
   270  										)
   271  									)
   272  									Typ=Expr
   273  									Src=<test.opt:8:24>
   274  								)
   275  								Typ=Expr
   276  								Src=<test.opt:8:23>
   277  							)
   278  							Typ=SubOp1
   279  							Src=<test.opt:8:12>
   280  						)
   281  						Typ=SubOp1
   282  						Src=<test.opt:8:5>
   283  					)
   284  				)
   285  				Typ=Op
   286  				Src=<test.opt:8:1>
   287  			)
   288  			Replace=(Func Name=SubOp1 Args=(Slice) Typ=SubOp1 Src=<test.opt:8:51>)
   289  			Src=<test.opt:7:1>
   290  		)
   291  		(Rule
   292  			Comments=(Comments)
   293  			Name="MultipleNames"
   294  			Tags=(Tags)
   295  			Match=(Func
   296  				Name=Op
   297  				Args=(Slice
   298  					(Bind
   299  						Label="input"
   300  						Target=(And
   301  							Left=(Func
   302  								Name=(Names SubOp1 SubOp2)
   303  								Args=(Slice)
   304  								Typ=[SubOp1 | SubOp2]
   305  								Src=<test.opt:11:12>
   306  							)
   307  							Right=(CustomFunc
   308  								Name=Func
   309  								Args=(Slice
   310  									(CustomFunc
   311  										Name=OpName
   312  										Args=(Slice
   313  											(Ref Label="input" Src=<test.opt:11:46>)
   314  										)
   315  										Src=<test.opt:11:38>
   316  									)
   317  								)
   318  								Typ=Expr
   319  								Src=<test.opt:11:32>
   320  							)
   321  							Typ=[SubOp1 | SubOp2]
   322  							Src=<test.opt:11:12>
   323  						)
   324  						Typ=[SubOp1 | SubOp2]
   325  						Src=<test.opt:11:5>
   326  					)
   327  				)
   328  				Typ=Op
   329  				Src=<test.opt:11:1>
   330  			)
   331  			Replace=(Func
   332  				Name=(CustomFunc
   333  					Name=OpName
   334  					Args=(Slice
   335  						(Ref Label="input" Typ=[SubOp1 | SubOp2] Src=<test.opt:11:68>)
   336  					)
   337  					Src=<test.opt:11:60>
   338  				)
   339  				Args=(Slice)
   340  				Typ=[SubOp1 | SubOp2]
   341  				Src=<test.opt:11:59>
   342  			)
   343  			Src=<test.opt:10:1>
   344  		)
   345  	)
   346  )
   347  
   348  #
   349  # Compile custom match function.
   350  #
   351  compile
   352  define Op {
   353      Input Expr
   354  }
   355  
   356  [CustomFunc]
   357  (Op $input:* & (Func $input (SubFunc $input (SubSubFunc)))) => $input
   358  ----
   359  (Compiled
   360  	(Defines
   361  		(Define
   362  			Comments=(Comments)
   363  			Tags=(Tags)
   364  			Name="Op"
   365  			Fields=(DefineFields
   366  				(DefineField Comments=(Comments) Name="Input" Type="Expr" Src=<test.opt:2:5>)
   367  			)
   368  			Src=<test.opt:1:1>
   369  		)
   370  	)
   371  	(Rules
   372  		(Rule
   373  			Comments=(Comments)
   374  			Name="CustomFunc"
   375  			Tags=(Tags)
   376  			Match=(Func
   377  				Name=Op
   378  				Args=(Slice
   379  					(Bind
   380  						Label="input"
   381  						Target=(And
   382  							Left=(Any Typ=Expr)
   383  							Right=(CustomFunc
   384  								Name=Func
   385  								Args=(Slice
   386  									(Ref Label="input" Src=<test.opt:6:22>)
   387  									(CustomFunc
   388  										Name=SubFunc
   389  										Args=(Slice
   390  											(Ref Label="input" Src=<test.opt:6:38>)
   391  											(CustomFunc Name=SubSubFunc Args=(Slice) Src=<test.opt:6:45>)
   392  										)
   393  										Src=<test.opt:6:29>
   394  									)
   395  								)
   396  								Typ=Expr
   397  								Src=<test.opt:6:16>
   398  							)
   399  							Typ=Expr
   400  							Src=<test.opt:6:12>
   401  						)
   402  						Typ=Expr
   403  						Src=<test.opt:6:5>
   404  					)
   405  				)
   406  				Typ=Op
   407  				Src=<test.opt:6:1>
   408  			)
   409  			Replace=(Ref Label="input" Typ=Expr Src=<test.opt:6:64>)
   410  			Src=<test.opt:5:1>
   411  		)
   412  	)
   413  )
   414  
   415  #
   416  # Use string expressions with op matcher, construct, and custom functions.
   417  #
   418  compile
   419  define Op {
   420      Input Expr
   421  }
   422  
   423  [Strings]
   424  (Op $input:"foo" & (Func "bar")) => (Op (Func "bar"))
   425  ----
   426  (Compiled
   427  	(Defines
   428  		(Define
   429  			Comments=(Comments)
   430  			Tags=(Tags)
   431  			Name="Op"
   432  			Fields=(DefineFields
   433  				(DefineField Comments=(Comments) Name="Input" Type="Expr" Src=<test.opt:2:5>)
   434  			)
   435  			Src=<test.opt:1:1>
   436  		)
   437  	)
   438  	(Rules
   439  		(Rule
   440  			Comments=(Comments)
   441  			Name="Strings"
   442  			Tags=(Tags)
   443  			Match=(Func
   444  				Name=Op
   445  				Args=(Slice
   446  					(Bind
   447  						Label="input"
   448  						Target=(And
   449  							Left="foo"
   450  							Right=(CustomFunc
   451  								Name=Func
   452  								Args=(Slice "bar")
   453  								Typ=Expr
   454  								Src=<test.opt:6:20>
   455  							)
   456  							Typ=<string>
   457  							Src=<test.opt:6:12>
   458  						)
   459  						Typ=<string>
   460  						Src=<test.opt:6:5>
   461  					)
   462  				)
   463  				Typ=Op
   464  				Src=<test.opt:6:1>
   465  			)
   466  			Replace=(Func
   467  				Name=Op
   468  				Args=(Slice
   469  					(CustomFunc
   470  						Name=Func
   471  						Args=(Slice "bar")
   472  						Typ=Expr
   473  						Src=<test.opt:6:41>
   474  					)
   475  				)
   476  				Typ=Op
   477  				Src=<test.opt:6:37>
   478  			)
   479  			Src=<test.opt:5:1>
   480  		)
   481  	)
   482  )
   483  
   484  #
   485  # Use list expressions with match and replace functions.
   486  #
   487  compile
   488  define Op {
   489      Input1 Expr
   490      Input2 Expr
   491      Input3 Expr
   492      Input4 Expr
   493      Input5 Expr
   494      Input6 Expr
   495  }
   496  
   497  [Lists]
   498  (Op
   499      [ ... (Op) ... ]
   500      [ (Op) ... ]
   501      [ ... (Op) ]
   502      [ ... ... ]
   503      [ (Op) ]
   504      [ ]
   505  )
   506  =>
   507  (Op
   508      [ (Op) (Op) ]
   509      [ (Op) ]
   510      [ ]
   511      (Func [ (Op) (Op) ])
   512  )
   513  ----
   514  (Compiled
   515  	(Defines
   516  		(Define
   517  			Comments=(Comments)
   518  			Tags=(Tags)
   519  			Name="Op"
   520  			Fields=(DefineFields
   521  				(DefineField Comments=(Comments) Name="Input1" Type="Expr" Src=<test.opt:2:5>)
   522  				(DefineField Comments=(Comments) Name="Input2" Type="Expr" Src=<test.opt:3:5>)
   523  				(DefineField Comments=(Comments) Name="Input3" Type="Expr" Src=<test.opt:4:5>)
   524  				(DefineField Comments=(Comments) Name="Input4" Type="Expr" Src=<test.opt:5:5>)
   525  				(DefineField Comments=(Comments) Name="Input5" Type="Expr" Src=<test.opt:6:5>)
   526  				(DefineField Comments=(Comments) Name="Input6" Type="Expr" Src=<test.opt:7:5>)
   527  			)
   528  			Src=<test.opt:1:1>
   529  		)
   530  	)
   531  	(Rules
   532  		(Rule
   533  			Comments=(Comments)
   534  			Name="Lists"
   535  			Tags=(Tags)
   536  			Match=(Func
   537  				Name=Op
   538  				Args=(Slice
   539  					(List
   540  						Items=(Slice
   541  							(ListAny)
   542  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:12:11>)
   543  							(ListAny)
   544  						)
   545  						Typ=Expr
   546  						Src=<test.opt:12:5>
   547  					)
   548  					(List
   549  						Items=(Slice
   550  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:13:7>)
   551  							(ListAny)
   552  						)
   553  						Typ=Expr
   554  						Src=<test.opt:13:5>
   555  					)
   556  					(List
   557  						Items=(Slice
   558  							(ListAny)
   559  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:14:11>)
   560  						)
   561  						Typ=Expr
   562  						Src=<test.opt:14:5>
   563  					)
   564  					(List
   565  						Items=(Slice (ListAny) (ListAny))
   566  						Typ=Expr
   567  						Src=<test.opt:15:5>
   568  					)
   569  					(List
   570  						Items=(Slice
   571  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:16:7>)
   572  						)
   573  						Typ=Expr
   574  						Src=<test.opt:16:5>
   575  					)
   576  					(List Items=(Slice) Typ=Expr Src=<test.opt:17:5>)
   577  				)
   578  				Typ=Op
   579  				Src=<test.opt:11:1>
   580  			)
   581  			Replace=(Func
   582  				Name=Op
   583  				Args=(Slice
   584  					(List
   585  						Items=(Slice
   586  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:21:7>)
   587  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:21:12>)
   588  						)
   589  						Typ=Expr
   590  						Src=<test.opt:21:5>
   591  					)
   592  					(List
   593  						Items=(Slice
   594  							(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:22:7>)
   595  						)
   596  						Typ=Expr
   597  						Src=<test.opt:22:5>
   598  					)
   599  					(List Items=(Slice) Typ=Expr Src=<test.opt:23:5>)
   600  					(CustomFunc
   601  						Name=Func
   602  						Args=(Slice
   603  							(List
   604  								Items=(Slice
   605  									(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:24:13>)
   606  									(Func Name=Op Args=(Slice) Typ=Op Src=<test.opt:24:18>)
   607  								)
   608  								Typ=<list>
   609  								Src=<test.opt:24:11>
   610  							)
   611  						)
   612  						Typ=Expr
   613  						Src=<test.opt:24:5>
   614  					)
   615  				)
   616  				Typ=Op
   617  				Src=<test.opt:20:1>
   618  			)
   619  			Src=<test.opt:10:1>
   620  		)
   621  	)
   622  )
   623  
   624  #
   625  # Bind expressions in all parts of rule.
   626  #
   627  compile
   628  define Op {
   629      Input Expr
   630  }
   631  
   632  [Binding]
   633  (Op $matchOp:(Op (Func $matchArg:"foo")))
   634  =>
   635  (Op $replaceOp:(Op (Func $replaceArg:"foo")))
   636  ----
   637  (Compiled
   638  	(Defines
   639  		(Define
   640  			Comments=(Comments)
   641  			Tags=(Tags)
   642  			Name="Op"
   643  			Fields=(DefineFields
   644  				(DefineField Comments=(Comments) Name="Input" Type="Expr" Src=<test.opt:2:5>)
   645  			)
   646  			Src=<test.opt:1:1>
   647  		)
   648  	)
   649  	(Rules
   650  		(Rule
   651  			Comments=(Comments)
   652  			Name="Binding"
   653  			Tags=(Tags)
   654  			Match=(Func
   655  				Name=Op
   656  				Args=(Slice
   657  					(Bind
   658  						Label="matchOp"
   659  						Target=(Func
   660  							Name=Op
   661  							Args=(Slice
   662  								(CustomFunc
   663  									Name=Func
   664  									Args=(Slice
   665  										(Bind Label="matchArg" Target="foo" Typ=<string> Src=<test.opt:6:24>)
   666  									)
   667  									Typ=Expr
   668  									Src=<test.opt:6:18>
   669  								)
   670  							)
   671  							Typ=Op
   672  							Src=<test.opt:6:14>
   673  						)
   674  						Typ=Op
   675  						Src=<test.opt:6:5>
   676  					)
   677  				)
   678  				Typ=Op
   679  				Src=<test.opt:6:1>
   680  			)
   681  			Replace=(Func
   682  				Name=Op
   683  				Args=(Slice
   684  					(Bind
   685  						Label="replaceOp"
   686  						Target=(Func
   687  							Name=Op
   688  							Args=(Slice
   689  								(CustomFunc
   690  									Name=Func
   691  									Args=(Slice
   692  										(Bind Label="replaceArg" Target="foo" Typ=<string> Src=<test.opt:8:26>)
   693  									)
   694  									Typ=Expr
   695  									Src=<test.opt:8:20>
   696  								)
   697  							)
   698  							Typ=Op
   699  							Src=<test.opt:8:16>
   700  						)
   701  						Typ=Op
   702  						Src=<test.opt:8:5>
   703  					)
   704  				)
   705  				Typ=Op
   706  				Src=<test.opt:8:1>
   707  			)
   708  			Src=<test.opt:5:1>
   709  		)
   710  	)
   711  )
   712  
   713  #
   714  # Test type inference.
   715  #
   716  compile
   717  [Join]
   718  define InnerJoin {
   719      Left  Expr
   720      Right Expr
   721      On    FiltersExpr
   722  }
   723  
   724  [Join]
   725  define LeftJoin {
   726      Left  Expr
   727      Right Expr
   728      On    FiltersExpr
   729  }
   730  
   731  # Test AndExpr with left type as a subset of right type.
   732  [AndExpr1]
   733  (InnerJoin $left:(LeftJoin) & (InnerJoin | LeftJoin)) => $left
   734  
   735  # Test AndExpr with right type as a subset of left type.
   736  [AndExpr2]
   737  (InnerJoin $left:(LeftJoin | InnerJoin) & (LeftJoin)) => $left
   738  
   739  # Test NotExpr.
   740  [NotExpr]
   741  (InnerJoin $left:* & ^(LeftJoin | InnerJoin)) => $left
   742  
   743  # Test list matching and construction.
   744  [ListExpr]
   745  (InnerJoin $left:* $right:* $on:[ ... $item:* ... ]) => (LeftJoin $left $right [ $item ])
   746  
   747  # Test custom match function and custom construct function.
   748  [CustomFunction]
   749  (InnerJoin $left:* & (MatchFunc $left) $right:* $on:*) => (ConstructFunc $left $on)
   750  
   751  # Test construction with dynamic choice of names.
   752  [DynamicName]
   753  (InnerJoin $left:* $right:(Join $innerLeft:*) $on:*) => ((OpName $right) $left $innerLeft $on)
   754  
   755  # Test strings + numbers.
   756  [Values]
   757  (InnerJoin $left:"foo" $right:5) => (LeftJoin $left $right)
   758  ----
   759  (Compiled
   760  	(Defines
   761  		(Define
   762  			Comments=(Comments)
   763  			Tags=(Tags Join)
   764  			Name="InnerJoin"
   765  			Fields=(DefineFields
   766  				(DefineField Comments=(Comments) Name="Left" Type="Expr" Src=<test.opt:3:5>)
   767  				(DefineField Comments=(Comments) Name="Right" Type="Expr" Src=<test.opt:4:5>)
   768  				(DefineField Comments=(Comments) Name="On" Type="FiltersExpr" Src=<test.opt:5:5>)
   769  			)
   770  			Src=<test.opt:1:1>
   771  		)
   772  		(Define
   773  			Comments=(Comments)
   774  			Tags=(Tags Join)
   775  			Name="LeftJoin"
   776  			Fields=(DefineFields
   777  				(DefineField Comments=(Comments) Name="Left" Type="Expr" Src=<test.opt:10:5>)
   778  				(DefineField Comments=(Comments) Name="Right" Type="Expr" Src=<test.opt:11:5>)
   779  				(DefineField Comments=(Comments) Name="On" Type="FiltersExpr" Src=<test.opt:12:5>)
   780  			)
   781  			Src=<test.opt:8:1>
   782  		)
   783  	)
   784  	(Rules
   785  		(Rule
   786  			Comments=(Comments # Test AndExpr with left type as a subset of right type.)
   787  			Name="AndExpr1"
   788  			Tags=(Tags)
   789  			Match=(Func
   790  				Name=InnerJoin
   791  				Args=(Slice
   792  					(Bind
   793  						Label="left"
   794  						Target=(And
   795  							Left=(Func Name=LeftJoin Args=(Slice) Typ=LeftJoin Src=<test.opt:17:18>)
   796  							Right=(Func
   797  								Name=(Names InnerJoin LeftJoin)
   798  								Args=(Slice)
   799  								Typ=[InnerJoin | LeftJoin]
   800  								Src=<test.opt:17:31>
   801  							)
   802  							Typ=LeftJoin
   803  							Src=<test.opt:17:18>
   804  						)
   805  						Typ=LeftJoin
   806  						Src=<test.opt:17:12>
   807  					)
   808  				)
   809  				Typ=InnerJoin
   810  				Src=<test.opt:17:1>
   811  			)
   812  			Replace=(Ref Label="left" Typ=LeftJoin Src=<test.opt:17:58>)
   813  			Src=<test.opt:16:1>
   814  		)
   815  		(Rule
   816  			Comments=(Comments # Test AndExpr with right type as a subset of left type.)
   817  			Name="AndExpr2"
   818  			Tags=(Tags)
   819  			Match=(Func
   820  				Name=InnerJoin
   821  				Args=(Slice
   822  					(Bind
   823  						Label="left"
   824  						Target=(And
   825  							Left=(Func
   826  								Name=(Names LeftJoin InnerJoin)
   827  								Args=(Slice)
   828  								Typ=[LeftJoin | InnerJoin]
   829  								Src=<test.opt:21:18>
   830  							)
   831  							Right=(Func Name=LeftJoin Args=(Slice) Typ=LeftJoin Src=<test.opt:21:43>)
   832  							Typ=LeftJoin
   833  							Src=<test.opt:21:18>
   834  						)
   835  						Typ=LeftJoin
   836  						Src=<test.opt:21:12>
   837  					)
   838  				)
   839  				Typ=InnerJoin
   840  				Src=<test.opt:21:1>
   841  			)
   842  			Replace=(Ref Label="left" Typ=LeftJoin Src=<test.opt:21:58>)
   843  			Src=<test.opt:20:1>
   844  		)
   845  		(Rule
   846  			Comments=(Comments # Test NotExpr.)
   847  			Name="NotExpr"
   848  			Tags=(Tags)
   849  			Match=(Func
   850  				Name=InnerJoin
   851  				Args=(Slice
   852  					(Bind
   853  						Label="left"
   854  						Target=(And
   855  							Left=(Any Typ=Expr)
   856  							Right=(Not
   857  								Input=(Func
   858  									Name=(Names LeftJoin InnerJoin)
   859  									Args=(Slice)
   860  									Typ=[LeftJoin | InnerJoin]
   861  									Src=<test.opt:25:23>
   862  								)
   863  								Typ=Expr
   864  								Src=<test.opt:25:22>
   865  							)
   866  							Typ=Expr
   867  							Src=<test.opt:25:18>
   868  						)
   869  						Typ=Expr
   870  						Src=<test.opt:25:12>
   871  					)
   872  				)
   873  				Typ=InnerJoin
   874  				Src=<test.opt:25:1>
   875  			)
   876  			Replace=(Ref Label="left" Typ=Expr Src=<test.opt:25:50>)
   877  			Src=<test.opt:24:1>
   878  		)
   879  		(Rule
   880  			Comments=(Comments # Test list matching and construction.)
   881  			Name="ListExpr"
   882  			Tags=(Tags)
   883  			Match=(Func
   884  				Name=InnerJoin
   885  				Args=(Slice
   886  					(Bind Label="left" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:29:12>)
   887  					(Bind Label="right" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:29:20>)
   888  					(Bind
   889  						Label="on"
   890  						Target=(List
   891  							Items=(Slice
   892  								(ListAny)
   893  								(Bind Label="item" Target=(Any) Src=<test.opt:29:39>)
   894  								(ListAny)
   895  							)
   896  							Typ=FiltersExpr
   897  							Src=<test.opt:29:33>
   898  						)
   899  						Typ=FiltersExpr
   900  						Src=<test.opt:29:29>
   901  					)
   902  				)
   903  				Typ=InnerJoin
   904  				Src=<test.opt:29:1>
   905  			)
   906  			Replace=(Func
   907  				Name=LeftJoin
   908  				Args=(Slice
   909  					(Ref Label="left" Typ=Expr Src=<test.opt:29:67>)
   910  					(Ref Label="right" Typ=Expr Src=<test.opt:29:73>)
   911  					(List
   912  						Items=(Slice
   913  							(Ref Label="item" Src=<test.opt:29:82>)
   914  						)
   915  						Typ=FiltersExpr
   916  						Src=<test.opt:29:80>
   917  					)
   918  				)
   919  				Typ=LeftJoin
   920  				Src=<test.opt:29:57>
   921  			)
   922  			Src=<test.opt:28:1>
   923  		)
   924  		(Rule
   925  			Comments=(Comments # Test custom match function and custom construct function.)
   926  			Name="CustomFunction"
   927  			Tags=(Tags)
   928  			Match=(Func
   929  				Name=InnerJoin
   930  				Args=(Slice
   931  					(Bind
   932  						Label="left"
   933  						Target=(And
   934  							Left=(Any Typ=Expr)
   935  							Right=(CustomFunc
   936  								Name=MatchFunc
   937  								Args=(Slice
   938  									(Ref Label="left" Src=<test.opt:33:33>)
   939  								)
   940  								Typ=Expr
   941  								Src=<test.opt:33:22>
   942  							)
   943  							Typ=Expr
   944  							Src=<test.opt:33:18>
   945  						)
   946  						Typ=Expr
   947  						Src=<test.opt:33:12>
   948  					)
   949  					(Bind Label="right" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:33:40>)
   950  					(Bind Label="on" Target=(Any Typ=FiltersExpr) Typ=FiltersExpr Src=<test.opt:33:49>)
   951  				)
   952  				Typ=InnerJoin
   953  				Src=<test.opt:33:1>
   954  			)
   955  			Replace=(CustomFunc
   956  				Name=ConstructFunc
   957  				Args=(Slice
   958  					(Ref Label="left" Typ=Expr Src=<test.opt:33:74>)
   959  					(Ref Label="on" Typ=FiltersExpr Src=<test.opt:33:80>)
   960  				)
   961  				Src=<test.opt:33:59>
   962  			)
   963  			Src=<test.opt:32:1>
   964  		)
   965  		(Rule
   966  			Comments=(Comments # Test construction with dynamic choice of names.)
   967  			Name="DynamicName"
   968  			Tags=(Tags)
   969  			Match=(Func
   970  				Name=InnerJoin
   971  				Args=(Slice
   972  					(Bind Label="left" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:37:12>)
   973  					(Bind
   974  						Label="right"
   975  						Target=(Func
   976  							Name=Join
   977  							Args=(Slice
   978  								(Bind Label="innerLeft" Target=(Any Typ=Expr) Typ=Expr Src=<test.opt:37:33>)
   979  							)
   980  							Typ=[InnerJoin | LeftJoin]
   981  							Src=<test.opt:37:27>
   982  						)
   983  						Typ=[InnerJoin | LeftJoin]
   984  						Src=<test.opt:37:20>
   985  					)
   986  					(Bind Label="on" Target=(Any Typ=FiltersExpr) Typ=FiltersExpr Src=<test.opt:37:47>)
   987  				)
   988  				Typ=InnerJoin
   989  				Src=<test.opt:37:1>
   990  			)
   991  			Replace=(Func
   992  				Name=(CustomFunc
   993  					Name=OpName
   994  					Args=(Slice
   995  						(Ref Label="right" Typ=[InnerJoin | LeftJoin] Src=<test.opt:37:66>)
   996  					)
   997  					Src=<test.opt:37:58>
   998  				)
   999  				Args=(Slice
  1000  					(Ref Label="left" Typ=Expr Src=<test.opt:37:74>)
  1001  					(Ref Label="innerLeft" Typ=Expr Src=<test.opt:37:80>)
  1002  					(Ref Label="on" Typ=FiltersExpr Src=<test.opt:37:91>)
  1003  				)
  1004  				Typ=[InnerJoin | LeftJoin]
  1005  				Src=<test.opt:37:57>
  1006  			)
  1007  			Src=<test.opt:36:1>
  1008  		)
  1009  		(Rule
  1010  			Comments=(Comments # Test strings + numbers.)
  1011  			Name="Values"
  1012  			Tags=(Tags)
  1013  			Match=(Func
  1014  				Name=InnerJoin
  1015  				Args=(Slice
  1016  					(Bind Label="left" Target="foo" Typ=<string> Src=<test.opt:41:12>)
  1017  					(Bind Label="right" Target=5 Typ=<int64> Src=<test.opt:41:24>)
  1018  				)
  1019  				Typ=InnerJoin
  1020  				Src=<test.opt:41:1>
  1021  			)
  1022  			Replace=(Func
  1023  				Name=LeftJoin
  1024  				Args=(Slice
  1025  					(Ref Label="left" Typ=<string> Src=<test.opt:41:47>)
  1026  					(Ref Label="right" Typ=<int64> Src=<test.opt:41:53>)
  1027  				)
  1028  				Typ=LeftJoin
  1029  				Src=<test.opt:41:37>
  1030  			)
  1031  			Src=<test.opt:40:1>
  1032  		)
  1033  	)
  1034  )
  1035  
  1036  #
  1037  # Compile errors.
  1038  #
  1039  compile
  1040  [Tag]
  1041  define Op {
  1042      Input Expr
  1043  }
  1044  define Op {
  1045      Input1 Expr
  1046      Input2 Expr
  1047      Input3 Expr
  1048  }
  1049  
  1050  [UnrecognizedName]
  1051  (Unknown) => (Unknown)
  1052  
  1053  [TooManyOpNameArgs]
  1054  (Op) => ((OpName "foo" "bar"))
  1055  
  1056  [InvalidOpNameArg]
  1057  (Op) => ((OpName "foo"))
  1058  
  1059  [DuplicateLabel]
  1060  (Op $input:"foo" $input:"bar") => (Op)
  1061  
  1062  [DuplicateLabel2]
  1063  (Op $input:"foo") => (Op $input:"bar")
  1064  
  1065  [UnrecognizedLabel]
  1066  (Op $input:* & (Func $unknown)) => (Op)
  1067  
  1068  [DuplicateName]
  1069  (Op) => (Op)
  1070  
  1071  [DuplicateName]
  1072  (Op) => (Op)
  1073  
  1074  [MatchRef]
  1075  (Op $ref) => (Op)
  1076  
  1077  [CustomMultiNames]
  1078  (Op (Func | Func2)) => (Op)
  1079  
  1080  [CustomList]
  1081  (Op (Func [])) => (Op)
  1082  
  1083  [CustomList2]
  1084  (Op (Func [ ... (SubFunc) ... ])) => (Op)
  1085  
  1086  [CustomBool]
  1087  (Op (Func (SubFunc) & (SubFunc))) => (Op)
  1088  
  1089  [CustomWildcard]
  1090  (Op (Func *)) => (Op)
  1091  
  1092  [OpInCustom]
  1093  (Op (Func (Op))) => (Op)
  1094  
  1095  [ConstructTag]
  1096  (Op) => (Tag)
  1097  
  1098  [MatchLiteralName]
  1099  (Op (Op $bind:Op)) => (Op Op (Func Op))
  1100  
  1101  [IllegalLiteralName]
  1102  (Op) => (Op Op (Func Unknown))
  1103  
  1104  [IllegalLiteralName2]
  1105  (Op) => (Op Op (Func Op) Unknown)
  1106  
  1107  [DynamicMatchName]
  1108  ((Op)) => (Op)
  1109  
  1110  [DynamicMatchName2]
  1111  (Op ((Op))) => (Op)
  1112  
  1113  [MultipleCustomFuncNames]
  1114  (Op (Func | Func2)) => (Op)
  1115  
  1116  [MultipleCustomFuncNames2]
  1117  (Op) => (Op (Func | Func2))
  1118  
  1119  [ListMatcher]
  1120  (Op [ ... (SubFunc) ... (SubFunc) ]) => (Op)
  1121  
  1122  [ListConstructor]
  1123  (Op) => (Op [ (SubFunc) ... ])
  1124  
  1125  [ConstructorMultipleNames]
  1126  (Op) => (Op | Op)
  1127  
  1128  [NotEnoughMatchFields]
  1129  (Op * * * *) => (Op)
  1130  ----
  1131  test.opt:5:1: duplicate 'Op' define statement
  1132  test.opt:12:1: unrecognized match name 'Unknown'
  1133  test.opt:15:10: too many arguments to OpName function
  1134  test.opt:18:10: invalid OpName argument: argument must be a variable reference
  1135  test.opt:21:18: duplicate bind label 'input'
  1136  test.opt:24:26: duplicate bind label 'input'
  1137  test.opt:27:22: unrecognized variable name 'unknown'
  1138  test.opt:32:1: duplicate rule name 'DuplicateName'
  1139  test.opt:36:5: match pattern cannot use variable references
  1140  test.opt:39:5: custom function cannot have multiple names
  1141  test.opt:42:11: custom match function cannot use lists
  1142  test.opt:45:11: custom match function cannot use lists
  1143  test.opt:48:11: custom match function cannot use boolean expressions
  1144  test.opt:51:11: custom match function cannot use wildcard matcher
  1145  test.opt:54:11: custom function name cannot be an operator name
  1146  test.opt:57:9: construct name cannot be a tag
  1147  test.opt:60:5: cannot match literal name 'Op'
  1148  test.opt:63:16: Unknown is not an operator name
  1149  test.opt:66:9: Unknown is not an operator name
  1150  test.opt:69:1: cannot match dynamic name
  1151  test.opt:72:5: cannot match dynamic name
  1152  test.opt:75:5: custom function cannot have multiple names
  1153  test.opt:78:13: constructor cannot have multiple names
  1154  test.opt:81:25: list matcher cannot contain multiple expressions
  1155  test.opt:84:13: list constructor cannot use '...'
  1156  test.opt:87:9: constructor cannot have multiple names
  1157  test.opt:90:1: Op has only 3 fields
  1158  
  1159  # Type inference errors.
  1160  compile
  1161  [Tag]
  1162  define Op {
  1163      Input1 Expr
  1164      Input2 Expr
  1165  }
  1166  
  1167  define SubOp {
  1168      Input Expr
  1169      def SubOpDef
  1170  }
  1171  
  1172  define SubOp2 {
  1173      Input Expr
  1174  }
  1175  
  1176  [CannotInferConstructOps]
  1177  (Op $input1:*) => ((OpName $input))
  1178  
  1179  [ConstructOpsNotEquivalent]
  1180  (Op $input1:(SubOp2 | SubOp $input:* $def:*)) => ((OpName $input1))
  1181  
  1182  [ConstructOpsNotEquivalent2]
  1183  (Op $input1:(Op | SubOp $input:* $def:*)) => ((OpName $input1))
  1184  
  1185  [MatchPatternsContradict]
  1186  (Op $input1:(Op) & (SubOp)) => $input1
  1187  ----
  1188  test.opt:17:28: unrecognized variable name 'input'
  1189  test.opt:20:13: SubOp2 has only 1 fields
  1190  test.opt:23:13: SubOp and Op fields do not have same types
  1191  test.opt:26:13: match patterns contradict one another; both cannot match