From dd2be2cb8713f6faa7c7a49abfaa7b95f70bc8b2 Mon Sep 17 00:00:00 2001 From: FelixBrendel Date: Sat, 6 Oct 2018 01:10:43 +0200 Subject: [PATCH] okay --- bin/test.lsp | 1 + build.bat | 2 +- src/env.c | 7 ++++--- src/error.c | 3 +++ src/eval.c | 9 ++++----- src/helpers.c | 35 ++++++++++++++++++++++++++++++++++- src/io.c | 7 ++++++- src/main.c | 47 ++++++++++++++++++++++++++++++++++++++--------- src/parse.c | 14 +++++++++++--- src/test.lsp | 13 ------------- todo.org | 13 ++++++------- 11 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 bin/test.lsp delete mode 100644 src/test.lsp diff --git a/bin/test.lsp b/bin/test.lsp new file mode 100644 index 0000000..f07f3dd --- /dev/null +++ b/bin/test.lsp @@ -0,0 +1 @@ +(/ (+ 1 (- 100 7 3)) 2) diff --git a/build.bat b/build.bat index 3b8fbf4..40d7812 100644 --- a/build.bat +++ b/build.bat @@ -19,7 +19,7 @@ if %errorlevel% == 0 ( move %exeName% ..\%binDir%\ > NUL pushd ..\%binDir% echo ---------- Running ---------- - call timecmd %exeName% + call timecmd %exeName% test.lsp del %exeName% /S /Q > NUL popd ) else ( diff --git a/src/env.c b/src/env.c index 654c008..c93fe4a 100644 --- a/src/env.c +++ b/src/env.c @@ -54,9 +54,10 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { } } - char* message; - asprintf(&message, "Symbol not defined: %s\n", sym->identifier); - panic(message); + create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil()); + /* char* message; */ + /* asprintf(&message, "Symbol not defined: %s\n", sym->identifier); */ + /* panic(message); */ return nullptr; } diff --git a/src/error.c b/src/error.c index 1e44324..764aab0 100644 --- a/src/error.c +++ b/src/error.c @@ -6,6 +6,7 @@ typedef enum { Error_Type_Not_A_Function, Error_Type_Not_Yet_Implemented, Error_Type_Syntax_Error, + Error_Type_Unexpected_Eof, Error_Type_Unknown_Error, } Error_Type; @@ -40,6 +41,8 @@ char* Error_Type_to_string(Error_Type type) { case Error_Type_Type_Missmatch: return "Type Missmatch"; case Error_Type_Not_Yet_Implemented: return "Not yet implemented"; case Error_Type_Syntax_Error: return "Syntax Error"; + case Error_Type_Unexpected_Eof: return "Unexpected EOF"; default: return "Unknown Error"; } } + diff --git a/src/eval.c b/src/eval.c index f7a8224..223d16d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -43,6 +43,8 @@ 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; \ } @@ -56,7 +58,6 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { case Ast_Node_Type_Number: case Ast_Node_Type_String: return node; - case Ast_Node_Type_Pair: { Ast_Node* operator = eval_expr(node->value.pair->first, env); Ast_Node* operands = node->value.pair->rest; @@ -81,9 +82,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { } else if (string_equal("if", operator_name)) { int operands_length = list_length(operands); if (operands_length != 2 && operands_length != 3) { - if (!error) - create_error(Error_Type_Wrong_Number_Of_Arguments, operands); - return nullptr; + report_error(Error_Type_Wrong_Number_Of_Arguments); } Ast_Node* condition = operands->value.pair->first; @@ -144,7 +143,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { } default: - report_error(Error_Type_Unknown_Error); + report_error(Error_Type_Not_A_Function); } #undef report_error } diff --git a/src/helpers.c b/src/helpers.c index bd29be9..08eea07 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -57,10 +57,11 @@ char* read_entire_file (char* filename) { } /* Allocate our buffer to that size. */ - fileContent = malloc(sizeof(char) * (bufsize)); + fileContent = malloc(sizeof(char) * (bufsize) +1); /* Read the entire file into memory. */ size_t newLen = fread(fileContent, sizeof(char), bufsize, fp); + fileContent[bufsize-1] = '\0'; if ( ferror( fp ) != 0 ) { fputs("Error reading file", stderr); } @@ -72,3 +73,35 @@ char* read_entire_file (char* filename) { return fileContent; /* Don't forget to call free() later! */ } + +char* read_line() { + char * line = malloc(100), * linep = line; + size_t lenmax = 100, len = lenmax; + int c; + + if(line == NULL) + return NULL; + + for(;;) { + c = fgetc(stdin); + if(c == EOF) + break; + + if(--len == 0) { + len = lenmax; + char * linen = realloc(linep, lenmax *= 2); + + if(linen == NULL) { + free(linep); + return NULL; + } + line = linen + (line - linep); + linep = linen; + } + + if((*line++ = c) == '\n') + break; + } + *line = '\0'; + return linep; +} diff --git a/src/io.c b/src/io.c index 6f76347..14672ef 100644 --- a/src/io.c +++ b/src/io.c @@ -77,9 +77,14 @@ void print(Ast_Node* node) { Ast_Node* head = node; printf("("); - while (1) { + // NOTE(Felix): We cold do a while true here, however in case + // we want to print a broken list (for logging the error) we + // should do mo checks. + while (head) { print(head->value.pair->first); head = head->value.pair->rest; + if (!head) + return; if (head->type != Ast_Node_Type_Pair) break; printf(" "); diff --git a/src/main.c b/src/main.c index 3343dd4..e6c4651 100644 --- a/src/main.c +++ b/src/main.c @@ -17,16 +17,45 @@ #include "./testing.c" int main (int argc, char *argv[]) { - /* if (argc > 1) { */ - /* char* fileContent = read_entire_file(argv[1]); */ - /* if (fileContent) { */ - /* printf("File: %s\n", fileContent); */ - /* } */ - /* } else { */ - /* printf("No source provided.\n"); */ - /* } */ + 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"); + } else { + printf("The file could not be read\n"); + } + } 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"); + } + } - run_all_tests(); return 0; } diff --git a/src/parse.c b/src/parse.c index 420b555..ca63f11 100644 --- a/src/parse.c +++ b/src/parse.c @@ -196,6 +196,11 @@ Ast_Node* parse_expression(char* text, int* index_in_text) { } eat_until_code(text, index_in_text); + if (text[(*index_in_text)] == '\0') { + create_error(Error_Type_Unexpected_Eof, expression); + return nullptr; + } + if (text[(*index_in_text)] == ')') { head->value.pair->rest = create_ast_node_nil(); @@ -237,8 +242,10 @@ Ast_Node_Array_List* parse_program(char* text) { while (text[index_in_text] != '\0') { switch (text[index_in_text]) { case '(': { - append_to_Ast_Node_Array_List( - program, parse_expression(text, &index_in_text)); + Ast_Node* parsed = parse_expression(text, &index_in_text); + if (error) + return nullptr; + append_to_Ast_Node_Array_List(program, parsed); } break; case ';': { eat_comment_line(text, &index_in_text); @@ -249,8 +256,9 @@ Ast_Node_Array_List* parse_program(char* text) { ++index_in_text; } break; default: - create_error(Error_Type_Syntax_Error, nullptr); /* syntax error */ + create_error(Error_Type_Syntax_Error, create_ast_node_nil()); + return nullptr; } } return program; diff --git a/src/test.lsp b/src/test.lsp deleted file mode 100644 index be768b8..0000000 --- a/src/test.lsp +++ /dev/null @@ -1,13 +0,0 @@ -(+ 1 (- 100 7) 3) - -(defun unpack (&rest args) - (car args)) -(unpack '(1 2)) - -(defun add (&rest args) - (if args - (+ (first args) - (apply 'add 'args))) - 0) - -(add 2 123 99) diff --git a/todo.org b/todo.org index 82915cf..a2cb9b1 100644 --- a/todo.org +++ b/todo.org @@ -15,9 +15,12 @@ ** DONE if CLOSED: [2018-09-18 Di 12:14] -** TODO and (short circuiting) -** TODO or -** TODO not +** DONE and (short circuiting) + CLOSED: [2018-10-05 Fr 22:21] +** DONE or + CLOSED: [2018-10-05 Fr 22:21] +** DONE not + CLOSED: [2018-10-05 Fr 22:21] #+begin_src emacs-lisp (not 1) ;; == (not . (1 . nil)) (not (expression 1 3)) ;; == (not . ((expression . (1 . (3 . nil))) . nil)) @@ -34,16 +37,12 @@ ** TODO load (import) ** TODO define - ** TODO lambda ** TODO progn - ** TODO eval ** TODO quote - ** TODO print ** TODO read - ** TODO help * Types