stdc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "pocketpy/pocketpy.h"
  2. #include "pocketpy/interpreter/vm.h"
  3. #include <string.h>
  4. #define DEF_BUILTIN_MEMORY_T(Char_, char_, tp_int_, py_newint_, py_toint_, py_i64_) \
  5. static bool stdc_##Char_##__new__(int argc, py_Ref argv) { \
  6. char_* ud = py_newobject(py_retval(), tp_stdc_##Char_, 0, sizeof(char_)); \
  7. if(argc == 2) { \
  8. PY_CHECK_ARG_TYPE(1, tp_int_); \
  9. *ud = (char_)py_toint_(&argv[1]); \
  10. } else if(argc > 2) { \
  11. return TypeError("expected 1 or 2 arguments, got %d", argc); \
  12. } \
  13. return true; \
  14. } \
  15. static bool stdc_##Char_##__get_value(int argc, py_Ref argv) { \
  16. PY_CHECK_ARGC(1); \
  17. char_* ud = py_touserdata(argv); \
  18. py_newint_(py_retval(), (py_i64_)(*ud)); \
  19. return true; \
  20. } \
  21. static bool stdc_##Char_##__set_value(int argc, py_Ref argv) { \
  22. PY_CHECK_ARGC(2); \
  23. char_* ud = py_touserdata(argv); \
  24. PY_CHECK_ARG_TYPE(1, tp_int_); \
  25. *ud = (char_)py_toint_(&argv[1]); \
  26. py_newnone(py_retval()); \
  27. return true; \
  28. } \
  29. static bool stdc_##Char_##__read_STATIC(int argc, py_Ref argv) { \
  30. PY_CHECK_ARGC(2); \
  31. PY_CHECK_ARG_TYPE(0, tp_int); \
  32. PY_CHECK_ARG_TYPE(1, tp_int); \
  33. char_* p = (char_*)(intptr_t)py_toint(&argv[0]); \
  34. int offset = py_toint(&argv[1]); \
  35. py_newint_(py_retval(), (py_i64_)(p[offset])); \
  36. return true; \
  37. } \
  38. static bool stdc_##Char_##__write_STATIC(int argc, py_Ref argv) { \
  39. PY_CHECK_ARGC(3); \
  40. PY_CHECK_ARG_TYPE(0, tp_int); \
  41. PY_CHECK_ARG_TYPE(1, tp_int); \
  42. PY_CHECK_ARG_TYPE(2, tp_int_); \
  43. char_* p = (char_*)(intptr_t)py_toint(&argv[0]); \
  44. int offset = py_toint(&argv[1]); \
  45. p[offset] = (char_)py_toint_(&argv[2]); \
  46. py_newnone(py_retval()); \
  47. return true; \
  48. } \
  49. static bool stdc_##Char_##__array_STATIC(int argc, py_Ref argv) { \
  50. PY_CHECK_ARGC(1); \
  51. PY_CHECK_ARG_TYPE(0, tp_int); \
  52. int length = py_toint(argv); \
  53. int size = sizeof(char_) * length; \
  54. py_newobject(py_retval(), tp_stdc_##Char_, 0, size); \
  55. return true; \
  56. } \
  57. static bool stdc_##Char_##__getitem__(int argc, py_Ref argv) { \
  58. PY_CHECK_ARGC(2); \
  59. char_* ud = py_touserdata(argv); \
  60. PY_CHECK_ARG_TYPE(1, tp_int); \
  61. int index = py_toint(&argv[1]); \
  62. py_newint_(py_retval(), (py_i64_)(ud[index])); \
  63. return true; \
  64. } \
  65. static bool stdc_##Char_##__setitem__(int argc, py_Ref argv) { \
  66. PY_CHECK_ARGC(3); \
  67. char_* ud = py_touserdata(argv); \
  68. PY_CHECK_ARG_TYPE(1, tp_int); \
  69. PY_CHECK_ARG_TYPE(2, tp_int_); \
  70. int index = py_toint(&argv[1]); \
  71. ud[index] = (char_)py_toint_(&argv[2]); \
  72. py_newnone(py_retval()); \
  73. return true; \
  74. } \
  75. static void pk__bind_stdc_##Char_(py_Ref mod) { \
  76. py_Type type = py_newtype(#Char_, tp_stdc_Memory, mod, NULL); \
  77. py_tpsetfinal(type); \
  78. assert(type == tp_stdc_##Char_); \
  79. py_bindmagic(type, __new__, stdc_##Char_##__new__); \
  80. py_bindmagic(type, __getitem__, stdc_##Char_##__getitem__); \
  81. py_bindmagic(type, __setitem__, stdc_##Char_##__setitem__); \
  82. py_bindproperty(type, "value", stdc_##Char_##__get_value, stdc_##Char_##__set_value); \
  83. py_bindstaticmethod(type, "read", stdc_##Char_##__read_STATIC); \
  84. py_bindstaticmethod(type, "write", stdc_##Char_##__write_STATIC); \
  85. py_bindstaticmethod(type, "array", stdc_##Char_##__array_STATIC); \
  86. py_newint(py_emplacedict(py_tpobject(type), py_name("size")), sizeof(char_)); \
  87. }
  88. DEF_BUILTIN_MEMORY_T(Char, char, tp_int, py_newint, py_toint, py_i64)
  89. DEF_BUILTIN_MEMORY_T(UChar, unsigned char, tp_int, py_newint, py_toint, py_i64)
  90. DEF_BUILTIN_MEMORY_T(Short, short, tp_int, py_newint, py_toint, py_i64)
  91. DEF_BUILTIN_MEMORY_T(UShort, unsigned short, tp_int, py_newint, py_toint, py_i64)
  92. DEF_BUILTIN_MEMORY_T(Int, int, tp_int, py_newint, py_toint, py_i64)
  93. DEF_BUILTIN_MEMORY_T(UInt, unsigned int, tp_int, py_newint, py_toint, py_i64)
  94. DEF_BUILTIN_MEMORY_T(Long, long, tp_int, py_newint, py_toint, py_i64)
  95. DEF_BUILTIN_MEMORY_T(ULong, unsigned long, tp_int, py_newint, py_toint, py_i64)
  96. DEF_BUILTIN_MEMORY_T(LongLong, long long, tp_int, py_newint, py_toint, py_i64)
  97. DEF_BUILTIN_MEMORY_T(ULongLong, unsigned long long, tp_int, py_newint, py_toint, py_i64)
  98. DEF_BUILTIN_MEMORY_T(Float, float, tp_float, py_newfloat, py_tofloat, float)
  99. DEF_BUILTIN_MEMORY_T(Double, double, tp_float, py_newfloat, py_tofloat, double)
  100. DEF_BUILTIN_MEMORY_T(Pointer, void*, tp_int, py_newint, py_toint, py_i64)
  101. DEF_BUILTIN_MEMORY_T(Bool, bool, tp_bool, py_newbool, py_tobool, bool)
  102. #undef DEF_BUILTIN_MEMORY_T
  103. static bool stdc_malloc(int argc, py_Ref argv) {
  104. PY_CHECK_ARGC(1);
  105. PY_CHECK_ARG_TYPE(0, tp_int);
  106. py_i64 size = py_toint(&argv[0]);
  107. void* p = py_malloc(size);
  108. py_newint(py_retval(), (py_i64)(intptr_t)p);
  109. return true;
  110. }
  111. static bool stdc_free(int argc, py_Ref argv) {
  112. PY_CHECK_ARGC(1);
  113. PY_CHECK_ARG_TYPE(0, tp_int);
  114. void* p = (void*)(intptr_t)py_toint(&argv[0]);
  115. py_free(p);
  116. py_newnone(py_retval());
  117. return true;
  118. }
  119. static bool stdc_memcpy(int argc, py_Ref argv) {
  120. PY_CHECK_ARGC(3);
  121. PY_CHECK_ARG_TYPE(0, tp_int); // dst
  122. void* dst = (void*)(intptr_t)py_toint(&argv[0]);
  123. PY_CHECK_ARG_TYPE(2, tp_int); // n
  124. py_i64 n = py_toint(&argv[2]);
  125. void* src;
  126. if(py_istype(&argv[1], tp_bytes)) {
  127. int size;
  128. src = py_tobytes(&argv[1], &size);
  129. if(size < n) n = size;
  130. } else {
  131. PY_CHECK_ARG_TYPE(1, tp_int); // src
  132. src = (void*)(intptr_t)py_toint(&argv[1]);
  133. }
  134. memcpy(dst, src, (size_t)n);
  135. py_newnone(py_retval());
  136. return true;
  137. }
  138. static bool stdc_memset(int argc, py_Ref argv) {
  139. PY_CHECK_ARGC(3);
  140. PY_CHECK_ARG_TYPE(0, tp_int);
  141. PY_CHECK_ARG_TYPE(1, tp_int);
  142. PY_CHECK_ARG_TYPE(2, tp_int);
  143. void* dst = (void*)(intptr_t)py_toint(&argv[0]);
  144. int value = (int)py_toint(&argv[1]);
  145. py_i64 n = py_toint(&argv[2]);
  146. memset(dst, value, (size_t)n);
  147. py_newnone(py_retval());
  148. return true;
  149. }
  150. static bool stdc_memcmp(int argc, py_Ref argv) {
  151. PY_CHECK_ARGC(3);
  152. PY_CHECK_ARG_TYPE(0, tp_int);
  153. PY_CHECK_ARG_TYPE(1, tp_int);
  154. PY_CHECK_ARG_TYPE(2, tp_int);
  155. void* p1 = (void*)(intptr_t)py_toint(&argv[0]);
  156. void* p2 = (void*)(intptr_t)py_toint(&argv[1]);
  157. py_i64 n = py_toint(&argv[2]);
  158. int res = memcmp(p1, p2, (size_t)n);
  159. py_newint(py_retval(), (py_i64)res);
  160. return true;
  161. }
  162. static bool stdc_addressof(int argc, py_Ref argv) {
  163. PY_CHECK_ARGC(1);
  164. if(!py_checkinstance(argv, tp_stdc_Memory)) return false;
  165. void* ud = py_touserdata(argv);
  166. py_newint(py_retval(), (py_i64)(intptr_t)ud);
  167. return true;
  168. }
  169. static bool stdc_sizeof(int argc, py_Ref argv) {
  170. PY_CHECK_ARGC(1);
  171. PY_CHECK_ARG_TYPE(0, tp_type);
  172. py_Type type = py_totype(&argv[0]);
  173. if(!py_issubclass(type, tp_stdc_Memory)) {
  174. return TypeError("expected a type derived from stdc.Memory");
  175. }
  176. py_assign(py_retval(), py_getdict(py_tpobject(type), py_name("size")));
  177. return true;
  178. }
  179. static bool stdc_read_cstr(int argc, py_Ref argv) {
  180. PY_CHECK_ARGC(1);
  181. PY_CHECK_ARG_TYPE(0, tp_int);
  182. char* p = (char*)(intptr_t)py_toint(&argv[0]);
  183. py_newstr(py_retval(), p);
  184. return true;
  185. }
  186. static bool stdc_write_cstr(int argc, py_Ref argv) {
  187. PY_CHECK_ARGC(2);
  188. PY_CHECK_ARG_TYPE(0, tp_int);
  189. PY_CHECK_ARG_TYPE(1, tp_str);
  190. char* p = (char*)(intptr_t)py_toint(&argv[0]);
  191. c11_sv sv = py_tosv(&argv[1]);
  192. memcpy(p, sv.data, sv.size);
  193. p[sv.size] = '\0';
  194. py_newnone(py_retval());
  195. return true;
  196. }
  197. static bool stdc_read_bytes(int argc, py_Ref argv) {
  198. PY_CHECK_ARGC(2);
  199. PY_CHECK_ARG_TYPE(0, tp_int);
  200. PY_CHECK_ARG_TYPE(1, tp_int);
  201. unsigned char* p = (unsigned char*)(intptr_t)py_toint(&argv[0]);
  202. int size = py_toint(&argv[1]);
  203. unsigned char* dst = py_newbytes(py_retval(), size);
  204. memcpy(dst, p, size);
  205. return true;
  206. }
  207. static bool stdc_write_bytes(int argc, py_Ref argv) {
  208. PY_CHECK_ARGC(2);
  209. PY_CHECK_ARG_TYPE(0, tp_int);
  210. PY_CHECK_ARG_TYPE(1, tp_bytes);
  211. unsigned char* p = (unsigned char*)(intptr_t)py_toint(&argv[0]);
  212. int size;
  213. unsigned char* src = py_tobytes(&argv[1], &size);
  214. memcpy(p, src, size);
  215. py_newnone(py_retval());
  216. return true;
  217. }
  218. void pk__add_module_stdc() {
  219. py_Ref mod = py_newmodule("stdc");
  220. py_bindfunc(mod, "malloc", stdc_malloc);
  221. py_bindfunc(mod, "free", stdc_free);
  222. py_bindfunc(mod, "memcpy", stdc_memcpy);
  223. py_bindfunc(mod, "memset", stdc_memset);
  224. py_bindfunc(mod, "memcmp", stdc_memcmp);
  225. py_bindfunc(mod, "addressof", stdc_addressof);
  226. py_bindfunc(mod, "sizeof", stdc_sizeof);
  227. py_bindfunc(mod, "read_cstr", stdc_read_cstr);
  228. py_bindfunc(mod, "write_cstr", stdc_write_cstr);
  229. py_bindfunc(mod, "read_bytes", stdc_read_bytes);
  230. py_bindfunc(mod, "write_bytes", stdc_write_bytes);
  231. py_Type Memory = py_newtype("Memory", tp_object, mod, NULL);
  232. assert(Memory == tp_stdc_Memory);
  233. pk__bind_stdc_Char(mod);
  234. pk__bind_stdc_UChar(mod);
  235. pk__bind_stdc_Short(mod);
  236. pk__bind_stdc_UShort(mod);
  237. pk__bind_stdc_Int(mod);
  238. pk__bind_stdc_UInt(mod);
  239. pk__bind_stdc_Long(mod);
  240. pk__bind_stdc_ULong(mod);
  241. pk__bind_stdc_LongLong(mod);
  242. pk__bind_stdc_ULongLong(mod);
  243. for(int size = 1; size <= 8; size *= 2) {
  244. for(py_Type t = tp_stdc_Char; t <= tp_stdc_ULongLong; t += 2) {
  245. py_Ref size_var = py_getdict(py_tpobject(t), py_name("size"));
  246. if(py_toint(size_var) == size) {
  247. char buf[16];
  248. snprintf(buf, sizeof(buf), "Int%d", size * 8);
  249. py_setdict(mod, py_name(buf), py_tpobject(t));
  250. snprintf(buf, sizeof(buf), "UInt%d", size * 8);
  251. py_setdict(mod, py_name(buf), py_tpobject(t + 1));
  252. break;
  253. }
  254. }
  255. }
  256. for(py_Type t = tp_stdc_Char; t <= tp_stdc_ULongLong; t += 2) {
  257. py_Ref size_var = py_getdict(py_tpobject(t), py_name("size"));
  258. if(py_toint(size_var) == sizeof(size_t)) {
  259. py_setdict(mod, py_name("SizeT"), py_tpobject(t + 1));
  260. break;
  261. }
  262. }
  263. if(sizeof(void*) == 4) {
  264. py_setdict(mod, py_name("IntPtrT"), py_getdict(mod, py_name("Int32")));
  265. py_setdict(mod, py_name("UIntPtrT"), py_getdict(mod, py_name("UInt32")));
  266. } else if(sizeof(void*) == 8) {
  267. py_setdict(mod, py_name("IntPtrT"), py_getdict(mod, py_name("Int64")));
  268. py_setdict(mod, py_name("UIntPtrT"), py_getdict(mod, py_name("UInt64")));
  269. } else {
  270. c11__abort("unsupported pointer size");
  271. }
  272. pk__bind_stdc_Float(mod);
  273. pk__bind_stdc_Double(mod);
  274. pk__bind_stdc_Pointer(mod);
  275. pk__bind_stdc_Bool(mod);
  276. }