Advertisement
Guest User

Untitled

a guest
Mar 26th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.90 KB | None | 0 0
  1. (*
  2. HX-2019-03-26-2:
  3.  
  4. The original code is available at
  5. https://gist.github.com/ashalkhakov/c3577e97b20020fde31f84447fd1e056
  6.  
  7. I turned runCommand into a polymorphic function and
  8. also made Command a linear datatype (i.e., dataviewtype)
  9.  
  10. *)
  11.  
  12. (*
  13.  
  14. inspired by this discussion:
  15.  
  16. https://groups.google.com/forum/#!topic/ats-lang-users/fICcWumT9RE
  17.  
  18. runnable over at glot.io:
  19.  
  20. https://glot.io/snippets/fapb07meuz
  21.  
  22. to build and run:
  23.  
  24. patscc -DATS_MEMALLOC_LIBC main.dats && a.out
  25. *)
  26. #include
  27. "share/atspre_staload.hats"
  28.  
  29. %{
  30.  
  31. // NOTE: this is really from ATS2 prelude
  32. // (newer version of prelude includes this)
  33. extern
  34. atstype_ptr
  35. atspre_fileref_get_line_string_main2
  36. (
  37. atstype_int bsz0
  38. , atstype_ptr filp0
  39. , atstype_ref nlen0 // int *nlen
  40. )
  41. {
  42. //
  43. int bsz = bsz0 ;
  44. int ofs1 = 0, ofs2 = 0;
  45. int *nlen = (int*)nlen0;
  46. FILE *filp = (FILE*)filp0 ;
  47. char *buf1, *buf2, *pres ;
  48. //
  49. buf1 = atspre_malloc_gc(bsz) ;
  50. //
  51. while (1) {
  52. buf2 = buf1+ofs1 ;
  53. pres = fgets(buf2, bsz-ofs1, filp) ;
  54. if (!pres)
  55. {
  56. if (feof(filp))
  57. {
  58. *buf2 = '\0' ;
  59. *nlen = ofs1 ; return buf1 ;
  60. } else {
  61. atspre_mfree_gc(buf1) ;
  62. *nlen = -1 ; return (char*)0 ;
  63. } // end of [if]
  64. }
  65. //
  66. ofs2 = strlen(buf2) ;
  67. //
  68. if
  69. (ofs2 > 0) ofs1 += ofs2 ; else return buf1;
  70. //
  71. // HX: ofs1 > 0 holds at this point
  72. // HX: the newline symbol needs to be trimmed:
  73. //
  74. if(
  75. buf1[ofs1-1]=='\n'
  76. ) {
  77. buf1[ofs1-1] = '\0'; *nlen = ofs1-1 ; return buf1 ;
  78. } // end of [if]
  79. //
  80. // HX: there is room // so there are no more chars:
  81. //
  82. if (ofs1+1 < bsz) { ( *nlen = ofs1 ) ; return buf1 ; }
  83. //
  84. // HX: there is no room // another call to [fgets] is needed:
  85. //
  86. bsz *= 2 ;
  87. buf2 = buf1 ;
  88. buf1 = atspre_malloc_gc(bsz) ;
  89. memcpy(buf1, buf2, ofs1) ; atspre_mfree_gc(buf2) ;
  90. } // end of [while]
  91. //
  92. return buf1 ; // HX: this is really deadcode
  93. //
  94. } // end of [atspre_fileref_get_line_string_main2]
  95.  
  96. %}
  97.  
  98. (* ****** ****** *)
  99.  
  100. // well, this is untested and may be ignored.
  101. // initially this block was introduced so that
  102. // we might allocate the temporaries for "binds" on stack
  103. %{^
  104.  
  105. #include <alloca.h>
  106.  
  107. #if __STDC_VERSION__ >= 201112L /* C11 */
  108.  
  109. #include <stdalign.h>
  110.  
  111. #define ALIGN_OF(type) (alignof(type))
  112.  
  113. #else /* not C11 */
  114.  
  115. #define ALIGN_OF(type) ((size_t)&((struct { char c; type d; } *)0)->d)
  116.  
  117. #endif
  118.  
  119. // using GCC "statement expressions"
  120. #define ALLOCA_TYPE(type) ({ \
  121. const int align = ALIGN_OF(type); \
  122. const int n = sizeof(type); \
  123. void *p = alloca(n + align - 1); \
  124. (type *)(((UINT_PTR)p + (ALIGN_OF(type) - 1)) & ~(ALIGN_OF(type) - 1)); \
  125. })
  126.  
  127. %}
  128.  
  129. (* ****** ****** *)
  130.  
  131. // an abstract type of "commands"
  132. absvtype
  133. Command_vtype
  134. (a:vt@ype) = ptr
  135. vtypedef Command(a:vt@ype) = Command_vtype(a)
  136.  
  137. // a command interpreter
  138. // NOTE: it requires the user to provide a continuation
  139. extern
  140. fun
  141. {a:vt@ype}
  142. runCommand
  143. (cmd:Command(a)): a
  144. extern
  145. fun
  146. runCommand2
  147. {a:vt@ype}
  148. (cmd:Command(a), &a? >> a): void
  149.  
  150. implement
  151. {a}
  152. runCommand(cmd) =
  153. let var r0: a in runCommand2(cmd, r0); r0 end
  154.  
  155. // the returned command will perform c1, then c2
  156. extern
  157. fun seq
  158. (c1:Command(unit), c2: Command(unit)): Command(unit)
  159.  
  160. // a more powerful sequencing operator: this feeds the output of c1
  161. // into c2
  162. extern
  163. fun
  164. {a:vt@ype}
  165. {b:vt@ype}
  166. bind
  167. ( c1:Command(a)
  168. , c2: (&a >> _?) -<cloptr1> Command(b)): Command(b)
  169.  
  170. // build a command that will provide us with input from user
  171. extern
  172. fun cread (): Command(string)
  173. // build a command to print a string to console
  174. extern
  175. fun cprint (s:string): Command(unit)
  176.  
  177. (* ****** ****** *)
  178.  
  179. extern
  180. fun
  181. fgetstring
  182. (inp: FILEref): string
  183.  
  184. fun
  185. {a:vt@ype}
  186. assign(r0: &a? >> a, x0: a): void = (r0 := x0)
  187.  
  188. local
  189.  
  190. extern
  191. fun
  192. runCommand
  193. {a:vt@ype}
  194. (c:Command(a:vt@ype), &a? >> a): void
  195.  
  196. datavtype
  197. Command(vt@ype) =
  198. | Nop(unit)
  199. | Read(string)
  200. | Print(unit) of string
  201. | Seq(unit) of (Command(unit), Command(unit))
  202. | {a,b:vt@ype} Bind(b) of (Command(a), (&a >> a?) -<cloptr1> Command(b), a?)
  203.  
  204. assume Command_vtype = Command
  205.  
  206. in // in of [local]
  207.  
  208. implement
  209. cprint (s) = Print s
  210. implement
  211. cread () = Read ()
  212. implement
  213. seq(c1, c2) = Seq(c1, c2)
  214. implement
  215. {a}{b}
  216. bind(c1, fc2) =
  217. Bind(c1, fc2, $UNSAFE.castvwtp0{a?}(0))
  218.  
  219. implement
  220. fgetstring (inp) = let
  221. //
  222. var nlen: int // uninitialized
  223. val line = fileref_get_line_string_main(inp, nlen)
  224. prval () = lemma_strnptr_param(line)
  225. //
  226. in
  227. g0ofg1(strnptr2string(line))
  228. end // end of [fgetstring]
  229.  
  230. implement
  231. runCommand2{a}
  232. (cmd, r0) =
  233. case+ cmd of
  234. | ~Nop() =>
  235. assign<unit>(r0, unit)
  236. | ~Print(s) =>
  237. let
  238. val () = print (s)
  239. in assign<unit>(r0, unit) end
  240. | ~Read() =>
  241. let
  242. val x0 =
  243. fgetstring(stdin_ref)
  244. in
  245. assign<string>(r0, x0)
  246. end
  247. | ~Seq (c1, c2) =>
  248. (runCommand2(c1, r0); runCommand2(c2, r0))
  249. | @Bind(c1, fc2, r1) =>
  250. let
  251. val () =
  252. runCommand2(c1, r1)
  253. val fc2 = fc2
  254. val cmd2 = fc2(r1)
  255. in
  256. free@(cmd); cloptr_free($UNSAFE.castvwtp0{cloptr(void)}(fc2)); runCommand2(cmd2, r0)
  257. end
  258.  
  259. end // end of [local]
  260. //
  261. (* ****** ****** *)
  262.  
  263. extern
  264. fun
  265. test0 (): void
  266. implement
  267. test0 () = let
  268. val hello =
  269. let val h1 = cprint "hi" val h2 = cprint "hi" in seq (h1, h2) end // here. twice the effect!
  270. val hello = seq (hello, cprint "\n")
  271. val unit() = runCommand (hello)
  272.  
  273. // a bigger program
  274. // (this one shows how the interpreter interacts with the command-building
  275. // process, which is our program)
  276. val greet = let
  277. val h = cprint "what is your name?\n"
  278. val g = cread ()
  279. val f =
  280. lam (name: &string): Command(unit) =<cloptr1>
  281. let val name = name in seq (cprint "hello, ", seq (cprint name, cprint "\n")) end
  282. in
  283. seq (h, bind (g, f))
  284. end
  285. val unit() = runCommand (greet)
  286. in
  287. (*nop*)
  288. end
  289.  
  290. implement
  291. main0 () = test0 ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement