|
- typedef enum {
- Environment_Type_Let,
- Environment_Type_Lambda,
- Environment_Type_Macro,
- } Environment_Type;
-
- struct Environment {
- struct Environment* parent;
- Environment_Type type;
-
- int capacity;
- int next_index;
- // TODO(Felix): Use a hashmap here.
- char** keys;
- Ast_Node** values;
- };
-
- typedef struct Environment Environment;
-
- Environment* create_child_environment(Environment* parent, Environment_Type type) {
- Environment* env = new(Environment);
-
- int start_capacity = 16;
-
- env->type = type;
- env->parent = parent;
- env->capacity = start_capacity;
- env->next_index = 0;
- env->keys = (char**)malloc(start_capacity * sizeof(char*));
- env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*));
-
- return env;
- }
-
- Environment* create_empty_environment(Environment_Type type) {
- return create_child_environment(nullptr, type);
- }
-
- void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
- if (env->type == Environment_Type_Macro) {
- // NOTE(Felix): we know we have a parent because every
- // environment has a parent except the top level environment.
- // However the top level environment is not a let-environment,
- // so we would not land here
- define_symbol(symbol, value, env->parent);
- return;
- }
-
- // NOTE(Felix): right now we are simply adding the symol at the
- // back of the list without checking if it already exists but are
- // also searching for thesymbol from the back, so we will find the
- // latest defined one first, but a bit messy. Later we should use
- // a hashmap here. @refactor
- if (env->next_index == env->capacity) {
- env->capacity *= 2;
- env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
- env->values = (Ast_Node**)realloc(env->values, env->capacity * sizeof(Ast_Node*));
- }
-
- env->keys [env->next_index] = symbol->value.symbol->identifier;
- env->values[env->next_index] = value;
- ++env->next_index;
- }
-
- void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
- if (env->type != Environment_Type_Macro) {
- create_error(Error_Type_Unknown_Error, symbol);
- return;
- }
-
- env->type = Environment_Type_Lambda;
- define_symbol(symbol, value, env);
- env->type = Environment_Type_Macro;
- }
-
- void print_environment(Environment* env);
-
- Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) {
- for (int i = env->next_index - 1; i >= 0; --i)
- if (string_equal(env->keys[i], sym->identifier))
- return env->values[i];
- return nullptr;
- }
-
- Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) {
- Ast_Node* result;
- do {
- if (env->type != Environment_Type_Lambda) {
- result = lookup_symbol_in_this_envt(sym, env);
- if (result) return result;
- }
- env = env->parent;
- } while (env);
- return nullptr;
- }
-
- Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) {
- Ast_Node* result;
- do {
- result = lookup_symbol_in_this_envt(sym, env);
- if (result) return result;
- if (env->type == Environment_Type_Lambda)
- break;
-
- env = env->parent;
- } while (env);
-
- if (env) {
- do {
- if (env->type != Environment_Type_Lambda) {
- result = lookup_symbol_in_this_envt(sym, env);
- if (result) return result;
- }
- env = env->parent;
- } while (env);
- }
-
- return nullptr;
- }
-
- Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
- // first check current environment
- Ast_Node* result;
- result = lookup_symbol_in_this_envt(sym, env);
- if (result)
- return result;
-
- if (env->parent) {
- if (env->type == Environment_Type_Lambda) {
- result = lookup_symbol_from_lambda_env(sym, env->parent);
- } else {
- result = lookup_symbol_from_let_or_macro_env(sym, env->parent);
- }
-
- if (result)
- return result;
- }
-
- if (string_equal(sym->identifier, "nil")) {
- return create_ast_node_nil();
- }
- if (string_equal(sym->identifier, "t")) {
- return create_ast_node_t();
- }
-
- result = create_ast_node_built_in_function(sym->identifier);
- if (result)
- return result;
-
- create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil());
- /* printf("%s\n", sym->identifier); */
- return nullptr;
- }
- void print_indent(int indent) {
- for (int i = 0; i < indent; ++i) {
- printf(" ");
- }
- }
-
- void print_environment_indent(Environment* env, int indent) {
- for (int i = 0; i < env->next_index; ++i) {
- print_indent(indent);
- printf("%s -> ", env->keys[i]);
- print(env->values[i]);
- printf("\n");
- }
- if (env->parent) {
- print_indent(indent);
- printf("parent");
- if (env->parent->type == Environment_Type_Lambda)
- printf(" (lambda)");
- else if (env->parent->type == Environment_Type_Macro)
- printf(" (macro)");
- else if (env->parent->type == Environment_Type_Let)
- printf(" (let)");
- printf(":\n");
- print_environment_indent(env->parent, indent+4);
- }
- }
-
- void print_environment(Environment* env) {
- printf("\n=== Environment ===\n");
- print_environment_indent(env, 0);
- }
|