io.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Declarations for high-level IO functions.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #ifndef __KP_IO__
  14. #define __KP_IO__ 1
  15. #include "interp.hpp"
  16. #include "stream.hpp"
  17. #include "initop.hpp"
  18. #include "str.hpp"
  19. #include "function.hpp"
  20. #include "symbol.hpp"
  21. #include "array.hpp"
  22. #include "utils/lazy.hpp"
  23. KP_DECLS_BEGIN
  24. struct reader
  25. {
  26. interpreter *interp;
  27. valref pairs_valref;
  28. local_varobj<array> pairs;
  29. object stpairs[16];
  30. uint32_t pair_cnt;
  31. char stbuf[256];
  32. char *bufp;
  33. int bufcnt;
  34. int bufmax;
  35. int toktype;
  36. stream *src;
  37. uint32_t lineno = 0;
  38. int bq_level = 0;
  39. bool unquoted = false;
  40. package *ipkg;
  41. reader (interpreter *interp, object input, package *ipkg = nullptr);
  42. bool readable_p () const
  43. {
  44. return (!this->src->eos_p () && !this->src->err_p ());
  45. }
  46. void take ();
  47. result<void> handle_sym (object pkg, object name);
  48. result<bool> read_token (schar& ch, int digs);
  49. void expand ();
  50. object getlbl (object label) const;
  51. object* putlbl (object label);
  52. result<bool> nextc (schar& ch);
  53. void push_ch (const schar& ch);
  54. result<uint32_t> peek ();
  55. result<object> read_sexpr ();
  56. result<object> read_sexpr (object label);
  57. result<object> read_list (object label);
  58. result<object> read_bq (object label);
  59. result<object> read_comma (object label);
  60. result<object> read_array (object label);
  61. result<object> read_table (object label);
  62. result<object> read_tuple (object label);
  63. result<object> read_bvector ();
  64. result<object> read_str ();
  65. result<object> read_char ();
  66. ~reader ();
  67. };
  68. // Expand a string (With possible interpolation).
  69. KP_EXPORT result<object> expand_str (interpreter *interp, object str);
  70. // Expand a backquote expression.
  71. KP_EXPORT result<object> expand_bq (interpreter *interp, object form);
  72. // Write an object to a stream, using the parameters in INFO.
  73. KP_EXPORT result<int64_t> xwrite (interpreter *interp, stream *strm,
  74. object obj, io_info& info);
  75. inline result<int64_t>
  76. xwrite (interpreter *interp, stream *strm, object obj)
  77. {
  78. io_info info;
  79. return (xwrite (interp, strm, obj, info));
  80. }
  81. template <typename ...Args>
  82. result<object> sprintf_helper (interpreter *interp, const char *fmt,
  83. Args... args)
  84. {
  85. local_varobj<string> sf;
  86. uint32_t sp = interp->stklen ();
  87. sf.local_init (fmt);
  88. KP_VTRY (interp->growstk (2 + sizeof... (args)),
  89. intern (interp, "%fmt-str", as_package (root_package)));
  90. *interp->stkend++ = symval (interp->retval);
  91. *interp->stkend++ = sf.as_obj ();
  92. KP_VTRY (push_all_helper (interp, args...));
  93. return (call_n (interp, interp->stklen () - sp - 1));
  94. }
  95. #define KP_SPRINTF(Interp, Fmt, ...) \
  96. KP_CALL_DISP (KP_CALL, (Interp), khipu::sprintf_helper, (Fmt), ##__VA_ARGS__)
  97. // Object (de)serialization.
  98. enum
  99. {
  100. PACK_NIL = 0x74,
  101. PACK_EMPTY_ARRAY = 0x75,
  102. PACK_EMPTY_BVECTOR = 0x76,
  103. PACK_EMPTY_STR = 0x77,
  104. PACK_INT8 = 0x78,
  105. PACK_FIXINT = 0x79,
  106. PACK_CHAR8 = 0x7a,
  107. PACK_REF_INT32 = 0x7b,
  108. PACK_REF_OBJ = 0x7c,
  109. PACK_TYPESPEC = 0x7d,
  110. PACK_END = 0x7e,
  111. };
  112. struct pack_cache
  113. {
  114. local_varobj<array> l_obj;
  115. object st_tab[256];
  116. valref ref;
  117. uint32_t n_elem;
  118. uint32_t n_old;
  119. bool evict;
  120. uint32_t size () const;
  121. object* data ();
  122. pack_cache (interpreter *interp);
  123. object get (interpreter *interp, object key);
  124. result<void> put (interpreter *interp, object key, object val);
  125. };
  126. struct pack_info
  127. {
  128. valref map;
  129. valref offset;
  130. lazy<pack_cache> pcache;
  131. pack_cache *cache;
  132. stream *bstream;
  133. const char *errmsg;
  134. pack_info (interpreter *interp);
  135. result<void> init (interpreter *interp, bool cache);
  136. result<void> add_mapping (interpreter *interp, object key, object val);
  137. object get (interpreter *interp, object obj);
  138. void touch (interpreter *interp, int offset);
  139. exception error (const char *msg)
  140. {
  141. this->errmsg = msg;
  142. return (exception ());
  143. }
  144. ~pack_info ()
  145. {
  146. if (this->cache)
  147. destroy (this->cache);
  148. }
  149. struct eviction_guard
  150. {
  151. bool *oldp;
  152. eviction_guard (pack_info& info, bool use)
  153. {
  154. if (use && info.cache->evict)
  155. *(this->oldp = &info.cache->evict) = false;
  156. else
  157. this->oldp = nullptr;
  158. }
  159. ~eviction_guard ()
  160. {
  161. if (this->oldp)
  162. *this->oldp = true;
  163. }
  164. };
  165. };
  166. KP_EXPORT result<int64_t> xpack (interpreter *interp, stream *strm,
  167. object obj, pack_info& info);
  168. KP_EXPORT result<int64_t> xpack (interpreter *interp, stream *strm,
  169. object obj, object *map, size_t nmap);
  170. template <typename ...Args>
  171. inline result<int64_t> xpack_with (interpreter *interp, stream *strm,
  172. object obj, Args... args)
  173. {
  174. object tmp[] = { args..., 0 };
  175. return (xpack (interp, strm, obj, tmp, KP_NELEM (tmp) - 1));
  176. }
  177. inline result<int64_t> xpack (interpreter *interp, stream *strm, object obj)
  178. {
  179. return (xpack (interp, strm, obj, nullptr, 0));
  180. }
  181. KP_EXPORT result<object> xunpack (interpreter *interp,
  182. stream *strm, pack_info& info);
  183. inline result<object> xunpack (interpreter *interp, stream *strm)
  184. {
  185. pack_info info { interp };
  186. KP_VTRY (info.init (interp, false));
  187. return (xunpack (interp, strm, info));
  188. }
  189. // Print a full backtrace starting from FRAME to stream STRMP.
  190. KP_EXPORT result<void> print_backtrace (interpreter *interp, uint32_t frame,
  191. stream *strmp, io_info& info);
  192. // Safely write a raised object to a stream.
  193. KP_EXPORT void write_exc (interpreter *interp, stream *strm,
  194. object exc, io_info& info);
  195. KP_EXPORT init_op init_io;
  196. KP_DECLS_END
  197. #endif