| @@ -36,7 +36,7 @@ | |||
| (font-lock-add-keywords 'c++-mode | |||
| '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" . | |||
| font-lock-keyword-face))))))) | |||
| (c++-mode . ((eval . (company-clang-set-prefix "main.cpp")) | |||
| (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) | |||
| (eval . (flycheck-mode 0)) | |||
| (eval . (rainbow-mode 0)) | |||
| ))) | |||
| @@ -122,6 +122,48 @@ struct { | |||
| #define TOKENPASTE2(x, y) TOKENPASTE(x, y) | |||
| #define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&] | |||
| /* | |||
| Usage of the create_error_macros: | |||
| */ | |||
| #define __create_error(keyword, ...) \ | |||
| create_error( \ | |||
| __FILE__, __LINE__, \ | |||
| Memory::get_or_create_lisp_object_keyword(keyword), \ | |||
| __VA_ARGS__) | |||
| #define create_out_of_memory_error(...) \ | |||
| __create_error("out-of-memory", __VA_ARGS__) | |||
| #define create_generic_error(...) \ | |||
| __create_error("generic", __VA_ARGS__) | |||
| #define create_parsing_error(...) \ | |||
| __create_error("parsing-error", __VA_ARGS__) | |||
| #define create_symbol_undefined_error(...) \ | |||
| __create_error("symbol-undefined", __VA_ARGS__) | |||
| #define create_type_missmatch_error(expected, actual) \ | |||
| __create_error("type-missmatch", \ | |||
| "Type missmatch: expected %s, got %s", \ | |||
| expected, actual) | |||
| #define create_wrong_number_of_arguments_error(expected, actual) \ | |||
| __create_error("wrong-number-of-arguments", \ | |||
| "Wrong number of arguments: expected %d, got %d", \ | |||
| expected, actual) | |||
| #define assert_type(_node, _type) \ | |||
| do { \ | |||
| if (_node->type != _type) { \ | |||
| create_type_missmatch_error("symbol", Lisp_Object_Type_to_string(_node->type)); \ | |||
| return nullptr; \ | |||
| } \ | |||
| } while(0) | |||
| #define console_normal "\x1B[0m" | |||
| #define console_red "\x1B[31m" | |||
| #define console_green "\x1B[32m" | |||
| @@ -45,8 +45,8 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||
| return Memory::t; | |||
| } | |||
| printf("%s\n", Memory::get_c_str(identifier)); | |||
| create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | |||
| create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data); | |||
| return nullptr; | |||
| } | |||
| @@ -7,40 +7,69 @@ proc delete_error() -> void { | |||
| } | |||
| } | |||
| proc create_error(Error_Type type, Source_Code_Location* location) -> void { | |||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { | |||
| if_debug { | |||
| printf("Error created in:\n%s:%d\n", c_file_name, c_file_line); | |||
| } | |||
| delete_error(); | |||
| debug_break(); | |||
| error = new(Error); | |||
| error->type = type; | |||
| error->location = location; | |||
| error->message = message; | |||
| } | |||
| proc Error_Type_to_string(Error_Type type) -> const char* { | |||
| switch (type) { | |||
| case Error_Type::Assertion_Error: return "Assertion failed"; | |||
| case Error_Type::File_Not_Found: return "File not found"; | |||
| case Error_Type::Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments"; | |||
| case Error_Type::Ill_Formed_Lambda_List: return "Evaluation-error: Ill formed lambda list"; | |||
| 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::Not_Yet_Implemented: return "Evaluation-error: Not yet implemented"; | |||
| case Error_Type::Symbol_Not_Defined: return "Evaluation-error: Symbol not defined"; | |||
| case Error_Type::Syntax_Error: return "Syntax Error"; | |||
| case Error_Type::Trailing_Garbage: return "Evaluation-error: Trailing garbage following expression"; | |||
| case Error_Type::Type_Missmatch: return "Evaluation-error: Type Missmatch"; | |||
| case Error_Type::Unbalanced_Parenthesis: return "Parsing-error: Unbalanced parenthesis"; | |||
| case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF"; | |||
| case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument"; | |||
| case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments"; | |||
| case Error_Type::Out_Of_Memory: return "Runtime-error: Out of memory"; | |||
| default: return "this error type doesn't have a desciption.."; | |||
| } | |||
| } | |||
| proc assert_type(Lisp_Object* node, Lisp_Object_Type type) -> void { | |||
| if (!node) | |||
| create_error(Error_Type::Unknown_Error, nullptr); | |||
| if (node->type == type) return; | |||
| create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation); | |||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void { | |||
| // HACK(Felix): the length of all error strings is 200!!!!!!!!!! | |||
| int length = 200; | |||
| String* formatted_string = Memory::create_string("", length); | |||
| int written_length; | |||
| va_list args; | |||
| va_start(args, format); | |||
| written_length = vsnprintf(&formatted_string->data, length, format, args); | |||
| va_end(args); | |||
| formatted_string->length = written_length; | |||
| create_error(c_file_name, c_file_line, type, formatted_string); | |||
| } | |||
| // proc Error_Type_to_string(Error_Type type) -> const char* { | |||
| // switch (type) { | |||
| // case Error_Type::Assertion_Error: return "Assertion failed"; | |||
| // case Error_Type::File_Not_Found: return "File not found"; | |||
| // case Error_Type::Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments"; | |||
| // case Error_Type::Ill_Formed_Lambda_List: return "Evaluation-error: Ill formed lambda list"; | |||
| // 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::Not_Yet_Implemented: return "Evaluation-error: Not yet implemented"; | |||
| // case Error_Type::Symbol_Not_Defined: return "Evaluation-error: Symbol not defined"; | |||
| // case Error_Type::Syntax_Error: return "Syntax Error"; | |||
| // case Error_Type::Trailing_Garbage: return "Evaluation-error: Trailing garbage following expression"; | |||
| // case Error_Type::Type_Missmatch: return "Evaluation-error: Type Missmatch"; | |||
| // case Error_Type::Unbalanced_Parenthesis: return "Parsing-error: Unbalanced parenthesis"; | |||
| // case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF"; | |||
| // case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument"; | |||
| // case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments"; | |||
| // case Error_Type::Out_Of_Memory: return "Runtime-error: Out of memory"; | |||
| // default: return "this error type doesn't have a desciption.."; | |||
| // } | |||
| // } | |||
| // proc assert_type(Lisp_Object* node, Lisp_Object_Type type) -> void { | |||
| // if (!node) { | |||
| // create_generic_error( | |||
| // "The node where the type should have" | |||
| // "been checked was nullptr."); | |||
| // return; | |||
| // } | |||
| // if (node->type != type) | |||
| // create_type_missmatch_error( | |||
| // "" | |||
| // ); | |||
| // } | |||
| @@ -5,18 +5,17 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| // positional arguments | |||
| for (int i = 0; i < function->positional_arguments->next_index; ++i) { | |||
| if (arguments->type == Lisp_Object_Type::Pair) { | |||
| // TODO(Felix): here we create new lisp_object_symbols from | |||
| // their identifiers but before we converted them to | |||
| // strings from symbols... Wo maybe just use the symbols? | |||
| define_symbol( | |||
| Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||
| arguments->value.pair.first, new_env); | |||
| } else { | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||
| create_wrong_number_of_arguments_error(function->positional_arguments->next_index, i); | |||
| return nullptr; | |||
| } | |||
| // TODO(Felix): here we create new lisp_object_symbols from | |||
| // their identifiers but before we converted them to | |||
| // strings from symbols... Wo maybe just use the symbols? | |||
| define_symbol( | |||
| Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||
| arguments->value.pair.first, new_env); | |||
| arguments = arguments->value.pair.rest; | |||
| } | |||
| @@ -46,8 +45,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| // necessary keywords then we have to count the rest | |||
| // as :rest here, instead od always creating an error | |||
| // (special case with default variables) | |||
| puts("??"); | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| create_generic_error( | |||
| "The function does not take the keyword argument ':%s'", | |||
| &(arguments->value.pair.first->value.identifier)); | |||
| return nullptr; | |||
| } | |||
| @@ -61,7 +61,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| // necessary keywords then we have to count the rest | |||
| // as :rest here, instead od always creating an error | |||
| // (special case with default variables) | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| create_generic_error( | |||
| "The function already read the keyword argument ':%s'", | |||
| &(arguments->value.pair.first->value.identifier)); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -70,7 +72,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| // not already read in, is there a next element to actually | |||
| // set it to? | |||
| if (arguments->value.pair.rest->type != Lisp_Object_Type::Pair) { | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| create_generic_error( | |||
| "Attempting to set the keyword argument ':%s', but no value was supplied.", | |||
| &(arguments->value.pair.first->value.identifier)); | |||
| return nullptr; | |||
| } | |||
| @@ -107,7 +111,10 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| if (function->keyword_arguments->values->data[i] == nullptr) { | |||
| // if this one does not have a default value | |||
| if (!was_set) { | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| create_generic_error( | |||
| "There was no value supplied for the required " | |||
| "keyword argument ':%s'.", | |||
| &defined_keyword->data); | |||
| return nullptr; | |||
| } | |||
| } else { | |||
| @@ -135,7 +142,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||
| arguments, new_env); | |||
| } else { | |||
| // rest was not declared but additional arguments were found | |||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| create_generic_error( | |||
| "A rest argument was not declared " | |||
| "but the function was called with additional arguments."); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -180,13 +189,17 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||
| string_equal(arguments->value.pair.first->value.identifier, "rest")) | |||
| break; | |||
| else { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error("A non recognized marker was found " | |||
| "in the lambda list: ':%s'", | |||
| &arguments->value.pair.first->value.identifier); | |||
| return; | |||
| } | |||
| } | |||
| if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error("Only symbols and keywords can be " | |||
| "parsed here, but found '%s'", | |||
| Lisp_Object_Type_to_string(arguments->value.pair.first->type)); | |||
| return; | |||
| } | |||
| @@ -202,7 +215,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||
| // keywords, | |||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||
| if (arguments->type != Lisp_Object_Type::Nil) | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error("The lambda list must be nil terminated."); | |||
| return; | |||
| } | |||
| @@ -210,25 +223,32 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||
| string_equal(arguments->value.pair.first->value.identifier, "keys")) | |||
| { | |||
| arguments = arguments->value.pair.rest; | |||
| if (arguments->type != Lisp_Object_Type::Pair || | |||
| arguments->value.pair.first->type != Lisp_Object_Type::Symbol) | |||
| { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||
| create_parsing_error("Actual keys have to follow the :keys indicator."); | |||
| } | |||
| // if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) { | |||
| // create_parsing_error( | |||
| // "Only symbols can be parsed here, but found '%s'.", | |||
| // Lisp_Object_Type_to_string(arguments->value.pair.first->type)); | |||
| // return; | |||
| // } | |||
| while (arguments->type == Lisp_Object_Type::Pair) { | |||
| if (arguments->value.pair.first->type == Lisp_Object_Type::Keyword) { | |||
| if (string_equal(arguments->value.pair.first->value.identifier, "rest")) | |||
| break; | |||
| else { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error( | |||
| "Only the :rest keyword can be parsed here, but got ':%s'.", | |||
| &arguments->value.pair.first->value.identifier->data); | |||
| return; | |||
| } | |||
| } | |||
| if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error( | |||
| "Only symbols can be parsed here, but found '%s'.", | |||
| Lisp_Object_Type_to_string(arguments->value.pair.first->type)); | |||
| return; | |||
| } | |||
| @@ -250,7 +270,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||
| next->value.pair.first); | |||
| arguments = next->value.pair.rest; | |||
| } else { | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error("Expecting a value after 'defaults-to'"); | |||
| return; | |||
| } | |||
| } else { | |||
| @@ -268,7 +288,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||
| // if there is a rest argument | |||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||
| if (arguments->type != Lisp_Object_Type::Nil) | |||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| create_parsing_error("The lambda list must be nil terminated."); | |||
| return; | |||
| } | |||
| @@ -1,6 +1,8 @@ | |||
| proc assert_type(Lisp_Object*, Lisp_Object_Type) -> void; | |||
| // proc assert_type(Lisp_Object*, Lisp_Object_Type) -> void; | |||
| proc built_in_load(String*, Environment*) -> Lisp_Object*; | |||
| proc create_error(Error_Type, Source_Code_Location*) -> void; | |||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void; | |||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void; | |||
| proc create_error(Lisp_Object* type, const char* message, const char* c_file_name, int c_file_line) -> void; | |||
| proc eval_arguments(Lisp_Object*, Environment*, int*) -> Lisp_Object*; | |||
| proc eval_expr(Lisp_Object*, Environment*) -> Lisp_Object*; | |||
| proc is_truthy (Lisp_Object*, Environment*) -> bool; | |||
| @@ -8,3 +10,8 @@ proc list_length(Lisp_Object*) -> int; | |||
| proc load_built_ins_into_environment(Environment*) -> void; | |||
| proc parse_argument_list(Lisp_Object*, Function*) -> void; | |||
| proc print_environment(Environment*) -> void; | |||
| proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char*; | |||
| namespace Memory { | |||
| proc get_or_create_lisp_object_keyword(const char* identifier) -> Lisp_Object*; | |||
| } | |||
| @@ -281,19 +281,19 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> | |||
| proc print_error_location() -> void { | |||
| if (error->location) { | |||
| printf("%s (line %d, position %d)", | |||
| Memory::get_c_str(error->location->file), | |||
| error->location->line, | |||
| error->location->column); | |||
| } else { | |||
| printf("no source code location avaliable"); | |||
| } | |||
| // if (error->location) { | |||
| // printf("%s (line %d, position %d)", | |||
| // Memory::get_c_str(error->location->file), | |||
| // error->location->line, | |||
| // error->location->column); | |||
| // } else { | |||
| // printf("no source code location avaliable"); | |||
| // } | |||
| } | |||
| proc log_error() -> void { | |||
| printf("%s%s%s\n", console_red, | |||
| Error_Type_to_string(error->type), | |||
| Memory::get_c_str(error->message), | |||
| console_normal); | |||
| printf(" in: %s", console_cyan); | |||
| print_error_location(); | |||
| @@ -3,7 +3,7 @@ namespace Memory { | |||
| // ------------------ | |||
| // lisp_object | |||
| // ------------------ | |||
| int object_memory_size; | |||
| int object_memory_size; | |||
| Int_Array_List* free_spots_in_object_memory; | |||
| Lisp_Object* object_memory; | |||
| int next_index_in_object_memory = 0; | |||
| @@ -82,13 +82,33 @@ namespace Memory { | |||
| return create_string(str, (int)strlen(str)); | |||
| } | |||
| // proc create_string_formatted (const char* format, ...) -> String* { | |||
| // // HACK(Felix): the length of all strings is 200!!!!!!!!!! | |||
| // // HACK(Felix): the length of all strings is 200!!!!!!!!!! | |||
| // int length = 200; | |||
| // String* ret = create_string("", length); | |||
| // int written_length; | |||
| // va_list args; | |||
| // va_start(args, format); | |||
| // written_length = vsnprintf(&ret->data, length, format, args); | |||
| // va_end(args); | |||
| // ret->length = written_length; | |||
| // return ret; | |||
| // } | |||
| proc create_lisp_object() -> Lisp_Object* { | |||
| int index; | |||
| // if we have no free spots then append at the end | |||
| if (free_spots_in_object_memory->next_index == 0) { | |||
| // if we still have space | |||
| if (object_memory_size == next_index_in_object_memory) { | |||
| create_error(Error_Type::Out_Of_Memory, nullptr); | |||
| create_out_of_memory_error( | |||
| "There is not enough space in the lisp object" | |||
| "memory to allocate additional lisp objects. " | |||
| "Maybe try increasing the Memory size when " | |||
| "calling Memory::init()"); | |||
| return nullptr; | |||
| } | |||
| index = next_index_in_object_memory++; | |||
| @@ -162,6 +182,9 @@ namespace Memory { | |||
| } | |||
| proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* { | |||
| // TODO(Felix): This is really bad: we create a new string | |||
| // even if the symbol/keyword is already existing, just to | |||
| // check IF it exists and then never deleting it. | |||
| return get_or_create_lisp_object_symbol( | |||
| Memory::create_string(identifier)); | |||
| } | |||
| @@ -177,6 +200,9 @@ namespace Memory { | |||
| } | |||
| proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* { | |||
| // TODO(Felix): This is really bad: we create a new string | |||
| // even if the symbol/keyword is already existing, just to | |||
| // check IF it exists and then never deleting it. | |||
| return get_or_create_lisp_object_keyword( | |||
| Memory::create_string(keyword)); | |||
| } | |||
| @@ -166,15 +166,15 @@ namespace Parser { | |||
| // we found the end of the string | |||
| text[*index_in_text+string_length] = '\0'; | |||
| String* string = Memory::create_string("", string_length); | |||
| if (!unescape_string(text+(*index_in_text))) { | |||
| create_error( | |||
| Error_Type::Unknown_Error, | |||
| create_source_code_location(parser_file, parser_line, parser_col)); | |||
| create_parsing_error( | |||
| "The string '%s' at %s:%d:%d could not be unescaped.", | |||
| text+(*index_in_text), parser_file, parser_line, parser_col); | |||
| return nullptr; | |||
| } | |||
| String* string = Memory::create_string("", string_length); | |||
| // TODO(Felix): manually copy to parse control sequences | |||
| // correctly without the need to unescape the string, also | |||
| // better for keeping track of the encountered new lines and | |||
| @@ -314,7 +314,9 @@ namespace Parser { | |||
| eat_until_code(text, index_in_text); | |||
| if (text[(*index_in_text)] == '\0') { | |||
| create_error(Error_Type::Unexpected_Eof, create_source_code_location(parser_file, parser_line, parser_col)); | |||
| create_parsing_error( | |||
| "Unexpected EOF in %s:%d:%d", | |||
| parser_file, parser_line, parser_col); | |||
| return nullptr; | |||
| } | |||
| @@ -337,7 +339,9 @@ namespace Parser { | |||
| eat_until_code(text, index_in_text); | |||
| if (text[(*index_in_text)] != ')') | |||
| create_error(Error_Type::Syntax_Error, create_source_code_location(parser_file, parser_line, parser_col)); | |||
| create_parsing_error( | |||
| "Expected ')' after the element after the '.' in %s:%d:%d", | |||
| create_source_code_location(parser_file, parser_line, parser_col)); | |||
| ++parser_col; | |||
| ++(*index_in_text); | |||
| break; | |||
| @@ -362,14 +366,11 @@ namespace Parser { | |||
| // (define-syntax defun (name args :rest body) (...)) | |||
| if (arguments_length < 2) { | |||
| create_error(Error_Type::Wrong_Number_Of_Arguments, expression->sourceCodeLocation); | |||
| create_wrong_number_of_arguments_error(3, arguments_length); | |||
| return nullptr; | |||
| } | |||
| if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) { | |||
| create_error(Error_Type::Type_Missmatch, expression->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| assert_type(arguments->value.pair.first, Lisp_Object_Type::Symbol); | |||
| // extract the name | |||
| Lisp_Object* symbol_for_macro = arguments->value.pair.first; | |||
| @@ -429,7 +430,8 @@ namespace Parser { | |||
| // that, when an entry is not found immidiately, we | |||
| // know for sure that it does not exist in the table. | |||
| create_error(Error_Type::Not_Yet_Implemented, expression->sourceCodeLocation); | |||
| create_generic_error("deleting macros has not yet be implemented," | |||
| "and I don't know if it is a good idea to do so."); | |||
| return nullptr; | |||
| } else { | |||
| // if threre is a macro named like this, then macroexpand | |||
| @@ -478,7 +480,9 @@ namespace Parser { | |||
| eat_until_code(text, &index_in_text); | |||
| if (text[(index_in_text)] == '\0') | |||
| return result; | |||
| create_error(Error_Type::Trailing_Garbage, create_source_code_location(parser_file, parser_line, parser_col)); | |||
| create_parsing_error("Trainling garbage after expression at %s:%d:%d", | |||
| parser_file, parser_line, parser_col); | |||
| return nullptr; | |||
| } | |||
| @@ -573,7 +577,8 @@ namespace Parser { | |||
| } break; | |||
| default: | |||
| /* syntax error */ | |||
| create_error(Error_Type::Syntax_Error, create_source_code_location(parser_file, parser_line, parser_col)); | |||
| create_parsing_error("Garbage in file scope at %s:%d:%d", | |||
| parser_file, parser_line, parser_col); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -6,11 +6,13 @@ | |||
| #include <string.h> | |||
| #include <cmath> | |||
| #include <ctype.h> | |||
| // #include <type_traits> | |||
| #include <stdarg.h> | |||
| #include <functional> | |||
| #undef _CRT_SECURE_NO_DEPRECATE | |||
| #undef _CRT_SECURE_NO_WARNINGS | |||
| namespace Slime { | |||
| // namespace Slime { | |||
| #include "./defines.cpp" | |||
| #include "./structs.cpp" | |||
| #include "./forward_decls.cpp" | |||
| @@ -24,7 +26,4 @@ namespace Slime { | |||
| #include "./built_ins.cpp" | |||
| #include "./testing.cpp" | |||
| #include "./undefines.cpp" | |||
| } | |||
| #undef _CRT_SECURE_NO_DEPRECATE | |||
| #undef _CRT_SECURE_NO_WARNINGS | |||
| // } | |||
| @@ -26,25 +26,25 @@ enum struct Function_Type { | |||
| Macro | |||
| }; | |||
| enum struct Error_Type { | |||
| Assertion_Error, | |||
| File_Not_Found, | |||
| Ill_Formed_Arguments, | |||
| Ill_Formed_Lambda_List, | |||
| Ill_Formed_List, | |||
| Not_A_Function, | |||
| Not_Yet_Implemented, | |||
| Out_Of_Memory, | |||
| Symbol_Not_Defined, | |||
| Syntax_Error, | |||
| Trailing_Garbage, | |||
| Type_Missmatch, | |||
| Unbalanced_Parenthesis, | |||
| Unexpected_Eof, | |||
| Unknown_Error, | |||
| Unknown_Keyword_Argument, | |||
| Wrong_Number_Of_Arguments, | |||
| }; | |||
| // enum struct Error_Type { | |||
| // Assertion_Error, | |||
| // File_Not_Found, | |||
| // Ill_Formed_Arguments, | |||
| // Ill_Formed_Lambda_List, | |||
| // Ill_Formed_List, | |||
| // Not_A_Function, | |||
| // Not_Yet_Implemented, | |||
| // Out_Of_Memory, | |||
| // Symbol_Not_Defined, | |||
| // Syntax_Error, | |||
| // Trailing_Garbage, | |||
| // Type_Missmatch, | |||
| // Unbalanced_Parenthesis, | |||
| // Unexpected_Eof, | |||
| // Unknown_Error, | |||
| // Unknown_Keyword_Argument, | |||
| // Wrong_Number_Of_Arguments, | |||
| // }; | |||
| enum struct Log_Level { | |||
| None, | |||
| @@ -141,12 +141,15 @@ struct Environment { | |||
| int capacity; | |||
| int next_index; | |||
| // TODO(Felix): Use a hashmap here. | |||
| char** keys; | |||
| char** keys; | |||
| Lisp_Object** values; | |||
| }; | |||
| struct Error { | |||
| Error_Type type; | |||
| Source_Code_Location* location; | |||
| Lisp_Object* position; | |||
| // type has to be a keyword | |||
| Lisp_Object* type; | |||
| String* message; | |||
| }; | |||
| @@ -1,3 +1,4 @@ | |||
| * TODO rename sliem to plisk | |||
| * TODO BUG 1: eval dot notation | |||
| #+BEGIN_SRC lisp | |||
| (eval `(+ . ,(list 1 2 3))) | |||