| @@ -1,6 +1,6 @@ | |||
| void assert_type (Ast_Node* node, Ast_Node_Type type) { | |||
| if (!node) | |||
| create_error(Error_Type_Unknown_Error, node); | |||
| create_error(Error_Type_Unknown_Error, nullptr); | |||
| if (node->type == type) return; | |||
| create_error(Error_Type_Type_Missmatch, node); | |||
| create_error(Error_Type_Type_Missmatch, node->sourceCodeLocation); | |||
| } | |||
| @@ -214,6 +214,7 @@ typedef struct { | |||
| } Built_In_Function; | |||
| struct Ast_Node { | |||
| Source_Code_Location* sourceCodeLocation; | |||
| Ast_Node_Type type; | |||
| union { | |||
| Symbol* symbol; | |||
| @@ -2,40 +2,40 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env); | |||
| bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) { | |||
| if (n1 == n2) | |||
| return true; | |||
| return true; | |||
| if (n1->type != n2->type) | |||
| return false; | |||
| return false; | |||
| switch (n1->type) { | |||
| case Ast_Node_Type_Built_In_Function: | |||
| return n1->value.built_in_function->type | |||
| == n2->value.built_in_function->type; | |||
| return n1->value.built_in_function->type | |||
| == n2->value.built_in_function->type; | |||
| case Ast_Node_Type_Function: | |||
| // if they have the same pointer, true is | |||
| // returned a few lines above | |||
| return false; | |||
| // if they have the same pointer, true is | |||
| // returned a few lines above | |||
| return false; | |||
| case Ast_Node_Type_Keyword: | |||
| return string_equal( | |||
| n1->value.keyword->identifier, | |||
| n2->value.keyword->identifier); | |||
| return string_equal( | |||
| n1->value.keyword->identifier, | |||
| n2->value.keyword->identifier); | |||
| case Ast_Node_Type_T: | |||
| case Ast_Node_Type_Nil: | |||
| return true; | |||
| return true; | |||
| case Ast_Node_Type_Number: | |||
| return | |||
| n1->value.number->value == | |||
| n2->value.number->value; | |||
| return | |||
| n1->value.number->value == | |||
| n2->value.number->value; | |||
| case Ast_Node_Type_Pair: | |||
| create_error(Error_Type_Not_Yet_Implemented, n1); | |||
| return false; | |||
| create_error(Error_Type_Not_Yet_Implemented, n1->sourceCodeLocation); | |||
| return false; | |||
| case Ast_Node_Type_String: | |||
| return string_equal( | |||
| n1->value.string->value, | |||
| n2->value.string->value); | |||
| return string_equal( | |||
| n1->value.string->value, | |||
| n2->value.string->value); | |||
| case Ast_Node_Type_Symbol: | |||
| return string_equal( | |||
| n1->value.symbol->identifier, | |||
| n2->value.symbol->identifier); | |||
| return string_equal( | |||
| n1->value.symbol->identifier, | |||
| n2->value.symbol->identifier); | |||
| } | |||
| // we should never reach here | |||
| @@ -44,32 +44,32 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) { | |||
| Ast_Node* built_in_equals(Ast_Node* operands) { | |||
| if (operands->type == Ast_Node_Type_Nil) | |||
| return create_ast_node_t(); | |||
| return create_ast_node_t(); | |||
| Ast_Node* first = operands->value.pair->first; | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| if (!ast_node_equal(operands->value.pair->first, first)) | |||
| return create_ast_node_nil(); | |||
| operands = operands->value.pair->rest; | |||
| if (!ast_node_equal(operands->value.pair->first, first)) | |||
| return create_ast_node_nil(); | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_t(); | |||
| return create_ast_node_t(); | |||
| } | |||
| Ast_Node* built_in_greater(Ast_Node* operands) { | |||
| double last_number = strtod("Inf", NULL); | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| if (operands->value.pair->first->value.number->value >= last_number) | |||
| return create_ast_node_nil(); | |||
| if (operands->value.pair->first->value.number->value >= last_number) | |||
| return create_ast_node_nil(); | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_t(); | |||
| @@ -79,15 +79,15 @@ Ast_Node* built_in_greater_equal(Ast_Node* operands) { | |||
| double last_number = strtod("Inf", NULL); | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| if (operands->value.pair->first->value.number->value > last_number) | |||
| return create_ast_node_nil(); | |||
| if (operands->value.pair->first->value.number->value > last_number) | |||
| return create_ast_node_nil(); | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_t(); | |||
| @@ -97,15 +97,15 @@ Ast_Node* built_in_less(Ast_Node* operands) { | |||
| double last_number = strtod("-Inf", NULL); | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| if (operands->value.pair->first->value.number->value <= last_number) | |||
| return create_ast_node_nil(); | |||
| if (operands->value.pair->first->value.number->value <= last_number) | |||
| return create_ast_node_nil(); | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_t(); | |||
| @@ -115,15 +115,15 @@ Ast_Node* built_in_less_equal(Ast_Node* operands) { | |||
| double last_number = strtod("-Inf", NULL); | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| if (operands->value.pair->first->value.number->value < last_number) | |||
| return create_ast_node_nil(); | |||
| if (operands->value.pair->first->value.number->value < last_number) | |||
| return create_ast_node_nil(); | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| last_number = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_t(); | |||
| @@ -132,11 +132,11 @@ Ast_Node* built_in_less_equal(Ast_Node* operands) { | |||
| Ast_Node* built_in_add(Ast_Node* operands) { | |||
| double sum = 0; | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| sum += operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| try { | |||
| 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); | |||
| @@ -144,54 +144,54 @@ Ast_Node* built_in_add(Ast_Node* operands) { | |||
| Ast_Node* built_in_substract(Ast_Node* operands) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| double difference = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| difference -= operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->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) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| double product = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| product *= operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->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) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| double quotient = operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| while (operands->type == Ast_Node_Type_Pair) { | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| try { | |||
| assert_type(operands->value.pair->first, Ast_Node_Type_Number); | |||
| } | |||
| quotient /= operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| quotient /= operands->value.pair->first->value.number->value; | |||
| operands = operands->value.pair->rest; | |||
| } | |||
| return create_ast_node_number(quotient); | |||
| } | |||
| @@ -200,19 +200,19 @@ Ast_Node* built_in_divide(Ast_Node* operands) { | |||
| Ast_Node* built_in_load(char* file_name, Environment* env) { | |||
| char* file_content = read_entire_file(file_name); | |||
| if (file_content) { | |||
| Ast_Node* result = create_ast_node_nil(); | |||
| Ast_Node_Array_List* program; | |||
| try { | |||
| program = parse_program(file_content); | |||
| } | |||
| for (int i = 0; i < program->next_index; ++i) { | |||
| try { | |||
| result = eval_expr(program->data[i], env); | |||
| } | |||
| } | |||
| return result; | |||
| Ast_Node* result = create_ast_node_nil(); | |||
| Ast_Node_Array_List* program; | |||
| try { | |||
| program = parse_program(file_name, file_content); | |||
| } | |||
| for (int i = 0; i < program->next_index; ++i) { | |||
| try { | |||
| result = eval_expr(program->data[i], env); | |||
| } | |||
| } | |||
| return result; | |||
| } else { | |||
| create_error(Error_Type_Unknown_Error, create_ast_node_nil()); | |||
| return nullptr; | |||
| create_error(Error_Type_Unknown_Error, nullptr); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -64,7 +64,7 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { | |||
| void define_macro_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { | |||
| if (env->type != Environment_Type_Macro) { | |||
| create_error(Error_Type_Unknown_Error, symbol); | |||
| create_error(Error_Type_Unknown_Error, symbol->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -118,8 +118,9 @@ Ast_Node* lookup_symbol_from_let_or_macro_env(Symbol* sym, Environment* env) { | |||
| return nullptr; | |||
| } | |||
| Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { | |||
| Ast_Node* lookup_symbol(Ast_Node* node, Environment* env) { | |||
| // first check current environment | |||
| Symbol* sym = node->value.symbol; | |||
| Ast_Node* result; | |||
| result = lookup_symbol_in_this_envt(sym, env); | |||
| if (result) | |||
| @@ -147,7 +148,7 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { | |||
| if (result) | |||
| return result; | |||
| create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil()); | |||
| create_error(Error_Type_Symbol_Not_Defined, node->sourceCodeLocation); | |||
| /* printf("%s\n", sym->identifier); */ | |||
| return nullptr; | |||
| } | |||
| @@ -17,7 +17,7 @@ typedef enum { | |||
| typedef struct { | |||
| Error_Type type; | |||
| Ast_Node* location; | |||
| Source_Code_Location* location; | |||
| } Error; | |||
| Error* error; | |||
| @@ -29,7 +29,7 @@ void delete_error() { | |||
| } | |||
| } | |||
| void create_error(Error_Type type, Ast_Node* location) { | |||
| void create_error(Error_Type type, Source_Code_Location* location) { | |||
| delete_error(); | |||
| error = new(Error); | |||
| @@ -19,7 +19,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| arguments->value.pair->first, new_env); | |||
| } else { | |||
| // not enough arguments given | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| arguments = arguments->value.pair->rest; | |||
| @@ -47,7 +47,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| } | |||
| } | |||
| if (!accepted) { | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| @@ -61,7 +61,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| // 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); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -70,7 +70,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| // not already read in, is there a next element to actually | |||
| // set it to? | |||
| if (arguments->value.pair->rest->type != Ast_Node_Type_Pair) { | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| @@ -107,7 +107,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| 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); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| } else { | |||
| @@ -135,7 +135,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, E | |||
| arguments, new_env); | |||
| } else { | |||
| // rest was not declared but additional arguments were found | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -186,13 +186,13 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | |||
| break; | |||
| else { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| } | |||
| if (arguments->value.pair->first->type != Ast_Node_Type_Symbol) { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -208,7 +208,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| // keywords, | |||
| if (arguments->type != Ast_Node_Type_Pair) { | |||
| if (arguments->type != Ast_Node_Type_Nil) | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -219,7 +219,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| if (arguments->type != Ast_Node_Type_Pair || | |||
| arguments->value.pair->first->type != Ast_Node_Type_Symbol) | |||
| { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -228,13 +228,13 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| if (string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | |||
| break; | |||
| else { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| } | |||
| if (arguments->value.pair->first->type != Ast_Node_Type_Symbol) { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -256,7 +256,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| next->value.pair->first); | |||
| arguments = next->value.pair->rest; | |||
| } else { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| } else { | |||
| @@ -274,7 +274,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| // if there is a rest argument | |||
| if (arguments->type != Ast_Node_Type_Pair) { | |||
| if (arguments->type != Ast_Node_Type_Nil) | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| @@ -285,16 +285,16 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||
| if (arguments->type != Ast_Node_Type_Pair || | |||
| arguments->value.pair->first->type != Ast_Node_Type_Symbol) | |||
| { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| return; | |||
| } | |||
| function->rest_argument = arguments->value.pair->first->value.symbol->identifier; | |||
| if (arguments->value.pair->rest->type != Ast_Node_Type_Nil) { | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments); | |||
| create_error(Error_Type_Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | |||
| } | |||
| } else { | |||
| printf("this should not happen?"); | |||
| create_error(Error_Type_Unknown_Error, arguments); | |||
| create_error(Error_Type_Unknown_Error, arguments->sourceCodeLocation); | |||
| } | |||
| } | |||
| @@ -304,7 +304,7 @@ int list_length(Ast_Node* node) { | |||
| return 0; | |||
| if (node->type != Ast_Node_Type_Pair) { | |||
| create_error(Error_Type_Type_Missmatch, node); | |||
| create_error(Error_Type_Type_Missmatch, node->sourceCodeLocation); | |||
| return 0; | |||
| } | |||
| @@ -316,7 +316,7 @@ int list_length(Ast_Node* node) { | |||
| return len; | |||
| } | |||
| create_error(Error_Type_Ill_Formed_List, node); | |||
| create_error(Error_Type_Ill_Formed_List, node->sourceCodeLocation); | |||
| return 0; | |||
| } | |||
| @@ -353,7 +353,7 @@ Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_argumen | |||
| } else if (current_head->type == Ast_Node_Type_Nil) { | |||
| evaluated_arguments_head->value.pair->rest = current_head; | |||
| } else { | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments); | |||
| create_error(Error_Type_Ill_Formed_Arguments, arguments->sourceCodeLocation); | |||
| return nullptr; | |||
| } | |||
| ++(*out_arguments_length); | |||
| @@ -362,9 +362,9 @@ Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_argumen | |||
| } | |||
| Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||
| #define report_error(_type) { \ | |||
| create_error(_type, node); \ | |||
| return nullptr; \ | |||
| #define report_error(_type) { \ | |||
| create_error(_type, node->sourceCodeLocation); \ | |||
| return nullptr; \ | |||
| } | |||
| if (error) | |||
| @@ -378,7 +378,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||
| case Ast_Node_Type_Symbol: { | |||
| Ast_Node* symbol; | |||
| try { | |||
| symbol = lookup_symbol(node->value.symbol, env); | |||
| symbol = lookup_symbol(node, env); | |||
| } | |||
| return symbol; | |||
| } | |||
| @@ -14,6 +14,18 @@ | |||
| } \ | |||
| else label(body,__LINE__): | |||
| #define try_void \ | |||
| if (1) \ | |||
| goto label(body,__LINE__); \ | |||
| else \ | |||
| while (1) \ | |||
| if (1) { \ | |||
| if(error) return; \ | |||
| break; \ | |||
| } \ | |||
| else label(body,__LINE__): | |||
| #define define_array_list(type, name) \ | |||
| typedef struct { \ | |||
| type* data; \ | |||
| @@ -210,3 +222,19 @@ char* read_line() { | |||
| *line = '\0'; | |||
| return linep; | |||
| } | |||
| typedef struct { | |||
| char* file; | |||
| int line; | |||
| } Source_Code_Location; | |||
| Source_Code_Location* create_source_code_location(char* file, int line) { | |||
| if (!file) | |||
| return nullptr; | |||
| Source_Code_Location* ret = new(Source_Code_Location); | |||
| ret->file = file; | |||
| ret->line = line; | |||
| return ret; | |||
| } | |||
| @@ -96,12 +96,19 @@ void print(Ast_Node* node) { | |||
| } | |||
| } | |||
| void print_error_location() { | |||
| if (error->location) { | |||
| printf("%s: %d", error->location->file, error->location->line); | |||
| } else { | |||
| printf("no source code location avaliable"); | |||
| } | |||
| } | |||
| void log_error() { | |||
| printf("%s%s%s\n", console_red, | |||
| Error_Type_to_string(error->type), | |||
| console_normal); | |||
| printf(" in: %s", console_cyan); | |||
| print(error->location); | |||
| print_error_location(error->location); | |||
| printf("%s\n", console_normal); | |||
| } | |||
| @@ -18,30 +18,29 @@ | |||
| #include "./testing.c" | |||
| #include "./init.c" | |||
| int interprete_file (char* file_content) { | |||
| Ast_Node_Array_List* program = parse_program(file_content); | |||
| if (error) { | |||
| log_error(); | |||
| return 1; | |||
| void interprete_file (char* file_name) { | |||
| char* file_content = read_entire_file(file_name); | |||
| if (!file_content) { | |||
| create_error(Error_Type_Unknown_Error, nullptr); | |||
| } | |||
| Ast_Node_Array_List* program; | |||
| try_void { | |||
| parse_program(file_name, file_content); | |||
| } | |||
| Environment* env = create_empty_environment(Environment_Type_Let); | |||
| built_in_load("pre.slime", env); | |||
| if (error) { | |||
| log_error(); | |||
| return 1; | |||
| try_void { | |||
| built_in_load("pre.slime", env); | |||
| } | |||
| 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; | |||
| try_void { | |||
| result = eval_expr(program->data[i], env); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| int interprete_stdin () { | |||
| @@ -81,11 +80,9 @@ int main (int argc, char *argv[]) { | |||
| init(); | |||
| if (argc > 1) { | |||
| 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"); | |||
| interprete_file(argv[1]); | |||
| if (error) { | |||
| log_error(); | |||
| return 1; | |||
| } | |||
| } else { | |||
| @@ -1,3 +1,7 @@ | |||
| char* parser_file; | |||
| int parser_line; | |||
| // TODO(Felix): use the array list macro here? | |||
| Ast_Node_Array_List* create_Ast_Node_Array_List(int initial_length) { | |||
| Ast_Node_Array_List* ret = new (Ast_Node_Array_List); | |||
| @@ -29,6 +33,10 @@ void eat_comment_line(char* text, int* index_in_text) { | |||
| } while (text[(*index_in_text)] != '\n' && | |||
| text[(*index_in_text)] != '\r' && | |||
| text[(*index_in_text)] != '\0'); | |||
| if (text[(*index_in_text)] == '\n') { | |||
| ++parser_line; | |||
| } | |||
| } | |||
| void eat_whitespace(char* text, int* index_in_text) { | |||
| @@ -39,6 +47,9 @@ void eat_whitespace(char* text, int* index_in_text) { | |||
| text[(*index_in_text)] == '\r') { | |||
| ++(*index_in_text); | |||
| } | |||
| if (text[(*index_in_text)] == '\n') { | |||
| ++parser_line; | |||
| } | |||
| } | |||
| void eat_until_code(char* text, int* index_in_text) { | |||
| @@ -130,7 +141,9 @@ Ast_Node* parse_string(char* text, int* index_in_text) { | |||
| char* string = (char*)malloc(string_length*sizeof(char)+1); // plus null char | |||
| if (!unescape_string(text+(*index_in_text))) { | |||
| create_error(Error_Type_Unknown_Error, create_ast_node_nil()); | |||
| create_error( | |||
| Error_Type_Unknown_Error, | |||
| create_source_code_location(parser_file, parser_line)); | |||
| return nullptr; | |||
| } | |||
| strcpy(string, text+(*index_in_text)); | |||
| @@ -223,7 +236,7 @@ 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); | |||
| create_error(Error_Type_Unexpected_Eof, create_source_code_location(parser_file, parser_line)); | |||
| return nullptr; | |||
| } | |||
| @@ -244,7 +257,7 @@ Ast_Node* parse_expression(char* text, int* index_in_text) { | |||
| eat_until_code(text, index_in_text); | |||
| if (text[(*index_in_text)] != ')') | |||
| create_error(Error_Type_Syntax_Error, nullptr); | |||
| create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line)); | |||
| ++(*index_in_text); | |||
| break; | |||
| } else { | |||
| @@ -270,11 +283,13 @@ Ast_Node* parse_single_expression(char* 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()); | |||
| create_error(Error_Type_Trailing_Garbage, create_source_code_location(parser_file, parser_line)); | |||
| return nullptr; | |||
| } | |||
| Ast_Node_Array_List* parse_program(char* text) { | |||
| Ast_Node_Array_List* parse_program(char* file_name, char* text) { | |||
| parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1); | |||
| strcpy(parser_file, file_name); | |||
| Ast_Node_Array_List* program = create_Ast_Node_Array_List(16); | |||
| int index_in_text = 0; | |||
| @@ -297,7 +312,7 @@ Ast_Node_Array_List* parse_program(char* text) { | |||
| } break; | |||
| default: | |||
| /* syntax error */ | |||
| create_error(Error_Type_Syntax_Error, create_ast_node_nil()); | |||
| create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line)); | |||
| return nullptr; | |||
| } | |||
| } | |||