Felix Brendel 7 лет назад
Родитель
Сommit
716b72ff0f
4 измененных файлов: 175 добавлений и 170 удалений
  1. +3
    -1
      build.sh
  2. +92
    -91
      src/built_ins.c
  3. +65
    -65
      src/env.c
  4. +15
    -13
      src/eval.c

+ 3
- 1
build.sh Просмотреть файл

@@ -2,5 +2,7 @@ clang src/main.c -g -o ./bin/slime --std=c99 || exit 1

echo ""
echo "--- Output Start ---"
./bin/slime
pushd bin
./slime
popd
echo "--- Output End ---"

+ 92
- 91
src/built_ins.c Просмотреть файл

@@ -2,39 +2,40 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env);

bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
if (n1 == n2)
return true;
return true;
if (n1->type != n2->type)
return false;
return false;

switch (n1->type) {
case Ast_Node_Type_Built_In_Function:
return n1->value.built_in_function->type
== n2->value.built_in_function->type;
return n1->value.built_in_function->type
== n2->value.built_in_function->type;
case Ast_Node_Type_Function:
// if they have the same pointer, true is
// returned a few lines above
return false;
// if they have the same pointer, true is
// returned a few lines above
return false;
case Ast_Node_Type_Keyword:
return string_equal(
n1->value.keyword->identifier,
n2->value.keyword->identifier);
return string_equal(
n1->value.keyword->identifier,
n2->value.keyword->identifier);
case Ast_Node_Type_T:
case Ast_Node_Type_Nil:
return true;
return true;
case Ast_Node_Type_Number:
return
n1->value.number->value ==
n2->value.number->value;
return
n1->value.number->value ==
n2->value.number->value;
case Ast_Node_Type_Pair:
create_error(Error_Type_Not_Yet_Implemented, n1);
return false;
create_error(Error_Type_Not_Yet_Implemented, n1);
return false;
case Ast_Node_Type_String:
return string_equal(
n1->value.string->value,
n2->value.string->value);
return string_equal(
n1->value.string->value,
n2->value.string->value);
case Ast_Node_Type_Symbol:
return string_equal(
n1->value.symbol->identifier,
n2->value.symbol->identifier);
return string_equal(
n1->value.symbol->identifier,
n2->value.symbol->identifier);
}

// we should never reach here
@@ -43,32 +44,32 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {

Ast_Node* built_in_equals(Ast_Node* operands) {
if (operands->type == Ast_Node_Type_Nil)
return create_ast_node_t();
return create_ast_node_t();

Ast_Node* first = operands->value.pair->first;

while (operands->type == Ast_Node_Type_Pair) {
if (!ast_node_equal(operands->value.pair->first, first))
return create_ast_node_nil();
operands = operands->value.pair->rest;
if (!ast_node_equal(operands->value.pair->first, first))
return create_ast_node_nil();
operands = operands->value.pair->rest;
}

return create_ast_node_t();
return create_ast_node_t();
}

Ast_Node* built_in_greater(Ast_Node* operands) {
double last_number = strtod("Inf", NULL);

while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

if (operands->value.pair->first->value.number->value >= last_number)
return create_ast_node_nil();
if (operands->value.pair->first->value.number->value >= last_number)
return create_ast_node_nil();

last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}

return create_ast_node_t();
@@ -78,15 +79,15 @@ Ast_Node* built_in_greater_equal(Ast_Node* operands) {
double last_number = strtod("Inf", NULL);

while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

if (operands->value.pair->first->value.number->value > last_number)
return create_ast_node_nil();
if (operands->value.pair->first->value.number->value > last_number)
return create_ast_node_nil();

last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}

return create_ast_node_t();
@@ -96,15 +97,15 @@ Ast_Node* built_in_less(Ast_Node* operands) {
double last_number = strtod("-Inf", NULL);

while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

if (operands->value.pair->first->value.number->value <= last_number)
return create_ast_node_nil();
if (operands->value.pair->first->value.number->value <= last_number)
return create_ast_node_nil();

last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}

return create_ast_node_t();
@@ -114,15 +115,15 @@ Ast_Node* built_in_less_equal(Ast_Node* operands) {
double last_number = strtod("-Inf", NULL);

while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

if (operands->value.pair->first->value.number->value < last_number)
return create_ast_node_nil();
if (operands->value.pair->first->value.number->value < last_number)
return create_ast_node_nil();

last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
last_number = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}

return create_ast_node_t();
@@ -131,11 +132,11 @@ Ast_Node* built_in_less_equal(Ast_Node* operands) {
Ast_Node* built_in_add(Ast_Node* operands) {
double sum = 0;
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
sum += operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
sum += operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}

return create_ast_node_number(sum);
@@ -143,54 +144,54 @@ Ast_Node* built_in_add(Ast_Node* operands) {

Ast_Node* built_in_substract(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double difference = operands->value.pair->first->value.number->value;

operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

difference -= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
difference -= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(difference);
}

Ast_Node* built_in_multiply(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double product = operands->value.pair->first->value.number->value;

operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

product *= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
product *= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(product);
}

Ast_Node* built_in_divide(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double quotient = operands->value.pair->first->value.number->value;

operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
}
return create_ast_node_number(quotient);
}
@@ -199,19 +200,19 @@ Ast_Node* built_in_divide(Ast_Node* operands) {
Ast_Node* built_in_load(char* file_name, Environment* env) {
char* file_content = read_entire_file(file_name);
if (file_content) {
Ast_Node* result = create_ast_node_nil();
Ast_Node_Array_List* program;
try {
program = parse_program(file_content);
}
for (int i = 0; i < program->next_index; ++i) {
try {
result = eval_expr(program->data[i], env);
}
}
return result;
Ast_Node* result = create_ast_node_nil();
Ast_Node_Array_List* program;
try {
program = parse_program(file_content);
}
for (int i = 0; i < program->next_index; ++i) {
try {
result = eval_expr(program->data[i], env);
}
}
return result;
} else {
create_error(Error_Type_Unknown_Error, create_ast_node_nil());
return nullptr;
create_error(Error_Type_Unknown_Error, create_ast_node_nil());
return nullptr;
}
}

+ 65
- 65
src/env.c Просмотреть файл

@@ -6,10 +6,10 @@ typedef enum {

struct Environment {
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.
char** keys;
Ast_Node** values;
@@ -22,12 +22,12 @@ Environment* create_child_environment(Environment* parent, Environment_Type type

int start_capacity = 16;

env->type = type;
env->parent = parent;
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*));
env->keys = (char**)malloc(start_capacity * sizeof(char*));
env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*));

return env;
}
@@ -38,12 +38,12 @@ Environment* create_empty_environment(Environment_Type 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): 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
@@ -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
// 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->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;
@@ -63,9 +63,9 @@ void define_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) {
create_error(Error_Type_Unknown_Error, symbol);
return;
if (env->type != Environment_Type_Macro) {
create_error(Error_Type_Unknown_Error, symbol);
return;
}

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) {
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;
}

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;
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;
}
@@ -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* result;
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);

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;
@@ -123,29 +123,29 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
Ast_Node* result;
result = lookup_symbol_in_this_envt(sym, env);
if (result)
return 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 (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();
return create_ast_node_nil();
}
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);
if (result)
return result;
return result;

create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil());
/* printf("%s\n", sym->identifier); */
@@ -153,28 +153,28 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
}
void print_indent(int indent) {
for (int i = 0; i < indent; ++i) {
printf(" ");
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");
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);
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);
}
}



+ 15
- 13
src/eval.c Просмотреть файл

@@ -139,20 +139,21 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E
}
}

eval_time:
Ast_Node* result;
eval_time: {
Ast_Node* result;

// don't have to check every time if it is macro environment or
// not
if (function->is_macro)
new_env->type = Environment_Type_Macro;
// don't have to check every time if it is macro environment or
// not
if (function->is_macro)
new_env->type = Environment_Type_Macro;

try {
result = eval_expr(function->body, new_env);
}
try {
result = eval_expr(function->body, new_env);
}

free(new_env);
return result;
free(new_env);
return result;
}
}

/*
@@ -433,8 +434,8 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
// just make sure type was not redefined and
// returns something that is not a keyword
if (type->type == Ast_Node_Type_Keyword &&
string_equal(type->value.keyword->identifier, "dynamic-function") ||
string_equal(type->value.keyword->identifier, "dynamic-macro"))
(string_equal(type->value.keyword->identifier, "dynamic-function") ||
string_equal(type->value.keyword->identifier, "dynamic-macro")))
{
Ast_Node* fun = eval_expr(arguments->value.pair->first, env);
printf("\nMacro? %s\n", (fun->value.function->is_macro) ? "yes" : "no");
@@ -866,6 +867,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
case Ast_Node_Type_Keyword: return create_ast_node_keyword("keyword");
case Ast_Node_Type_Nil: return create_ast_node_keyword("nil");
case Ast_Node_Type_T: return create_ast_node_keyword("t");
case Ast_Node_Type_Number: return create_ast_node_keyword("number");
case Ast_Node_Type_Pair: return create_ast_node_keyword("pair");
case Ast_Node_Type_String: return create_ast_node_keyword("string");


Загрузка…
Отмена
Сохранить