on the way to better errors
This commit is contained in:
+1
-1
@@ -36,7 +36,7 @@
|
|||||||
(font-lock-add-keywords 'c++-mode
|
(font-lock-add-keywords 'c++-mode
|
||||||
'(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" .
|
'(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" .
|
||||||
font-lock-keyword-face)))))))
|
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 . (flycheck-mode 0))
|
||||||
(eval . (rainbow-mode 0))
|
(eval . (rainbow-mode 0))
|
||||||
)))
|
)))
|
||||||
|
|||||||
@@ -122,6 +122,48 @@ struct {
|
|||||||
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
|
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
|
||||||
#define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&]
|
#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_normal "\x1B[0m"
|
||||||
#define console_red "\x1B[31m"
|
#define console_red "\x1B[31m"
|
||||||
#define console_green "\x1B[32m"
|
#define console_green "\x1B[32m"
|
||||||
|
|||||||
+2
-2
@@ -45,8 +45,8 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
|
|||||||
return Memory::t;
|
return Memory::t;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s\n", Memory::get_c_str(identifier));
|
create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data);
|
||||||
create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+57
-28
@@ -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();
|
delete_error();
|
||||||
debug_break();
|
debug_break();
|
||||||
|
|
||||||
error = new(Error);
|
error = new(Error);
|
||||||
error->type = type;
|
error->type = type;
|
||||||
error->location = location;
|
error->message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc Error_Type_to_string(Error_Type type) -> const char* {
|
|
||||||
switch (type) {
|
proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void {
|
||||||
case Error_Type::Assertion_Error: return "Assertion failed";
|
// HACK(Felix): the length of all error strings is 200!!!!!!!!!!
|
||||||
case Error_Type::File_Not_Found: return "File not found";
|
|
||||||
case Error_Type::Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments";
|
int length = 200;
|
||||||
case Error_Type::Ill_Formed_Lambda_List: return "Evaluation-error: Ill formed lambda list";
|
String* formatted_string = Memory::create_string("", length);
|
||||||
case Error_Type::Ill_Formed_List: return "Evaluation-error: Ill formed list";
|
|
||||||
case Error_Type::Not_A_Function: return "Evaluation-error: Not a function";
|
int written_length;
|
||||||
case Error_Type::Not_Yet_Implemented: return "Evaluation-error: Not yet implemented";
|
va_list args;
|
||||||
case Error_Type::Symbol_Not_Defined: return "Evaluation-error: Symbol not defined";
|
va_start(args, format);
|
||||||
case Error_Type::Syntax_Error: return "Syntax Error";
|
written_length = vsnprintf(&formatted_string->data, length, format, args);
|
||||||
case Error_Type::Trailing_Garbage: return "Evaluation-error: Trailing garbage following expression";
|
va_end(args);
|
||||||
case Error_Type::Type_Missmatch: return "Evaluation-error: Type Missmatch";
|
|
||||||
case Error_Type::Unbalanced_Parenthesis: return "Parsing-error: Unbalanced parenthesis";
|
formatted_string->length = written_length;
|
||||||
case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF";
|
|
||||||
case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument";
|
create_error(c_file_name, c_file_line, type, formatted_string);
|
||||||
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 {
|
// proc Error_Type_to_string(Error_Type type) -> const char* {
|
||||||
if (!node)
|
// switch (type) {
|
||||||
create_error(Error_Type::Unknown_Error, nullptr);
|
// case Error_Type::Assertion_Error: return "Assertion failed";
|
||||||
if (node->type == type) return;
|
// case Error_Type::File_Not_Found: return "File not found";
|
||||||
create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
|
// 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(
|
||||||
|
// ""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|||||||
+43
-23
@@ -5,18 +5,17 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
|
|||||||
|
|
||||||
// positional arguments
|
// positional arguments
|
||||||
for (int i = 0; i < function->positional_arguments->next_index; ++i) {
|
for (int i = 0; i < function->positional_arguments->next_index; ++i) {
|
||||||
if (arguments->type == Lisp_Object_Type::Pair) {
|
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
|
// TODO(Felix): here we create new lisp_object_symbols from
|
||||||
// their identifiers but before we converted them to
|
// their identifiers but before we converted them to
|
||||||
// strings from symbols... Wo maybe just use the symbols?
|
// strings from symbols... Wo maybe just use the symbols?
|
||||||
define_symbol(
|
define_symbol(
|
||||||
Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
|
Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
|
||||||
arguments->value.pair.first, new_env);
|
arguments->value.pair.first, new_env);
|
||||||
} else {
|
|
||||||
|
|
||||||
create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
arguments = arguments->value.pair.rest;
|
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
|
// necessary keywords then we have to count the rest
|
||||||
// as :rest here, instead od always creating an error
|
// as :rest here, instead od always creating an error
|
||||||
// (special case with default variables)
|
// (special case with default variables)
|
||||||
puts("??");
|
create_generic_error(
|
||||||
create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
|
"The function does not take the keyword argument ':%s'",
|
||||||
|
&(arguments->value.pair.first->value.identifier));
|
||||||
return nullptr;
|
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
|
// necessary keywords then we have to count the rest
|
||||||
// as :rest here, instead od always creating an error
|
// as :rest here, instead od always creating an error
|
||||||
// (special case with default variables)
|
// (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;
|
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
|
// not already read in, is there a next element to actually
|
||||||
// set it to?
|
// set it to?
|
||||||
if (arguments->value.pair.rest->type != Lisp_Object_Type::Pair) {
|
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;
|
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 (function->keyword_arguments->values->data[i] == nullptr) {
|
||||||
// if this one does not have a default value
|
// if this one does not have a default value
|
||||||
if (!was_set) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +142,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) ->
|
|||||||
arguments, new_env);
|
arguments, new_env);
|
||||||
} else {
|
} else {
|
||||||
// rest was not declared but additional arguments were found
|
// 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;
|
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"))
|
string_equal(arguments->value.pair.first->value.identifier, "rest"))
|
||||||
break;
|
break;
|
||||||
else {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +215,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
|
|||||||
// keywords,
|
// keywords,
|
||||||
if (arguments->type != Lisp_Object_Type::Pair) {
|
if (arguments->type != Lisp_Object_Type::Pair) {
|
||||||
if (arguments->type != Lisp_Object_Type::Nil)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,25 +223,32 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
|
|||||||
string_equal(arguments->value.pair.first->value.identifier, "keys"))
|
string_equal(arguments->value.pair.first->value.identifier, "keys"))
|
||||||
{
|
{
|
||||||
arguments = arguments->value.pair.rest;
|
arguments = arguments->value.pair.rest;
|
||||||
if (arguments->type != Lisp_Object_Type::Pair ||
|
if (arguments->type != Lisp_Object_Type::Pair) {
|
||||||
arguments->value.pair.first->type != Lisp_Object_Type::Symbol)
|
create_parsing_error("Actual keys have to follow the :keys indicator.");
|
||||||
{
|
|
||||||
create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
// 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) {
|
while (arguments->type == Lisp_Object_Type::Pair) {
|
||||||
if (arguments->value.pair.first->type == Lisp_Object_Type::Keyword) {
|
if (arguments->value.pair.first->type == Lisp_Object_Type::Keyword) {
|
||||||
if (string_equal(arguments->value.pair.first->value.identifier, "rest"))
|
if (string_equal(arguments->value.pair.first->value.identifier, "rest"))
|
||||||
break;
|
break;
|
||||||
else {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +270,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
|
|||||||
next->value.pair.first);
|
next->value.pair.first);
|
||||||
arguments = next->value.pair.rest;
|
arguments = next->value.pair.rest;
|
||||||
} else {
|
} else {
|
||||||
create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
|
create_parsing_error("Expecting a value after 'defaults-to'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -268,7 +288,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
|
|||||||
// if there is a rest argument
|
// if there is a rest argument
|
||||||
if (arguments->type != Lisp_Object_Type::Pair) {
|
if (arguments->type != Lisp_Object_Type::Pair) {
|
||||||
if (arguments->type != Lisp_Object_Type::Nil)
|
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;
|
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 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_arguments(Lisp_Object*, Environment*, int*) -> Lisp_Object*;
|
||||||
proc eval_expr(Lisp_Object*, Environment*) -> Lisp_Object*;
|
proc eval_expr(Lisp_Object*, Environment*) -> Lisp_Object*;
|
||||||
proc is_truthy (Lisp_Object*, Environment*) -> bool;
|
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 load_built_ins_into_environment(Environment*) -> void;
|
||||||
proc parse_argument_list(Lisp_Object*, Function*) -> void;
|
proc parse_argument_list(Lisp_Object*, Function*) -> void;
|
||||||
proc print_environment(Environment*) -> 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*;
|
||||||
|
}
|
||||||
|
|||||||
+9
-9
@@ -281,19 +281,19 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) ->
|
|||||||
|
|
||||||
|
|
||||||
proc print_error_location() -> void {
|
proc print_error_location() -> void {
|
||||||
if (error->location) {
|
// if (error->location) {
|
||||||
printf("%s (line %d, position %d)",
|
// printf("%s (line %d, position %d)",
|
||||||
Memory::get_c_str(error->location->file),
|
// Memory::get_c_str(error->location->file),
|
||||||
error->location->line,
|
// error->location->line,
|
||||||
error->location->column);
|
// error->location->column);
|
||||||
} else {
|
// } else {
|
||||||
printf("no source code location avaliable");
|
// printf("no source code location avaliable");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
proc log_error() -> void {
|
proc log_error() -> void {
|
||||||
printf("%s%s%s\n", console_red,
|
printf("%s%s%s\n", console_red,
|
||||||
Error_Type_to_string(error->type),
|
Memory::get_c_str(error->message),
|
||||||
console_normal);
|
console_normal);
|
||||||
printf(" in: %s", console_cyan);
|
printf(" in: %s", console_cyan);
|
||||||
print_error_location();
|
print_error_location();
|
||||||
|
|||||||
+27
-1
@@ -82,13 +82,33 @@ namespace Memory {
|
|||||||
return create_string(str, (int)strlen(str));
|
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* {
|
proc create_lisp_object() -> Lisp_Object* {
|
||||||
int index;
|
int index;
|
||||||
// if we have no free spots then append at the end
|
// if we have no free spots then append at the end
|
||||||
if (free_spots_in_object_memory->next_index == 0) {
|
if (free_spots_in_object_memory->next_index == 0) {
|
||||||
// if we still have space
|
// if we still have space
|
||||||
if (object_memory_size == next_index_in_object_memory) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
index = next_index_in_object_memory++;
|
index = next_index_in_object_memory++;
|
||||||
@@ -162,6 +182,9 @@ namespace Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* {
|
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(
|
return get_or_create_lisp_object_symbol(
|
||||||
Memory::create_string(identifier));
|
Memory::create_string(identifier));
|
||||||
}
|
}
|
||||||
@@ -177,6 +200,9 @@ namespace Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* {
|
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(
|
return get_or_create_lisp_object_keyword(
|
||||||
Memory::create_string(keyword));
|
Memory::create_string(keyword));
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-15
@@ -166,15 +166,15 @@ namespace Parser {
|
|||||||
// we found the end of the string
|
// we found the end of the string
|
||||||
text[*index_in_text+string_length] = '\0';
|
text[*index_in_text+string_length] = '\0';
|
||||||
|
|
||||||
String* string = Memory::create_string("", string_length);
|
|
||||||
|
|
||||||
if (!unescape_string(text+(*index_in_text))) {
|
if (!unescape_string(text+(*index_in_text))) {
|
||||||
create_error(
|
create_parsing_error(
|
||||||
Error_Type::Unknown_Error,
|
"The string '%s' at %s:%d:%d could not be unescaped.",
|
||||||
create_source_code_location(parser_file, parser_line, parser_col));
|
text+(*index_in_text), parser_file, parser_line, parser_col);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String* string = Memory::create_string("", string_length);
|
||||||
|
|
||||||
// TODO(Felix): manually copy to parse control sequences
|
// TODO(Felix): manually copy to parse control sequences
|
||||||
// correctly without the need to unescape the string, also
|
// correctly without the need to unescape the string, also
|
||||||
// better for keeping track of the encountered new lines and
|
// better for keeping track of the encountered new lines and
|
||||||
@@ -314,7 +314,9 @@ namespace Parser {
|
|||||||
|
|
||||||
eat_until_code(text, index_in_text);
|
eat_until_code(text, index_in_text);
|
||||||
if (text[(*index_in_text)] == '\0') {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +339,9 @@ namespace Parser {
|
|||||||
eat_until_code(text, index_in_text);
|
eat_until_code(text, index_in_text);
|
||||||
|
|
||||||
if (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;
|
++parser_col;
|
||||||
++(*index_in_text);
|
++(*index_in_text);
|
||||||
break;
|
break;
|
||||||
@@ -362,14 +366,11 @@ namespace Parser {
|
|||||||
|
|
||||||
// (define-syntax defun (name args :rest body) (...))
|
// (define-syntax defun (name args :rest body) (...))
|
||||||
if (arguments_length < 2) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) {
|
assert_type(arguments->value.pair.first, Lisp_Object_Type::Symbol);
|
||||||
create_error(Error_Type::Type_Missmatch, expression->sourceCodeLocation);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the name
|
// extract the name
|
||||||
Lisp_Object* symbol_for_macro = arguments->value.pair.first;
|
Lisp_Object* symbol_for_macro = arguments->value.pair.first;
|
||||||
@@ -429,7 +430,8 @@ namespace Parser {
|
|||||||
// that, when an entry is not found immidiately, we
|
// that, when an entry is not found immidiately, we
|
||||||
// know for sure that it does not exist in the table.
|
// 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;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
// if threre is a macro named like this, then macroexpand
|
// if threre is a macro named like this, then macroexpand
|
||||||
@@ -478,7 +480,9 @@ namespace Parser {
|
|||||||
eat_until_code(text, &index_in_text);
|
eat_until_code(text, &index_in_text);
|
||||||
if (text[(index_in_text)] == '\0')
|
if (text[(index_in_text)] == '\0')
|
||||||
return result;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +577,8 @@ namespace Parser {
|
|||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
/* syntax error */
|
/* 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-6
@@ -6,11 +6,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
// #include <type_traits>
|
#include <stdarg.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#undef _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#undef _CRT_SECURE_NO_WARNINGS
|
||||||
|
|
||||||
namespace Slime {
|
// namespace Slime {
|
||||||
#include "./defines.cpp"
|
#include "./defines.cpp"
|
||||||
#include "./structs.cpp"
|
#include "./structs.cpp"
|
||||||
#include "./forward_decls.cpp"
|
#include "./forward_decls.cpp"
|
||||||
@@ -24,7 +26,4 @@ namespace Slime {
|
|||||||
#include "./built_ins.cpp"
|
#include "./built_ins.cpp"
|
||||||
#include "./testing.cpp"
|
#include "./testing.cpp"
|
||||||
#include "./undefines.cpp"
|
#include "./undefines.cpp"
|
||||||
}
|
// }
|
||||||
|
|
||||||
#undef _CRT_SECURE_NO_DEPRECATE
|
|
||||||
#undef _CRT_SECURE_NO_WARNINGS
|
|
||||||
|
|||||||
+24
-21
@@ -26,25 +26,25 @@ enum struct Function_Type {
|
|||||||
Macro
|
Macro
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct Error_Type {
|
// enum struct Error_Type {
|
||||||
Assertion_Error,
|
// Assertion_Error,
|
||||||
File_Not_Found,
|
// File_Not_Found,
|
||||||
Ill_Formed_Arguments,
|
// Ill_Formed_Arguments,
|
||||||
Ill_Formed_Lambda_List,
|
// Ill_Formed_Lambda_List,
|
||||||
Ill_Formed_List,
|
// Ill_Formed_List,
|
||||||
Not_A_Function,
|
// Not_A_Function,
|
||||||
Not_Yet_Implemented,
|
// Not_Yet_Implemented,
|
||||||
Out_Of_Memory,
|
// Out_Of_Memory,
|
||||||
Symbol_Not_Defined,
|
// Symbol_Not_Defined,
|
||||||
Syntax_Error,
|
// Syntax_Error,
|
||||||
Trailing_Garbage,
|
// Trailing_Garbage,
|
||||||
Type_Missmatch,
|
// Type_Missmatch,
|
||||||
Unbalanced_Parenthesis,
|
// Unbalanced_Parenthesis,
|
||||||
Unexpected_Eof,
|
// Unexpected_Eof,
|
||||||
Unknown_Error,
|
// Unknown_Error,
|
||||||
Unknown_Keyword_Argument,
|
// Unknown_Keyword_Argument,
|
||||||
Wrong_Number_Of_Arguments,
|
// Wrong_Number_Of_Arguments,
|
||||||
};
|
// };
|
||||||
|
|
||||||
enum struct Log_Level {
|
enum struct Log_Level {
|
||||||
None,
|
None,
|
||||||
@@ -141,12 +141,15 @@ struct Environment {
|
|||||||
|
|
||||||
int capacity;
|
int capacity;
|
||||||
int next_index;
|
int next_index;
|
||||||
|
|
||||||
// TODO(Felix): Use a hashmap here.
|
// TODO(Felix): Use a hashmap here.
|
||||||
char** keys;
|
char** keys;
|
||||||
Lisp_Object** values;
|
Lisp_Object** values;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Error {
|
struct Error {
|
||||||
Error_Type type;
|
Lisp_Object* position;
|
||||||
Source_Code_Location* location;
|
// type has to be a keyword
|
||||||
|
Lisp_Object* type;
|
||||||
|
String* message;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user