%{^
#include <stdio.h>

void* resource_new();
void resource_free(void* r);
void do_something(void (*f)(void* r), void* arg);
void resource_use(void* r);
%}

%{
void* resource_new() { return ATS_MALLOC(10); }
void resource_use(void* r) { printf("using: %p\n", r); }
void resource_free(void* r) { ATS_FREE(r); }
void do_something(void (*f)(void*), void* arg) { printf("a\n"); f(arg); printf("b\n"); }
%}

absviewtype resource (l:addr)
viewtypedef resource1 = [l:addr | l > null] resource l
extern fun resource_new():resource1 = "mac#resource_new"
extern fun resource_use(r: !resource1):void = "mac#resource_use"
extern fun resource_free(r: resource1):void = "mac#resource_free"
viewtypedef func = () -<lincloptr1> void
extern fun do_something(f: (func) -<fun1> void, arg: func):void = "mac#do_something"

fun callback(f: func):void = let val () = f() in cloptr_free(f) end

implement main() = let
  extern prfun __borrow {l:addr} (pf: ! resource1 @ l): (resource1 @ l, resource1 @ l -<lin,prf> void)
  var r = resource_new();
  var r2 = resource_new();
  prval (pf, pff) = __borrow(view@ r)
  prval (pf2, pff2) = __borrow(view@ r2)

  val () = do_something(callback, llam () => let
                                               val () = resource_use(r);
                                               val () = resource_use(r2);
                                               prval () = pff(pf)
                                               prval () = pff2(pf2)
                                             in () end) 
  val () = resource_free(r2);
  val () = resource_free(r);
in
  ()
end