Advertisement
chemoelectric

Untitled

Mar 21st, 2022
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.75 KB | None | 0 0
  1. (*------------------------------------------------------------------*)
  2.  
  3. (* The Rosetta Code linear list type can contain any vt@ype.
  4. (The ‘@’ means it doesn’t have to be the size of a pointer.
  5. You can read {0 <= n} as ‘for all non-negative n’. *)
  6. dataviewtype rclist_vt (vt : vt@ype+, n : int) =
  7. | rclist_vt_nil (vt, 0)
  8. | {0 <= n} rclist_vt_cons (vt, n + 1) of (vt, rclist_vt (vt, n))
  9.  
  10. (* An axiom one will need: lists never have negative lengths. *)
  11. extern praxi {vt : vt@ype}
  12. rclist_vt_param
  13. {n : int}
  14. (lst : !rclist_vt (vt, n)) :<prf> [0 <= n] void
  15.  
  16. (*------------------------------------------------------------------*)
  17.  
  18. (* For simplicity, the Rosetta Code linear list deletion routine will
  19. be specifically for lists of ‘int’. *)
  20.  
  21. (* Some things that will be needed. *)
  22. #include "share/atspre_staload.hats"
  23.  
  24. (* The list is passed by reference and will be overwritten with
  25. the new list. It will be proven that the new list is either
  26. equal in length to the original or exactly one node shorter
  27. than it.
  28. (One might notice that in type expressions the equals sign
  29. is ‘==’, even though in executable code it is ‘=’. There are
  30. two distinct sublanguages; to my knowledge, this is merely how
  31. the operators happen to be assigned in each sublanguage, within
  32. the compiler’s prelude.) *)
  33. extern fun
  34. rclist_int_delete
  35. {m : int} (* ‘for all list lengths m’ *)
  36. (lst : &rclist_vt (int, m) >> (* & = pass by reference *)
  37. (* The new type will be a list of the same
  38. length or one less. *)
  39. [n : int | n == m || (m <> 0 && n == m - 1)]
  40. rclist_vt (int, n),
  41. x : int) : void
  42.  
  43. (* The implementation is rather involved, and it will help to have
  44. some convenient notation. The :: operator is already declared
  45. in the compiler’s prelude as a right-associative infix operator. *)
  46. #define NIL rclist_vt_nil ()
  47. #define :: rclist_vt_cons
  48.  
  49. implement
  50. rclist_int_delete {m} (lst, x) =
  51. let
  52. (* A recursive nested function that finds and deletes the node. *)
  53. fun
  54. find {k : int | 1 <= k}
  55. .<k>. (* Means: ‘k must uniformly decrease towards zero.’
  56. If so, that is proof that ‘find’ terminates. *)
  57. (lst : &rclist_vt (int, k) >>
  58. [j : int | j == k || j == k - 1]
  59. rclist_vt (int, j),
  60. x : int) : void =
  61. case+ lst of
  62. | (_ :: NIL) => () (* x was not found. Do nothing. *)
  63. | (_ :: v :: _) when v = x =>
  64. {
  65. val+ @ (u :: tl) = lst (* @ = unfold. tl will be mutable. *)
  66. val+ ~ (v :: tail) = tl (* ~ = consume. The v node will be
  67. freed back into the heap. *)
  68. val () = (tl := tail) (* Replace the u node’s tail with the
  69. shortened tail. *)
  70. prval () = fold@ lst (* Refold. *)
  71. }
  72. | (_ :: _ :: _) =>
  73. {
  74. val+ @ (_ :: tl) = lst (* Unfold, so tl will be
  75. referenceable. *)
  76. val () = find (tl, x) (* Loop by tail recursion. *)
  77. prval () = fold@ lst (* Refold. Using ‘prval’ rather than
  78. ‘val’ means this statement applies
  79. only to the typechecking phase. *)
  80. }
  81.  
  82. (* The following is needed to prove that lst does not have a
  83. negative length. *)
  84. prval _ = rclist_vt_param lst
  85. in
  86. case+ lst of
  87. | NIL => () (* An empty list. Do nothing. *)
  88. (* In the following, the ‘~’ means that the v node is consumed.
  89. It will be freed back into the heap. The type notation
  90. ‘(v : int)’ is because (perhaps due to an overload of the
  91. ‘=’ operator) the typechecker had difficulty determining its
  92. type. *)
  93. | ~(v :: tail) when (v : int) = x =>
  94. (* The first element matches. Replace the list with its tail. *)
  95. lst := tail
  96. | (_ :: _) => find (lst, x) (* Search in the list. *)
  97. end
  98.  
  99. (* Now let’s try it. *)
  100.  
  101. overload delete with rclist_int_delete
  102.  
  103. val A = 123
  104. val B = 789
  105. val C = 456
  106.  
  107. (* ‘var’ instead of ‘val’, to make lst a mutable variable that can be
  108. passed by reference. *)
  109. var lst = A :: C :: B :: NIL
  110.  
  111. val () = delete (lst, C)
  112.  
  113. fun
  114. loop {k : int | 0 <= k} .<k>.
  115. (p : !rclist_vt (int, k)) : void =
  116. case+ p of
  117. | NIL => ()
  118. | head :: tail =>
  119. begin
  120. println! (head);
  121. loop tail
  122. end
  123. prval () = rclist_vt_param lst
  124. val () = loop lst
  125.  
  126. (*------------------------------------------------------------------*)
  127.  
  128. implement
  129. main0 () = ()
  130.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement