You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

185 lines
5.3 KiB

  1. typedef enum {
  2. Environment_Type_Let,
  3. Environment_Type_Lambda,
  4. Environment_Type_Macro,
  5. } Environment_Type;
  6. struct Environment {
  7. struct Environment* parent;
  8. Environment_Type type;
  9. int capacity;
  10. int next_index;
  11. // TODO(Felix): Use a hashmap here.
  12. char** keys;
  13. Ast_Node** values;
  14. };
  15. typedef struct Environment Environment;
  16. Environment* create_child_environment(Environment* parent, Environment_Type type) {
  17. Environment* env = new(Environment);
  18. int start_capacity = 16;
  19. env->type = type;
  20. env->parent = parent;
  21. env->capacity = start_capacity;
  22. env->next_index = 0;
  23. env->keys = (char**)malloc(start_capacity * sizeof(char*));
  24. env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*));
  25. return env;
  26. }
  27. Environment* create_empty_environment(Environment_Type type) {
  28. return create_child_environment(nullptr, type);
  29. }
  30. void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
  31. if (env->type == Environment_Type_Macro) {
  32. // NOTE(Felix): we know we have a parent because every
  33. // environment has a parent except the top level environment.
  34. // However the top level environment is not a let-environment,
  35. // so we would not land here
  36. define_symbol(symbol, value, env->parent);
  37. return;
  38. }
  39. // NOTE(Felix): right now we are simply adding the symol at the
  40. // back of the list without checking if it already exists but are
  41. // also searching for thesymbol from the back, so we will find the
  42. // latest defined one first, but a bit messy. Later we should use
  43. // a hashmap here. @refactor
  44. if (env->next_index == env->capacity) {
  45. env->capacity *= 2;
  46. env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
  47. env->values = (Ast_Node**)realloc(env->values, env->capacity * sizeof(Ast_Node*));
  48. }
  49. env->keys [env->next_index] = symbol->value.symbol->identifier;
  50. env->values[env->next_index] = value;
  51. ++env->next_index;
  52. }
  53. void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
  54. if (env->type != Environment_Type_Macro) {
  55. create_error(Error_Type_Unknown_Error, symbol);
  56. return;
  57. }
  58. env->type = Environment_Type_Lambda;
  59. define_symbol(symbol, value, env);
  60. env->type = Environment_Type_Macro;
  61. }
  62. void print_environment(Environment* env);
  63. Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) {
  64. for (int i = env->next_index - 1; i >= 0; --i)
  65. if (string_equal(env->keys[i], sym->identifier))
  66. return env->values[i];
  67. return nullptr;
  68. }
  69. Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) {
  70. Ast_Node* result;
  71. do {
  72. if (env->type != Environment_Type_Lambda) {
  73. result = lookup_symbol_in_this_envt(sym, env);
  74. if (result) return result;
  75. }
  76. env = env->parent;
  77. } while (env);
  78. return nullptr;
  79. }
  80. Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) {
  81. Ast_Node* result;
  82. do {
  83. result = lookup_symbol_in_this_envt(sym, env);
  84. if (result) return result;
  85. if (env->type == Environment_Type_Lambda)
  86. break;
  87. env = env->parent;
  88. } while (env);
  89. if (env) {
  90. do {
  91. if (env->type != Environment_Type_Lambda) {
  92. result = lookup_symbol_in_this_envt(sym, env);
  93. if (result) return result;
  94. }
  95. env = env->parent;
  96. } while (env);
  97. }
  98. return nullptr;
  99. }
  100. Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
  101. // first check current environment
  102. Ast_Node* result;
  103. result = lookup_symbol_in_this_envt(sym, env);
  104. if (result)
  105. return result;
  106. if (env->parent) {
  107. if (env->type == Environment_Type_Lambda) {
  108. result = lookup_symbol_from_lambda_env(sym, env->parent);
  109. } else {
  110. result = lookup_symbol_from_let_or_macro_env(sym, env->parent);
  111. }
  112. if (result)
  113. return result;
  114. }
  115. if (string_equal(sym->identifier, "nil")) {
  116. return create_ast_node_nil();
  117. }
  118. if (string_equal(sym->identifier, "t")) {
  119. return create_ast_node_t();
  120. }
  121. result = create_ast_node_built_in_function(sym->identifier);
  122. if (result)
  123. return result;
  124. create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil());
  125. /* printf("%s\n", sym->identifier); */
  126. return nullptr;
  127. }
  128. void print_indent(int indent) {
  129. for (int i = 0; i < indent; ++i) {
  130. printf(" ");
  131. }
  132. }
  133. void print_environment_indent(Environment* env, int indent) {
  134. for (int i = 0; i < env->next_index; ++i) {
  135. print_indent(indent);
  136. printf("%s -> ", env->keys[i]);
  137. print(env->values[i]);
  138. printf("\n");
  139. }
  140. if (env->parent) {
  141. print_indent(indent);
  142. printf("parent");
  143. if (env->parent->type == Environment_Type_Lambda)
  144. printf(" (lambda)");
  145. else if (env->parent->type == Environment_Type_Macro)
  146. printf(" (macro)");
  147. else if (env->parent->type == Environment_Type_Let)
  148. printf(" (let)");
  149. printf(":\n");
  150. print_environment_indent(env->parent, indent+4);
  151. }
  152. }
  153. void print_environment(Environment* env) {
  154. printf("\n=== Environment ===\n");
  155. print_environment_indent(env, 0);
  156. }