aboutsummaryrefslogtreecommitdiff
path: root/frontend/convertcases.icl
diff options
context:
space:
mode:
authorronny2002-08-22 12:18:39 +0000
committerronny2002-08-22 12:18:39 +0000
commitb8b6f1a62f670982ebd3b6d3df3c8a0fd9d77425 (patch)
treea61f044da4e671baec98e5f5cd2bc610f81315a7 /frontend/convertcases.icl
parentAdd partitioning variants (diff)
transform implicit cases on rhs variables, see comment before splitCases in convertcases
git-svn-id: https://svn.cs.ru.nl/repos/clean-compiler/trunk@1188 1f8540f1-abd5-4d5b-9d24-4c5ce8603e2d
Diffstat (limited to 'frontend/convertcases.icl')
-rw-r--r--frontend/convertcases.icl652
1 files changed, 596 insertions, 56 deletions
diff --git a/frontend/convertcases.icl b/frontend/convertcases.icl
index ba07654..25e2f49 100644
--- a/frontend/convertcases.icl
+++ b/frontend/convertcases.icl
@@ -3,7 +3,7 @@
*/
implementation module convertcases
-import syntax, transform, checksupport, StdCompare, check, utilities, trans, general //, RWSDebug
+import syntax, transform, checksupport, StdCompare, check, utilities, trans, general; // , RWSDebug
// exactZip fails when its arguments are of unequal length
exactZip` :: ![.a] ![.b] -> [(.a,.b)]
@@ -38,7 +38,7 @@ convertCasesOfFunctions groups main_dcl_module_n dcl_functions common_defs fun_d
= addNewFunctionsToGroups common_defs cs_fun_heap cs_new_functions main_dcl_module_n groups imported_types imported_conses type_heaps cs_var_heap
(imported_functions, imported_conses) = foldSt split collected_imports ([], imported_conses)
= (imported_functions, groups, { fundef \\ fundef <- [ fundef \\ fundef <-: fun_defs ] ++ new_fun_defs },
- imported_types, imported_conses, cs_var_heap, type_heaps, cs_expr_heap)
+ imported_types, imported_conses, cs_var_heap, type_heaps, /* abort "that's enough" */ cs_expr_heap)
where
convert_groups group_nr groups dcl_functions common_defs main_dcl_module_n fun_defs_and_ci
| group_nr == size groups
@@ -64,7 +64,12 @@ where
ds = { ds_lets = [], ds_var_heap = rcs_var_heap, ds_expr_heap = rcs_expr_heap}
(tb_rhs, ds) = distributeLets 1 tb_rhs ds -*-> "dis"
(tb_rhs, {ds_var_heap, ds_expr_heap}) = buildLetExpr tb_rhs ds -*-> "build"
- = (TransformedBody {body & tb_rhs = tb_rhs }, (rcs_imports, { cs & cs_var_heap = ds_var_heap, cs_expr_heap = ds_expr_heap}))
+
+ (_, {ss_expr_heap, ss_var_heap})
+ = findSplitCases {si_moved = False, si_next_alt=No} tb_rhs
+ {ss_var_heap=ds_var_heap, ss_expr_heap = ds_expr_heap}
+
+ = (TransformedBody {body & tb_rhs = tb_rhs }, (rcs_imports, { cs & cs_var_heap = ss_var_heap, cs_expr_heap = ss_expr_heap}))
-*-> ("eliminate_code_sharing_in_function (distributeLets)", 2, tb_rhs)
split :: SymbKind (ImportedFunctions, ImportedConstructors) -> (ImportedFunctions, ImportedConstructors)
@@ -540,7 +545,7 @@ where
new_depth = depth + 1
(local_lets, ds_var_heap) = mark_local_let_vars new_depth tot_ref_counts ds_var_heap
- -*-> ("ref_counts", case_expr, tot_ref_counts, ref_counts_in_patterns)
+ // -*-> ("ref_counts", case_expr, tot_ref_counts, ref_counts_in_patterns)
with
mark_local_let_vars new_depth tot_ref_counts var_heap
@@ -740,6 +745,320 @@ where
# (bind_src, cp_info) = distributeLets depth bind_src cp_info
= ({ bind & bind_src = bind_src }, cp_info)
+/*
+ Split case expressions.
+
+ Splitting a case expression can be necessary because of limitations in
+ the compiler's backend. The backend can only handle case expressions that
+ match on left-hand-side variable and are on root positions (right-hand-side
+ of functions, the resulting expression of let expressions on a root
+ position and the right-hand side or default of case expressions an on a
+ root position). The exact test can be found in convertRootCases.
+
+ There's a difference in the semantics of implicit cases (which are written
+ as patterns by the programmer) and explicit cases (written as case expres-
+ sions by the programmer).
+
+ Implicit cases (denoted as case'):
+
+ fi x y
+ = case' x of / fi 1 2 \
+ 1 -> case' y of | syntax tree for = 3 |
+ 2 -> 3 | fi _ _ |
+ _ -> 4 \ = 4 /
+
+ (fi 1 2) reduces to 2
+
+ Explicit cases:
+
+ fe x y
+ = case x of
+ 1 -> case y of
+ 2 -> 3
+ _ -> 4
+
+ (fe 1 2) reduces to <<run-time error>>
+
+ The frontend introduces functions for cases expressions that are explicit
+ or that the backend can't handle. For the example above:
+
+ fe x y
+ = _c1 x y
+ _c1 x y
+ = case' x of
+ 1 -> _c2
+ _ -> 4
+ _c2 y
+ = case' y of
+ 2 -> 3
+
+ This agrees with the semantics: the function _c2 will fail during
+ evaluation of (fe 1 2).
+
+ Problems occur when there's an implicit case expression that can't be
+ handled by the backend. These case expressions result from transformations
+ in the compiler (fusion in transform.icl and the conversion of dynamics).
+ For example, in the function
+
+ f
+ = case' 1 of
+ 1 -> case' 2 of
+ 3 -> 4
+ _ -> 5
+
+ f should reduce to 5, but in the direct translation
+
+ f
+ = _c1 1
+ _c1 x
+ = case' x of
+ 1 -> _c2 2
+ _ -> 5
+ _c2 y
+ = case' y of
+ 3 -> 4
+
+ f erroneously reduces to <<run-time error>>.
+
+ The solution is to split the case in _c1, introduce a function for the
+ second part (the default alternative of _c1), and call this function from
+ both _c1 and _c2
+
+ f
+ = _c1 1
+ _c1 x
+ = case' x of
+ 1 -> _c2 2
+ _ -> _f
+ _c2 y
+ = case' y of
+ 3 -> 4
+ _ -> _f
+ _f
+ = 5
+
+ This transformation is done in two phases. First findSplitCases determines
+ where cases should be split, and to which alternative of an outer case
+ a case should pass control if it doesn't have a default. This information
+ is recorded in the expression heap (accessed through the case_info_ptr).
+
+ The actual splitting, the introduction of new functions, and the
+ introduction of calls to these functions is done in convertRootCases.
+*/
+
+:: SplitState =
+ { ss_expr_heap :: !.ExpressionHeap
+ , ss_var_heap :: !.VarHeap
+ }
+
+:: SplitInfo =
+ { si_next_alt :: !Optional NextAlt
+ , si_moved :: !Bool
+ }
+
+class findSplitCases e :: !SplitInfo !e !*SplitState -> (Bool, *SplitState)
+
+(:-) infixl
+(:-) a f
+ :== f a
+
+instance findSplitCases (Optional a) | findSplitCases a where
+ findSplitCases _ No ss
+ = (False, ss) <<- "findSplitCases (Opt No)"
+ findSplitCases si (Yes x) ss
+ = findSplitCases si x ss <<- "findSplitCases (Opt No)"
+
+instance findSplitCases Expression where
+ findSplitCases si (Let lad) ss
+ = findSplitCases si lad ss <<- "findSplitCases (Exp Let)"
+ findSplitCases si (Case kees) ss
+ = findSplitCases si kees ss <<- "findSplitCases (Exp Case)"
+ findSplitCases _ _ ss
+ = (False, ss) <<- "findSplitCases (Exp _)"
+
+instance findSplitCases Case where
+ findSplitCases si kees=:{case_info_ptr, case_guards, case_default} ss
+ # ss
+ = init_case_split_info case_info_ptr ss <<- "findSplitCases (Case)"
+ # (f2, ss)
+ = split_guards {si & si_next_alt = first_next_alt, si_moved = False} use_outer_alt case_guards (False, ss)
+ # (split, ss)
+ = nextAlts {si & si_moved = f2} kees ss
+ # (f3, ss)
+ = findSplitCases si case_default ss
+ = (split || f3, ss) ->> ("findSplitCases (Case)" +++ toString split +++ toString f2 +++ toString f3)
+ where
+ first_next_alt
+ = Yes {na_case = case_info_ptr, na_alt_nr = 1}
+ use_outer_alt
+ = use_outer_alt_for_last_alt case_default si
+
+ init_case_split_info case_info_ptr ss=:{ss_expr_heap}
+ # (case_info, ss_expr_heap)
+ = readPtr case_info_ptr ss_expr_heap
+ # type = case_type case_info
+ ss_expr_heap
+ = ss_expr_heap <:= (case_info_ptr,
+ EI_CaseTypeAndSplits type {sic_splits = [], sic_next_alt = No})
+ = {ss & ss_expr_heap = ss_expr_heap}
+// ->> (toString kees.case_ident, " = ", ptrToInt case_info_ptr)
+ where
+ case_type (EI_CaseTypeAndRefCounts type _)
+ = type
+ case_type (EI_CaseTypeAndSplits type _)
+ /*
+ The same case is encountered twice by findSplitCases. This can
+ happen because distributeLets doesn't copy expressions. So
+
+ Start
+ # x = case 1 of 1 -> 1
+ | True
+ = x
+ = x
+
+ is transformed to
+
+ Start
+ | True
+ = case 1 of 1 -> 1
+ = case 1 of 1 -> 1
+
+ but the two cases are shared in the syntax tree (and thus
+ have the same case_info_ptr). We just leave the case shared
+ under the assumption that in both instances it will be split
+ in exactly the same way.
+ */
+ = type
+ case_type info
+ = abort "case_type???" <<- info
+
+// split_guards :: SplitInfo (Optional (Optional NextAlt)) CasePatterns *SplitState -> (Bool, *SplitState)
+ split_guards si use_outer_alt (AlgebraicPatterns _ alts) ss
+ = split_alts si use_outer_alt alts ss
+ split_guards si use_outer_alt (BasicPatterns _ alts) ss
+ = split_alts si use_outer_alt alts ss
+ split_guards si use_outer_alt (OverloadedListPatterns _ _ alts) ss
+ = split_alts si use_outer_alt alts ss
+
+// split_alts :: SplitInfo (Optional (Optional NextAlt)) [a] *SplitState -> (Bool, *SplitState) | findSplitCases a
+ split_alts _ _ [] (s, ss)
+ = (s, ss)
+ split_alts _ (Yes si) [last] (f1, ss)
+ # (f2, ss)
+ = findSplitCases si last ss
+ = (f1 || f2, ss)
+ split_alts si last_next_alt [pattern : patterns] (f1, ss)
+ # (f2, ss)
+ = findSplitCases si pattern ss
+ = split_alts (incAltNr si) last_next_alt patterns (f1 || f2, ss)
+
+// use_outer_alt_for_last_alt :: (Optional Expression) ExprInfoPtr SplitInfo -> Optional (Optional NextAlt)
+ use_outer_alt_for_last_alt No si =: {si_next_alt, si_moved}
+ /*
+ This case has no default. If the last alternative fails,
+ control is passed to the outer case.
+ */
+ = Yes si // {si_next_alt, si_moved}
+ use_outer_alt_for_last_alt (Yes _) si
+ = No
+
+// debug ...
+instance toString (Optional a) | toString a where
+ toString No
+ = ""
+ toString (Yes x)
+ = toString x
+// ... debug
+
+class incAltNr a :: a -> a
+
+instance incAltNr Int where
+ incAltNr alt_nr
+ = alt_nr + 1
+
+instance incAltNr NextAlt where
+ incAltNr next_alt=:{na_alt_nr}
+ = {next_alt & na_alt_nr = incAltNr na_alt_nr}
+
+instance incAltNr (Optional a) | incAltNr a where
+ incAltNr No
+ = No
+ incAltNr (Yes x)
+ = Yes (incAltNr x)
+
+instance incAltNr SplitInfo where
+ incAltNr si=:{si_next_alt}
+ = {si & si_next_alt = incAltNr si_next_alt}
+
+instance findSplitCases AlgebraicPattern where
+ findSplitCases si {ap_expr} ss
+ = findSplitCases si ap_expr ss <<- "findSplitCases (AlgebraicPattern)"
+
+instance findSplitCases BasicPattern where
+ findSplitCases si {bp_expr} ss
+ = findSplitCases si bp_expr ss <<- "findSplitCases (BasicPattern)"
+
+instance findSplitCases Let where
+ findSplitCases si {let_expr} ss
+ = findSplitCases si let_expr ss <<- "findSplitCases (Let)"
+
+nextAlts :: SplitInfo Case *SplitState -> (Bool, *SplitState)
+nextAlts si=:{si_next_alt=Yes next_alt, si_moved} kees=:{case_info_ptr} ss
+ # (jumps, ss=:{ss_expr_heap})
+ = jumps_to_next_alt si_moved kees ss
+ | jumps
+ // update the info for this case
+ # (EI_CaseTypeAndSplits type splits, ss_expr_heap)
+ = readPtr case_info_ptr ss_expr_heap
+ ss_expr_heap
+ = ss_expr_heap <:= (case_info_ptr,
+ EI_CaseTypeAndSplits type {splits & sic_next_alt = Yes next_alt})
+
+ // update the info for the outer case
+ # (EI_CaseTypeAndSplits type splits, ss_expr_heap)
+ = readPtr next_alt.na_case ss_expr_heap
+ split
+ = {sc_alt_nr = next_alt.na_alt_nr, sc_call = No}
+ ss_expr_heap
+ = ss_expr_heap <:= (next_alt.na_case,
+ EI_CaseTypeAndSplits type {splits & sic_splits = [split : splits.sic_splits]})
+ ss_expr_heap
+ = ss_expr_heap
+ ->> (toString kees.case_ident, ptrToInt case_info_ptr,
+ "jumps to ", ptrToInt next_alt.na_case, next_alt.na_alt_nr)
+
+ = (True, {ss & ss_expr_heap = ss_expr_heap})
+ // otherwise
+ = (False, ss)
+ where
+/* stress test, convert all cases without a default
+ jumps_to_next_alt _ {case_default = No} ss
+ = (True, ss)
+*/
+/* stress test, convert all explicit cases (may change semantics for failing programs)
+ jumps_to_next_alt _ {case_default = No, case_explicit = True, case_expr}
+ = (True, ss) ->> (toString (ptrToInt case_info_ptr) +++ " jumps, because explicit")
+*/
+ jumps_to_next_alt True {case_default = No} ss
+ = (True, ss) ->> (toString (ptrToInt case_info_ptr) +++ " jumps, because alt was moved")
+ jumps_to_next_alt _ {case_default = No, case_explicit = False, case_expr} ss
+ | not (is_lhs_var case_expr ss.ss_var_heap)
+ = (True, ss) ->> (toString (ptrToInt case_info_ptr) +++ " jumps, because implicit no lhs var")
+ jumps_to_next_alt moved _ ss
+ = (False, ss) ->> (toString (ptrToInt case_info_ptr) +++ " doesn't jumps" +++ toString moved +++ toString kees.case_explicit)
+
+ is_lhs_var (Var {var_info_ptr}) var_heap
+ = case sreadPtr var_info_ptr var_heap of
+ VI_LocalLetVar
+ -> False
+ _
+ -> True
+ is_lhs_var _ _
+ = False
+
+nextAlts {si_moved} kees ss
+ = (False, ss) ->> ("nextAlts no outerdefault" +++ toString si_moved +++ toString kees.case_explicit)
+
newFunction :: !(Optional Ident) !FunctionBody ![FreeVar] ![AType] !AType !Int !(!Int, ![FunctionInfoPtr],!*FunctionHeap)
-> (! SymbIdent, !(!Int, ![FunctionInfoPtr],!*FunctionHeap))
newFunction opt_id fun_bodies local_vars arg_types result_type group_index state
@@ -911,10 +1230,12 @@ instance convertRootCases Expression where
(let_expr, cs) = convertRootCases (if (isEmpty let_strict_binds) ci {ci & ci_case_level=CaseLevelAfterGuardRoot}) let_expr cs
= (Let { lad & let_strict_binds = let_strict_binds, let_lazy_binds = let_lazy_binds, let_expr = let_expr }, cs)
- convertRootCases ci caseExpr=:(Case kees=:{case_expr, case_guards, case_default, case_explicit, case_info_ptr}) cs=:{cs_var_heap, cs_expr_heap}
+ convertRootCases ci caseExpr=:(Case kees=:{case_expr, case_guards, case_default, case_explicit, case_info_ptr}) cs
= case case_guards of // -*-> "convertRootCases, guards???" of
BasicPatterns BT_Bool patterns
| is_guard_case patterns case_default case_explicit case_expr
+ # ({case_expr, case_guards, case_default, case_explicit, case_info_ptr}, cs)
+ = splitCase ci kees cs
-> convert_boolean_case_into_guard ci case_expr patterns case_default case_info_ptr cs
_
-> case case_expr of
@@ -922,14 +1243,17 @@ instance convertRootCases Expression where
| not case_explicit || (case ci.ci_case_level of
CaseLevelAfterGuardRoot -> False
_ -> True)
- # (EI_CaseTypeAndRefCounts case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
+ # (EI_CaseTypeAndSplits case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
# (varInfo, cs_var_heap) = readPtr var.var_info_ptr cs.cs_var_heap
# cs = {cs & cs_expr_heap=cs_expr_heap, cs_var_heap=cs_var_heap} // -*-> varInfo
-> case varInfo of
VI_LocalLetVar
- -> convertCases ci caseExpr cs // -*-> "convertRootCases, no guards"
+ -> convertNonRootCase ci kees cs // -*-> "convertRootCases, no guards"
_
// | True <<- ("convertRootCases",varInfo)
+ # ({case_expr, case_guards, case_default, case_explicit, case_info_ptr}, cs)
+ = splitCase ci kees cs
+
# (case_expr, cs) = convertCases ci case_expr cs
# (case_guards, cs) = convertRootCasesCasePatterns ci case_guards case_type.ct_cons_types cs
# (case_default, cs)= convertRootCases ci case_default cs
@@ -976,6 +1300,145 @@ instance convertRootCases Expression where
convertRootCases ci expr cs
= convertCases ci expr cs
+splitCase :: ConvertInfo Case *ConvertState -> (Case, *ConvertState)
+splitCase ci kees=:{case_info_ptr} cs=:{cs_expr_heap}
+ # (EI_CaseTypeAndSplits case_type splits=:{sic_next_alt, sic_splits}, cs_expr_heap)
+ = readPtr case_info_ptr cs_expr_heap
+ # (kees, cs_expr_heap)
+ = addDefault sic_next_alt kees cs_expr_heap
+ | isEmpty sic_splits
+ // optimisation for the common case
+ = (kees, {cs & cs_expr_heap = cs_expr_heap}) ->> ("split: no", toString kees.case_ident, ptrToInt kees.case_info_ptr)
+ # sic_splits
+ = uniq (sortBy (>) sic_splits)
+
+ # cs_expr_heap
+ = cs_expr_heap <:= (case_info_ptr,
+ EI_CaseTypeAndSplits case_type {splits & sic_splits = []})
+
+ # (kees, case_type, cs=:{cs_expr_heap})
+ = split ci sic_splits (kees, case_type, {cs & cs_expr_heap = cs_expr_heap})->> ("split: yes", toString kees.case_ident, ptrToInt kees.case_info_ptr) //, sic_splits)
+ = (kees, {cs & cs_expr_heap = cs_expr_heap})
+
+class split a :: ConvertInfo a (Case, CaseType, *ConvertState) -> (Case, CaseType, *ConvertState)
+
+instance split [a] | split a where
+ split ci splits (kees, case_type, cs)
+ = foldSt (split ci) splits (kees, case_type, cs)
+
+instance split SplitCase where
+ split ci split=:{sc_alt_nr} (kees, case_type, cs=:{cs_expr_heap})
+ # (kees1, kees2)
+ = splitIt sc_alt_nr kees
+ # (case_type1, case_type2)
+ = splitIt sc_alt_nr case_type
+ # case_type_and_splits2
+ = EI_CaseTypeAndSplits case_type2 {sic_splits = [], sic_next_alt = No}
+ # (case_info_ptr2, cs_expr_heap)
+ = newPtr case_type_and_splits2 cs_expr_heap
+
+ # kees2
+ = {kees2 & case_info_ptr = case_info_ptr2}
+ # (call, cs)
+ = convertNonRootCase ci kees2 {cs & cs_expr_heap = cs_expr_heap}
+ # kees1
+ = {kees1 & case_default = Yes call}
+ # (EI_CaseTypeAndSplits _ splits1, cs_expr_heap)
+ = readPtr kees.case_info_ptr cs.cs_expr_heap
+ # case_type_and_splits1
+ = EI_CaseTypeAndSplits case_type1 {splits1 & sic_splits = [{split & sc_call = Yes call} : splits1.sic_splits]}
+ # cs_expr_heap
+ = cs_expr_heap <:= (kees.case_info_ptr, case_type_and_splits1)
+ = (kees1, case_type1, {cs & cs_expr_heap = cs_expr_heap})
+
+class splitIt a :: CaseAltNr a -> (a, a)
+
+instance splitIt Case where
+ splitIt alt_nr kees=:{case_guards}
+ # (case_guards1, case_guards2)
+ = splitIt alt_nr case_guards
+ # kees1
+ = {kees & case_guards = case_guards1, case_default=No}
+ # kees2
+ = {kees & case_guards = case_guards2}
+ = (kees1, kees2)
+
+instance splitIt CaseType where
+ splitIt alt_nr case_type=:{ct_cons_types}
+ # (ct_cons_types1, ct_cons_types2)
+ = splitIt alt_nr ct_cons_types
+ # case_type1
+ = {case_type & ct_cons_types = ct_cons_types1}
+ # case_type2
+ = {case_type & ct_cons_types = ct_cons_types2}
+ = (case_type1, case_type2)
+
+instance splitIt CasePatterns where
+ splitIt alt_nr (AlgebraicPatterns type alts)
+ # (alts1, alts2)
+ = splitIt alt_nr alts
+ = (AlgebraicPatterns type alts1, AlgebraicPatterns type alts2)
+ splitIt alt_nr (BasicPatterns type alts)
+ # (alts1, alts2)
+ = splitIt alt_nr alts
+ = (BasicPatterns type alts1, BasicPatterns type alts2)
+ splitIt alt_nr (OverloadedListPatterns type decons alts)
+ # (alts1, alts2)
+ = splitIt alt_nr alts
+ = (OverloadedListPatterns type decons alts1, OverloadedListPatterns type decons alts2)
+
+instance splitIt [a] where
+ splitIt alt_nr l
+ = (take alt_nr l, drop alt_nr l)
+
+instance < SplitCase where
+ (<) a b
+ = a.sc_alt_nr < b.sc_alt_nr
+
+instance == SplitCase where
+ (==) a b
+ = a.sc_alt_nr == b.sc_alt_nr
+
+uniq :: [a] -> [a] | Eq a
+uniq [a : rest =: [b : t]]
+ | a == b
+ = uniq rest
+ // otherwise
+ = [a : uniq rest]
+uniq l
+ = l
+
+class addDefault a :: a Case *ExpressionHeap -> (Case, *ExpressionHeap)
+
+instance addDefault (Optional a) | addDefault a where
+ addDefault (Yes next_alt) kees expr_heap
+ = addDefault next_alt kees expr_heap
+ addDefault _ kees expr_heap
+ = (kees, expr_heap)
+
+instance addDefault NextAlt where
+ addDefault next_alt kees expr_heap
+ # (call, expr_heap)
+ = find_call next_alt expr_heap
+ = addDefault call kees expr_heap
+ where
+ find_call :: NextAlt *ExpressionHeap -> (Expression, *ExpressionHeap)
+ find_call {na_case, na_alt_nr} expr_heap
+ # (EI_CaseTypeAndSplits case_type {sic_splits}, expr_heap)
+ = readPtr na_case expr_heap
+ # sic_splits = sic_splits ->> ("find_call", ptrToInt na_case, na_alt_nr)
+ # call
+ = hd [ call
+ \\ {sc_call=Yes call, sc_alt_nr} <- sic_splits
+ | sc_alt_nr==na_alt_nr
+ ]
+ = (call, expr_heap)
+
+instance addDefault Expression where
+ addDefault expr kees=:{case_default=No} expr_heap
+ = ({kees & case_default=Yes expr}, expr_heap)
+ addDefault expr kees expr_heap
+ = abort ("trying to overwrite default of " +++ toString (ptrToInt kees.case_info_ptr) +++ " " +++ toString kees.case_ident)
convertRootCasesCasePatterns :: ConvertInfo CasePatterns [[AType]] *ConvertState -> (CasePatterns, *ConvertState)
convertRootCasesCasePatterns ci (BasicPatterns bt patterns) _ cs
# (patterns, cs)
@@ -1100,6 +1563,12 @@ where
# (expr, cs) = convertCases ci expr cs
= (TupleSelect tuple_symbol arg_nr expr, cs)
convertCases ci (Case case_expr) cs
+ // this is a case on a non-root position
+ # (_, {ss_expr_heap, ss_var_heap})
+ = findSplitCases {si_moved=False, si_next_alt=No} case_expr
+ {ss_var_heap=cs.cs_var_heap,ss_expr_heap = cs.cs_expr_heap}
+ cs
+ = {cs & cs_var_heap=ss_var_heap, cs_expr_heap = ss_expr_heap}
= convertNonRootCase ci case_expr cs
convertCases ci expr cs
= (expr, cs)
@@ -1116,25 +1585,82 @@ where
convertCases ci selector cs
= (selector, cs)
-convertNonRootCase ci=:{ci_bound_vars, ci_group_index, ci_common_defs} kees=:{ case_expr, case_guards, case_default, case_ident, case_info_ptr} cs
- # (EI_CaseTypeAndRefCounts case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
+convertDefault ci=:{ci_bound_vars, ci_group_index, ci_common_defs}
+ kees=:{case_ident, case_info_ptr, case_default=Yes defoult} cs
+ # (EI_CaseTypeAndSplits case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
+ cs = { cs & cs_expr_heap = cs_expr_heap }
+
+ (act_vars, form_vars, local_vars, defoult, old_fv_info_ptr_values,cs_var_heap)
+ = copy_case_expr ci_bound_vars defoult cs.cs_var_heap
+ cs = { cs & cs_var_heap = cs_var_heap}
+
+ (fun_symb, cs)
+ = new_case_function case_ident case_type.ct_result_type defoult form_vars local_vars
+ ci_bound_vars ci_group_index ci_common_defs cs
+
+ # cs_var_heap=fold2St restore_old_fv_info_ptr_value old_fv_info_ptr_values ci_bound_vars cs.cs_var_heap
+ with
+ restore_old_fv_info_ptr_value old_fv_info_ptr_value ({fv_info_ptr},type) var_heap
+ = writePtr fv_info_ptr old_fv_info_ptr_value var_heap
+ # cs = { cs & cs_var_heap = cs_var_heap}
+ = (App { app_symb = fun_symb, app_args = act_vars, app_info_ptr = nilPtr }, cs)
+
+convertNonRootCase ci=:{ci_bound_vars, ci_group_index, ci_common_defs} kees=:{ case_expr, case_ident, case_info_ptr} cs
+ # (is_degenerate, defoult)
+ = case_is_degenerate kees
+ | is_degenerate
+ # (EI_CaseTypeAndSplits case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
+ cs = { cs & cs_expr_heap = cs_expr_heap }
+
+// test ...
+ (defoult, cs) = convertRootCases ci defoult cs
+// ... test
+ (act_vars, form_vars, local_vars, caseExpr, old_fv_info_ptr_values,cs_var_heap)
+ = copy_case_expr ci_bound_vars (defoult) cs.cs_var_heap
+
+ cs = { cs & cs_var_heap = cs_var_heap}
+
+ (fun_symb, cs) = new_case_function case_ident case_type.ct_result_type caseExpr
+ form_vars local_vars
+ ci_bound_vars ci_group_index ci_common_defs cs
+
+ # cs_var_heap=restore_old_fv_info_ptr_values old_fv_info_ptr_values ci_bound_vars cs.cs_var_heap
+ with
+ restore_old_fv_info_ptr_values [old_fv_info_ptr_value:old_fv_info_ptr_values] [({fv_info_ptr},type):bound_vars] var_heap
+ # var_heap=writePtr fv_info_ptr old_fv_info_ptr_value var_heap
+ = restore_old_fv_info_ptr_values old_fv_info_ptr_values bound_vars var_heap
+ restore_old_fv_info_ptr_values [] bound_vars var_heap
+ = var_heap
+ # cs = { cs & cs_var_heap = cs_var_heap}
+
+ = (App { app_symb = fun_symb, app_args = act_vars, app_info_ptr = nilPtr }, cs)
+
+ // otherwise
+
+ # (EI_CaseTypeAndSplits case_type _, cs_expr_heap) = readPtr case_info_ptr cs.cs_expr_heap
cs = { cs & cs_expr_heap = cs_expr_heap }
(new_info_ptr, cs_var_heap) = newPtr (VI_LocalVar) cs.cs_var_heap
var_id = {id_name = "_x", id_info = nilPtr}
case_var = Var {var_name = var_id, var_info_ptr = new_info_ptr, var_expr_ptr = nilPtr}
case_free_var = { fv_def_level = NotALevel, fv_name = var_id, fv_info_ptr = new_info_ptr, fv_count = 0}
- cs = { cs & cs_var_heap = cs_var_heap}
kees = {kees & case_expr=case_var, case_explicit=False}
+ cs = { cs & cs_var_heap = cs_var_heap}
+
(case_expr, cs) = convertCases ci case_expr cs
+// test ...
+ (caseExpr, cs) = convertRootCases ci (Case kees) cs
+// ... test
(act_vars, form_vars, local_vars, caseExpr, old_fv_info_ptr_values,cs_var_heap)
- = copy_case_expr ci_bound_vars (Case kees) cs.cs_var_heap
+ = copy_case_expr ci_bound_vars caseExpr cs.cs_var_heap
+
cs = { cs & cs_var_heap = cs_var_heap}
- (fun_symb, cs) = new_case_function case_ident case_type caseExpr case_free_var form_vars local_vars
+ (fun_symb, cs) = new_case_function case_ident case_type.ct_result_type caseExpr
+ [(case_free_var, case_type.ct_pattern_type) : form_vars] local_vars
ci_bound_vars ci_group_index ci_common_defs cs
# cs_var_heap=restore_old_fv_info_ptr_values old_fv_info_ptr_values ci_bound_vars cs.cs_var_heap
@@ -1151,50 +1677,60 @@ where
get_case_var (Var var)
= var
- copy_case_expr bound_vars guards_and_default var_heap
+ case_is_degenerate {case_guards = AlgebraicPatterns _ [], case_default=Yes defoult}
+ = (True, defoult)
+ case_is_degenerate {case_guards = BasicPatterns _ [], case_default=Yes defoult}
+ = (True, defoult)
+ case_is_degenerate {case_guards = OverloadedListPatterns _ _ [], case_default=Yes defoult}
+ = (True, defoult)
+ case_is_degenerate _
+ = (False, undef)
+
+
+copy_case_expr bound_vars guards_and_default var_heap
// # var_heap = foldSt (\({fv_name,fv_info_ptr},type) -> writePtr fv_info_ptr (VI_BoundVar type) -*-> (fv_name,fv_info_ptr)) bound_vars var_heap
- # (old_fv_info_ptr_values,var_heap) = store_VI_BoundVar_in_bound_vars_and_save_old_values bound_vars [] var_heap
- with
- store_VI_BoundVar_in_bound_vars_and_save_old_values [({fv_info_ptr},type):bound_vars] old_fv_info_ptr_values var_heap
- # (old_fv_info_ptr_value,var_heap)=readPtr fv_info_ptr var_heap
- # var_heap=writePtr fv_info_ptr (VI_BoundVar type) var_heap
- # (old_fv_info_ptr_values,var_heap) = store_VI_BoundVar_in_bound_vars_and_save_old_values bound_vars old_fv_info_ptr_values var_heap
- = ([old_fv_info_ptr_value:old_fv_info_ptr_values],var_heap)
- store_VI_BoundVar_in_bound_vars_and_save_old_values [] old_fv_info_ptr_values var_heap
- = (old_fv_info_ptr_values,var_heap)
- (expr, {cp_free_vars, cp_var_heap, cp_local_vars}) = copy guards_and_default { cp_free_vars = [], cp_var_heap = var_heap, cp_local_vars = [] }
- (bound_vars, free_typed_vars, var_heap) = foldSt retrieve_variable cp_free_vars ([], [], cp_var_heap)
- = (bound_vars, free_typed_vars, cp_local_vars, expr, old_fv_info_ptr_values,var_heap)
+ # (old_fv_info_ptr_values,var_heap) = store_VI_BoundVar_in_bound_vars_and_save_old_values bound_vars [] var_heap
+ with
+ store_VI_BoundVar_in_bound_vars_and_save_old_values [({fv_info_ptr},type):bound_vars] old_fv_info_ptr_values var_heap
+ # (old_fv_info_ptr_value,var_heap)=readPtr fv_info_ptr var_heap
+ # var_heap=writePtr fv_info_ptr (VI_BoundVar type) var_heap
+ # (old_fv_info_ptr_values,var_heap) = store_VI_BoundVar_in_bound_vars_and_save_old_values bound_vars old_fv_info_ptr_values var_heap
+ = ([old_fv_info_ptr_value:old_fv_info_ptr_values],var_heap)
+ store_VI_BoundVar_in_bound_vars_and_save_old_values [] old_fv_info_ptr_values var_heap
+ = (old_fv_info_ptr_values,var_heap)
+ (expr, {cp_free_vars, cp_var_heap, cp_local_vars}) = copy guards_and_default { cp_free_vars = [], cp_var_heap = var_heap, cp_local_vars = [] }
+ (bound_vars, free_typed_vars, var_heap) = foldSt retrieve_variable cp_free_vars ([], [], cp_var_heap)
+ = (bound_vars, free_typed_vars, cp_local_vars, expr, old_fv_info_ptr_values,var_heap)
// -*-> ("copy_case_expr", length bound_vars, length free_typed_vars)
- where
- retrieve_variable (var_info_ptr, type) (bound_vars, free_typed_vars, var_heap)
- # (VI_FreeVar name new_ptr count type, var_heap) = readPtr var_info_ptr var_heap
- = ( [Var { var_name = name, var_info_ptr = var_info_ptr, var_expr_ptr = nilPtr} : bound_vars],
- [({ fv_def_level = NotALevel, fv_name = name, fv_info_ptr = new_ptr, fv_count = count }, type) : free_typed_vars], var_heap)
-
- new_case_function opt_id {ct_result_type,ct_pattern_type,ct_cons_types} caseExpr case_var free_vars local_vars
- bound_vars group_index common_defs cs=:{cs_expr_heap}
-
- # body
- = TransformedBody {tb_args=[case_var : [var \\ (var, _) <- free_vars]], tb_rhs=caseExpr}
- (_,type)
- = removeAnnotations
- { st_vars = []
- , st_args = [ct_pattern_type : [ type \\ (_, type) <- free_vars]]
- , st_args_strictness=NotStrict
- , st_arity = 1 + length free_vars
- , st_result = ct_result_type
- , st_context = []
- , st_attr_vars = []
- , st_attr_env = []
- }
- (body, cs)
- = convertCasesInBody body (Yes type) group_index common_defs cs
-
- # (fun_symb, (cs_next_fun_nr, cs_new_functions, cs_fun_heap))
- = newFunctionWithType opt_id body local_vars type group_index
- (cs.cs_next_fun_nr, cs.cs_new_functions, cs.cs_fun_heap)
- = (fun_symb, { cs & cs_fun_heap = cs_fun_heap, cs_next_fun_nr = cs_next_fun_nr, cs_new_functions = cs_new_functions })
+ where
+ retrieve_variable (var_info_ptr, type) (bound_vars, free_typed_vars, var_heap)
+ # (VI_FreeVar name new_ptr count type, var_heap) = readPtr var_info_ptr var_heap
+ = ( [Var { var_name = name, var_info_ptr = var_info_ptr, var_expr_ptr = nilPtr} : bound_vars],
+ [({ fv_def_level = NotALevel, fv_name = name, fv_info_ptr = new_ptr, fv_count = count }, type) : free_typed_vars], var_heap)
+
+new_case_function opt_id result_type rhs free_vars local_vars
+ bound_vars group_index common_defs cs=:{cs_expr_heap}
+
+ # body
+ = TransformedBody {tb_args=[var \\ (var, _) <- free_vars], tb_rhs=rhs}
+ (_,type)
+ = removeAnnotations
+ { st_vars = []
+ , st_args = [ type \\ (_, type) <- free_vars]
+ , st_args_strictness=NotStrict
+ , st_arity = length free_vars
+ , st_result = result_type
+ , st_context = []
+ , st_attr_vars = []
+ , st_attr_env = []
+ }
+// (body, cs)
+// = convertCasesInBody body (Yes type) group_index common_defs cs
+
+ # (fun_symb, (cs_next_fun_nr, cs_new_functions, cs_fun_heap))
+ = newFunctionWithType opt_id body local_vars type group_index
+ (cs.cs_next_fun_nr, cs.cs_new_functions, cs.cs_fun_heap)
+ = (fun_symb, { cs & cs_fun_heap = cs_fun_heap, cs_next_fun_nr = cs_next_fun_nr, cs_new_functions = cs_new_functions })
splitGuards :: CasePatterns -> [CasePatterns]
splitGuards (AlgebraicPatterns index patterns)
@@ -1331,7 +1867,7 @@ where
instance copy Case
where
- copy this_case=:{case_expr, case_guards, case_default} cp_info
+ copy this_case=:{case_expr, case_guards, case_default, case_info_ptr} cp_info
# ((case_expr,(case_guards,case_default)), cp_info) = copy (case_expr,(case_guards,case_default)) cp_info
= ({ this_case & case_expr = case_expr, case_guards = case_guards, case_default = case_default}, cp_info)
@@ -1409,4 +1945,8 @@ where
*/
(-*->) infixl
-(-*->) a b :== a // ---> b
+(-*->) a b :== a ---> b
+(->>) infixl
+(->>) a b :== a // ---> b
+(<<-) infixl
+(<<-) a b :== a // ---> b