From 4c33538e8ac540004d50e79ef7e897e426c2952a Mon Sep 17 00:00:00 2001 From: Felix Brendel Date: Wed, 19 Sep 2018 01:50:33 +0900 Subject: [PATCH] added error types and stuff --- .dir-locals.el | 2 +- ast.c | 32 +++++++++++++-------------- built_ins.c | 50 ++++++++++++++++++++--------------------- error.c | 41 ++++++++++++++++++++++++++++++++-- eval.c | 60 +++++++++++++++++++++++++++----------------------- io.c | 54 +++++++++++++++++++++++---------------------- testing.c | 15 +++++-------- todo.org | 11 ++++++++- 8 files changed, 157 insertions(+), 108 deletions(-) diff --git a/.dir-locals.el b/.dir-locals.el index 1909c38..b470be0 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -1,2 +1,2 @@ -((nil . ((eval . (flycheck-mode 0)) +((c-mode . ((eval . (flycheck-mode 0)) (eval . (rainbow-mode 0))))) diff --git a/ast.c b/ast.c index b2c916f..2d25288 100644 --- a/ast.c +++ b/ast.c @@ -8,7 +8,7 @@ typedef enum { Ast_Node_Type_Number, Ast_Node_Type_String, - Ast_Node_Type_Cons_Cell, + Ast_Node_Type_Pair, Ast_Node_Type_Function, Ast_Node_Type_Built_In_Function, } Ast_Node_Type; @@ -32,16 +32,16 @@ typedef struct { typedef struct { struct Ast_Node* first; struct Ast_Node* rest; -} Cons_Cell; +} Pair; typedef struct { - Cons_Cell* regular_params; - Cons_Cell* keyword_params; + Pair* regular_params; + Pair* keyword_params; } Lambda_List; typedef struct { Lambda_List* parameters; - Cons_Cell* form; + Pair* form; } Function; typedef struct { @@ -51,12 +51,12 @@ typedef struct { struct Ast_Node { Ast_Node_Type type; union { - Symbol* symbol; - Keyword* keyword; - Number* number; - String* string; - Cons_Cell* cons_cell; - Function* function; + Symbol* symbol; + Keyword* keyword; + Number* number; + String* string; + Pair* pair; + Function* function; Built_In_Function* built_in_function; } value; }; @@ -67,7 +67,7 @@ typedef struct Ast_Node Ast_Node; Ast_Node* create_ast_node_nil() { Ast_Node* node = new(Ast_Node); node->type = Ast_Node_Type_Nil; - node->value.cons_cell = NULL; + node->value.pair = NULL; return node; } @@ -106,9 +106,9 @@ Ast_Node* create_ast_node_built_in_function(char* identifier) { Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) { Ast_Node* node = new(Ast_Node); - node->type = Ast_Node_Type_Cons_Cell; - node->value.cons_cell = new(Cons_Cell); - node->value.cons_cell->first = first; - node->value.cons_cell->rest = rest; + node->type = Ast_Node_Type_Pair; + node->value.pair = new(Pair); + node->value.pair->first = first; + node->value.pair->rest = rest; return node; } diff --git a/built_ins.c b/built_ins.c index c98c560..d7131af 100644 --- a/built_ins.c +++ b/built_ins.c @@ -1,52 +1,52 @@ Ast_Node* built_in_add(Ast_Node* operands) { double sum = 0; - while (operands->type == Ast_Node_Type_Cons_Cell) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); - sum += operands->value.cons_cell->first->value.number->value; - operands = operands->value.cons_cell->rest; + while (operands->type == Ast_Node_Type_Pair) { + 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); } Ast_Node* built_in_substract(Ast_Node* operands) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); - double difference = operands->value.cons_cell->first->value.number->value; + assert_type(operands->value.pair->first, Ast_Node_Type_Number); + double difference = operands->value.pair->first->value.number->value; - operands = operands->value.cons_cell->rest; - while (operands->type == Ast_Node_Type_Cons_Cell) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); + operands = operands->value.pair->rest; + while (operands->type == Ast_Node_Type_Pair) { + assert_type(operands->value.pair->first, Ast_Node_Type_Number); - difference -= operands->value.cons_cell->first->value.number->value; - operands = operands->value.cons_cell->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) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); - double product = operands->value.cons_cell->first->value.number->value; + assert_type(operands->value.pair->first, Ast_Node_Type_Number); + double product = operands->value.pair->first->value.number->value; - operands = operands->value.cons_cell->rest; - while (operands->type == Ast_Node_Type_Cons_Cell) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); + operands = operands->value.pair->rest; + while (operands->type == Ast_Node_Type_Pair) { + assert_type(operands->value.pair->first, Ast_Node_Type_Number); - product *= operands->value.cons_cell->first->value.number->value; - operands = operands->value.cons_cell->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) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); - double quotient = operands->value.cons_cell->first->value.number->value; + assert_type(operands->value.pair->first, Ast_Node_Type_Number); + double quotient = operands->value.pair->first->value.number->value; - operands = operands->value.cons_cell->rest; - while (operands->type == Ast_Node_Type_Cons_Cell) { - assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number); + operands = operands->value.pair->rest; + while (operands->type == Ast_Node_Type_Pair) { + assert_type(operands->value.pair->first, Ast_Node_Type_Number); - quotient /= operands->value.cons_cell->first->value.number->value; - operands = operands->value.cons_cell->rest; + quotient /= operands->value.pair->first->value.number->value; + operands = operands->value.pair->rest; } return create_ast_node_number(quotient); } diff --git a/error.c b/error.c index b3d49e3..078a754 100644 --- a/error.c +++ b/error.c @@ -1,6 +1,43 @@ +typedef enum { + Error_Type_Ill_Formed_List, + Error_Type_Wrong_Number_Of_Arguments, + Error_Type_Type_Missmatch, + Error_Type_Symbol_Not_Defined, + Error_Type_Not_A_Function, + Error_Type_Not_Yet_Implemented, + Error_Type_Unknown_Error, +} Error_Type; + typedef struct { - char* message; - Ast_Node* location; + Error_Type type; + Ast_Node* location; } Error; Error* error; + +void delete_error() { + if (error) { + free(error); + error = NULL; + } +} + +void create_error(Error_Type type, Ast_Node* location) { + delete_error(); + + error = new(Error); + error->type = type; + error->location = 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_Unknown_Error: return "Unknown Error"; + } +} diff --git a/eval.c b/eval.c index 4b3f5d9..02996c2 100644 --- a/eval.c +++ b/eval.c @@ -7,24 +7,29 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env); int is_truthy (Ast_Node* expression, Environment* env); +int list_length(Ast_Node* node) { + if (node->type != Ast_Node_Type_Pair) { + create_error(Error_Type_Type_Missmatch, node); + return 0; + } + + return 1; +} + void eval_operands(Ast_Node* operands, Environment* env) { while (!error) { - if (operands->type == Ast_Node_Type_Cons_Cell) { - operands->value.cons_cell->first = eval_expr(operands->value.cons_cell->first, env); - operands = operands->value.cons_cell->rest; + if (operands->type == Ast_Node_Type_Pair) { + operands->value.pair->first = eval_expr(operands->value.pair->first, env); + operands = operands->value.pair->rest; } else { return; } } - // if we reach here we got an error - log_error("An error occurred while evaluating operands to a function:"); } Ast_Node* eval_expr(Ast_Node* node, Environment* env) { -#define report_error(_message) \ - error = new(Error); \ - error->message = _message; \ - error->location = node; \ +#define report_error(_type) \ + create_error(_type, node); \ return NULL Ast_Node* ret = new(Ast_Node); @@ -38,15 +43,15 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { case Ast_Node_Type_String: return node; - case Ast_Node_Type_Cons_Cell: { - Ast_Node* operator = eval_expr(node->value.cons_cell->first, env); - Ast_Node* operands = node->value.cons_cell->rest; + case Ast_Node_Type_Pair: { + Ast_Node* operator = eval_expr(node->value.pair->first, env); + 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.cons_cell->rest; + return node->value.pair->rest; } else if (string_equal("+", operator_name)) { eval_operands(operands, env); return built_in_add(operands); @@ -60,25 +65,24 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { eval_operands(operands, env); return built_in_divide(operands); } else if (string_equal("if", operator_name)) { - if (Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->type || - Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->value.cons_cell->rest->type || - Ast_Node_Type_Nil != operands->value.cons_cell->rest->value.cons_cell->rest->value.cons_cell->rest->type) - { - report_error("Ill formed if statement"); + if (list_length(operands) != 3) { + report_error(Error_Type_Wrong_Number_Of_Arguments); } - Ast_Node* then_part = operands->value.cons_cell->rest; - Ast_Node* else_part = then_part->value.cons_cell->rest; + Ast_Node* condition = operands->value.pair->first; + Ast_Node* then_part = operands->value.pair->rest; + Ast_Node* else_part = then_part->value.pair->rest; - if (is_truthy(operands->value.cons_cell->first, env)) - return eval_expr(then_part->value.cons_cell->first, env); + if (is_truthy(condition, env)) + return eval_expr(then_part->value.pair->first, env); else - return eval_expr(else_part->value.cons_cell->first, env); - } else if (string_equal("not", operator_name)) { - } else if (string_equal("and", operator_name)) { - } else if (string_equal("or", operator_name)) { + return eval_expr(else_part->value.pair->first, env); + /* } else if (string_equal("not", operator_name)) { */ + + /* } else if (string_equal("and", operator_name)) { */ + /* } else if (string_equal("or", operator_name)) { */ } else { - report_error("The operator is not yet implemented"); + report_error(Error_Type_Not_Yet_Implemented); } } @@ -88,7 +92,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { } default: - report_error("Unknown error"); + report_error(Error_Type_Unknown_Error); } #undef report_error } diff --git a/io.c b/io.c index 6410d62..c8617e4 100644 --- a/io.c +++ b/io.c @@ -1,3 +1,8 @@ +#define console_normal "\x1B[0m" +#define console_red "\x1B[31m" +#define console_green "\x1B[32m" +#define console_cyan "\x1B[36m" + typedef enum { Log_Level_None, @@ -24,11 +29,6 @@ void log_message(Log_Level type, char* message) { printf("%s: %s\n",prefix, message); } -void log_error(char* message) { - log_message(Log_Level_Critical, message); - log_message(Log_Level_Critical, error->message); -} - void panic(char* message) { log_message(Log_Level_Critical, message); @@ -36,24 +36,16 @@ void panic(char* message) { } -char* Ast_Node_Type_to_string (Ast_Node_Type type) { +char* Ast_Node_Type_to_string(Ast_Node_Type type) { switch (type) { - case(Ast_Node_Type_Nil): - return "nil"; - case(Ast_Node_Type_Number): - return "number"; - case(Ast_Node_Type_String): - return "string"; - case(Ast_Node_Type_Symbol): - return "symbol"; - case(Ast_Node_Type_Keyword): - return "keyword"; - case(Ast_Node_Type_Function): - return "function"; - case(Ast_Node_Type_Built_In_Function): - return "built-in function"; - case(Ast_Node_Type_Cons_Cell): - return "pair"; + case(Ast_Node_Type_Nil): return "nil"; + case(Ast_Node_Type_Number): return "number"; + case(Ast_Node_Type_String): return "string"; + case(Ast_Node_Type_Symbol): return "symbol"; + case(Ast_Node_Type_Keyword): return "keyword"; + case(Ast_Node_Type_Function): return "function"; + case(Ast_Node_Type_Built_In_Function): return "built-in function"; + case(Ast_Node_Type_Pair): return "pair"; } } @@ -80,14 +72,14 @@ void print(Ast_Node* node) { case (Ast_Node_Type_Built_In_Function): { printf("[built-in-function %s]", node->value.built_in_function->identifier); } break; - case (Ast_Node_Type_Cons_Cell): { + case (Ast_Node_Type_Pair): { Ast_Node* head = node; printf("("); while (1) { - print(head->value.cons_cell->first); - head = head->value.cons_cell->rest; - if (head->type != Ast_Node_Type_Cons_Cell) + print(head->value.pair->first); + head = head->value.pair->rest; + if (head->type != Ast_Node_Type_Pair) break; printf(" "); } @@ -101,3 +93,13 @@ void print(Ast_Node* node) { } break; } } + + +void log_error() { + printf("\t%s%s%s\n", console_red, + Error_Type_to_string(error->type), + console_normal); + printf("\t in: %s", console_cyan); + print(error->location); + printf("%s\n", console_normal); +} diff --git a/testing.c b/testing.c index 9942060..711f17e 100644 --- a/testing.c +++ b/testing.c @@ -1,7 +1,3 @@ -#define console_normal "\x1B[0m" -#define console_red "\x1B[31m" -#define console_green "\x1B[32m" - #define epsilon 2.2204460492503131E-16 #define testresult int @@ -16,16 +12,18 @@ __FILE__, __LINE__, (type)value, (type)variable) #define print_assert_not_equal_fail(variable, value, type, format) \ - printf("\n\tAssertion failed for '" #variable "'" \ + printf("\n\tAssertion failed for '" #variable "'" \ "\n\t in %s:%d" \ "\n\texpected not: " format \ "\n\tgot anyways: " format "\n", \ __FILE__, __LINE__, (type)value, (type)variable) + /* print_assert_not_equal_fail(error, 0, int, "%d"); \ */ #define assert_no_error(error) \ if (error) { \ - print_assert_not_equal_fail(error, 0, int, "%d"); \ - printf("\t%s%s%s\n", console_red, error->message,console_normal); \ + printf("\n\tExpected no error to occur," \ + " but an error occured anyways:\n"); \ + log_error(); \ return fail; \ } \ @@ -63,13 +61,12 @@ #define invoke_test(name) \ printf("" #name ":"); \ for(int i = 0; i < 45 - strlen(#name); ++i) \ - printf(" "); \ + printf(" "); \ if (name() == pass) \ printf("%spassed%s\n", console_green, console_normal); \ else { \ printf("%sfailed%s\n", console_red, console_normal); \ if(error) { \ - log_error("Error while running test" #name); \ free(error); \ error = NULL; \ } \ diff --git a/todo.org b/todo.org index 177e31a..f23a0fc 100644 --- a/todo.org +++ b/todo.org @@ -14,9 +14,18 @@ ** DONE if CLOSED: [2018-09-18 Di 12:14] -** TODO and +** TODO and (short circuiting) ** TODO or ** TODO not +#+begin_src emacs-lisp +(not 1) ;; == (not . (1 . nil)) +(not (expression 1 3)) ;; == (not . ((expression . (1 . (3 . nil))) . nil)) +(not) ;; == (not . nil) +(not 1 2) ;; == (not . (1 . (2 . nil))) +#+end_src + +#+RESULTS: +: t ** TODO first (car) ** TODO rest (cdr)