Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

132 linhas
4.2 KiB

  1. proc define_symbol(Lisp_Object* symbol, Lisp_Object* value) -> void {
  2. // NOTE(Felix): right now we are simply adding the symol at the
  3. // back of the list without checking if it already exists but are
  4. // also searching for thesymbol from the back, so we will find the
  5. // latest defined one first, but a bit messy. Later we should use
  6. // a hashmap here. @refactor
  7. Environment* env = get_current_environment();
  8. if (env->next_index == env->capacity) {
  9. env->capacity *= 2;
  10. env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
  11. env->values = (Lisp_Object**)realloc(env->values, env->capacity * sizeof(Lisp_Object*));
  12. }
  13. env->keys [env->next_index] = Memory::get_c_str(symbol->value.symbol.identifier);
  14. env->values[env->next_index] = value;
  15. ++env->next_index;
  16. }
  17. proc lookup_symbol_in_this_envt(String* identifier, Environment* env) -> Lisp_Object* {
  18. for (int i = env->next_index - 1; i >= 0; --i)
  19. if (string_equal(env->keys[i], Memory::get_c_str(identifier)))
  20. return env->values[i];
  21. return nullptr;
  22. }
  23. proc environment_binds_symbol(String* identifier, Environment* env) -> bool {
  24. return lookup_symbol_in_this_envt(identifier, env) != nullptr;
  25. }
  26. proc find_binding_environment(String* identifier, Environment* env) -> Environment* {
  27. if (environment_binds_symbol(identifier, env))
  28. return env;
  29. for (int i = 0; i < env->parents.next_index; ++i) {
  30. if (environment_binds_symbol(identifier, env->parents.data[i]))
  31. return env->parents.data[i];
  32. }
  33. return get_root_environment();
  34. }
  35. proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  36. // first check current environment
  37. String* identifier = node->value.symbol.identifier;
  38. Lisp_Object* result;
  39. result = lookup_symbol_in_this_envt(identifier, env);
  40. if (result)
  41. return result;
  42. for (int i = 0; i < env->parents.next_index; ++i) {
  43. result = try_lookup_symbol(node, env->parents.data[i]);
  44. if (result)
  45. return result;
  46. }
  47. if (string_equal(Memory::get_c_str(identifier), "nil")) {
  48. return Memory::nil;
  49. }
  50. if (string_equal(Memory::get_c_str(identifier), "t")) {
  51. return Memory::t;
  52. }
  53. return nullptr;
  54. }
  55. inline proc push_environment(Environment* env) -> void {
  56. using namespace Globals::Current_Execution;
  57. append_to_array_list(&envi_stack, env);
  58. }
  59. inline proc pop_environment() -> void {
  60. using namespace Globals::Current_Execution;
  61. --envi_stack.next_index;
  62. }
  63. inline proc get_root_environment() -> Environment* {
  64. using namespace Globals::Current_Execution;
  65. return envi_stack.data[0];
  66. }
  67. inline proc get_current_environment() -> Environment* {
  68. using namespace Globals::Current_Execution;
  69. return envi_stack.data[envi_stack.next_index-1];
  70. }
  71. proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  72. assert_type(node, Lisp_Object_Type::Symbol);
  73. Lisp_Object* result = try_lookup_symbol(node, env);
  74. if (result)
  75. return result;
  76. String* identifier = node->value.symbol.identifier;
  77. create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data);
  78. print_environment(env);
  79. return nullptr;
  80. }
  81. proc print_indent(int indent) -> void {
  82. for (int i = 0; i < indent; ++i) {
  83. printf(" ");
  84. }
  85. }
  86. proc print_environment_indent(Environment* env, int indent) -> void {
  87. if(env == get_root_environment()) {
  88. print_indent(indent);
  89. printf("[built-ins]-Environment (%lld)\n", (long long)env);
  90. return;
  91. }
  92. for (int i = 0; i < env->next_index; ++i) {
  93. print_indent(indent);
  94. printf("-> %s :: ", env->keys[i]);
  95. print(env->values[i]);
  96. printf(" (%lld)", (long long)env->values[i]);
  97. puts("");
  98. }
  99. for (int i = 0; i < env->parents.next_index; ++i) {
  100. print_indent(indent);
  101. printf("parent (%lld)", (long long)env->parents.data[i]);
  102. puts(":");
  103. print_environment_indent(env->parents.data[i], indent+4);
  104. }
  105. }
  106. proc print_environment(Environment* env) -> void {
  107. printf("\n=== Environment === (%lld)\n", (long long)env);
  108. print_environment_indent(env, 0);
  109. }