
// put these in Functions.mo, then uncomment the calls from Main.mo

function compareInt
  input Integer i1;
  input Integer i2;
  output Boolean b;
algorithm
  b := i1 < i2;
end compareInt;

function compareReal
  input Real r1;
  input Real r2;
  output Boolean b;
algorithm
  b := r1 <. r2;
end compareReal;

function compareString
  input String s1;
  input String s2;
  output Boolean b;
algorithm
  b := matchcontinue (s1, s2)
    local Integer z;
    case (s1, s2)
      equation
        0 = string_compare(s1, s2);
      then false;
    case (s1, s2)
      equation
        z = string_compare(s1, s2);
        true = (z < 0);
      then true;
    case (s1, s2)
      equation
        z = string_compare(s1, s2);
        false = (z < 0);
      then false;        
  end matchcontinue;
end compareString;

function quicksort
  replaceable type Type_a subtypeof Any;
  input  list<Type_a> inList;
  input  list<Type_a> accList;  
  function FuncType 
    input Type_a el1;
    input Type_a el2;
    output Boolean cmp;
  end FuncType;
  input FuncType comparator;
  output list<Type_a> outList;
algorithm
  outList := matchcontinue (inList, accList, comparator)
    local
      list<Type_a> l, smaller, greater, acc, lst1, lst2, lst3;
      Type_a x;
    case ({}, acc, _) then acc;
    case (x::l, acc, comparator) 
      equation
        (smaller, greater) = partition (x, l, comparator);
        lst1 = quicksort (greater, acc, comparator);
        lst2 = x::lst1;
        lst3 = quicksort (smaller, lst2, comparator);
      then lst3;
  end matchcontinue;
end quicksort;
  
function partition 
  replaceable type Type_a subtypeof Any;
  input  Type_a inList;
  input  list<Type_a> accList;  
  function FuncType 
    input Type_a el1;
    input Type_a el2;
    output Boolean cmp;
  end FuncType;
  input FuncType comparator;
  output list<Type_a> outList1;
  output list<Type_a> outList2;  
algorithm
  (outList1,outList2) := matchcontinue (inList, accList, comparator)
    local 
      Type_a x, y;
      list<Type_a> l, smaller, greater;
      //function FuncType 
      //  input Type_a el1;
      //  input Type_a el2;
      //  output Boolean cmp;
      //end FuncType;
      FuncType comparator;
    case (x, nil, _) then (nil, nil); 
    case (x, y::l, comparator)  
      equation
        (smaller, greater) = partition (x, l, comparator);
        true = comparator(y, x);
      then (y::smaller, greater);
    case (x, y::l, comparator)  
      equation
        (smaller, greater) = partition (x, l, comparator);
        false = comparator(y, x);
      then (smaller, y::greater);
  end matchcontinue;
end partition;

function orderList
  replaceable type Type_a subtypeof Any;
  input  list<Type_a> inList;
  function FuncType 
    input Type_a el1;
    input Type_a el2;
    output Boolean cmp;
  end FuncType;
  input FuncType comparator;
  output list<Type_a> outList;
algorithm
  outList := matchcontinue (inList, comparator)
    local list<Type_a> lst, lstResult;
    case ({}, _) then {};
    case (lst, comparator)
      equation 
        lstResult = quicksort(lst, {}, comparator);
      then lstResult;
  end matchcontinue;
end orderList;

// transformer functions
function transformInt2Real
  input Integer i;
  output Real r;
algorithm
  r := intReal(i);
end transformInt2Real;

function transformInt2String
  input Integer i;
  output String s;
algorithm
  s := intString(i);
end transformInt2String;

function transformReal2String
  input Real r;
  output String s;
algorithm
  s := realString(r);
end transformReal2String;

// mapping functions
function map1
  replaceable type Type_a subtypeof Any;
  replaceable type Type_b subtypeof Any;
  input  list<Type_a> inList;
  function FuncType 
    input  Type_a elIn;
    output Type_b elOut;
  end FuncType;
  input FuncType f;
  output list<Type_b> outList;
algorithm
  outList := matchcontinue(inList, f)
    local 
      list<Type_b> lst;
      list<Type_a> rest;
      Type_a x;
      Type_b y;
    case ({},_) then {};
    case (x::rest, f) 
      equation
        y = f(x);
        lst = map1(rest, f);
      then y::lst;
  end matchcontinue;
end map1;

function map0
  replaceable type Type_a subtypeof Any;
  input  list<Type_a> inList;
  function FuncType 
    input  Type_a elIn;
  end FuncType;
  input FuncType f;
algorithm
  outList := matchcontinue(inList, f)
    local 
      list<Type_a> rest;
      Type_a x;
    case ({},_) then ();
    case (x::rest, f) 
      equation
        f(x);
        map0(rest, f);
      then ();
  end matchcontinue;
end map0;

function printElement
  input String str;
algorithm
  print(str);
  print(" ");
end printElement;
