From 2006e3b45cc188960fc65eea9c0327a7d14789c3 Mon Sep 17 00:00:00 2001 From: FelixBrendel Date: Sat, 13 Oct 2018 22:51:01 +0200 Subject: [PATCH] Use the parse arguments --- src/assert.c | 11 ++---- src/ast.c | 13 +++++++ src/built_ins.c | 92 ++++++++++++++++++++++++------------------------- src/error.c | 2 ++ src/eval.c | 73 +++++++++++++++++++++++++++++---------- src/init.c | 18 ++++++++++ src/main.c | 4 ++- src/parse.c | 6 ---- 8 files changed, 139 insertions(+), 80 deletions(-) create mode 100644 src/init.c diff --git a/src/assert.c b/src/assert.c index ea07f62..d2dd9aa 100644 --- a/src/assert.c +++ b/src/assert.c @@ -1,13 +1,6 @@ void assert_type (Ast_Node* node, Ast_Node_Type type) { + if (!node) + create_error(Error_Type_Unknown_Error, node); if (node->type == type) return; - - /* char *wanted, *got, *message; */ - /* wanted = Ast_Node_Type_to_string(type); */ - /* got = Ast_Node_Type_to_string(node->type); */ - /* asprintf(&message, "Type assertion failed:\n\t" */ - /* "Wanted: %s\n\t" */ - /* "Got : %s\n", wanted, got); */ - /* panic(message); */ - create_error(Error_Type_Type_Missmatch, node); } diff --git a/src/ast.c b/src/ast.c index 96c4ec3..2215d7b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -134,6 +134,19 @@ struct Ast_Node { // was forward declarated typedef struct Ast_Node Ast_Node; +typedef struct { + Ast_Node** data; + int length; + int next_index; +} Ast_Node_Array_List; + +typedef struct { + Ast_Node_Array_List* positional_arguments; + // TODO(Felix): Really use hashmap (keyword[sting] -> + // value[Ast_Node*]) here + Ast_Node_Array_List* keyword_keys; + Ast_Node_Array_List* keyword_values; +} Parsed_Arguments; Ast_Node* create_ast_node_nil() { Ast_Node* node = new(Ast_Node); diff --git a/src/built_ins.c b/src/built_ins.c index 259eba0..bd1c660 100644 --- a/src/built_ins.c +++ b/src/built_ins.c @@ -39,84 +39,84 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) { return false; } -Ast_Node* built_in_equals(Ast_Node* operands) { - if (operands->type == Ast_Node_Type_Nil) - return create_ast_node_number(1); - - Ast_Node* first = operands->value.pair->first; - - while (operands->type == Ast_Node_Type_Pair) { - if (!ast_node_equal(operands->value.pair->first, first)) +Ast_Node* built_in_equals(Parsed_Arguments* arguments) { + for (int i = 0; i < arguments->positional_arguments->next_index-1; ++i) { + if (!ast_node_equal( + arguments->positional_arguments->data[i], + arguments->positional_arguments->data[i+1])) return create_ast_node_nil(); - operands = operands->value.pair->rest; } - return create_ast_node_number(1); } -Ast_Node* built_in_add(Ast_Node* operands) { +Ast_Node* built_in_add(Parsed_Arguments* arguments) { double sum = 0; - while (operands->type == Ast_Node_Type_Pair) { + for (int i = 0; i < arguments->positional_arguments->next_index; ++i) { try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number); } - sum += operands->value.pair->first->value.number->value; - operands = operands->value.pair->rest; + sum += arguments->positional_arguments->data[i]->value.number->value; } return create_ast_node_number(sum); } -Ast_Node* built_in_substract(Ast_Node* operands) { +Ast_Node* built_in_substract(Parsed_Arguments* arguments) { + if (arguments->positional_arguments->next_index == 0) + return create_ast_node_number(0); + try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(*arguments->positional_arguments->data, 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) { + if (arguments->positional_arguments->next_index == 1) { + return create_ast_node_number(-(*arguments->positional_arguments->data)->value.number->value); + } + + // okay we have at least 2 arguments + double difference = (*arguments->positional_arguments->data)->value.number->value; + for (int i = 1; i < arguments->positional_arguments->next_index; ++i) { try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number); } - - difference -= operands->value.pair->first->value.number->value; - operands = operands->value.pair->rest; + difference -= arguments->positional_arguments->data[i]->value.number->value; } + 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); - } - double product = operands->value.pair->first->value.number->value; - - operands = operands->value.pair->rest; - while (operands->type == Ast_Node_Type_Pair) { +Ast_Node* built_in_multiply(Parsed_Arguments* arguments) { + double product = 1; + for (int i = 0; i < arguments->positional_arguments->next_index; ++i) { try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number); } - - product *= operands->value.pair->first->value.number->value; - operands = operands->value.pair->rest; + product *= arguments->positional_arguments->data[i]->value.number->value; } + return create_ast_node_number(product); } -Ast_Node* built_in_divide(Ast_Node* operands) { +Ast_Node* built_in_divide(Parsed_Arguments* arguments) { + if (arguments->positional_arguments->next_index == 0) + return create_ast_node_number(1); + try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(*arguments->positional_arguments->data, 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) { + if (arguments->positional_arguments->next_index == 1) { + return create_ast_node_number((*arguments->positional_arguments->data)->value.number->value); + } + + // okay we have at least 2 arguments + double difference = (*arguments->positional_arguments->data)->value.number->value; + for (int i = 1; i < arguments->positional_arguments->next_index; ++i) { try { - assert_type(operands->value.pair->first, Ast_Node_Type_Number); + assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number); } - - quotient /= operands->value.pair->first->value.number->value; - operands = operands->value.pair->rest; + difference /= arguments->positional_arguments->data[i]->value.number->value; } - return create_ast_node_number(quotient); + + return create_ast_node_number(difference); } diff --git a/src/error.c b/src/error.c index b83e07b..b95fb9c 100644 --- a/src/error.c +++ b/src/error.c @@ -2,6 +2,7 @@ typedef enum { Error_Type_Ill_Formed_List, Error_Type_Ill_Formed_Arguments, Error_Type_Wrong_Number_Of_Arguments, + Error_Type_Unknown_Keyword_Argument, Error_Type_Type_Missmatch, Error_Type_Symbol_Not_Defined, Error_Type_Not_A_Function, @@ -39,6 +40,7 @@ char* Error_Type_to_string(Error_Type type) { switch (type) { case Error_Type_Ill_Formed_List: return "Evaluation-error: Ill formed list"; case Error_Type_Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments"; + case Error_Type_Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument"; case Error_Type_Not_A_Function: return "Evaluation-error: Not a function"; case Error_Type_Symbol_Not_Defined: return "Evaluation-error: Symbol not defined"; case Error_Type_Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments"; diff --git a/src/eval.c b/src/eval.c index 7222487..a98ed3e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -56,14 +56,6 @@ Ast_Node* copy_list(Ast_Node* node) { return result; } -typedef struct { - Ast_Node_Array_List* positional_arguments; - // TODO(Felix): Really use hashmap (keyword[sting] -> - // value[Ast_Node*]) here - Ast_Node_Array_List* keyword_keys; - Ast_Node_Array_List* keyword_values; -} Parsed_Arguments; - Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env) { // TODO(Felix): if arguments is nil then maybe return a constant // Parsed_Arguments_nil? @@ -114,6 +106,15 @@ Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env return result; } +Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { + // NOTE(Felix): This will be a hashmap lookup later + for (int i = 0; i < args->keyword_keys->next_index; ++i) { + if (string_equal(args->keyword_keys->data[i]->value.keyword->identifier, keyword)) + return args->keyword_values->data[i]; + } + return nullptr; +} + Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_arguments_length) { *out_arguments_length = 0; if (arguments->type == Ast_Node_Type_Nil) { @@ -279,25 +280,27 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { // to evaluate the arguments; eval_arguments will also tell // us the arguments_length. Ast_Node* evaluated_arguments; + Parsed_Arguments* evaluated_and_parsed_arguments; try { evaluated_arguments = eval_arguments(arguments, env, &arguments_length); + evaluated_and_parsed_arguments = eval_and_parse_arguments(arguments, env); } switch (operator->value.built_in_function->type) { case Built_In_Addition: { - return built_in_add(evaluated_arguments); + return built_in_add(evaluated_and_parsed_arguments); } case Built_In_Subtraction: { - return built_in_substract(evaluated_arguments); + return built_in_substract(evaluated_and_parsed_arguments); } case Built_In_Multiplication: { - return built_in_multiply(evaluated_arguments); + return built_in_multiply(evaluated_and_parsed_arguments); } case Built_In_Division: { - return built_in_divide(evaluated_arguments); + return built_in_divide(evaluated_and_parsed_arguments); } case Built_In_Equal: { - return built_in_equals(evaluated_arguments); + return built_in_equals(evaluated_and_parsed_arguments); } case Built_In_Pair: { if (arguments_length != 2) { @@ -355,12 +358,46 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { return evaluated_arguments; } case Built_In_Print: { - if (arguments_length != 1) { + /* if (arguments_length != 1) { */ + /* report_error(Error_Type_Wrong_Number_Of_Arguments); */ + /* } */ + /* print(evaluated_arguments->value.pair->first); */ + /* printf("\n"); */ + /* return arguments->value.pair->first; */ + + if (evaluated_and_parsed_arguments->positional_arguments->next_index == 0) { report_error(Error_Type_Wrong_Number_Of_Arguments); } - print(evaluated_arguments->value.pair->first); - printf("\n"); - return arguments->value.pair->first; + + char* sep = " "; + char* end = "\n"; + + Ast_Node* temp = extract_keyword_value("sep", evaluated_and_parsed_arguments); + if (temp) { + try { + assert_type(temp, Ast_Node_Type_String); + } + sep = temp->value.string->value; + } + + temp = extract_keyword_value("end", evaluated_and_parsed_arguments); + if (temp) { + try { + assert_type(temp, Ast_Node_Type_String); + } + end = temp->value.string->value; + } + + print(*evaluated_and_parsed_arguments->positional_arguments->data); + for (int i = 1; i < evaluated_and_parsed_arguments->positional_arguments->next_index; ++i) { + printf("%s", sep); + print(*(evaluated_and_parsed_arguments->positional_arguments->data+i)); + } + printf("%s", end); + + // return last positional argument + return *(evaluated_and_parsed_arguments->positional_arguments->data+ + (evaluated_and_parsed_arguments->positional_arguments->next_index-1)); } case Built_In_Read: { if (arguments_length > 1) { @@ -415,7 +452,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { } - // assume it's lambda function and evaluate the arguments + // assume it's lambda function and evaluate the arguments arguments = eval_arguments(arguments, env, &arguments_length); } diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..0936392 --- /dev/null +++ b/src/init.c @@ -0,0 +1,18 @@ +// for colored console output +#ifdef _WIN32 +#include +#pragma comment(lib, "Kernel32.lib") +#endif + +void init () { + // On Windows: manually enable colored console output +#ifdef _WIN32 + SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), + ENABLE_PROCESSED_OUTPUT | + ENABLE_WRAP_AT_EOL_OUTPUT | + ENABLE_VIRTUAL_TERMINAL_PROCESSING); +#endif + + // TODO(Felix): Init the constants here (Bulit-in function + // ast_nodes, nil, ..more?) +} diff --git a/src/main.c b/src/main.c index bcb9172..c2275bc 100644 --- a/src/main.c +++ b/src/main.c @@ -15,6 +15,7 @@ #include "./built_ins.c" #include "./eval.c" #include "./testing.c" +#include "./init.c" int interprete_file (char* file_content) { Ast_Node_Array_List* program = parse_program(file_content); @@ -62,8 +63,9 @@ int interprete_stdin () { return 0; } - int main (int argc, char *argv[]) { + init(); + if (argc > 1) { char* file_content = read_entire_file(argv[1]); if (file_content) { diff --git a/src/parse.c b/src/parse.c index f191246..c0b63e8 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,9 +1,3 @@ -typedef struct { - Ast_Node** data; - int length; - int next_index; -} Ast_Node_Array_List; - Ast_Node_Array_List* create_Ast_Node_Array_List() { Ast_Node_Array_List* ret = new (Ast_Node_Array_List);