quote eval define print read

This commit is contained in:
FelixBrendel
2018-10-07 23:32:44 +02:00
parent dd2be2cb87
commit 905500ab98
13 changed files with 275 additions and 80 deletions
-3
View File
@@ -1,3 +0,0 @@
((c-mode . ((eval . (company-clang-set-prefix "main.c"))
(eval . (flycheck-mode 0))
(eval . (rainbow-mode 0)))))
+34 -12
View File
@@ -1,7 +1,8 @@
struct Environment {
struct Environment* parent;
int key_count;
int capacity;
int next_index;
char** keys;
Ast_Node* values;
};
@@ -11,16 +12,37 @@ typedef struct Environment Environment;
Environment* create_empty_environment() {
Environment* env = new(Environment);
env->parent = nullptr;
env->key_count = 0;
env->keys = nullptr;
env->values = nullptr;
int start_capacity = 1;
env->parent = nullptr;
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;
}
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
// NOTE(Felix): right now we are simmply 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;
}
Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
for (int i = 0; i < env->key_count; ++i)
for (int i = env->next_index - 1; i >= 0; --i)
if (string_equal(env->keys[i], sym->identifier))
return env->values+i;
@@ -30,19 +52,19 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
char* built_in_names[] = {
// Math stuff
"+", "-", "*", "/",
">", "<", "=",
">", "<", "=", "<=", ">=",
// Conditional stuff
"if", "and", "or", "not",
// Cons stuff
"first", "rest", "pair",
// rest
"load", "define",
"load", "define",
"lambda", "progn",
"eval", "quote",
"print", "read",
"help"
"eval", "quote",
"print", "read",
"help", "exit"
};
int built_in_count = 23;
int built_in_count = 26;
for (int i = 0; i < built_in_count; ++i) {
if (string_equal(built_in_names[i], sym->identifier)) {
+11 -8
View File
@@ -7,6 +7,8 @@ typedef enum {
Error_Type_Not_Yet_Implemented,
Error_Type_Syntax_Error,
Error_Type_Unexpected_Eof,
Error_Type_Unbalanced_Parenthesis,
Error_Type_Trailing_Garbage,
Error_Type_Unknown_Error,
} Error_Type;
@@ -34,15 +36,16 @@ void create_error(Error_Type type, Ast_Node* location) {
char* Error_Type_to_string(Error_Type type) {
switch (type) {
case Error_Type_Ill_Formed_List: return "Ill formed list";
case Error_Type_Not_A_Function: return "Not a function";
case Error_Type_Symbol_Not_Defined: return "Symbol not defined";
case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments";
case Error_Type_Type_Missmatch: return "Type Missmatch";
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
case Error_Type_Ill_Formed_List: return "Evaluation-error: Ill formed list";
case Error_Type_Not_A_Function: return "Evaluation-error: Not a function";
case Error_Type_Symbol_Not_Defined: return "Evaluation-error: Symbol not defined";
case Error_Type_Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
case Error_Type_Type_Missmatch: return "Evaluation-error: Type Missmatch";
case Error_Type_Not_Yet_Implemented: return "Evaluation-error: Not yet implemented";
case Error_Type_Trailing_Garbage: return "Evaluation-error: Trailing garbage following expression";
case Error_Type_Syntax_Error: return "Syntax Error";
case Error_Type_Unexpected_Eof: return "Unexpected EOF";
case Error_Type_Unexpected_Eof: return "Parsing-error: Unexpected EOF";
case Error_Type_Unbalanced_Parenthesis: return "Parsing-error: Unbalanced parenthesis";
default: return "Unknown Error";
}
}
+91 -8
View File
@@ -1,9 +1,5 @@
/* Ast_Node* apply_to_lambda () {} */
/* Ast_Node* apply_to_built_in (Ast_Node* function, Ast_Node* arguments) { */
/* } */
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
bool is_truthy (Ast_Node* expression, Environment* env);
@@ -43,10 +39,10 @@ void eval_operands(Ast_Node* operands, Environment* env) {
Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
#define report_error(_type) { \
create_error(_type, node); \
log_error(); \
exit(1); \
return nullptr; \
}
if (error)
return nullptr;
Ast_Node* ret = new(Ast_Node);
switch (node->type) {
@@ -56,31 +52,112 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Ast_Node_Type_Symbol:
return lookup_symbol(node->value.symbol, env);
case Ast_Node_Type_Number:
case Ast_Node_Type_Keyword:
case Ast_Node_Type_String:
return node;
case Ast_Node_Type_Pair: {
Ast_Node* operator = eval_expr(node->value.pair->first, env);
if (error) return nullptr;
Ast_Node* operands = node->value.pair->rest;
// check for built ins functions
if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier;
if (string_equal("quote", operator_name)) {
return node->value.pair->rest;
int operands_length = list_length(operands);
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
return operands->value.pair->first;
} else if (string_equal("eval", operator_name)) {
int operands_length = list_length(operands);
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
if (error) return nullptr;
return eval_expr(operands->value.pair->first, env);
} else if (string_equal("+", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
return built_in_add(operands);
} else if (string_equal("-", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
return built_in_substract(operands);
} else if (string_equal("*", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
return built_in_multiply(operands);
} else if (string_equal("/", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
return built_in_divide(operands);
} else if (string_equal("define", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
if (operands_length != 2) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
Ast_Node* symbol = operands->value.pair->first;
if (symbol->type != Ast_Node_Type_Symbol)
report_error(Error_Type_Type_Missmatch);
Ast_Node* value = operands->value.pair->rest->value.pair->first;
value = eval_expr(value, env);
define_symbol(symbol, value, env);
return value;
} else if (string_equal("exit", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
if (operands_length == 1) {
Ast_Node* error_code = operands->value.pair->first;
if (error_code->type != Ast_Node_Type_Number)
report_error(Error_Type_Type_Missmatch);
exit((int)error_code->value.number->value);
}
exit(0);
} else if (string_equal("print", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
eval_operands(operands, env);
if (error) return nullptr;
print(operands->value.pair->first);
printf("\n");
return operands->value.pair->first;
} else if (string_equal("read", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
if (operands_length == 1) {
eval_operands(operands, env);
if (error) return nullptr;
Ast_Node* prompt = operands->value.pair->first;
if (prompt->type == Ast_Node_Type_String)
printf("%s", prompt->value.string->value);
else
print(operands->value.pair->first);
}
char* line = read_line();
return create_ast_node_string(line, (int)strlen(line));
} else if (string_equal("if", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
if (operands_length != 2 && operands_length != 3) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
@@ -89,7 +166,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
Ast_Node* then_part = operands->value.pair->rest;
Ast_Node* else_part = then_part->value.pair->rest;
if (is_truthy(condition, env))
bool truthy = is_truthy(condition, env);
if (error) return nullptr;
if (truthy)
return eval_expr(then_part->value.pair->first, env);
else if (operands_length == 3)
return eval_expr(else_part->value.pair->first, env);
@@ -102,6 +181,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Ill_Formed_List);
}
result &= is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
operands = operands->value.pair->rest;
if (!result) return create_ast_node_nil();
@@ -116,6 +196,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Ill_Formed_List);
}
result |= is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
operands = operands->value.pair->rest;
if (result) return create_ast_node_number(1);;
@@ -129,6 +210,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
return nullptr;
}
bool truthy = is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
if (truthy)
return create_ast_node_nil();
return create_ast_node_number(1);
@@ -150,6 +232,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
bool is_truthy (Ast_Node* expression, Environment* env) {
Ast_Node* result = eval_expr(expression, env);
if (error) return false;
switch (result->type) {
case Ast_Node_Type_Nil: return false;
/* case Ast_Node_Type_Number: return result->value.number->value != 0; */
+52 -32
View File
@@ -16,46 +16,66 @@
#include "./eval.c"
#include "./testing.c"
int interprete_file (char* file_content) {
Ast_Node_Array_List* program = parse_program(file_content);
if (error) {
log_error();
return 1;
}
Environment* env = create_empty_environment();
Ast_Node* result = create_ast_node_nil();
for (int i = 0; i < program->next_index; ++i) {
result = eval_expr(program->data[i], env);
if (error) {
log_error();
return 1;
}
}
print(result);
printf("\n");
return 0;
}
int interprete_stdin () {
printf("Welcome to the lispy interpreter.\n");
char* line;
Environment* env = create_empty_environment();
Ast_Node* parsed, * evaluated;
while (true) {
printf(">");
line = read_line();
parsed = parse_single_expression(line);
if (error) {
log_error();
delete_error();
continue;
}
evaluated = eval_expr(parsed, env);
if (error) {
log_error();
delete_error();
continue;
}
print(evaluated);
printf("\n");
}
return 0;
}
int main (int argc, char *argv[]) {
if (argc > 1) {
char* fileContent = read_entire_file(argv[1]);
if (fileContent) {
Ast_Node_Array_List* program = parse_program(fileContent);
if (error) {
log_error();
exit(1);
}
Environment* env = create_empty_environment();
Ast_Node* result = create_ast_node_nil();
for (int i = 0; i < program->next_index; ++i) {
result = eval_expr(program->data[i], env);
if (error) {
log_error();
exit(1);
}
}
print(result);
printf("\n");
char* file_content = read_entire_file(argv[1]);
if (file_content) {
return interprete_file(file_content);
} else {
printf("The file could not be read\n");
return 1;
}
} else {
run_all_tests();
printf("Welcome to the lispy interpreter.\n");
char* line;
Environment* env = create_empty_environment();
Ast_Node* parsed, * evaluated;
while (true) {
printf(">");
line = read_line();
parsed = parse_single_expression(line);
evaluated = eval_expr(parsed, env);
print(evaluated);
printf("\n");
}
return interprete_stdin();
}
return 0;
}
+14 -8
View File
@@ -18,10 +18,8 @@ Ast_Node_Array_List* create_Ast_Node_Array_List() {
void append_to_Ast_Node_Array_List(Ast_Node_Array_List* list, Ast_Node* node) {
if (list->next_index == list->length) {
list->length *= 2;
list->data =
(Ast_Node**)realloc(list->data, list->length * sizeof(Ast_Node));
list->data = (Ast_Node**)realloc(list->data, list->length * sizeof(Ast_Node));
}
list->data[list->next_index++] = node;
}
@@ -231,7 +229,17 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
Ast_Node* parse_single_expression(char* text) {
int index_in_text = 0;
return parse_expression(text, &index_in_text);
Ast_Node* result;
eat_until_code(text, &index_in_text);
if (text[(index_in_text)] == '(')
result = parse_expression(text, &index_in_text);
else
result = parse_atom(text, &index_in_text);
eat_until_code(text, &index_in_text);
if (text[(index_in_text)] == '\0')
return result;
create_error(Error_Type_Trailing_Garbage, create_ast_node_nil());
return nullptr;
}
Ast_Node_Array_List* parse_program(char* text) {
@@ -247,13 +255,11 @@ Ast_Node_Array_List* parse_program(char* text) {
return nullptr;
append_to_Ast_Node_Array_List(program, parsed);
} break;
case ';': {
eat_comment_line(text, &index_in_text);
} break;
case ';':
case ' ':
case '\t':
case '\n': {
++index_in_text;
eat_until_code(text, &index_in_text);
} break;
default:
/* syntax error */