packages feed

language-ats-0.1.1.3: test/data/DivideConquerPar.dats

(***********************************************************************)
(*                                                                     *)
(*                         Applied Type System                         *)
(*                                                                     *)
(***********************************************************************)

(*
** ATS/Postiats - Unleashing the Potential of Types!
** Copyright (C) 2011-2017 Hongwei Xi, ATS Trustful Software, Inc.
** All rights reserved
**
** ATS is free software;  you can  redistribute it and/or modify it under
** the terms of  the GNU GENERAL PUBLIC LICENSE (GPL) as published by the
** Free Software Foundation; either version 3, or (at  your  option)  any
** later version.
** 
** ATS is distributed in the hope that it will be useful, but WITHOUT ANY
** WARRANTY; without  even  the  implied  warranty  of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
** for more details.
** 
** You  should  have  received  a  copy of the GNU General Public License
** along  with  ATS;  see the  file COPYING.  If not, please write to the
** Free Software Foundation,  51 Franklin Street, Fifth Floor, Boston, MA
** 02110-1301, USA.
*)

(* ****** ****** *)

(* Author: Hongwei Xi *)
(* Start time: February, 2017 *)
(* Authoremail: hwxiATcsDOTbuDOTedu *)

(* ****** ****** *)
//
#define
ATS_PACKNAME
"ATSLIB.libats\
.BUCS320.DivideConquerPar"
//
(* ****** ****** *)
//
#staload
UN =
"prelude/SATS/unsafe.sats"
//
(* ****** ****** *)
//
#staload
"libats/ML/SATS/basis.sats"
#staload
"libats/ML/SATS/list0.sats"
//
#staload
"prelude/DATS/list_vt.dats"
#staload
"libats/ML/SATS/atspre.sats"
//
(* ****** ****** *)
//
#include "./../mydepies.hats"
//
(* ****** ****** *)
//
typedef
input = $DivideConquer.input
typedef
output = $DivideConquer.output
//
(* ****** ****** *)
//
vtypedef
fwork = () -<lincloptr1> void
vtypedef fworklst = List0_vt_(fwork)
//
typedef
spinref = $SPINREF.spinref(int)
//
(* ****** ****** *)
//
extern
fun{}
DivideConquerPar$submit
  (fwork): void
extern
fun{}
DivideConquerPar$submit2
  (x0: input, fwork): void
//
(* ****** ****** *)
//
datatype
fworkshop =
| FWORKSHOP_chanlst of
  $FWORKSHOP_chanlst.fworkshop
| FWORKSHOP_channel of
  $FWORKSHOP_channel.fworkshop
//
extern
fun{}
DivideConquerPar$fworkshop(): fworkshop
//
(* ****** ****** *)

implement
{}(*tmp*)
DivideConquerPar$submit
  (fwork) = let
//
val
fworkshop =
DivideConquerPar$fworkshop<>
  ((*void*))
//
in
//
case+
fworkshop
of (*case+*)
| FWORKSHOP_chanlst(fws) =>
  {
    val () =
    $FWORKSHOP_chanlst.fworkshop_insert_lincloptr
    ( fws
    , llam() => 0 where
      {
        val () = fwork()
        val () = // fwork needs to be freed
        cloptr_free($UN.castvwtp0{cloptr(void)}(fwork))
      } // end of [fworkshop_insert_lincloptr]
    )
  } (* FWORKSHOP_chanlst *)
| FWORKSHOP_channel(fws) =>
  {
    val () =
    $FWORKSHOP_channel.fworkshop_insert_lincloptr
    ( fws
    , llam() => 0 where
      {
        val () = fwork()
        val () = // fwork needs to be freed
        cloptr_free($UN.castvwtp0{cloptr(void)}(fwork))
      } // end of [fworkshop_insert_lincloptr]
    )
  } (* FWORKSHOP_channel *)
//
end // end of [DivideConquerPar$submit]

(* ****** ****** *)
//
implement
{}(*tmp*)
DivideConquerPar$submit2
  (x0, fwork) =
(
  DivideConquerPar$submit<>(fwork)
)
//
(* ****** ****** *)
//
#staload
DC = $DivideConquer
#staload
DC_cont = $DivideConquer_cont
//
(* ****** ****** *)

implement
{}(*tmp*)
$DC.DivideConquer$solve
  (x0) = let
//
#staload $NWAITER
//
val NW =
  nwaiter_create_exn()
val NWT =
  nwaiter_initiate(NW)
val NWT =
  $UN.castvwtp0{ptr}(NWT)
//
var res: output
//
val ((*void*)) =
$DC_cont.DivideConquer_cont$solve<>
( x0
, lam(r0) =>
  nwaiter_ticket_put(NWT) where
  {
    val () =
    $UN.ptr0_set<output>(addr@res, r0)
    val NWT =
    $UN.castvwtp0{nwaiter_ticket}(NWT)
  } (* end of [lam] *)
) (* end of [val] *)
//
val () = nwaiter_waitfor(NW)
val () = nwaiter_destroy(NW)
//
in
  $UN.ptr0_get<output>(addr@res)
end // end of [DivideConquer$solve]

(* ****** ****** *)

implement
{}(*tmp*)
$DC_cont.DivideConquer_cont$conquer
  (_, xs, k0) = let
//
#staload
$SPINREF // opening it
//
fun
spinref_decget
  (spnr: spinref) : int = let
//
var env: int = 0
typedef tenv = int
//
implement
spinref_process$fwork<int><tenv>
  (x, env) =
  let val () = (x := x - 1) in env := x end
//
in
//
let val () =
  spinref_process_env<int><tenv>(spnr, env) in env
end // end of [let]
//
end // end of [spinref_decget]
//
fun
loop2
{n:nat}
(
  x0: input
, xs: list(input, n)
, rs: !list_vt(output, n+1)
, spnr: spinref, res: list0(output)
) : void = let
  val+
  @list_vt_cons
    (r0, rs1) = rs
  // list_vt_cons
  val addr_r0 = addr@(r0)
  val () =
  DivideConquerPar$submit2<>
  ( x0
  , llam() =>
    (
    $DC_cont.DivideConquer_cont$solve
    ( x0
    , lam(r0) => let
        val () =
        $UN.ptr0_set<output>
          (addr_r0, r0)
        // end of [$UN.ptr0_set]
        val c0 = spinref_decget(spnr)
      in
        if (c0 > 0)
          then (
            // unfinished
          ) (* end of [then] *)
          else k0(res) where
          {
            val () =
            $SPINVAR.spinvar_destroy($UN.castvwtp0(spnr))
          } (* end of [else] *)
      end // end of [let] // end of [lam]
    )
    ) (* llam *)
  ) (* end of [val] *)
//
in
//
case+ xs of
| list_nil() => () where
  {
    prval ((*folded*)) = fold@(rs)
  }
| list_cons(x1, xs) => () where
  {
    val () =
    loop2(x1, xs, rs1, spnr, res)
    prval ((*folded*)) = fold@(rs)
  }
end (* end of [loop2] *)
//
val xs = g1ofg0(xs); val n0 = length(xs)
//
in (* in-of-let *)
//
ifcase
| n0 = 0 =>
  k0(list0_nil())
| n0 = 1 => let
    val+list_sing(x0) = xs
  in
    $DC_cont.DivideConquer_cont$solve(x0, lam(r0) => k0(list0_sing(r0)))
  end // end of [n0 = 1]
| _(* n0 >= 2 *) => let
//
    val rs =
    list_map_cloref<input><output>
    (
      xs, lam _ => _
    ) (* end of [val] *)
    val res =
    $UN.castvwtp1{list0(output)}(rs)
//
    val+list_cons(x, xs) = xs
    val ((*void*)) = loop2(x, xs, rs, spinref_create_exn<int>(n0), res)
    prval ((*void*)) = $UN.cast2void(rs)
//
  in
    // nothing
  end // end of [n0 >= 2]
//
end // end of [DivideConquer_cont$conquer]

(* ****** ****** *)

(* end of [DivideConquerPar.dats] *)