|
|
@@ -6,10 +6,10 @@ typedef enum { |
|
|
|
|
|
|
|
|
struct Environment { |
|
|
struct Environment { |
|
|
struct Environment* parent; |
|
|
struct Environment* parent; |
|
|
Environment_Type type; |
|
|
|
|
|
|
|
|
Environment_Type type; |
|
|
|
|
|
|
|
|
int capacity; |
|
|
|
|
|
int next_index; |
|
|
|
|
|
|
|
|
int capacity; |
|
|
|
|
|
int next_index; |
|
|
// TODO(Felix): Use a hashmap here. |
|
|
// TODO(Felix): Use a hashmap here. |
|
|
char** keys; |
|
|
char** keys; |
|
|
Ast_Node** values; |
|
|
Ast_Node** values; |
|
|
@@ -22,12 +22,12 @@ Environment* create_child_environment(Environment* parent, Environment_Type type |
|
|
|
|
|
|
|
|
int start_capacity = 16; |
|
|
int start_capacity = 16; |
|
|
|
|
|
|
|
|
env->type = type; |
|
|
|
|
|
env->parent = parent; |
|
|
|
|
|
|
|
|
env->type = type; |
|
|
|
|
|
env->parent = parent; |
|
|
env->capacity = start_capacity; |
|
|
env->capacity = start_capacity; |
|
|
env->next_index = 0; |
|
|
env->next_index = 0; |
|
|
env->keys = (char**)malloc(start_capacity * sizeof(char*)); |
|
|
|
|
|
env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*)); |
|
|
|
|
|
|
|
|
env->keys = (char**)malloc(start_capacity * sizeof(char*)); |
|
|
|
|
|
env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*)); |
|
|
|
|
|
|
|
|
return env; |
|
|
return env; |
|
|
} |
|
|
} |
|
|
@@ -38,12 +38,12 @@ Environment* create_empty_environment(Environment_Type type) { |
|
|
|
|
|
|
|
|
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
if (env->type == Environment_Type_Macro) { |
|
|
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): 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 |
|
|
// NOTE(Felix): right now we are simply adding the symol at the |
|
|
@@ -52,9 +52,9 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
// latest defined one first, but a bit messy. Later we should use |
|
|
// latest defined one first, but a bit messy. Later we should use |
|
|
// a hashmap here. @refactor |
|
|
// a hashmap here. @refactor |
|
|
if (env->next_index == env->capacity) { |
|
|
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->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->keys [env->next_index] = symbol->value.symbol->identifier; |
|
|
@@ -64,8 +64,8 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
|
|
|
|
|
|
void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { |
|
|
if (env->type != Environment_Type_Macro) { |
|
|
if (env->type != Environment_Type_Macro) { |
|
|
create_error(Error_Type_Unknown_Error, symbol); |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
create_error(Error_Type_Unknown_Error, symbol); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
env->type = Environment_Type_Lambda; |
|
|
env->type = Environment_Type_Lambda; |
|
|
@@ -77,19 +77,19 @@ void print_environment(Environment* env); |
|
|
|
|
|
|
|
|
Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) { |
|
|
Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) { |
|
|
for (int i = env->next_index - 1; i >= 0; --i) |
|
|
for (int i = env->next_index - 1; i >= 0; --i) |
|
|
if (string_equal(env->keys[i], sym->identifier)) |
|
|
|
|
|
return env->values[i]; |
|
|
|
|
|
|
|
|
if (string_equal(env->keys[i], sym->identifier)) |
|
|
|
|
|
return env->values[i]; |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) { |
|
|
Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) { |
|
|
Ast_Node* result; |
|
|
Ast_Node* result; |
|
|
do { |
|
|
do { |
|
|
if (env->type != Environment_Type_Lambda) { |
|
|
|
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
|
|
|
if (result) return result; |
|
|
|
|
|
} |
|
|
|
|
|
env = env->parent; |
|
|
|
|
|
|
|
|
if (env->type != Environment_Type_Lambda) { |
|
|
|
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
|
|
|
if (result) return result; |
|
|
|
|
|
} |
|
|
|
|
|
env = env->parent; |
|
|
} while (env); |
|
|
} while (env); |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
} |
|
|
} |
|
|
@@ -97,22 +97,22 @@ Ast_Node* lookup_symbol_from_lambda_env(Symbol* sym, Environment* env) { |
|
|
Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) { |
|
|
Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) { |
|
|
Ast_Node* result; |
|
|
Ast_Node* result; |
|
|
do { |
|
|
do { |
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
|
|
|
if (result) return result; |
|
|
|
|
|
if (env->type == Environment_Type_Lambda) |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
|
|
|
if (result) return result; |
|
|
|
|
|
if (env->type == Environment_Type_Lambda) |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
env = env->parent; |
|
|
|
|
|
|
|
|
env = env->parent; |
|
|
} while (env); |
|
|
} while (env); |
|
|
|
|
|
|
|
|
if (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); |
|
|
|
|
|
|
|
|
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; |
|
|
return nullptr; |
|
|
@@ -123,29 +123,29 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { |
|
|
Ast_Node* result; |
|
|
Ast_Node* result; |
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
result = lookup_symbol_in_this_envt(sym, env); |
|
|
if (result) |
|
|
if (result) |
|
|
return result; |
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
|
if (env->parent) { |
|
|
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 (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")) { |
|
|
if (string_equal(sym->identifier, "nil")) { |
|
|
return create_ast_node_nil(); |
|
|
|
|
|
|
|
|
return create_ast_node_nil(); |
|
|
} |
|
|
} |
|
|
if (string_equal(sym->identifier, "t")) { |
|
|
if (string_equal(sym->identifier, "t")) { |
|
|
return create_ast_node_t(); |
|
|
|
|
|
|
|
|
return create_ast_node_t(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
result = create_ast_node_built_in_function(sym->identifier); |
|
|
result = create_ast_node_built_in_function(sym->identifier); |
|
|
if (result) |
|
|
if (result) |
|
|
return result; |
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
|
create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil()); |
|
|
create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil()); |
|
|
/* printf("%s\n", sym->identifier); */ |
|
|
/* printf("%s\n", sym->identifier); */ |
|
|
@@ -153,28 +153,28 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { |
|
|
} |
|
|
} |
|
|
void print_indent(int indent) { |
|
|
void print_indent(int indent) { |
|
|
for (int i = 0; i < indent; ++i) { |
|
|
for (int i = 0; i < indent; ++i) { |
|
|
printf(" "); |
|
|
|
|
|
|
|
|
printf(" "); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void print_environment_indent(Environment* env, int indent) { |
|
|
void print_environment_indent(Environment* env, int indent) { |
|
|
for (int i = 0; i < env->next_index; ++i) { |
|
|
for (int i = 0; i < env->next_index; ++i) { |
|
|
print_indent(indent); |
|
|
|
|
|
printf("%s -> ", env->keys[i]); |
|
|
|
|
|
print(env->values[i]); |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
print_indent(indent); |
|
|
|
|
|
printf("%s -> ", env->keys[i]); |
|
|
|
|
|
print(env->values[i]); |
|
|
|
|
|
printf("\n"); |
|
|
} |
|
|
} |
|
|
if (env->parent) { |
|
|
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); |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|