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 @@ % (c) The GRASP/AQUA Project, Glasgow University, 1997-1998 % % Author: Juan J. Quintela \section{Module @Check@ in @deSugar@} \begin{code} ... ... @@ -56,61 +57,69 @@ import Outputable \end{code} This module performs checks about if one list of equations are: - Overlapped - Non exhaustive \begin{itemize} \item Overlapped \item Non exhaustive \end{itemize} 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: Two Techniques for Compiling Lazy Pattern Matching Luc Maranguet \begin{quotation} {\em Two Techniques for Compiling Lazy Pattern Matching}, Luc Maranguet, INRIA Rocquencourt (RR-2385, 1994) The algorithm is based in the first Technique, but there are some differences: - We don't generate code - We have constructors and literals (not only literals as in the \end{quotation} The algorithm is based on the first technique, but there are some differences: \begin{itemize} \item We don't generate code \item We have constructors and literals (not only literals as in the 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 \end{itemize} (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: - The patterns that are not recognized - The equations that are not overlapped It simplify the patterns and then call check' (the same semantics),and it \begin{itemize} \item The patterns that are not recognized \item The equations that are not overlapped \end{itemize} It simplify the patterns and then call @check'@ (the same semantics), and it needs to reconstruct the patterns again .... The problem appear with things like: \begin{verbatim} f [x,y] = .... f (x:xs) = ..... \end{verbatim} We want to put the two patterns with the same syntax, (prefix form) and then all the constructors are equal: \begin{verbatim} f (: x (: y [])) = .... 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. 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 wrote: \begin{verbatim} f [x,y] = .. \end{verbatim} He don't want a warning message written: \begin{verbatim} f (: x (: y [])) ........ \end{verbatim} Then we need to use InPats. Juan Quintela 5 JUL 1998 \begin{quotation} Juan Quintela 5 JUL 1998\\ User-friendliness and compiler writers are no friends. \end{quotation} \begin{code} type WarningPat = InPat Name ... ... @@ -178,11 +187,11 @@ untidy_lit lit = lit 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 the reason top have two functions, check is the external interface, check' is called recursively. @check'@ is called recursively. There are several cases: \begin{item} \begin{itemize} \item There are no equations: Everything is OK. \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 ... ... @@ -198,7 +207,7 @@ There are several cases: \item In the general case, there can exist literals ,constructors or only vars in the first column, we actuate in consequence. \end{item} \end{itemize} \begin{code} ... ... @@ -243,7 +252,7 @@ split_by_literals qs = process_literals used_lits qs used_lits = get_used_lits qs \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. \begin{code} ... ... @@ -256,7 +265,7 @@ process_explicit_literals lits qs = (concat pats, unionManyUniqSets indexs) \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 must be one Variable to be complete. ... ... @@ -297,7 +306,7 @@ remove_first_column_lit lit qs = \end{code} This function splits the equations @qs@ in groups that deal with the same constructor same constructor. \begin{code} ... ... @@ -327,7 +336,7 @@ constructor, using all the constructors that appears in the first column of the pattern matching. 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. \begin{code} ... ... @@ -362,15 +371,15 @@ Here remove first column is more difficult that with literals due to the fact that constructors can have arguments. For instance, the matrix \begin{verbatim} (: x xs) y z y \end{verbatim} is transformed in: \begin{verbatim} x xs y _ _ y \end{verbatim} \begin{code} remove_first_column :: TypecheckedPat -- Constructor ... ... @@ -436,7 +445,8 @@ get_unused_cons used_cons = unused_cons Just (ty_con,_) = splitTyConApp_maybe ty all_cons = tyConDataCons ty_con 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 ... ... @@ -446,7 +456,8 @@ all_vars _ = False remove_var :: EquationInfo -> EquationInfo 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 (EqnInfo _ _ ((ConPat _ _ _ _ _):_) _) = True ... ... @@ -481,39 +492,43 @@ is_var_lit lit (EqnInfo _ _ ((NPat lit' _ _):_) _) | lit == lit' = True is_var_lit lit _ = False \end{code} The difference beteewn make_con and make_whole_con is that make_wole_con creates a new constructor with all their arguments, and make_Con takes a list of argumntes, creates the contructor geting thir argumnts from the list. See where are used for details. The difference beteewn @make_con@ and @make_whole_con@ is that @make_wole_con@ creates a new constructor with all their arguments, and @make_con@ takes a list of argumntes, creates the contructor getting their arguments from the list. See where \fbox{\ ???\ } are used for details. We need to reconstruct the patterns (make the constructors infix and similar) at the same time that we create the constructors. You can tell tuple constructors using \begin{verbatim} Id.isTupleCon \end{verbatim} You can see if one constructor is infix with this clearer code :-)))))))))) \begin{verbatim} Lex.isLexConSym (Name.occNameString (Name.getOccName con)) \end{verbatim} Rather clumsy but it works. (Simon Peyton Jones) We con'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], not x:xs .... 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]@, 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: ((,) x y) returns to be (x, y) ((:) x xs) returns to be (x:xs) (x:(...:[]) returns to be [x,...] \begin{tabular}{lll} @((,) x y)@ & returns to be & @(x, y)@ \\ @((:) 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 contructors until the [] to know taht we need to use the second case, not the second. contructors until the @[]@ to know that we need to use the second case, not the second. \fbox{\ ???\ } % \begin{code} isInfixCon con = isDataSymOcc (getOccName con) ... ... @@ -560,9 +575,9 @@ new_wild_pat :: WarningPat new_wild_pat = WildPatIn \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 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. \begin{code} ... ...
 ... ... @@ -89,7 +89,8 @@ dsMonoBinds auto_scc (PatMonoBind pat grhss locn) rest -- Common case: one exported variable -- 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 ) dsMonoBinds (addSccs auto_scc exps) binds [] thenDs \ core_prs -> let ... ... @@ -207,7 +208,8 @@ worthSCC (Con _ _) = False worthSCC core_expr = True \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} addDictScc var rhs = returnDs rhs ... ...
 ... ... @@ -180,9 +180,10 @@ unboxArg arg Just (arg2_tycon,_) = maybe_arg2_tycon can'tSeeDataConsPanic thing ty = pprPanic "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"]) = pprPanic "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} ... ...
 ... ... @@ -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. This may seem a bit odd, but (source) let bindings can contain unboxed binds like \begin{verbatim} C x# = e \end{verbatim} This must be transformed to a case expression and, if the type has more than one constructor, may fail. ... ... @@ -83,7 +83,8 @@ dsLet (ThenBinds b1 b2) body -- Special case for bindings which bind unlifted variables -- 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] = ASSERT (case is_rec of {NonRecursive -> True; other -> False}) putSrcLocDs loc $... ... @@ -93,7 +94,8 @@ dsLet (MonoBind (AbsBinds [] [] binder_triples inlines (PatMonoBind pat grhss lo bind (tyvars, g, l) body = ASSERT( null tyvars ) bindNonRec g (Var l) body 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 where result_ty = coreExprType body ... ... @@ -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} 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?) 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.] 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)... 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) \end{code} Type lambda and application ~~~~~~~~~~~~~~~~~~~~~~~~~~~ \noindent \underline{\bf Type lambda and application} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} dsExpr (TyLam tyvars expr) = dsExpr expr thenDs \ core_expr -> ... ... @@ -383,8 +386,9 @@ dsExpr (TyApp expr tys) \end{code} Various data construction things ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \noindent \underline{\bf Various data construction things} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} dsExpr (ExplicitListOut ty xs) = go xs ... ... @@ -443,25 +447,26 @@ dsExpr (ArithSeqOut expr (FromThenTo from thn two)) returnDs (mkApps expr2 [from2, thn2, two2]) \end{code} Record construction and update ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \noindent \underline{\bf Record construction and update} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For record construction we do this (assuming T has three arguments) \begin{verbatim} T { op2 = e } ==> let err = /\a -> recConErr a T (recConErr t1 "M.lhs/230/op1") e (recConErr t1 "M.lhs/230/op3") recConErr then converts its arugment string into a proper message \end{verbatim} @recConErr@ then converts its arugment string into a proper message 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} dsExpr (RecordConOut data_con con_expr rbinds) ... ... @@ -489,13 +494,13 @@ dsExpr (RecordConOut data_con con_expr rbinds) \end{code} Record update is a little harder. Suppose we have the decl: \begin{verbatim} data T = T1 {op1, op2, op3 :: Int} | T2 {op4, op2 :: Int} | T3 \end{verbatim} Then we translate as follows: \begin{verbatim} r { op2 = e } ===> let op2 = e in ... ... @@ -503,9 +508,9 @@ Then we translate as follows: T1 op1 _ op3 -> T1 op1 op2 op3 T2 op4 _ -> T2 op4 op2 other -> recUpdError "M.lhs/230" 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 \end{verbatim} 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 might do some argument-evaluation first; and may have to throw away some dictionaries. ... ... @@ -569,8 +574,10 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds) ok (sel_id, _, _) = recordSelectorFieldLabel sel_id elem con_fields \end{code} Dictionary lambda and application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \noindent \underline{\bf Dictionary lambda and application} % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @DictLam@ and @DictApp@ turn into the regular old things. (OLD:) @DictFunApp@ also becomes a curried application, albeit slightly more complicated; reminiscent of fully-applied constructors. ... ... @@ -654,12 +661,14 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty dsExpr expr thenDs \ expr2 -> let (_, a_ty) = splitAppTy (coreExprType expr2) -- Must be of form (m a) fail_expr = HsApp (TyApp (HsVar fail_id) [b_ty]) (HsLitOut (HsString (_PK_ msg)) stringTy) fail_expr = HsApp (TyApp (HsVar fail_id) [b_ty]) (HsLitOut (HsString (_PK_ msg)) stringTy) msg = ASSERT2( isNotUsgTy a_ty, ppr a_ty ) ASSERT2( isNotUsgTy b_ty, ppr b_ty ) "Pattern match failure in do expression, " ++ showSDoc (ppr locn) main_match = mkSimpleMatch [pat] (HsDoOut do_or_lc stmts return_id then_id fail_id result_ty locn) (HsDoOut do_or_lc stmts return_id then_id fail_id result_ty locn) (Just result_ty) locn the_matches | failureFreePat pat = [main_match] ... ...  ... ... @@ -48,14 +48,14 @@ import Outputable Desugaring of @foreign@ declarations is naturally split up into parts, an @import@ and an @export@ part. A @foreign import@ declaration \begin{verbatim} foreign import cc nm f :: prim_args -> IO prim_res \end{verbatim} is the same as \begin{verbatim} f :: prim_args -> IO prim_res f a1 ... an = _ccall_ nm cc a1 ... an \end{verbatim} so we reuse the desugaring code in @DsCCall@ to deal with these. \begin{code} ... ... @@ -63,8 +63,10 @@ dsForeigns :: Module -> [TypecheckedForeignDecl] -> DsM ( [CoreBind] -- desugared foreign imports , [CoreBind] -- helper functions for foreign exports , SDoc -- Header file prototypes for "foreign exported" functions. , SDoc -- C stubs to use when calling "foreign exported" funs. , SDoc -- Header file prototypes for -- "foreign exported" functions. , SDoc -- C stubs to use when calling -- "foreign exported" functions. ) dsForeigns mod_name fos = foldlDs combine ([],[],empty,empty) fos where ... ... @@ -99,7 +101,7 @@ dsForeigns mod_name fos = foldlDs combine ([],[],empty,empty) fos Desugaring foreign imports is just the matter of creating a binding that on its RHS unboxes its arguments, performs the external call (using the CCallOp primop), before boxing the result up and returning it. (using the @CCallOp@ primop), before boxing the result up and returning it. \begin{code} dsFImport :: Id ... ... @@ -201,16 +203,16 @@ dsFLabel nm ext_name = returnDs (NonRec nm fo_rhs) \end{code} The function that does most of the work for 'foreign export' declarations. (see below for the boilerplate code a 'foreign export' declaration expands The function that does most of the work for @foreign export@' declarations. (see below for the boilerplate code a @foreign export@' declaration expands into.) For each 'foreign export foo' in a module M we generate: * a C function 'foo', which calls * a Haskell stub 'M.$ffoo', which calls the user-written Haskell function 'M.foo'. For each @foreign export foo@' in a module M we generate: \begin{itemize} \item a C function @foo@', which calls \item a Haskell stub @M.\$ffoo@', which calls \end{itemize} the user-written Haskell function @M.foo@'. \begin{code} dsFExport :: Id ... ... @@ -291,7 +293,8 @@ dsFExport i ty mod_name ext_name cconv isDyn = ExtName fs _ -> fs Dynamic -> panic "dsFExport: Dynamic - shouldn't ever happen." (h_stub, c_stub) = fexportEntry c_nm f_helper_glob wrapper_arg_tys the_result_ty cconv isDyn (h_stub, c_stub) = fexportEntry c_nm f_helper_glob wrapper_arg_tys the_result_ty cconv isDyn in returnDs (NonRec f_helper_glob the_body, h_stub, c_stub) ... ... @@ -333,7 +336,7 @@ dsFExport i ty mod_name ext_name cconv isDyn = \end{code} "foreign export dynamic" lets you dress up Haskell IO actions @foreign export dynamic@ lets you dress up Haskell IO actions of some fixed type behind an externally callable interface (i.e., as a C function pointer). Useful for callbacks and stuff. ... ... @@ -376,7 +379,8 @@ dsFExportDynamic i ty mod_name ext_name cconv = fe_nm = toCName fe_id fe_ext_name = ExtName (_PK_ fe_nm) Nothing in dsFExport i export_ty mod_name fe_ext_name cconv True thenDs \ (fe@(NonRec fe_helper fe_expr), h_code, c_code) -> dsFExport i export_ty mod_name fe_ext_name cconv True thenDs \ (fe@(NonRec fe_helper fe_expr), h_code, c_code) -> newSysLocalDs arg_ty thenDs \ cback -> dsLookupGlobalValue makeStablePtr_NAME thenDs \ makeStablePtrId -> let ... ...
 ... ... @@ -32,7 +32,7 @@ It desugars: where binds \end{verbatim} producing an expression with a runtime error in the corner if necessary. The type argument gives the type of the ei. necessary. The type argument gives the type of the @ei@. \begin{code} dsGuarded :: TypecheckedGRHSs -> DsM CoreExpr ... ... @@ -103,7 +103,8 @@ matchGuard (BindStmt pat rhs locn : stmts) ctx matchSinglePat core_rhs ctx pat match_result \end{code} -- Should *fail* if e returns D Should {\em fail} if @e@ returns @D@ \begin{verbatim} f x | p <- e', let C y# = e, f y# = r1 | otherwise = r2 \end{verbatim} \ No newline at end of file
 ... ... @@ -44,11 +44,11 @@ outPatType (DictPat ds ms) = case (length ds_ms) of \end{code} Nota bene: DsBinds relies on the fact that at least for simple Nota bene: @DsBinds@ relies on the fact that at least for simple tuple patterns @collectTypedPatBinders@ returns the binders in the same order as they appear in the tuple. collectTypedBinders and collectedTypedPatBinders are the exportees. @collectTypedBinders@ and @collectedTypedPatBinders@ are the exportees. \begin{code} collectTypedMonoBinders :: TypecheckedMonoBinds -> [Id] ... ...
 ... ... @@ -216,7 +216,7 @@ dsLookupGlobalValue name us genv loc mod_and_grp warns %************************************************************************ %* * %* type synonym EquationInfo and access functions for its pieces * \subsection{Type synonym @EquationInfo@ and access functions for its pieces} %* * %************************************************************************ ... ...
 ... ... @@ -57,7 +57,7 @@ import Outputable %************************************************************************ %* * %* Building lets \subsection{ Building lets} %* * %************************************************************************ ... ... @@ -78,7 +78,7 @@ mkDsLets binds body = foldr mkDsLet body binds %************************************************************************ %* * %* Selecting match variables \subsection{ Selecting match variables} %* * %************************************************************************ ... ... @@ -224,7 +224,8 @@ mkCoAlgCaseMatchResult var match_alts -- Stuff for newtype (con_id, arg_ids, match_result) = head match_alts arg_id = head arg_ids