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

127 строки
3.9 KiB

  1. namespace Slime {
  2. proc define_symbol(Lisp_Object* symbol, Lisp_Object* value) -> void {
  3. profile_with_comment(&symbol->value.symbol->data);
  4. Environment* env = get_current_environment();
  5. env->hm.set_object((void*)symbol, value);
  6. }
  7. inline proc lookup_symbol_in_this_envt(Lisp_Object* sym, Environment* env) -> Lisp_Object* {
  8. return (Lisp_Object*)env->hm.get_object((void*)sym);
  9. }
  10. proc environment_binds_symbol(Lisp_Object* sym, Environment* env) -> bool {
  11. return lookup_symbol_in_this_envt(sym, env) != nullptr;
  12. }
  13. proc find_binding_environment(Lisp_Object* sym, Environment* env) -> Environment* {
  14. if (environment_binds_symbol(sym, env))
  15. return env;
  16. for (auto it : env->parents) {
  17. if (Environment* ret = find_binding_environment(sym, it))
  18. return ret;
  19. }
  20. return nullptr;
  21. }
  22. proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  23. // first check current environment
  24. Lisp_Object* result;
  25. result = lookup_symbol_in_this_envt(node, env);
  26. if (result)
  27. return result;
  28. for (int i = 0; i < env->parents.next_index; ++i) {
  29. result = try_lookup_symbol(node, env->parents.data[i]);
  30. if (result)
  31. return result;
  32. }
  33. auto nil_sym = Memory::get_symbol("nil");
  34. auto t_sym = Memory::get_symbol("t");
  35. if (node == nil_sym) {
  36. return Memory::nil;
  37. }
  38. if (node == t_sym) {
  39. return Memory::t;
  40. }
  41. return nullptr;
  42. }
  43. inline proc push_environment(Environment* env) -> void {
  44. using namespace Globals::Current_Execution;
  45. envi_stack.append(env);
  46. }
  47. inline proc pop_environment() -> void {
  48. using namespace Globals::Current_Execution;
  49. --envi_stack.next_index;
  50. }
  51. inline proc get_root_environment() -> Environment* {
  52. using namespace Globals::Current_Execution;
  53. return envi_stack.data[0];
  54. }
  55. inline proc get_current_environment() -> Environment* {
  56. using namespace Globals::Current_Execution;
  57. return envi_stack.data[envi_stack.next_index-1];
  58. }
  59. proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  60. profile_with_comment(&node->value.symbol->data);
  61. // print(node);
  62. assert_type(node, Lisp_Object_Type::Symbol);
  63. Lisp_Object* result = try_lookup_symbol(node, env);
  64. if (result)
  65. return result;
  66. String* identifier = node->value.symbol;
  67. print_environment(env);
  68. printf("\n");
  69. create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data);
  70. return nullptr;
  71. }
  72. proc print_environment_indent(Environment* env, int indent) -> void {
  73. proc print_indent = [](int indent) {
  74. for (int i = 0; i < indent; ++i) {
  75. printf(" ");
  76. }
  77. };
  78. if(env == get_root_environment()) {
  79. print_indent(indent);
  80. printf("[built-ins]-Environment (%lld)\n", (long long)env);
  81. return;
  82. }
  83. for_hash_map (env->hm) {
  84. print_indent(indent);
  85. printf("-> %s :: ", &(((Lisp_Object*)key)->value.symbol->data));
  86. print((Lisp_Object*)value);
  87. printf(" (0x%016llx)", (unsigned long long)value);
  88. puts("");
  89. }
  90. for (int i = 0; i < env->parents.next_index; ++i) {
  91. print_indent(indent);
  92. printf("parent (0x%016llx)", (long long)env->parents.data[i]);
  93. puts(":");
  94. print_environment_indent(env->parents.data[i], indent+4);
  95. }
  96. }
  97. proc print_environment(Environment* env) -> void {
  98. printf("\n=== Environment === (0x%016llx)\n", (long long)env);
  99. print_environment_indent(env, 0);
  100. }
  101. }