2 % (c) The GRASP/AQUA Project, Glasgow University, 1997-1998
4 % Author: Juan J. Quintela <quintela@krilin.dc.fi.udc.es>
9 module Check ( check , ExhaustivePat ) where
13 import TcHsSyn ( TypecheckedPat )
14 import DsHsSyn ( outPatType )
17 import DsUtils ( EquationInfo(..),
23 import DataCon ( DataCon, isTupleCon, isUnboxedTupleCon,
25 import Name ( Name, mkLocalName, getOccName, isDataSymOcc, getName, mkSrcVarOcc )
30 import TysPrim ( intPrimTy,
37 import TysWiredIn ( nilDataCon, consDataCon,
39 mkUnboxedTupleTy, unboxedTupleCon,
43 floatTy, floatDataCon,
44 doubleTy, doubleDataCon,
49 import Unique ( unboundKey )
50 import TyCon ( tyConDataCons )
51 import SrcLoc ( noSrcLoc )
55 #include "HsVersions.h"
58 This module performs checks about if one list of equations are:
62 To discover that we go through the list of equations in a tree-like fashion.
64 If you like theory, a similar algorithm is described in:
65 Two Techniques for Compiling Lazy Pattern Matching
67 INRIA Rocquencourt (RR-2385, 1994)
69 The algorithm is based in the first Technique, but there are some differences:
70 - We don't generate code
71 - We have constructors and literals (not only literals as in the
73 - We don't use directions, we must select the columns from
76 (By the way the second technique is really similar to the one used in
77 Match.lhs to generate code)
79 This function takes the equations of a pattern and returns:
80 - The patterns that are not recognized
81 - The equations that are not overlapped
83 It simplify the patterns and then call check' (the same semantics),and it
84 needs to reconstruct the patterns again ....
86 The problem appear with things like:
90 We want to put the two patterns with the same syntax, (prefix form) and
91 then all the constructors are equal:
92 f (: x (: y [])) = ....
95 (more about that in simplify_eqns)
97 We would prefer to have a WarningPat of type String, but Strings and the
98 Pretty Printer are not friends.
100 We use InPat in WarningPat instead of OutPat because we need to print the
101 warning messages in the same way they are introduced, i.e. if the user
105 He don't want a warning message written:
107 f (: x (: y [])) ........
109 Then we need to use InPats.
111 Juan Quintela 5 JUL 1998
112 User-friendliness and compiler writers are no friends.
116 type WarningPat = InPat Name
117 type ExhaustivePat = ([WarningPat], [(Name, [HsLit])])
120 check :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
121 check qs = (untidy_warns, incomplete)
123 (warns, incomplete) = check' (simplify_eqns qs)
124 untidy_warns = map untidy_exhaustive warns
126 untidy_exhaustive :: ExhaustivePat -> ExhaustivePat
127 untidy_exhaustive ([pat], messages) =
128 ([untidy_no_pars pat], map untidy_message messages)
129 untidy_exhaustive (pats, messages) =
130 (map untidy_pars pats, map untidy_message messages)
132 untidy_message :: (Name, [HsLit]) -> (Name, [HsLit])
133 untidy_message (string, lits) = (string, map untidy_lit lits)
136 The function @untidy@ does the reverse work of the @simplify_pat@ funcion.
142 untidy_no_pars :: WarningPat -> WarningPat
143 untidy_no_pars p = untidy False p
145 untidy_pars :: WarningPat -> WarningPat
146 untidy_pars p = untidy True p
148 untidy :: NeedPars -> WarningPat -> WarningPat
149 untidy _ p@WildPatIn = p
150 untidy _ p@(VarPatIn name) = p
151 untidy _ (LitPatIn lit) = LitPatIn (untidy_lit lit)
152 untidy _ p@(ConPatIn name []) = p
153 untidy b (ConPatIn name pats) =
154 pars b (ConPatIn name (map untidy_pars pats))
155 untidy b (ConOpPatIn pat1 name fixity pat2) =
156 pars b (ConOpPatIn (untidy_pars pat1) name fixity (untidy_pars pat2))
157 untidy _ (ListPatIn pats) = ListPatIn (map untidy_no_pars pats)
158 untidy _ (TuplePatIn pats boxed) = TuplePatIn (map untidy_no_pars pats) boxed
160 untidy _ (SigPatIn pat ty) = panic "Check.untidy: SigPatIn"
161 untidy _ (LazyPatIn pat) = panic "Check.untidy: LazyPatIn"
162 untidy _ (AsPatIn name pat) = panic "Check.untidy: AsPatIn"
163 untidy _ (NPlusKPatIn name lit) = panic "Check.untidy: NPlusKPatIn"
164 untidy _ (NegPatIn ipat) = panic "Check.untidy: NegPatIn"
165 untidy _ (ParPatIn pat) = panic "Check.untidy: ParPatIn"
166 untidy _ (RecPatIn name fields) = panic "Check.untidy: RecPatIn"
167 -- [(name, InPat name, Bool)] -- True <=> source used punning
169 pars :: NeedPars -> WarningPat -> WarningPat
170 pars True p = ParPatIn p
173 untidy_lit :: HsLit -> HsLit
174 untidy_lit (HsCharPrim c) = HsChar c
175 --untidy_lit (HsStringPrim s) = HsString s
179 This equation is the same that check, the only difference is that the
180 boring work is done, that work needs to be done only once, this is
181 the reason top have two functions, check is the external interface,
182 check' is called recursively.
184 There are several cases:
187 \item There are no equations: Everything is OK.
188 \item There are only one equation, that can fail, and all the patterns are
189 variables. Then that equation is used and the same equation is
191 \item All the patterns are variables, and the match can fail, there are
192 more equations then the results is the result of the rest of equations
193 and this equation is used also.
195 \item The general case, if all the patterns are variables (here the match
196 can't fail) then the result is that this equation is used and this
197 equation doesn't generate non-exhaustive cases.
199 \item In the general case, there can exist literals ,constructors or only
200 vars in the first column, we actuate in consequence.
207 check' :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
208 check' [] = ([([],[])],emptyUniqSet)
210 check' [EqnInfo n ctx ps (MatchResult CanFail _)]
211 | all_vars ps = ([(take (length ps) (repeat new_wild_pat),[])], unitUniqSet n)
213 check' qs@((EqnInfo n ctx ps (MatchResult CanFail _)):_)
214 | all_vars ps = (pats, addOneToUniqSet indexs n)
216 (pats,indexs) = check' (tail qs)
218 check' qs@((EqnInfo n ctx ps result):_)
219 | all_vars ps = ([], unitUniqSet n)
220 -- | nplusk = panic "Check.check': Work in progress: nplusk"
221 -- | npat = panic "Check.check': Work in progress: npat ?????"
222 | literals = split_by_literals qs
223 | constructors = split_by_constructor qs
224 | only_vars = first_column_only_vars qs
225 | otherwise = panic "Check.check': Not implemented :-("
227 constructors = or (map is_con qs)
228 literals = or (map is_lit qs)
229 -- npat = or (map is_npat qs)
230 -- nplusk = or (map is_nplusk qs)
231 only_vars = and (map is_var qs)
234 Here begins the code to deal with literals, we need to split the matrix
235 in different matrix beginning by each literal and a last matrix with the
239 split_by_literals :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
240 split_by_literals qs = process_literals used_lits qs
242 used_lits = get_used_lits qs
245 process_explicit_literals is a function that process each literal that appears
246 in the column of the matrix.
249 process_explicit_literals :: [HsLit] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
250 process_explicit_literals lits qs = (concat pats, unionManyUniqSets indexs)
252 pats_indexs = map (\x -> construct_literal_matrix x qs) lits
253 (pats,indexs) = unzip pats_indexs
258 Process_literals calls process_explicit_literals to deal with the literals
259 that appears in the matrix and deal also with the rest of the cases. It
260 must be one Variable to be complete.
264 process_literals :: [HsLit] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
265 process_literals used_lits qs
266 | length default_eqns == 0 = ([make_row_vars used_lits (head qs)]++pats,indexs)
267 | otherwise = (pats_default,indexs_default)
269 (pats,indexs) = process_explicit_literals used_lits qs
270 default_eqns = (map remove_var (filter is_var qs))
271 (pats',indexs') = check' default_eqns
272 pats_default = [(new_wild_pat:ps,constraints) | (ps,constraints) <- (pats')] ++ pats
273 indexs_default = unionUniqSets indexs' indexs
276 Here we have selected the literal and we will select all the equations that
277 begins for that literal and create a new matrix.
280 construct_literal_matrix :: HsLit -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
281 construct_literal_matrix lit qs =
282 (map (\ (xs,ys) -> (new_lit:xs,ys)) pats,indexs)
284 (pats,indexs) = (check' (remove_first_column_lit lit qs))
285 new_lit = LitPatIn lit
287 remove_first_column_lit :: HsLit
290 remove_first_column_lit lit qs =
291 map shift_pat (filter (is_var_lit lit) qs)
293 shift_pat (EqnInfo n ctx [] result) = panic "Check.shift_var: no patterns"
294 shift_pat (EqnInfo n ctx (_:ps) result) = EqnInfo n ctx ps result
298 This function splits the equations @qs@ in groups that deal with the
303 split_by_constructor :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
305 split_by_constructor qs | length unused_cons /= 0 = need_default_case used_cons unused_cons qs
306 | otherwise = no_need_default_case used_cons qs
308 used_cons = get_used_cons qs
309 unused_cons = get_unused_cons used_cons
313 The first column of the patterns matrix only have vars, then there is
317 first_column_only_vars :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
318 first_column_only_vars qs = (map (\ (xs,ys) -> (new_wild_pat:xs,ys)) pats,indexs)
320 (pats,indexs) = check' (map remove_var qs)
324 This equation takes a matrix of patterns and split the equations by
325 constructor, using all the constructors that appears in the first column
326 of the pattern matching.
328 We can need a default clause or not ...., it depends if we used all the
329 constructors or not explicitly. The reasoning is similar to process_literals,
330 the difference is that here the default case is not always needed.
333 no_need_default_case :: [TypecheckedPat] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
334 no_need_default_case cons qs = (concat pats, unionManyUniqSets indexs)
336 pats_indexs = map (\x -> construct_matrix x qs) cons
337 (pats,indexs) = unzip pats_indexs
339 need_default_case :: [TypecheckedPat] -> [DataCon] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
340 need_default_case used_cons unused_cons qs
341 | length default_eqns == 0 = (pats_default_no_eqns,indexs)
342 | otherwise = (pats_default,indexs_default)
344 (pats,indexs) = no_need_default_case used_cons qs
345 default_eqns = (map remove_var (filter is_var qs))
346 (pats',indexs') = check' default_eqns
347 pats_default = [(make_whole_con c:ps,constraints) |
348 c <- unused_cons, (ps,constraints) <- pats'] ++ pats
349 new_wilds = make_row_vars_for_constructor (head qs)
350 pats_default_no_eqns = [(make_whole_con c:new_wilds,[]) | c <- unused_cons] ++ pats
351 indexs_default = unionUniqSets indexs' indexs
353 construct_matrix :: TypecheckedPat -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
354 construct_matrix con qs =
355 (map (make_con con) pats,indexs)
357 (pats,indexs) = (check' (remove_first_column con qs))
360 Here remove first column is more difficult that with literals due to the fact
361 that constructors can have arguments.
363 For instance, the matrix
375 remove_first_column :: TypecheckedPat -- Constructor
378 remove_first_column (ConPat con _ _ _ con_pats) qs =
379 map shift_var (filter (is_var_con con) qs)
381 new_wilds = [WildPat (outPatType arg_pat) | arg_pat <- con_pats]
382 shift_var (EqnInfo n ctx (ConPat _ _ _ _ ps':ps) result) =
383 EqnInfo n ctx (ps'++ps) result
384 shift_var (EqnInfo n ctx (WildPat _ :ps) result) =
385 EqnInfo n ctx (new_wilds ++ ps) result
386 shift_var _ = panic "Check.Shift_var:No done"
388 make_row_vars :: [HsLit] -> EquationInfo -> ExhaustivePat
389 make_row_vars used_lits (EqnInfo _ _ pats _ ) =
390 (VarPatIn new_var:take (length (tail pats)) (repeat new_wild_pat),[(new_var,used_lits)])
391 where new_var = hash_x
393 hash_x = mkLocalName unboundKey {- doesn't matter much -}
394 (mkSrcVarOcc SLIT("#x"))
397 make_row_vars_for_constructor :: EquationInfo -> [WarningPat]
398 make_row_vars_for_constructor (EqnInfo _ _ pats _ ) = take (length (tail pats)) (repeat new_wild_pat)
400 compare_cons :: TypecheckedPat -> TypecheckedPat -> Bool
401 compare_cons (ConPat id1 _ _ _ _) (ConPat id2 _ _ _ _) = id1 == id2
403 remove_dups :: [TypecheckedPat] -> [TypecheckedPat]
405 remove_dups (x:xs) | or (map (\y -> compare_cons x y) xs) = remove_dups xs
406 | otherwise = x : remove_dups xs
408 get_used_cons :: [EquationInfo] -> [TypecheckedPat]
409 get_used_cons qs = remove_dups [con | (EqnInfo _ _ (con@(ConPat _ _ _ _ _):_) _) <- qs]
411 remove_dups' :: [HsLit] -> [HsLit]
413 remove_dups' (x:xs) | x `elem` xs = remove_dups' xs
414 | otherwise = x : remove_dups' xs
417 get_used_lits :: [EquationInfo] -> [HsLit]
418 get_used_lits qs = remove_dups' all_literals
420 all_literals = get_used_lits' qs
422 get_used_lits' :: [EquationInfo] -> [HsLit]
423 get_used_lits' [] = []
424 get_used_lits' ((EqnInfo _ _ ((LitPat lit _):_) _):qs) =
425 lit : get_used_lits qs
426 get_used_lits' ((EqnInfo _ _ ((NPat lit _ _):_) _):qs) =
427 lit : get_used_lits qs
428 get_used_lits' (q:qs) =
431 get_unused_cons :: [TypecheckedPat] -> [DataCon]
432 get_unused_cons used_cons = unused_cons
434 (ConPat _ ty _ _ _) = head used_cons
435 Just (ty_con,_) = splitTyConApp_maybe ty
436 all_cons = tyConDataCons ty_con
437 used_cons_as_id = map (\ (ConPat id _ _ _ _) -> id) used_cons
438 unused_cons = uniqSetToList (mkUniqSet all_cons `minusUniqSet` mkUniqSet used_cons_as_id)
440 all_vars :: [TypecheckedPat] -> Bool
442 all_vars (WildPat _:ps) = all_vars ps
445 remove_var :: EquationInfo -> EquationInfo
446 remove_var (EqnInfo n ctx (WildPat _:ps) result) = EqnInfo n ctx ps result
447 remove_var _ = panic "Check:remove_var: equation not begin with a variable"
449 is_con :: EquationInfo -> Bool
450 is_con (EqnInfo _ _ ((ConPat _ _ _ _ _):_) _) = True
453 is_lit :: EquationInfo -> Bool
454 is_lit (EqnInfo _ _ ((LitPat _ _):_) _) = True
455 is_lit (EqnInfo _ _ ((NPat _ _ _):_) _) = True
458 is_npat :: EquationInfo -> Bool
459 is_npat (EqnInfo _ _ ((NPat _ _ _):_) _) = True
462 is_nplusk :: EquationInfo -> Bool
463 is_nplusk (EqnInfo _ _ ((NPlusKPat _ _ _ _ _):_) _) = True
466 is_var :: EquationInfo -> Bool
467 is_var (EqnInfo _ _ ((WildPat _):_) _) = True
470 is_var_con :: DataCon -> EquationInfo -> Bool
471 is_var_con con (EqnInfo _ _ ((WildPat _):_) _) = True
472 is_var_con con (EqnInfo _ _ ((ConPat id _ _ _ _):_) _) | id == con = True
473 is_var_con con _ = False
475 is_var_lit :: HsLit -> EquationInfo -> Bool
476 is_var_lit lit (EqnInfo _ _ ((WildPat _):_) _) = True
477 is_var_lit lit (EqnInfo _ _ ((LitPat lit' _):_) _) | lit == lit' = True
478 is_var_lit lit (EqnInfo _ _ ((NPat lit' _ _):_) _) | lit == lit' = True
479 is_var_lit lit _ = False
482 The difference beteewn make_con and make_whole_con is that
483 make_wole_con creates a new constructor with all their arguments, and
484 make_Con takes a list of argumntes, creates the contructor geting thir
485 argumnts from the list. See where are used for details.
487 We need to reconstruct the patterns (make the constructors infix and
488 similar) at the same time that we create the constructors.
490 You can tell tuple constructors using
494 You can see if one constructor is infix with this clearer code :-))))))))))
496 Lex.isLexConSym (Name.occNameString (Name.getOccName con))
498 Rather clumsy but it works. (Simon Peyton Jones)
501 We con't mind the nilDataCon because it doesn't change the way to
502 print the messsage, we are searching only for things like: [1,2,3],
505 In reconstruct_pat we want to "undo" the work that we have done in simplify_pat
507 ((,) x y) returns to be (x, y)
508 ((:) x xs) returns to be (x:xs)
509 (x:(...:[]) returns to be [x,...]
511 The difficult case is the third one becouse we need to follow all the
512 contructors until the [] to know taht we need to use the second case,
516 isInfixCon con = isDataSymOcc (getOccName con)
518 is_nil (ConPatIn con []) = con == getName nilDataCon
521 is_list (ListPatIn _) = True
524 return_list id q = id == consDataCon && (is_nil q || is_list q)
526 make_list p q | is_nil q = ListPatIn [p]
527 make_list p (ListPatIn ps) = ListPatIn (p:ps)
528 make_list _ _ = panic "Check.make_list: Invalid argument"
530 make_con :: TypecheckedPat -> ExhaustivePat -> ExhaustivePat
531 make_con (ConPat id _ _ _ _) (p:q:ps, constraints)
532 | return_list id q = (make_list p q : ps, constraints)
533 | isInfixCon id = ((ConOpPatIn p name fixity q) : ps, constraints)
534 where name = getName id
535 fixity = panic "Check.make_con: Guessing fixity"
537 make_con (ConPat id _ _ _ pats) (ps,constraints)
538 | isTupleCon id = (TuplePatIn pats_con True : rest_pats, constraints)
539 | isUnboxedTupleCon id = (TuplePatIn pats_con False : rest_pats, constraints)
540 | otherwise = (ConPatIn name pats_con : rest_pats, constraints)
541 where num_args = length pats
543 pats_con = take num_args ps
544 rest_pats = drop num_args ps
547 make_whole_con :: DataCon -> WarningPat
548 make_whole_con con | isInfixCon con = ConOpPatIn new_wild_pat name fixity new_wild_pat
549 | otherwise = ConPatIn name pats
551 fixity = panic "Check.make_whole_con: Guessing fixity"
553 arity = dataConSourceArity con
554 pats = take arity (repeat new_wild_pat)
557 new_wild_pat :: WarningPat
558 new_wild_pat = WildPatIn
561 This equation makes the same thing that tidy in Match.lhs, the
562 difference is that here we can do all the tidy in one place and in the
563 Match tidy it must be done one column each time due to bookkeeping
568 simplify_eqns :: [EquationInfo] -> [EquationInfo]
569 simplify_eqns [] = []
570 simplify_eqns ((EqnInfo n ctx pats result):qs) =
571 (EqnInfo n ctx pats' result) : simplify_eqns qs
573 pats' = map simplify_pat pats
575 simplify_pat :: TypecheckedPat -> TypecheckedPat
577 simplify_pat pat@(WildPat gt) = pat
578 simplify_pat (VarPat id) = WildPat (idType id)
580 simplify_pat (LazyPat p) = simplify_pat p
581 simplify_pat (AsPat id p) = simplify_pat p
583 simplify_pat (ConPat id ty tvs dicts ps) = ConPat id ty tvs dicts (map simplify_pat ps)
585 simplify_pat (ListPat ty ps) = foldr (\ x -> \y -> ConPat consDataCon list_ty [] [] [x, y])
586 (ConPat nilDataCon list_ty [] [] [])
587 (map simplify_pat ps)
588 where list_ty = mkListTy ty
591 simplify_pat (TuplePat ps True) = ConPat (tupleCon arity)
592 (mkTupleTy arity (map outPatType ps)) [] []
593 (map simplify_pat ps)
597 simplify_pat (TuplePat ps False)
598 = ConPat (unboxedTupleCon arity)
599 (mkUnboxedTupleTy arity (map outPatType ps)) [] []
600 (map simplify_pat ps)
604 simplify_pat (RecPat id ty tvs dicts [])
605 = ConPat id ty tvs dicts [wild_pat]
607 wild_pat = WildPat gt
608 gt = panic "Check.symplify_pat: gessing gt"
610 simplify_pat (RecPat id ty tvs dicts idps)
611 = ConPat id ty tvs dicts pats
613 pats = map (\ (id,p,_)-> simplify_pat p) idps
615 simplify_pat pat@(LitPat lit lit_ty)
616 | isUnboxedType lit_ty = pat
618 | lit_ty == charTy = ConPat charDataCon charTy [] [] [LitPat (mk_char lit) charPrimTy]
620 | otherwise = pprPanic "Check.simplify_pat: LitPat:" (ppr pat)
622 mk_char (HsChar c) = HsCharPrim c
624 simplify_pat (NPat lit lit_ty hsexpr) = better_pat
627 | lit_ty == charTy = ConPat charDataCon lit_ty [] [] [LitPat (mk_char lit) charPrimTy]
628 | lit_ty == intTy = ConPat intDataCon lit_ty [] [] [LitPat (mk_int lit) intPrimTy]
629 | lit_ty == wordTy = ConPat wordDataCon lit_ty [] [] [LitPat (mk_word lit) wordPrimTy]
630 | lit_ty == addrTy = ConPat addrDataCon lit_ty [] [] [LitPat (mk_addr lit) addrPrimTy]
631 | lit_ty == floatTy = ConPat floatDataCon lit_ty [] [] [LitPat (mk_float lit) floatPrimTy]
632 | lit_ty == doubleTy = ConPat doubleDataCon lit_ty [] [] [LitPat (mk_double lit) doublePrimTy]
634 -- Convert the literal pattern "" to the constructor pattern [].
635 | null_str_lit lit = ConPat nilDataCon lit_ty [] [] []
636 | lit_ty == stringTy =
637 foldr (\ x -> \y -> ConPat consDataCon list_ty [] [] [x, y])
638 (ConPat nilDataCon list_ty [] [] [])
640 | otherwise = NPat lit lit_ty hsexpr
642 list_ty = mkListTy lit_ty
644 mk_int (HsInt i) = HsIntPrim i
645 mk_int l@(HsLitLit s) = l
647 mk_head_char (HsString s) = HsCharPrim (_HEAD_ s)
648 mk_string (HsString s) =
649 map (\ c -> ConPat charDataCon charTy [] []
650 [LitPat (HsCharPrim c) charPrimTy])
653 mk_char (HsChar c) = HsCharPrim c
654 mk_char l@(HsLitLit s) = l
656 mk_word l@(HsLitLit s) = l
658 mk_addr l@(HsLitLit s) = l
660 mk_float (HsInt i) = HsFloatPrim (fromInteger i)
661 mk_float (HsFrac f) = HsFloatPrim f
662 mk_float l@(HsLitLit s) = l
664 mk_double (HsInt i) = HsDoublePrim (fromInteger i)
665 mk_double (HsFrac f) = HsDoublePrim f
666 mk_double l@(HsLitLit s) = l
668 null_str_lit (HsString s) = _NULL_ s
669 null_str_lit other_lit = False
671 one_str_lit (HsString s) = _LENGTH_ s == (1::Int)
672 one_str_lit other_lit = False
674 simplify_pat (NPlusKPat id hslit ty hsexpr1 hsexpr2) =
676 where ty = panic "Check.simplify_pat: Gessing ty"
678 simplify_pat (DictPat dicts methods) =
679 case num_of_d_and_ms of
680 0 -> simplify_pat (TuplePat [] True)
681 1 -> simplify_pat (head dict_and_method_pats)
682 _ -> simplify_pat (TuplePat dict_and_method_pats True)
684 num_of_d_and_ms = length dicts + length methods
685 dict_and_method_pats = map VarPat (dicts ++ methods)