diff --git a/Compiler/Util/List.mo b/Compiler/Util/List.mo index 8315d555382..c45d0d6fd69 100644 --- a/Compiler/Util/List.mo +++ b/Compiler/Util/List.mo @@ -162,12 +162,21 @@ public function fill input Integer inCount; output list outList; algorithm - if inCount >= 0 then - outList := fill_tail(inElement, inCount, {}); - else - Debug.fprintln(Flags.FAILTRACE, "- List.fill failed with negative value " - + intString(inCount)); - end if; + outList := matchcontinue(inElement, inCount) + case (_, _) + equation + true = inCount >= 0; + then + fill_tail(inElement, inCount, {}); + + else + equation + Debug.fprintln(Flags.FAILTRACE, "- List.fill failed with negative value " + +& intString(inCount)); + then + fail(); + + end matchcontinue; end fill; protected function fill_tail @@ -202,7 +211,7 @@ public function intRange2 protected Integer step; algorithm - step := if inStart < inStop then 1 else -1; + step := Util.if_(intLt(inStart, inStop), 1, -1); outRange := intRange_tail(inStart, step, inStop); end intRange2; @@ -223,21 +232,44 @@ protected function intRange_tail input Integer inStep; input Integer inStop; output list outResult; -protected - String error_str; - Boolean is_done; -algorithm - if inStep == 0 then // Step-size of 0 will lead to infinite loop. - error_str := stringDelimitList( - list(intString(e) for e in {inStart, inStep, inStop}), ":"); - Error.addMessage(Error.ZERO_STEP_IN_ARRAY_CONSTRUCTOR, {error_str}); - fail(); - elseif inStart == inStop then - outResult := {inStart}; - else - is_done := if inStep > 0 then inStart > inStop else inStart < inStop; - outResult := intRange_tail2(inStart, inStep, inStop, inGt, is_done, {}); - end if; +algorithm + outResult := matchcontinue(inStart, inStep, inStop) + local + String error_str; + Boolean is_done; + + case (_, 0, _) + equation + error_str = stringDelimitList( + map({inStart, inStep, inStop}, intString), ":"); + Error.addMessage(Error.ZERO_STEP_IN_ARRAY_CONSTRUCTOR, {error_str}); + then + fail(); + + case (_, _, _) + equation + false = intEq(inStep, 0); + true = (inStart == inStop); + then + {inStart}; + + case (_, _, _) + equation + false = intEq(inStep, 0); + true = (inStep > 0); + is_done = (inStart > inStop); + then + intRange_tail2(inStart, inStep, inStop, intGt, is_done, {}); + + case (_, _, _) + equation + false = intEq(inStep, 0); + true = (inStep < 0); + is_done = (inStart < inStop); + then + intRange_tail2(inStart, inStep, inStop, intLt, is_done, {}); + + end matchcontinue; end intRange_tail; protected function intRange_tail2 @@ -255,19 +287,25 @@ protected function intRange_tail2 input Integer inValue2; output Boolean outRes; end CompFunc; -protected - Integer next; - list vals; - Boolean is_done; -algorithm - if isDone then - outValues := listReverse(inValues); - else - next := inStart + inStep; - vals := inStart :: inValues; - is_done := compFunc(next, inStop); - outValues := intRange_tail2(next, inStep, inStop, compFunc, is_done, vals); - end if; +algorithm + outValues := match(inStart, inStep, inStop, compFunc, isDone, inValues) + local + Integer next; + list vals; + Boolean is_done; + + case (_, _, _, _, true, _) + then listReverse(inValues); + + else + equation + next = inStart + inStep; + vals = inStart :: inValues; + is_done = compFunc(next, inStop); + then + intRange_tail2(next, inStep, inStop, compFunc, is_done, vals); + + end match; end intRange_tail2; public function toOption @@ -336,7 +374,7 @@ public function isEqual input Boolean inEqualLength; output Boolean outIsEqual; algorithm - outIsEqual := match(inList1, inList2, inEqualLength) + outIsEqual := matchcontinue(inList1, inList2, inEqualLength) local ElementType e1, e2; list rest1, rest2; @@ -344,11 +382,14 @@ algorithm case ({}, {}, _) then true; case ({}, _, false) then true; case (_, {}, false) then true; - case (e1 :: rest1, e2 :: rest2, _) guard(equality(e1 = e2)) - then isEqual(rest1, rest2, inEqualLength); + case (e1 :: rest1, e2 :: rest2, _) + equation + equality(e1 = e2); + then + isEqual(rest1, rest2, inEqualLength); else false; - end match; + end matchcontinue; end isEqual; public function isEqualOnTrue @@ -2394,7 +2435,7 @@ public function map output ElementOutType outElement; end MapFunc; algorithm - outList := list(inFunc(e) for e in inList); + outList := listReverse(map_tail(inList, inFunc, {})); end map; public function mapReverse @@ -2410,9 +2451,39 @@ public function mapReverse output ElementOutType outElement; end MapFunc; algorithm - outList := listReverse(inFunc(e) for e in inList); + outList := map_tail(inList, inFunc, {}); end mapReverse; +protected function map_tail + "Tail-recursive implementation of map." + input list inList; + input MapFunc inFunc; + input list inAccumList; + output list outList; + + partial function MapFunc + input ElementInType inElement; + output ElementOutType outElement; + end MapFunc; +algorithm + outList := match(inList, inFunc, inAccumList) + local + ElementInType head; + ElementOutType new_head; + list rest; + list accum; + + case ({}, _, _) then inAccumList; + + case (head :: rest, _, _) + equation + new_head = inFunc(head); + accum = map_tail(rest, inFunc, new_head :: inAccumList); + then + accum; + end match; +end map_tail; + public function map_2 "Takes a list and a function, and creates two new lists by applying the function to each element of the list."