implementation module utilities // compile using the "reuse unique nodes option" import StdEnv, general from _aconcat import arrayConcat /* Utility routines. */ StringToCharList` :: !String !Int !Int -> [Char] StringToCharList` string 0 index = [] StringToCharList` string length index = [string.[index] : StringToCharList` string (dec length) (inc index)] stringToCharList :: !String -> [Char] stringToCharList string = StringToCharList` string (size string) 0 charListToString :: ![Char] -> String charListToString [hd:tl] = toString hd +++ charListToString tl charListToString [] = "" revCharListToString :: !Int ![Char] -> String revCharListToString max_index l # string = createArray (max_index + 1) '\0' = fill_string max_index l string where fill_string :: !Int ![Char] !*String -> *String fill_string n [ char : rest] string = fill_string (n - 1) rest { string & [n] = char } fill_string (-1) [] string = string /* revCharListToString [hd:tl] = revCharListToString tl +++ toString hd revCharListToString [] = "" */ isUpperCaseName :: ! String -> Bool isUpperCaseName id = ('A' <= c && c <= 'Z') || c == '_' where c =: id.[0] isLowerCaseName :: ! String -> Bool isLowerCaseName id = 'a' <= c && c <= 'z' where c =: id.[0] isFunnyIdName :: ! String -> Bool isFunnyIdName id = isSpecialChar id.[0] isSpecialChar :: !Char -> Bool isSpecialChar '~' = True isSpecialChar '@' = True isSpecialChar '#' = True isSpecialChar '$' = True isSpecialChar '%' = True isSpecialChar '^' = True isSpecialChar '?' = True isSpecialChar '!' = True isSpecialChar '+' = True isSpecialChar '-' = True isSpecialChar '*' = True isSpecialChar '<' = True isSpecialChar '>' = True isSpecialChar '\\' = True isSpecialChar '/' = True isSpecialChar '|' = True isSpecialChar '&' = True isSpecialChar '=' = True isSpecialChar ':' = True isSpecialChar '.' = True isSpecialChar c = False isNotEmpty :: ![a] -> Bool isNotEmpty [] = False isNotEmpty _ = True strictMap :: !(.a -> .b) ![.a] -> [.b] strictMap f [x : xs] #! head = f x tail = strictMap f xs = [head : tail] strictMap f xs = [] strictMapAppend :: !(.a -> .b) ![.a] !u:[.b] -> v:[.b], [u <= v] strictMapAppend f [x : xs] tail #! x = f x xs = strictMapAppend f xs tail = [x : xs] strictMapAppend f [] tail = tail mapAppend :: !(.a -> .b) ![.a] !u:[.b] -> u:[.b] mapAppend f [x : xs] tail # x = f x xs = mapAppend f xs tail = [x : xs] mapAppend f [] tail = tail mapAppendSt :: !(.a -> .(.b -> (.c,.b))) ![.a] !u:[.c] !.b -> !(!u:[.c],!.b) mapAppendSt f [x : xs] tail s # (x, s) = f x s (xs, s) = mapAppendSt f xs tail s = ([x : xs], s) mapAppendSt f [] tail s = (tail, s) /* mapSt :: !(.a -> (.st -> (.c,.st))) ![.a] !.st -> (![.c],!.st) mapSt f [x : xs] s # (x, s) = f x s (xs, s) = mapSt f xs s = ([x : xs], s) mapSt f [] s = ([], s) */ //mapSt :: !(.a -> (.st -> (.c,.st))) ![.a] !.st -> (![.c],!.st) mapSt f l s :== map_st l s where map_st [x : xs] s # (x, s) = f x s mapSt_result = map_st xs s (xs, _) = mapSt_result #! s = second_of_2_tuple mapSt_result = ([x : xs], s) map_st [] s = ([], s) second_of_2_tuple t :== e2 where (_,e2) = t app2St :: !(!.(.a -> .(.st -> (.c,.st))),!.(.e -> .(.st -> (.f,.st)))) !(.a,.e) !.st -> (!(.c,.f),!.st) app2St (f,g) (x,y) s # (x, s) = f x s (y, s) = g y s = ((x,y), s) // foldl2 :: !(.c -> .(.a -> .(.b -> .c))) !.c ![.a] ![.b] -> .c foldl2 op r l1 l2 :== foldl2 r l1 l2 where foldl2 r [x : xs] [y : ys] = foldl2 (op r x y) xs ys foldl2 r [] [] = r //foldr2 :: !(.a -> .(.b -> .(.c -> .c))) !.c ![.a] ![.b] -> .c foldr2 op r l1 l2 :== foldr2 r l1 l2 where foldr2 r [x : xs] [y : ys] = op x y (foldr2 r xs ys) foldr2 r [] [] = r fold2St op l1 l2 st :== fold_st2 l1 l2 st where fold_st2 [x : xs] [y : ys] st = op x y (fold_st2 xs ys st) fold_st2 [] [] st = st fold_st2 [] ys st = abort ("fold_st2: second argument list contains more elements") fold_st2 xs [] st = abort ("fold_st2: first argument list contains more elements") unsafeFold2St op l1 l2 st :== ufold_st2 l1 l2 st where ufold_st2 [x : xs] [y : ys] st = ufold_st2 xs ys (op x y st) ufold_st2 _ _ st = st unsafeFold3St op l1 l2 l3 st :== ufold_st3 l1 l2 l3 st where ufold_st3 [x : xs] [y : ys] [z : zs] st = ufold_st3 xs ys zs (op x y z st) ufold_st3 _ _ _ st = st // foldSt :: !(.a -> .(.st -> .st)) ![.a] !.st -> .st foldSt op r l :== fold_st r l where fold_st [] st = st fold_st [a:x] st = fold_st x (op a st) // iFoldSt :: (Int -> .(.b -> .b)) !Int !Int .b -> .b iFoldSt op fr to st :== i_fold_st fr to st where i_fold_st fr to st | fr >= to = st = i_fold_st (inc fr) to (op fr st) iterateSt op st :== iterate_st op st where iterate_st op st # (continue, st) = op st | continue = iterate_st op st = st mapFilterYesSt f l st :== map_filter_yes_st l st where map_filter_yes_st [] st #! st = st = ([], st) map_filter_yes_st [h:t] st #! (opt_f_h , st) = f h st (t2, st) = map_filter_yes_st t st (f_h_t2, _) = optCons opt_f_h t2 st = st = (f_h_t2, st) iMapFilterYesSt f fr to st :== i_map_filter_yes_st fr to st where i_map_filter_yes_st fr to st #! st = st | fr >= to = ([], st) #! (opt_f_fr, st) = f fr st (t, st) = i_map_filter_yes_st (inc fr) to st (f_fr_t2, _) = optCons opt_f_fr t st = st = (f_fr_t2, st) foldlArrayStWithIndex f a st :== fold_a_st_i 0 a st where fold_a_st_i i a st | i==size a = st # (ai, a) = a![i] = fold_a_st_i (i+1) a (f i ai st) foldlArraySt f a st :== fold_a_st 0 a st where fold_a_st i a st | i==size a = st # (ai, a) = a![i] = fold_a_st (i+1) a (f ai st) foldrArraySt f a st :== foldr_a_st (size a-1) a st where foldr_a_st i a st | i==(-1) = st # (ai, a) = a![i] = foldr_a_st (i-1) a (f ai st) optCons :: !(Optional .a) !u:[.a] -> (!v:[.a], !Int) ,[u <= v] optCons No l = (l, 0) optCons (Yes x) l = ([x:l], 0) eqMerge :: ![a] ![a] -> [a] | Eq a eqMerge [a : x] y | isMember a y = eqMerge x y = [a : eqMerge x y] eqMerge x y = y revAppend :: ![a] ![a] -> [a] // Reverse the list using the second argument as accumulator. revAppend [] acc = acc revAppend [x : xs] acc = revAppend xs [x : acc] revMap :: !(.a -> .b) ![.a] !u:[.b] -> u:[.b] revMap f [] acc = acc revMap f [x : xs] acc = revMap f xs [f x : acc] /* zip2Append :: [.a] [.b] u:[w:(.a,.b)] -> v:[x:(.a,.b)], [w <= x, u <= v] zip2Append [] [] tail = tail zip2Append [x : xs] [y : ys] tail = [(x,y) : zip2Append xs ys tail] */ :: Bag x = Empty | Single !x | Pair !(Bag x) !(Bag x) uniqueBagToList :: !*(Bag x) -> [x] // exploits reuse of unique nodes (if compiled with that option) uniqueBagToList bag = accumulate_elements bag [] where accumulate_elements :: !*(Bag x) [x] -> [x] accumulate_elements Empty accu = accu accumulate_elements (Single element) accu = [element : accu] accumulate_elements (Pair bag1 bag2) accu = accumulate_elements bag1 (accumulate_elements bag2 accu) bagToList :: !(Bag x) -> [x] bagToList bag = accumulate_elements bag [] where accumulate_elements :: !(Bag x) [x] -> [x] accumulate_elements Empty accu = accu accumulate_elements (Single element) accu = [element : accu] accumulate_elements (Pair bag1 bag2) accu = accumulate_elements bag1 (accumulate_elements bag2 accu) isEmptyBag :: !(Bag x) -> Bool isEmptyBag Empty = True isEmptyBag _ = False :: DAG = { dag_nr_of_nodes :: !Int , dag_get_children :: !Int -> [Int] } :: PartitioningState = { ps_marks :: !.{# Int} , ps_next_num :: !Int , ps_groups :: ![[Int]] , ps_deps :: ![Int] } NotChecked :== -1 partitionateDAG :: !DAG ![Int] -> [[Int]] partitionateDAG pi=:{dag_nr_of_nodes} roots # partitioning_info = { ps_marks = createArray dag_nr_of_nodes NotChecked, ps_deps = [], ps_next_num = 0, ps_groups = [] } {ps_groups} = foldSt (partitionate_node pi) roots partitioning_info = ps_groups where partitionate_node :: !DAG !Int !*PartitioningState -> *PartitioningState partitionate_node pi node_index ps=:{ps_marks} | ps_marks.[node_index] == NotChecked = snd (partitionate_unvisited_node node_index pi ps) = ps partitionate_unvisited_node :: !Int !DAG !*PartitioningState -> (!Int, !*PartitioningState) partitionate_unvisited_node node_index pi ps=:{ps_next_num} # children = pi.dag_get_children node_index (min_dep, ps) = visit_children children pi.dag_nr_of_nodes pi (push_on_dep_stack node_index ps) = try_to_close_group node_index ps_next_num min_dep pi ps push_on_dep_stack :: !Int !*PartitioningState -> *PartitioningState push_on_dep_stack node_index ps=:{ps_deps,ps_marks,ps_next_num} = { ps & ps_deps = [node_index : ps_deps], ps_marks = { ps_marks & [node_index] = ps_next_num}, ps_next_num = inc ps_next_num} visit_children :: ![Int] !Int !DAG !*PartitioningState -> (!Int, !*PartitioningState) visit_children [child:children] min_dep pi ps=:{ps_marks} #! mark = ps_marks.[child] | mark == NotChecked # (mark, ps) = partitionate_unvisited_node child pi ps = visit_children children (min min_dep mark) pi ps = visit_children children (min min_dep mark) pi ps visit_children [] min_dep nr_of_nodes ps = (min_dep, ps) try_to_close_group :: !Int !Int !Int !DAG !*PartitioningState -> (!Int, !*PartitioningState) try_to_close_group node_index next_num min_dep pi ps=:{ps_marks, ps_deps, ps_groups} | next_num <= min_dep # (ps_deps, ps_marks, group) = close_group node_index ps_deps ps_marks [] pi ps = { ps & ps_deps = ps_deps, ps_marks = ps_marks, ps_groups = [group : ps_groups] } = (pi.dag_nr_of_nodes, ps) = (min_dep, ps) close_group :: !Int ![Int] !*{# Int} ![Int] !DAG -> (![Int], !*{# Int}, ![Int]) close_group node_index [d:ds] marks group pi # marks = { marks & [d] = pi.dag_nr_of_nodes } | d == node_index = (ds, marks, [d : group]) = close_group node_index ds marks [d : group] pi replaceTwoDimArrElt :: !Int !Int !.e !{!*{!.e}} -> (!.e, !{!.{!.e}}) replaceTwoDimArrElt ix1 ix2 el arr # (inner_array, arr) = replace arr ix1 {} (el2, inner_array) = replace inner_array ix2 el = (el2, { arr & [ix1] = inner_array }) /* crashes! replaceTwoDimArrElt ix1 ix2 el arr = code { | A:arr el B:ix2 ix1 push_b 0 | A:arr el B:ix2 ix1 ix1 update_b 2 1 | A:arr el B:ix2 ix2 ix1 update_b 0 2 | A:arr el B:ix1 ix2 ix1 push_a 1 | A:arr el arr B:ix1 ix2 ix1 select _ 1 0 | A:arr el arr.[ix1] B:ix1 ix2 push_array 0 updatepop_a 0 1 replace _ 1 0 | A:arr arr.[ix1]* new_el B:ix1 push_a 2 | A:arr arr.[ix1]* new_el arr B:ix1 update_a 1 3 | A:new_el arr.[ix1]* new_el arr B:ix1 update_a 2 1 | A:new_el arr.[ix1]* arr.[ix1]* arr B:ix1 update _ 1 0 | A:new_el arr.[ix1]* arr* update_a 2 1 | A:new_el new_el arr* update_a 0 2 | A:arr* new_el arr* pop_a 1 | A:arr* new_el } */