Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

509 строки
17 KiB

  1. namespace Memory {
  2. // ------------------
  3. // global symbol / keyword table
  4. // ------------------
  5. String_Hash_Map* global_symbol_table;
  6. String_Hash_Map* global_keyword_table;
  7. // ------------------
  8. // lisp_objects
  9. // ------------------
  10. int object_memory_size;
  11. Int_Array_List free_spots_in_object_memory;
  12. Lisp_Object* object_memory;
  13. int next_index_in_object_memory = 0;
  14. // ------------------
  15. // environments
  16. // ------------------
  17. int environment_memory_size;
  18. Environment_Array_List free_spots_in_environment_memory;
  19. Environment* environment_memory;
  20. int next_index_in_environment_memory = 0;
  21. // ------------------
  22. // strings
  23. // ------------------
  24. int string_memory_size; // = 4096 * 1024; // == 98304kb == 96mb
  25. // free_spots_in_string_memory is an arraylist of pointers into
  26. // the string_memory, where dead String objects live (which give
  27. // information about their size)
  28. Void_Ptr_Array_List free_spots_in_string_memory;
  29. String* string_memory;
  30. String* next_free_spot_in_string_memory;
  31. // ------------------
  32. // immutables
  33. // ------------------
  34. Lisp_Object* nil = nullptr;
  35. Lisp_Object* t = nullptr;
  36. proc print_status() {
  37. printf("Memory Status:\n"
  38. " - %f%% of the object_memory is used\n"
  39. " - %d of %d total Lisp_Objects are in use\n"
  40. " - %d holes in used memory (fragmentation)\n",
  41. (1.0*next_index_in_object_memory - free_spots_in_object_memory.next_index)/object_memory_size,
  42. next_index_in_object_memory - free_spots_in_object_memory.next_index, object_memory_size,
  43. free_spots_in_object_memory.next_index);
  44. printf("Memory Status:\n"
  45. " - %f%% of the string_memory is used\n"
  46. " - %d holes in used memory (fragmentation)\n",
  47. (1.0*(size_t)next_free_spot_in_string_memory - (size_t)string_memory)/string_memory_size,
  48. free_spots_in_string_memory.next_index);
  49. }
  50. inline proc get_c_str(String* str) -> char* {
  51. return &str->data;
  52. }
  53. inline proc get_c_str(Lisp_Object* str) -> char* {
  54. assert_type(str, Lisp_Object_Type::String);
  55. return get_c_str(str->value.string);
  56. }
  57. inline proc get_type(Lisp_Object* node) -> Lisp_Object_Type {
  58. // the type is in the bits 0 to 5 (including)
  59. return (Lisp_Object_Type) ((u64)node->flags & (u64)0b11111);
  60. }
  61. inline proc set_type(Lisp_Object* node, Lisp_Object_Type type) {
  62. // the type is in the bits 0 to 5 (including)
  63. u64 bitmask = (u64)-1;
  64. bitmask -= 0b11111;
  65. bitmask += (u64) type;
  66. node->flags = (u64)(node->flags) | bitmask;
  67. }
  68. proc hash(String* str) -> u64 {
  69. // TODO(Felix): When parsing symbols or keywords, compute the
  70. // hash while reading them in.
  71. u64 value = str->data << 7;
  72. for (int i = 1; i < str->length; ++i) {
  73. char c = ((char*)&str->data)[i];
  74. value = (1000003 * value) ^ c;
  75. }
  76. value ^= str->length;
  77. return value;
  78. }
  79. proc create_string(const char* str, int len) -> String* {
  80. // TODO(Felix): check the holes first, not just always append
  81. // at the end
  82. String* ret = next_free_spot_in_string_memory;
  83. ret->length = len;
  84. strcpy(&ret->data, str);
  85. // now update the next_free_spot_in_string_memory pointer:
  86. // overstrep the counter and the first char (thik of it as if
  87. // we were overstepping the last ('\0') char) and then we only
  88. // need to overstep 'len' more chars
  89. next_free_spot_in_string_memory += 1;
  90. // overstep the other chars
  91. next_free_spot_in_string_memory = ((String*)((char*)next_free_spot_in_string_memory)+len);
  92. return ret;
  93. }
  94. proc delete_string(String* str) {
  95. append_to_array_list(&free_spots_in_string_memory, (void*)str);
  96. }
  97. proc duplicate_string(String* str) -> String* {
  98. return create_string(get_c_str(str), str->length);
  99. }
  100. proc create_string (const char* str) -> String* {
  101. return create_string(str, (int)strlen(str));
  102. }
  103. // proc create_string_formatted (const char* format, ...) -> String* {
  104. // // HACK(Felix): the length of all strings is 200!!!!!!!!!!
  105. // // HACK(Felix): the length of all strings is 200!!!!!!!!!!
  106. // int length = 200;
  107. // String* ret = create_string("", length);
  108. // int written_length;
  109. // va_list args;
  110. // va_start(args, format);
  111. // written_length = vsnprintf(&ret->data, length, format, args);
  112. // va_end(args);
  113. // ret->length = written_length;
  114. // return ret;
  115. // }
  116. proc create_lisp_object() -> Lisp_Object* {
  117. int index;
  118. // if we have no free spots then append at the end
  119. if (free_spots_in_object_memory.next_index == 0) {
  120. // if we still have space
  121. if (object_memory_size == next_index_in_object_memory) {
  122. create_out_of_memory_error(
  123. "There is not enough space in the lisp object "
  124. "memory to allocate additional lisp objects. "
  125. "Maybe try increasing the Memory size when "
  126. "calling Memory::init()");
  127. return nullptr;
  128. }
  129. index = next_index_in_object_memory++;
  130. } else {
  131. // else fill a free spot, and remove the free spot
  132. index = free_spots_in_object_memory.data[free_spots_in_object_memory.next_index--];
  133. }
  134. Lisp_Object* object = object_memory+index;
  135. object->flags = 0;
  136. object->sourceCodeLocation = nullptr;
  137. object->userType = nullptr;
  138. object->docstring = nullptr;
  139. return object;
  140. }
  141. proc free_everything() {
  142. free(global_symbol_table);
  143. free(global_keyword_table);
  144. free(object_memory);
  145. free(environment_memory);
  146. free(string_memory);
  147. }
  148. proc init(int oms, int ems, int sms) {
  149. global_symbol_table = create_String_hashmap();
  150. global_keyword_table = create_String_hashmap();
  151. object_memory_size = oms;
  152. environment_memory_size = ems;
  153. string_memory_size = sms;
  154. free_spots_in_object_memory = create_Int_array_list();
  155. free_spots_in_environment_memory = create_Environment_array_list();
  156. free_spots_in_string_memory = create_Void_Ptr_array_list();
  157. object_memory = (Lisp_Object*)malloc(object_memory_size * sizeof(Lisp_Object));
  158. environment_memory = (Environment*)malloc(environment_memory_size * sizeof(Environment));
  159. string_memory = (String*)malloc(string_memory_size * sizeof(char));
  160. next_free_spot_in_string_memory = string_memory;
  161. // init nil
  162. try_void nil = create_lisp_object();
  163. set_type(nil, Lisp_Object_Type::Nil);
  164. // init t
  165. try_void t = create_lisp_object();
  166. set_type(t, Lisp_Object_Type::T);
  167. try_void Parser::standard_in = create_string("stdin");
  168. Globals::Current_Execution::envi_stack.next_index = 0;
  169. push_environment(create_built_ins_environment());
  170. }
  171. proc reset() -> void {
  172. free_spots_in_object_memory.next_index = 0;
  173. free_spots_in_environment_memory.next_index = 0;
  174. free_spots_in_string_memory.next_index = 0;
  175. global_symbol_table = create_String_hashmap();
  176. global_keyword_table = create_String_hashmap();
  177. try_void Parser::standard_in = create_string("stdin");
  178. // because t and nil are always there we start the index at 2
  179. next_index_in_object_memory = 2;
  180. next_index_in_environment_memory = 0;
  181. next_free_spot_in_string_memory = string_memory;
  182. Globals::Current_Execution::envi_stack.next_index = 0;
  183. push_environment(create_built_ins_environment());
  184. }
  185. proc create_lisp_object_pointer(void* ptr) -> Lisp_Object* {
  186. Lisp_Object* node;
  187. try node = create_lisp_object();
  188. set_type(node, Lisp_Object_Type::Pointer);
  189. node->value.pointer = ptr;
  190. return node;
  191. }
  192. proc create_lisp_object_hash_map() -> Lisp_Object* {
  193. Lisp_Object* node;
  194. try node = create_lisp_object();
  195. set_type(node, Lisp_Object_Type::HashMap);
  196. node->value.hashMap = create_Lisp_Obj_hashmap();
  197. return node;
  198. }
  199. proc create_lisp_object_number(double number) -> Lisp_Object* {
  200. Lisp_Object* node;
  201. try node = create_lisp_object();
  202. set_type(node, Lisp_Object_Type::Number);
  203. node->value.number = number;
  204. return node;
  205. }
  206. proc create_lisp_object_string(String* str) -> Lisp_Object* {
  207. Lisp_Object* node;
  208. try node = create_lisp_object();
  209. set_type(node, Lisp_Object_Type::String);
  210. node->value.string = str;
  211. return node;
  212. }
  213. proc create_lisp_object_string(const char* str) -> Lisp_Object* {
  214. Lisp_Object* node;
  215. try node = create_lisp_object();
  216. set_type(node, Lisp_Object_Type::String);
  217. node->value.string = create_string(str);
  218. return node;
  219. }
  220. proc allocate_vector(int size) -> Lisp_Object* {
  221. // NOTE(Felix): Vectors are now only allocated at the back of
  222. // the memory, we don't check the free list at all right now
  223. if (object_memory_size - next_index_in_object_memory < size) {
  224. create_out_of_memory_error(
  225. "There is not enough space in the lisp object "
  226. "memory to allocate additional lisp objects. "
  227. "Maybe try increasing the Memory size when "
  228. "calling Memory::init()");
  229. return nullptr;
  230. }
  231. int start = next_index_in_object_memory;
  232. next_index_in_object_memory += size;
  233. return object_memory+start;
  234. }
  235. proc create_lisp_object_vector(int length, Lisp_Object* element_list) -> Lisp_Object* {
  236. try assert_type(element_list, Lisp_Object_Type::Pair);
  237. Lisp_Object* node;
  238. try node = create_lisp_object();
  239. set_type(node, Lisp_Object_Type::Vector);
  240. node->value.vector.length = length;
  241. try node->value.vector.data = allocate_vector(length);
  242. Lisp_Object* head = element_list;
  243. int i = 0;
  244. while (head != Memory::nil) {
  245. node->value.vector.data[i] = *head->value.pair.first;
  246. head = head->value.pair.rest;
  247. ++i;
  248. }
  249. return node;
  250. }
  251. proc create_new_lisp_object_symbol(String* identifier) -> Lisp_Object* {
  252. Lisp_Object* node;
  253. try node = create_lisp_object();
  254. set_type(node, Lisp_Object_Type::Symbol);
  255. node->value.symbol.identifier = identifier;
  256. node->value.symbol.hash = hash(identifier);
  257. hm_set(global_symbol_table, get_c_str(identifier), node);
  258. return node;
  259. }
  260. proc create_new_lisp_object_keyword(String* keyword) -> Lisp_Object* {
  261. Lisp_Object* node;
  262. try node = create_lisp_object();
  263. set_type(node, Lisp_Object_Type::Keyword);
  264. node->value.symbol.identifier = keyword;
  265. node->value.symbol.hash = hash(keyword);
  266. hm_set(global_keyword_table, get_c_str(keyword), node);
  267. return node;
  268. }
  269. proc get_or_create_lisp_object_symbol(String* identifier) -> Lisp_Object* {
  270. if (auto ret = hm_get_object(global_symbol_table, get_c_str(identifier)))
  271. return (Lisp_Object*)ret;
  272. else
  273. return create_new_lisp_object_symbol(identifier);
  274. }
  275. proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* {
  276. if (auto ret = hm_get_object(global_symbol_table, (char*)identifier))
  277. return (Lisp_Object*)ret;
  278. else {
  279. String* str;
  280. try str = Memory::create_string(identifier);
  281. return create_new_lisp_object_symbol(str);
  282. }
  283. }
  284. proc get_or_create_lisp_object_keyword(String* keyword) -> Lisp_Object* {
  285. if (auto ret = hm_get_object(global_keyword_table, get_c_str(keyword)))
  286. return (Lisp_Object*)ret;
  287. else
  288. return create_new_lisp_object_keyword(keyword);
  289. }
  290. proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* {
  291. if (auto ret = hm_get_object(global_keyword_table, (char*)keyword))
  292. return (Lisp_Object*)ret;
  293. else {
  294. String* str;
  295. try str = Memory::create_string(keyword);
  296. return create_new_lisp_object_keyword(str);
  297. }
  298. }
  299. proc create_lisp_object_cfunction(bool is_special) -> Lisp_Object* {
  300. Lisp_Object* node;
  301. try node = create_lisp_object();
  302. set_type(node, Lisp_Object_Type::CFunction);
  303. // node->value.lambdaWrapper = new Lambda_Wrapper(function);
  304. node->value.cFunction = new(cFunction);
  305. node->value.cFunction->args = {};
  306. node->value.cFunction->is_special_form = is_special;
  307. return node;
  308. }
  309. proc create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) -> Lisp_Object* {
  310. Lisp_Object* node;
  311. try node = create_lisp_object();
  312. set_type(node, Lisp_Object_Type::Pair);
  313. // node->value.pair = new(Pair);
  314. node->value.pair.first = first;
  315. node->value.pair.rest = rest;
  316. return node;
  317. }
  318. proc copy_lisp_object(Lisp_Object* n) -> Lisp_Object* {
  319. // TODO(Felix): If argument is a list (pair), do a FULL copy,
  320. // we don't copy singleton objects
  321. if (n == Memory::nil || n == Memory::t ||
  322. Memory::get_type(n) == Lisp_Object_Type::Symbol ||
  323. Memory::get_type(n) == Lisp_Object_Type::Keyword)
  324. {
  325. return n;
  326. }
  327. Lisp_Object* target;
  328. try target = create_lisp_object();
  329. *target = *n;
  330. return target;
  331. }
  332. proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* {
  333. if (get_type(n) == Lisp_Object_Type::Pair)
  334. return n;
  335. return copy_lisp_object(n);
  336. }
  337. proc create_child_environment(Environment* parent) -> Environment* {
  338. Environment* env;
  339. // if we have no free spots then append at the end
  340. if (free_spots_in_environment_memory.next_index == 0) {
  341. int index;
  342. // if we still have space
  343. if (environment_memory_size == next_index_in_environment_memory) {
  344. create_out_of_memory_error(
  345. "There is not enough space in the environment "
  346. "memory to allocate additional environments. "
  347. "Maybe try increasing the Memory size when "
  348. "calling Memory::init()");
  349. return nullptr;
  350. }
  351. index = next_index_in_environment_memory++;
  352. env = environment_memory+index;
  353. } else {
  354. // else fill a free spot, and remove the free spot
  355. env = free_spots_in_environment_memory.data[--free_spots_in_environment_memory.next_index];
  356. }
  357. int start_capacity = 16;
  358. env->parents = create_Environment_array_list();
  359. if (parent)
  360. append_to_array_list(&env->parents, parent);
  361. env->hm = create_Void_Ptr_hashmap();
  362. return env;
  363. }
  364. proc create_empty_environment() -> Environment* {
  365. Environment* ret;
  366. try ret = create_child_environment(nullptr);
  367. return ret;
  368. }
  369. proc create_built_ins_environment() -> Environment* {
  370. Environment* ret;
  371. try ret = create_empty_environment();
  372. push_environment(ret);
  373. defer {
  374. pop_environment();
  375. };
  376. load_built_ins_into_environment();
  377. // save the current working directory
  378. //char* cwd = get_cwd();
  379. //defer {
  380. // change_cwd(cwd);
  381. // free(cwd);
  382. //};
  383. //// get the direction of the exe
  384. //char* exe_path = get_exe_dir();
  385. //change_cwd(exe_path);
  386. //free(exe_path);
  387. built_in_load(Memory::create_string("pre.slime"));
  388. return ret;
  389. }
  390. inline proc create_list(Lisp_Object* o1) -> Lisp_Object* {
  391. Lisp_Object* ret;
  392. try ret = create_lisp_object_pair(o1, nil);
  393. return ret;
  394. }
  395. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2) -> Lisp_Object* {
  396. Lisp_Object* ret;
  397. try ret = create_lisp_object_pair(o1, create_list(o2));
  398. return ret;
  399. }
  400. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3) -> Lisp_Object* {
  401. Lisp_Object* ret;
  402. try ret = create_lisp_object_pair(o1, create_list(o2, o3));
  403. return ret;
  404. }
  405. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4) -> Lisp_Object* {
  406. Lisp_Object* ret;
  407. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4));
  408. return ret;
  409. }
  410. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5) -> Lisp_Object* {
  411. Lisp_Object* ret;
  412. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4, o5));
  413. return ret;
  414. }
  415. inline proc create_list(Lisp_Object* o1, Lisp_Object* o2, Lisp_Object* o3, Lisp_Object* o4, Lisp_Object* o5, Lisp_Object* o6) -> Lisp_Object* {
  416. Lisp_Object* ret;
  417. try ret = create_lisp_object_pair(o1, create_list(o2, o3, o4, o5, o6));
  418. return ret;
  419. }
  420. }