/src/util/type.c

https://gitlab.com/CoyoteLang/compiler · C · 333 lines · 305 code · 16 blank · 12 comment · 39 complexity · c35c9f1821fe6e5b7725ef64caa057fe MD5 · raw file

  1. #include <util/type.h>
  2. #include <assert.h>
  3. // for type_get_by_name
  4. #include <string.h>
  5. // <DEBUG ONLY>
  6. #include <stdio.h>
  7. // </DEBUG ONLY>
  8. Type Tvoid = { TF_VOID };
  9. Type Tbool = { TF_BOOLEAN, { .uboolean = { 1, 1 } } };
  10. Type Tbyte = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 1, COY_TRUE } } },
  11. Tubyte = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 1, COY_FALSE } } };
  12. Type Tshort = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 2, COY_TRUE } } },
  13. Tushort = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 2, COY_FALSE } } };
  14. Type Tint = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 4, COY_TRUE } } },
  15. Tuint = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 4, COY_FALSE } } };
  16. Type Tlong = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 8, COY_TRUE } } },
  17. Tulong = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 8, COY_FALSE } } };
  18. //Type Tcent = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 16, COY_TRUE } } },
  19. // Tucent = { TF_INTEGER, { .uinteger = { 1, 1, COMPLEX_REAL, 16, COY_FALSE } } };
  20. Type Tfloat = { TF_REAL, { .ureal = { 1, 1, COMPLEX_REAL, 4 } } },
  21. Tdouble = { TF_REAL, { .ureal = { 1, 1, COMPLEX_REAL, 8 } } },
  22. Treal = { TF_REAL, { .ureal = { 1, 1, COMPLEX_REAL, 255 } } };
  23. Type Tchar = { TF_CHARACTER, { .ucharacter = { 1 } } },
  24. Twchar = { TF_CHARACTER, { .ucharacter = { 2 } } },
  25. Tdchar = { TF_CHARACTER, { .ucharacter = { 4 } } };
  26. Type Tstring = { TF_STRING, { .ustring = { &Tchar } } },
  27. Twstring = { TF_STRING, { .ustring = { &Twchar } } },
  28. Tdstring = { TF_STRING, { .ustring = { &Tdchar } } };
  29. Type Tmixed = { TF_MIXED };
  30. // unknowns
  31. Type TstringU = { TF_STRING, { .ustring = { NULL } } };
  32. // internals
  33. Type Ttype = { TF_TYPE };
  34. Type* type_get_by_name(const char* name)
  35. {
  36. #define GET(NAME) if(!strcmp(name, #NAME)) return &T##NAME
  37. GET(void);
  38. GET(bool);
  39. GET(byte); GET(ubyte);
  40. GET(short); GET(ushort);
  41. GET(int); GET(uint);
  42. GET(long); GET(ulong);
  43. //GET(cent); GET(ucent);
  44. GET(float); GET(double); GET(real);
  45. GET(char); GET(wchar); GET(dchar);
  46. GET(mixed);
  47. return NULL;
  48. }
  49. static COYusize type__complex_multiplier(TypeComplex com)
  50. {
  51. switch(com)
  52. {
  53. case COMPLEX_REAL:
  54. case COMPLEX_IMAG: return 1;
  55. case COMPLEX_COMPLEX: return 2;
  56. case COMPLEX_QUATERNION: return 4;
  57. }
  58. assert(0 && "Internal error: invalid type__complex_multiplier()");
  59. return 0;
  60. }
  61. COYusize type_sizeof(const Type* type)
  62. {
  63. switch(type->family)
  64. {
  65. case TF_VOID: return 0;
  66. case TF_BOOLEAN: return type->u.uboolean.dimx * type->u.uboolean.dimy;
  67. case TF_INTEGER: return type->u.uinteger.dimx * type->u.uinteger.dimy * type__complex_multiplier(type->u.uinteger.com) * type->u.uinteger.width;
  68. case TF_REAL: return type->u.ureal.dimx * type->u.ureal.dimy * type__complex_multiplier(type->u.ureal.com) * (type->u.ureal.width == Treal.u.ureal.width ? sizeof(COYreal) : type->u.ureal.width);
  69. case TF_CHARACTER: return type->u.ucharacter.width;
  70. case TF_STRUCT: assert(0 && "TODO: struct.sizeof"); return 0;
  71. case TF_CLASS:
  72. case TF_ARRAY:
  73. case TF_STRING:
  74. case TF_DICT:
  75. case TF_SET:
  76. case TF_OPTION:
  77. case TF_DELEGATE: return sizeof(void*);
  78. case TF_MIXED:
  79. case TF_TYPE: assert(0 && "Internal error: illegal type_sizeof() type"); return 0;
  80. }
  81. assert(0 && "Internal error: invalid type_sizeof()");
  82. return 0;
  83. }
  84. COYbool type_isnum(const Type* type)
  85. {
  86. switch(type->family)
  87. {
  88. case TF_BOOLEAN:
  89. case TF_INTEGER:
  90. case TF_REAL:
  91. case TF_CHARACTER:
  92. return COY_TRUE;
  93. case TF_VOID:
  94. case TF_STRUCT:
  95. case TF_CLASS:
  96. case TF_ARRAY:
  97. case TF_STRING:
  98. case TF_DICT:
  99. case TF_SET:
  100. case TF_DELEGATE:
  101. case TF_OPTION:
  102. case TF_MIXED:
  103. return COY_FALSE;
  104. case TF_TYPE:
  105. assert(0 && "Attempted to use isnum() on a type");
  106. }
  107. assert(0);
  108. return COY_FALSE;
  109. }
  110. COYbool type_isref(const Type* type)
  111. {
  112. switch(type->family)
  113. {
  114. case TF_VOID:
  115. case TF_BOOLEAN:
  116. case TF_INTEGER:
  117. case TF_REAL:
  118. case TF_CHARACTER:
  119. case TF_STRUCT:
  120. return COY_FALSE;
  121. case TF_CLASS:
  122. /*case TF_ARRAY:
  123. case TF_STRING:
  124. case TF_DICT:
  125. case TF_SET:*/
  126. case TF_DELEGATE:
  127. case TF_OPTION:
  128. case TF_MIXED:
  129. return COY_TRUE;
  130. case TF_ARRAY:
  131. case TF_STRING:
  132. case TF_DICT:
  133. case TF_SET:
  134. assert(0 && "TODO isref for ARRAY|STRING|DICT|SET");
  135. case TF_TYPE:
  136. assert(0 && "Attempted to use isref() on a type");
  137. }
  138. assert(0);
  139. return COY_FALSE;
  140. }
  141. static void type_dumpDBG_complex(TypeComplex com);
  142. static void type_dumpDBG_dim(COYubyte dimx, COYubyte dimy);
  143. static void type_dumpDBG_list(Type* const* items, COYuint nitems, const char* sep);
  144. static void type_dumpDBG_name(const Type* type);
  145. static void type_dumpDBG_complex(TypeComplex com)
  146. {
  147. switch(com)
  148. {
  149. case COMPLEX_REAL: break;
  150. case COMPLEX_IMAG: printf("i"); break;
  151. case COMPLEX_COMPLEX: printf("c"); break;
  152. case COMPLEX_QUATERNION: printf("q"); break;
  153. }
  154. }
  155. static void type_dumpDBG_dim(COYubyte dimx, COYubyte dimy)
  156. {
  157. if(dimx) printf("%u", dimx);
  158. if(dimy) printf("x%u", dimy);
  159. }
  160. static void type_dumpDBG_list(Type* const* items, COYuint nitems, const char* sep)
  161. {
  162. if(!sep) sep = "";
  163. COYuint i;
  164. for(i = 0; i < nitems; i++)
  165. {
  166. if(i) printf("%s", sep);
  167. type_dumpDBG_name(items[i]);
  168. }
  169. }
  170. static void type_dumpDBG_name(const Type* type)
  171. {
  172. if(!type)
  173. {
  174. printf("<null>");
  175. return;
  176. }
  177. switch(type->family)
  178. {
  179. case TF_VOID:
  180. printf("void");
  181. return;
  182. case TF_BOOLEAN:
  183. printf("bool");
  184. type_dumpDBG_dim(type->u.uboolean.dimx, type->u.uboolean.dimy);
  185. return;
  186. case TF_INTEGER:
  187. type_dumpDBG_complex(type->u.uinteger.com);
  188. if(!type->u.uinteger.is_signed) printf("u");
  189. switch(type->u.uinteger.width)
  190. {
  191. case 1: printf("byte"); break;
  192. case 2: printf("short"); break;
  193. case 4: printf("int"); break;
  194. case 8: printf("long"); break;
  195. default: assert(0);
  196. }
  197. type_dumpDBG_dim(type->u.uinteger.dimx, type->u.uinteger.dimy);
  198. return;
  199. case TF_REAL:
  200. type_dumpDBG_complex(type->u.ureal.com);
  201. switch(type->u.ureal.width)
  202. {
  203. case 4: printf("float"); break;
  204. case 8: printf("double"); break;
  205. case 16: printf("real"); break;
  206. default: assert(0);
  207. }
  208. type_dumpDBG_dim(type->u.ureal.dimx, type->u.ureal.dimy);
  209. return;
  210. case TF_CHARACTER:
  211. switch(type->u.ucharacter.width)
  212. {
  213. case 1: printf("char"); break;
  214. case 2: printf("wchar"); break;
  215. case 4: printf("dchar"); break;
  216. default: assert(0);
  217. }
  218. return;
  219. case TF_STRUCT:
  220. printf("struct %.*s", (int)type->u.ustruct.name->len, type->u.ustruct.name->ptr);
  221. return;
  222. case TF_CLASS:
  223. printf("class %.*s", (int)type->u.ustruct.name->len, type->u.ustruct.name->ptr);
  224. return;
  225. case TF_ARRAY:
  226. type_dumpDBG_name(type->u.uarray.val);
  227. printf("[]");
  228. return;
  229. case TF_STRING:
  230. if(type->u.ustring.val == &Tchar)
  231. printf("c");
  232. else if(type->u.ustring.val == &Twchar)
  233. printf("w");
  234. else if(type->u.ustring.val == &Tdchar)
  235. printf("d");
  236. else if(!type->u.ustring.val)
  237. printf("_");
  238. else
  239. assert(0);
  240. printf("string");
  241. return;
  242. case TF_DICT:
  243. type_dumpDBG_name(type->u.udict.val);
  244. printf("[");
  245. type_dumpDBG_name(type->u.udict.key);
  246. printf("]");
  247. return;
  248. case TF_SET:
  249. printf("set[");
  250. type_dumpDBG_name(type->u.uset.key);
  251. printf("]");
  252. return;
  253. case TF_DELEGATE:
  254. printf("delegate ");
  255. type_dumpDBG_name(type->u.udelegate.ret);
  256. printf("(");
  257. type_dumpDBG_list(type->u.udelegate.params, type->u.udelegate.nparams, ",");
  258. if(type->u.udelegate.has_varargs) printf("...");
  259. printf(")");
  260. return;
  261. case TF_OPTION:
  262. type_dumpDBG_name(type->u.uoption.base);
  263. printf("?");
  264. return;
  265. case TF_MIXED:
  266. printf("mixed");
  267. return;
  268. case TF_TYPE:
  269. printf("<type>");
  270. return;
  271. }
  272. assert(0);
  273. }
  274. void type_dumpDBG(const Type* type)
  275. {
  276. if(!type)
  277. {
  278. printf("<null>");
  279. return;
  280. }
  281. switch(type->family)
  282. {
  283. case TF_VOID:
  284. case TF_BOOLEAN:
  285. case TF_INTEGER:
  286. case TF_REAL:
  287. case TF_CHARACTER:
  288. case TF_ARRAY:
  289. case TF_STRING:
  290. case TF_DICT:
  291. case TF_SET:
  292. case TF_DELEGATE:
  293. case TF_OPTION:
  294. case TF_MIXED:
  295. case TF_TYPE:
  296. type_dumpDBG_name(type);
  297. return;
  298. case TF_STRUCT:
  299. type_dumpDBG_name(type);
  300. printf("{");
  301. type_dumpDBG_list(type->u.ustruct.fields, type->u.ustruct.nfields, ";");
  302. printf("}");
  303. return;
  304. case TF_CLASS:
  305. type_dumpDBG_name(type);
  306. if(type->u.uclass.ninherits)
  307. {
  308. printf(":");
  309. type_dumpDBG_list(type->u.uclass.inherits, type->u.uclass.ninherits, ",");
  310. }
  311. printf("{");
  312. type_dumpDBG_list(type->u.uclass.fields, type->u.uclass.nfields, ";");
  313. printf("}");
  314. return;
  315. }
  316. assert(0);
  317. }