Commit a6199582 by simonmar

### [project @ 1999-06-17 09:51:16 by simonmar]

Comment cleanup and literisation(?) by Wolfram Kahl <kahl@DI.Unipi.IT>.
parent 07e4037d
 ... @@ -2,6 +2,7 @@ ... @@ -2,6 +2,7 @@ % (c) The GRASP/AQUA Project, Glasgow University, 1997-1998 % (c) The GRASP/AQUA Project, Glasgow University, 1997-1998 % % % Author: Juan J. Quintela % Author: Juan J. Quintela \section{Module @Check@ in @deSugar@} \begin{code} \begin{code} ... @@ -56,61 +57,69 @@ import Outputable ... @@ -56,61 +57,69 @@ import Outputable \end{code} \end{code} This module performs checks about if one list of equations are: This module performs checks about if one list of equations are: - Overlapped \begin{itemize} - Non exhaustive \item Overlapped \item Non exhaustive \end{itemize} To discover that we go through the list of equations in a tree-like fashion. To discover that we go through the list of equations in a tree-like fashion. If you like theory, a similar algorithm is described in: If you like theory, a similar algorithm is described in: Two Techniques for Compiling Lazy Pattern Matching \begin{quotation} Luc Maranguet {\em Two Techniques for Compiling Lazy Pattern Matching}, Luc Maranguet, INRIA Rocquencourt (RR-2385, 1994) INRIA Rocquencourt (RR-2385, 1994) \end{quotation} The algorithm is based in the first Technique, but there are some differences: The algorithm is based on the first technique, but there are some differences: - We don't generate code \begin{itemize} - We have constructors and literals (not only literals as in the \item We don't generate code \item We have constructors and literals (not only literals as in the article) article) - We don't use directions, we must select the columns from \item We don't use directions, we must select the columns from left-to-right left-to-right \end{itemize} (By the way the second technique is really similar to the one used in (By the way the second technique is really similar to the one used in Match.lhs to generate code) @Match.lhs@ to generate code) This function takes the equations of a pattern and returns: This function takes the equations of a pattern and returns: - The patterns that are not recognized \begin{itemize} - The equations that are not overlapped \item The patterns that are not recognized \item The equations that are not overlapped It simplify the patterns and then call check' (the same semantics),and it \end{itemize} It simplify the patterns and then call @check'@ (the same semantics), and it needs to reconstruct the patterns again .... needs to reconstruct the patterns again .... The problem appear with things like: The problem appear with things like: \begin{verbatim} f [x,y] = .... f [x,y] = .... f (x:xs) = ..... f (x:xs) = ..... \end{verbatim} We want to put the two patterns with the same syntax, (prefix form) and We want to put the two patterns with the same syntax, (prefix form) and then all the constructors are equal: then all the constructors are equal: \begin{verbatim} f (: x (: y [])) = .... f (: x (: y [])) = .... f (: x xs) = ..... f (: x xs) = ..... \end{verbatim} (more about that in @simplify_eqns@) (more about that in simplify_eqns) We would prefer to have a @WarningPat@ of type @String@, but Strings and the We would prefer to have a WarningPat of type String, but Strings and the Pretty Printer are not friends. Pretty Printer are not friends. We use InPat in WarningPat instead of OutPat because we need to print the We use @InPat@ in @WarningPat@ instead of @OutPat@ because we need to print the warning messages in the same way they are introduced, i.e. if the user warning messages in the same way they are introduced, i.e. if the user wrote: wrote: \begin{verbatim} f [x,y] = .. f [x,y] = .. \end{verbatim} He don't want a warning message written: He don't want a warning message written: \begin{verbatim} f (: x (: y [])) ........ f (: x (: y [])) ........ \end{verbatim} Then we need to use InPats. Then we need to use InPats. \begin{quotation} Juan Quintela 5 JUL 1998 Juan Quintela 5 JUL 1998\\ User-friendliness and compiler writers are no friends. User-friendliness and compiler writers are no friends. \end{quotation} \begin{code} \begin{code} type WarningPat = InPat Name type WarningPat = InPat Name ... @@ -178,11 +187,11 @@ untidy_lit lit = lit ... @@ -178,11 +187,11 @@ untidy_lit lit = lit This equation is the same that check, the only difference is that the This equation is the same that check, the only difference is that the boring work is done, that work needs to be done only once, this is boring work is done, that work needs to be done only once, this is the reason top have two functions, check is the external interface, the reason top have two functions, check is the external interface, check' is called recursively. @check'@ is called recursively. There are several cases: There are several cases: \begin{item} \begin{itemize} \item There are no equations: Everything is OK. \item There are no equations: Everything is OK. \item There are only one equation, that can fail, and all the patterns are \item There are only one equation, that can fail, and all the patterns are variables. Then that equation is used and the same equation is variables. Then that equation is used and the same equation is ... @@ -198,7 +207,7 @@ There are several cases: ... @@ -198,7 +207,7 @@ There are several cases: \item In the general case, there can exist literals ,constructors or only \item In the general case, there can exist literals ,constructors or only vars in the first column, we actuate in consequence. vars in the first column, we actuate in consequence. \end{item} \end{itemize} \begin{code} \begin{code} ... @@ -243,7 +252,7 @@ split_by_literals qs = process_literals used_lits qs ... @@ -243,7 +252,7 @@ split_by_literals qs = process_literals used_lits qs used_lits = get_used_lits qs used_lits = get_used_lits qs \end{code} \end{code} process_explicit_literals is a function that process each literal that appears @process_explicit_literals@ is a function that process each literal that appears in the column of the matrix. in the column of the matrix. \begin{code} \begin{code} ... @@ -256,7 +265,7 @@ process_explicit_literals lits qs = (concat pats, unionManyUniqSets indexs) ... @@ -256,7 +265,7 @@ process_explicit_literals lits qs = (concat pats, unionManyUniqSets indexs) \end{code} \end{code} Process_literals calls process_explicit_literals to deal with the literals @process_literals@ calls @process_explicit_literals@ to deal with the literals that appears in the matrix and deal also with the rest of the cases. It that appears in the matrix and deal also with the rest of the cases. It must be one Variable to be complete. must be one Variable to be complete. ... @@ -297,7 +306,7 @@ remove_first_column_lit lit qs = ... @@ -297,7 +306,7 @@ remove_first_column_lit lit qs = \end{code} \end{code} This function splits the equations @qs@ in groups that deal with the This function splits the equations @qs@ in groups that deal with the same constructor same constructor. \begin{code} \begin{code} ... @@ -327,7 +336,7 @@ constructor, using all the constructors that appears in the first column ... @@ -327,7 +336,7 @@ constructor, using all the constructors that appears in the first column of the pattern matching. of the pattern matching. We can need a default clause or not ...., it depends if we used all the We can need a default clause or not ...., it depends if we used all the constructors or not explicitly. The reasoning is similar to process_literals, constructors or not explicitly. The reasoning is similar to @process_literals@, the difference is that here the default case is not always needed. the difference is that here the default case is not always needed. \begin{code} \begin{code} ... @@ -362,15 +371,15 @@ Here remove first column is more difficult that with literals due to the fact ... @@ -362,15 +371,15 @@ Here remove first column is more difficult that with literals due to the fact that constructors can have arguments. that constructors can have arguments. For instance, the matrix For instance, the matrix \begin{verbatim} (: x xs) y (: x xs) y z y z y \end{verbatim} is transformed in: is transformed in: \begin{verbatim} x xs y x xs y _ _ y _ _ y \end{verbatim} \begin{code} \begin{code} remove_first_column :: TypecheckedPat -- Constructor remove_first_column :: TypecheckedPat -- Constructor ... @@ -436,7 +445,8 @@ get_unused_cons used_cons = unused_cons ... @@ -436,7 +445,8 @@ get_unused_cons used_cons = unused_cons Just (ty_con,_) = splitTyConApp_maybe ty Just (ty_con,_) = splitTyConApp_maybe ty all_cons = tyConDataCons ty_con all_cons = tyConDataCons ty_con used_cons_as_id = map (\ (ConPat d _ _ _ _) -> d) used_cons used_cons_as_id = map (\ (ConPat d _ _ _ _) -> d) used_cons unused_cons = uniqSetToList (mkUniqSet all_cons minusUniqSet mkUniqSet used_cons_as_id) unused_cons = uniqSetToList (mkUniqSet all_cons minusUniqSet mkUniqSet used_cons_as_id) all_vars :: [TypecheckedPat] -> Bool all_vars :: [TypecheckedPat] -> Bool ... @@ -446,7 +456,8 @@ all_vars _ = False ... @@ -446,7 +456,8 @@ all_vars _ = False remove_var :: EquationInfo -> EquationInfo remove_var :: EquationInfo -> EquationInfo remove_var (EqnInfo n ctx (WildPat _:ps) result) = EqnInfo n ctx ps result remove_var (EqnInfo n ctx (WildPat _:ps) result) = EqnInfo n ctx ps result remove_var _ = panic "Check:remove_var: equation not begin with a variable" remove_var _ = panic "Check.remove_var: equation does not begin with a variable" is_con :: EquationInfo -> Bool is_con :: EquationInfo -> Bool is_con (EqnInfo _ _ ((ConPat _ _ _ _ _):_) _) = True is_con (EqnInfo _ _ ((ConPat _ _ _ _ _):_) _) = True ... @@ -481,39 +492,43 @@ is_var_lit lit (EqnInfo _ _ ((NPat lit' _ _):_) _) | lit == lit' = True ... @@ -481,39 +492,43 @@ is_var_lit lit (EqnInfo _ _ ((NPat lit' _ _):_) _) | lit == lit' = True is_var_lit lit _ = False is_var_lit lit _ = False \end{code} \end{code} The difference beteewn make_con and make_whole_con is that The difference beteewn @make_con@ and @make_whole_con@ is that make_wole_con creates a new constructor with all their arguments, and @make_wole_con@ creates a new constructor with all their arguments, and make_Con takes a list of argumntes, creates the contructor geting thir @make_con@ takes a list of argumntes, creates the contructor getting their argumnts from the list. See where are used for details. arguments from the list. See where \fbox{\ ???\ } are used for details. We need to reconstruct the patterns (make the constructors infix and We need to reconstruct the patterns (make the constructors infix and similar) at the same time that we create the constructors. similar) at the same time that we create the constructors. You can tell tuple constructors using You can tell tuple constructors using \begin{verbatim} Id.isTupleCon Id.isTupleCon \end{verbatim} You can see if one constructor is infix with this clearer code :-)))))))))) You can see if one constructor is infix with this clearer code :-)))))))))) \begin{verbatim} Lex.isLexConSym (Name.occNameString (Name.getOccName con)) Lex.isLexConSym (Name.occNameString (Name.getOccName con)) \end{verbatim} Rather clumsy but it works. (Simon Peyton Jones) Rather clumsy but it works. (Simon Peyton Jones) We con't mind the nilDataCon because it doesn't change the way to We don't mind the @nilDataCon@ because it doesn't change the way to print the messsage, we are searching only for things like: [1,2,3], print the messsage, we are searching only for things like: @[1,2,3]@, not x:xs .... not @x:xs@ .... In reconstruct_pat we want to "undo" the work that we have done in simplify_pat In @reconstruct_pat@ we want to undo'' the work that we have done in @simplify_pat@. In particular: In particular: ((,) x y) returns to be (x, y) \begin{tabular}{lll} ((:) x xs) returns to be (x:xs) @((,) x y)@ & returns to be & @(x, y)@ (x:(...:[]) returns to be [x,...] \\ @((:) x xs)@ & returns to be & @(x:xs)@ \\ @(x:(...:[])@ & returns to be & @[x,...]@ \end{tabular} % The difficult case is the third one becouse we need to follow all the The difficult case is the third one becouse we need to follow all the contructors until the [] to know taht we need to use the second case, contructors until the @[]@ to know that we need to use the second case, not the second. not the second. \fbox{\ ???\ } % \begin{code} \begin{code} isInfixCon con = isDataSymOcc (getOccName con) isInfixCon con = isDataSymOcc (getOccName con) ... @@ -560,9 +575,9 @@ new_wild_pat :: WarningPat ... @@ -560,9 +575,9 @@ new_wild_pat :: WarningPat new_wild_pat = WildPatIn new_wild_pat = WildPatIn \end{code} \end{code} This equation makes the same thing that tidy in Match.lhs, the This equation makes the same thing as @tidy@ in @Match.lhs@, the difference is that here we can do all the tidy in one place and in the difference is that here we can do all the tidy in one place and in the Match tidy it must be done one column each time due to bookkeeping @Match@ tidy it must be done one column each time due to bookkeeping constraints. constraints. \begin{code} \begin{code} ... ...
 ... @@ -89,7 +89,8 @@ dsMonoBinds auto_scc (PatMonoBind pat grhss locn) rest ... @@ -89,7 +89,8 @@ dsMonoBinds auto_scc (PatMonoBind pat grhss locn) rest -- Common case: one exported variable -- Common case: one exported variable -- All non-recursive bindings come through this way -- All non-recursive bindings come through this way dsMonoBinds auto_scc (AbsBinds all_tyvars dicts exps@[(tyvars, global, local)] inlines binds) rest dsMonoBinds auto_scc (AbsBinds all_tyvars dicts exps@[(tyvars, global, local)] inlines binds) rest = ASSERT( all (elem tyvars) all_tyvars ) = ASSERT( all (elem tyvars) all_tyvars ) dsMonoBinds (addSccs auto_scc exps) binds [] thenDs \ core_prs -> dsMonoBinds (addSccs auto_scc exps) binds [] thenDs \ core_prs -> let let ... @@ -207,7 +208,8 @@ worthSCC (Con _ _) = False ... @@ -207,7 +208,8 @@ worthSCC (Con _ _) = False worthSCC core_expr = True worthSCC core_expr = True \end{code} \end{code} If profiling and dealing with a dict binding, wrap the dict in "_scc_ DICT ": If profiling and dealing with a dict binding, wrap the dict in @_scc_ DICT @: \begin{code} \begin{code} addDictScc var rhs = returnDs rhs addDictScc var rhs = returnDs rhs ... ...
 ... @@ -180,9 +180,10 @@ unboxArg arg ... @@ -180,9 +180,10 @@ unboxArg arg Just (arg2_tycon,_) = maybe_arg2_tycon Just (arg2_tycon,_) = maybe_arg2_tycon can'tSeeDataConsPanic thing ty can'tSeeDataConsPanic thing ty = pprPanic "ERROR: Can't see the data constructor(s) for _ccall_/_casm_/foreign declaration" = pprPanic (hcat [text thing, text "; type: ", ppr ty, text "(try compiling with -fno-prune-tydecls ..)\n"]) "ERROR: Can't see the data constructor(s) for _ccall_/_casm_/foreign declaration" (hcat [ text thing, text "; type: ", ppr ty , text "(try compiling with -fno-prune-tydecls ..)\n"]) \end{code} \end{code} ... ...
 ... @@ -60,14 +60,14 @@ import Outputable ... @@ -60,14 +60,14 @@ import Outputable %* * %* * %************************************************************************ %************************************************************************ @dsLet@ is a match-result transformer, taking the MatchResult for the body @dsLet@ is a match-result transformer, taking the @MatchResult@ for the body and transforming it into one for the let-bindings enclosing the body. and transforming it into one for the let-bindings enclosing the body. This may seem a bit odd, but (source) let bindings can contain unboxed This may seem a bit odd, but (source) let bindings can contain unboxed binds like binds like \begin{verbatim} C x# = e C x# = e \end{verbatim} This must be transformed to a case expression and, if the type has This must be transformed to a case expression and, if the type has more than one constructor, may fail. more than one constructor, may fail. ... @@ -83,7 +83,8 @@ dsLet (ThenBinds b1 b2) body ... @@ -83,7 +83,8 @@ dsLet (ThenBinds b1 b2) body -- Special case for bindings which bind unlifted variables -- Special case for bindings which bind unlifted variables -- Silently ignore INLINE pragmas... -- Silently ignore INLINE pragmas... dsLet (MonoBind (AbsBinds [] [] binder_triples inlines (PatMonoBind pat grhss loc)) sigs is_rec) body dsLet (MonoBind (AbsBinds [] [] binder_triples inlines (PatMonoBind pat grhss loc)) sigs is_rec) body | or [isUnLiftedType (idType g) | (_, g, l) <- binder_triples] | or [isUnLiftedType (idType g) | (_, g, l) <- binder_triples] = ASSERT (case is_rec of {NonRecursive -> True; other -> False}) = ASSERT (case is_rec of {NonRecursive -> True; other -> False}) putSrcLocDs loc $putSrcLocDs loc$ ... @@ -93,7 +94,8 @@ dsLet (MonoBind (AbsBinds [] [] binder_triples inlines (PatMonoBind pat grhss lo ... @@ -93,7 +94,8 @@ dsLet (MonoBind (AbsBinds [] [] binder_triples inlines (PatMonoBind pat grhss lo bind (tyvars, g, l) body = ASSERT( null tyvars ) bind (tyvars, g, l) body = ASSERT( null tyvars ) bindNonRec g (Var l) body bindNonRec g (Var l) body in in mkErrorAppDs iRREFUT_PAT_ERROR_ID result_ty (showSDoc (ppr pat)) thenDs \ error_expr -> mkErrorAppDs iRREFUT_PAT_ERROR_ID result_ty (showSDoc (ppr pat)) thenDs \ error_expr -> matchSimply rhs PatBindMatch pat body' error_expr matchSimply rhs PatBindMatch pat body' error_expr where where result_ty = coreExprType body result_ty = coreExprType body ... @@ -124,17 +126,17 @@ dsExpr e@(HsVar var) = returnDs (Var var) ... @@ -124,17 +126,17 @@ dsExpr e@(HsVar var) = returnDs (Var var) %* * %* * %************************************************************************ %************************************************************************ We give int/float literals type Integer and Rational, respectively. We give int/float literals type @Integer@ and @Rational@, respectively. The typechecker will (presumably) have put \tr{from{Integer,Rational}s} The typechecker will (presumably) have put \tr{from{Integer,Rational}s} around them. around them. ToDo: put in range checks for when converting "i" ToDo: put in range checks for when converting @i@'' (or should that be in the typechecker?) (or should that be in the typechecker?) For numeric literals, we try to detect there use at a standard type For numeric literals, we try to detect there use at a standard type (Int, Float, etc.) are directly put in the right constructor. (@Int@, @Float@, etc.) are directly put in the right constructor. [NB: down with the @App@ conversion.] [NB: down with the @App@ conversion.] Otherwise, we punt, putting in a "NoRep" Core literal (where the Otherwise, we punt, putting in a @NoRep@ Core literal (where the representation decisions are delayed)... representation decisions are delayed)... See also below where we look for @DictApps@ for \tr{plusInt}, etc. See also below where we look for @DictApps@ for \tr{plusInt}, etc. ... @@ -370,8 +372,9 @@ dsExpr (HsIf guard_expr then_expr else_expr src_loc) ... @@ -370,8 +372,9 @@ dsExpr (HsIf guard_expr then_expr else_expr src_loc) \end{code} \end{code} Type lambda and application \noindent ~~~~~~~~~~~~~~~~~~~~~~~~~~~ \underline{\bf Type lambda and application} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} \begin{code} dsExpr (TyLam tyvars expr) dsExpr (TyLam tyvars expr) = dsExpr expr thenDs \ core_expr -> = dsExpr expr thenDs \ core_expr -> ... @@ -383,8 +386,9 @@ dsExpr (TyApp expr tys) ... @@ -383,8 +386,9 @@ dsExpr (TyApp expr tys) \end{code} \end{code} Various data construction things \noindent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \underline{\bf Various data construction things} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} \begin{code} dsExpr (ExplicitListOut ty xs) dsExpr (ExplicitListOut ty xs) = go xs = go xs ... @@ -443,25 +447,26 @@ dsExpr (ArithSeqOut expr (FromThenTo from thn two)) ... @@ -443,25 +447,26 @@ dsExpr (ArithSeqOut expr (FromThenTo from thn two)) returnDs (mkApps expr2 [from2, thn2, two2]) returnDs (mkApps expr2 [from2, thn2, two2]) \end{code} \end{code} Record construction and update \noindent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \underline{\bf Record construction and update} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For record construction we do this (assuming T has three arguments) For record construction we do this (assuming T has three arguments) \begin{verbatim} T { op2 = e } T { op2 = e } ==> ==> let err = /\a -> recConErr a let err = /\a -> recConErr a T (recConErr t1 "M.lhs/230/op1") T (recConErr t1 "M.lhs/230/op1") e e (recConErr t1 "M.lhs/230/op3") (recConErr t1 "M.lhs/230/op3") \end{verbatim} recConErr then converts its arugment string into a proper message @recConErr@ then converts its arugment string into a proper message before printing it as before printing it as \begin{verbatim} M.lhs, line 230: missing field op1 was evaluated \end{verbatim} M.lhs, line 230: Missing field in record construction op1 We also handle @C{}@ as valid construction syntax for an unlabelled constructor @C@, setting all of @C@'s fields to bottom. We also handle C{} as valid construction syntax for an unlabelled constructor C, setting all of C's fields to bottom. \begin{code} \begin{code} dsExpr (RecordConOut data_con con_expr rbinds) dsExpr (RecordConOut data_con con_expr rbinds) ... @@ -489,13 +494,13 @@ dsExpr (RecordConOut data_con con_expr rbinds) ... @@ -489,13 +494,13 @@ dsExpr (RecordConOut data_con con_expr rbinds) \end{code} \end{code} Record update is a little harder. Suppose we have the decl: Record update is a little harder. Suppose we have the decl: \begin{verbatim} data T = T1 {op1, op2, op3 :: Int} data T = T1 {op1, op2, op3 :: Int} | T2 {op4, op2 :: Int} | T2 {op4, op2 :: Int} | T3 | T3 \end{verbatim} Then we translate as follows: Then we translate as follows: \begin{verbatim} r { op2 = e } r { op2 = e } ===> ===> let op2 = e in let op2 = e in ... @@ -503,9 +508,9 @@ Then we translate as follows: ... @@ -503,9 +508,9 @@ Then we translate as follows: T1 op1 _ op3 -> T1 op1 op2 op3 T1 op1 _ op3 -> T1 op1 op2 op3 T2 op4 _ -> T2 op4 op2 T2 op4 _ -> T2 op4 op2 other -> recUpdError "M.lhs/230" other -> recUpdError "M.lhs/230" \end{verbatim} It's important that we use the constructor Ids for T1, T2 etc on the It's important that we use the constructor Ids for @T1@, @T2@ etc on the RHSs, and do not generate a Core Con directly, because the constructor RHSs, and do not generate a Core @Con@ directly, because the constructor might do some argument-evaluation first; and may have to throw away some might do some argument-evaluation first; and may have to throw away some dictionaries. dictionaries. ... @@ -569,8 +574,10 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds) ... @@ -569,8 +574,10 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds) ok (sel_id, _, _) = recordSelectorFieldLabel sel_id elem con_fields ok (sel_id, _, _) = recordSelectorFieldLabel sel_id elem con_fields \end{code} \end{code} Dictionary lambda and application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \noindent \underline{\bf Dictionary lambda and application} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @DictLam@ and @DictApp@ turn into the regular old things. @DictLam@ and @DictApp@ turn into the regular old things. (OLD:) @DictFunApp@ also becomes a curried application, albeit slightly more (OLD:) @DictFunApp@ also becomes a curried application, albeit slightly more complicated; reminiscent of fully-applied constructors. complicated; reminiscent of fully-applied constructors. ... @@ -654,12 +661,14 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty ... @@ -654,12 +661,14 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty dsExpr expr thenDs \ expr2 -> dsExpr expr thenDs \ expr2 -> let