diff --git a/src/.dir-locals.el b/src/.dir-locals.el index b470be0..7b889ee 100644 --- a/src/.dir-locals.el +++ b/src/.dir-locals.el @@ -1,2 +1,3 @@ -((c-mode . ((eval . (flycheck-mode 0)) - (eval . (rainbow-mode 0))))) +((c-mode . ((eval . (company-clang-set-prefix "main.c")) + (eval . (flycheck-mode 0)) + (eval . (rainbow-mode 0))))) diff --git a/src/ast.c b/src/ast.c index 2d25288..e344857 100644 --- a/src/ast.c +++ b/src/ast.c @@ -67,7 +67,7 @@ typedef struct Ast_Node Ast_Node; Ast_Node* create_ast_node_nil() { Ast_Node* node = new(Ast_Node); node->type = Ast_Node_Type_Nil; - node->value.pair = NULL; + node->value.pair = nullptr; return node; } diff --git a/src/built_ins.c b/src/built_ins.c index 408306e..d7131af 100644 --- a/src/built_ins.c +++ b/src/built_ins.c @@ -50,4 +50,3 @@ Ast_Node* built_in_divide(Ast_Node* operands) { } return create_ast_node_number(quotient); } - diff --git a/src/env.c b/src/env.c index c829411..654c008 100644 --- a/src/env.c +++ b/src/env.c @@ -11,10 +11,10 @@ typedef struct Environment Environment; Environment* create_empty_environment() { Environment* env = new(Environment); - env->parent = NULL; + env->parent = nullptr; env->key_count = 0; - env->keys = NULL; - env->values = NULL; + env->keys = nullptr; + env->values = nullptr; return env; } @@ -58,5 +58,5 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) { asprintf(&message, "Symbol not defined: %s\n", sym->identifier); panic(message); - return NULL; + return nullptr; } diff --git a/src/error.c b/src/error.c index c860e12..207c20e 100644 --- a/src/error.c +++ b/src/error.c @@ -18,7 +18,7 @@ Error* error; void delete_error() { if (error) { free(error); - error = NULL; + error = nullptr; } } diff --git a/src/eval.c b/src/eval.c index d698bb0..008516e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5,7 +5,8 @@ /* } */ Ast_Node* eval_expr(Ast_Node* node, Environment* env); -int is_truthy (Ast_Node* expression, Environment* env); +bool is_truthy (Ast_Node* expression, Environment* env); + int list_length(Ast_Node* node) { if (node->type == Ast_Node_Type_Nil) @@ -40,9 +41,10 @@ void eval_operands(Ast_Node* operands, Environment* env) { } Ast_Node* eval_expr(Ast_Node* node, Environment* env) { -#define report_error(_type) \ - create_error(_type, node); \ - return NULL +#define report_error(_type) { \ + create_error(_type, node); \ + return nullptr; \ + } Ast_Node* ret = new(Ast_Node); switch (node->type) { @@ -80,7 +82,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { int operands_length = list_length(operands); if (operands_length != 2 && operands_length != 3) { create_error(Error_Type_Wrong_Number_Of_Arguments, operands); - return NULL; + return nullptr; } Ast_Node* condition = operands->value.pair->first; @@ -92,10 +94,40 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { else if (operands_length == 3) return eval_expr(else_part->value.pair->first, env); else return create_ast_node_nil(); - /* } else if (string_equal("not", operator_name)) { */ - /* } else if (string_equal("and", operator_name)) { */ - /* } else if (string_equal("or", operator_name)) { */ + } else if (string_equal("and", operator_name)) { + bool result = true; + while (operands->type != Ast_Node_Type_Nil) { + if (operands->type != Ast_Node_Type_Pair) { + report_error(Error_Type_Ill_Formed_List); + } + result &= is_truthy(operands->value.pair->first, env); + operands = operands->value.pair->rest; + + if (!result) return create_ast_node_nil(); + } + + return create_ast_node_number(1); + + } else if (string_equal("or", operator_name)) { + bool result = false; + while (operands->type != Ast_Node_Type_Nil) { + if (operands->type != Ast_Node_Type_Pair) { + report_error(Error_Type_Ill_Formed_List); + } + result |= is_truthy(operands->value.pair->first, env); + operands = operands->value.pair->rest; + + if (result) return create_ast_node_number(1);; + } + + return create_ast_node_nil(); + } else if (string_equal("not", operator_name)) { + if (list_length(operands) != 1) { + create_error(Error_Type_Wrong_Number_Of_Arguments, operands); + return nullptr; + } + } else { report_error(Error_Type_Not_Yet_Implemented); } @@ -112,11 +144,11 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { #undef report_error } -int is_truthy (Ast_Node* expression, Environment* env) { +bool is_truthy (Ast_Node* expression, Environment* env) { Ast_Node* result = eval_expr(expression, env); switch (result->type) { - case Ast_Node_Type_Nil: return 0; + case Ast_Node_Type_Nil: return false; case Ast_Node_Type_Number: return result->value.number->value != 0; - default: return 1; + default: return true; } } diff --git a/src/helpers.c b/src/helpers.c index 5fb5d4b..bd29be9 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -1,4 +1,7 @@ #define new(type) (type*)malloc(sizeof(type)) +#define nullptr NULL + +typedef enum { false, true } bool; int string_equal(char* a, char* b) { return !strcmp(a, b); @@ -9,7 +12,7 @@ int _vscprintf_so(const char * format, va_list pargs) { int retval; va_list argcopy; va_copy(argcopy, pargs); - retval = vsnprintf(NULL, 0, format, argcopy); + retval = vsnprintf(nullptr, 0, format, argcopy); va_end(argcopy); return retval; } @@ -35,9 +38,9 @@ int asprintf(char *strp[], const char *fmt, ...) { // asprintf implementation end char* read_entire_file (char* filename) { - char *fileContent = NULL; + char *fileContent = nullptr; FILE *fp = fopen(filename, "r"); - if (fp != NULL) { + if (fp) { /* Go to the end of the file. */ if (fseek(fp, 0L, SEEK_END) == 0) { /* Get the size of the file. */ diff --git a/src/io.c b/src/io.c index bd64486..6f76347 100644 --- a/src/io.c +++ b/src/io.c @@ -24,7 +24,7 @@ void log_message(Log_Level type, char* message) { case Log_Level_Warning: prefix = "WARNING"; break; case Log_Level_Info: prefix = "INFO"; break; case Log_Level_Debug: prefix = "DEBUG"; break; - default: return; + default: return; } printf("%s: %s\n",prefix, message); } diff --git a/src/parse.c b/src/parse.c index f1db90d..7ce6d2a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,5 +8,5 @@ Ast_Node* parse_expression(char* expr) { // initial state is code Parser_State current_parser_state = Parser_State_Code; - return NULL; + return nullptr; } diff --git a/src/testing.c b/src/testing.c index 96ff2e1..0dcbbdf 100644 --- a/src/testing.c +++ b/src/testing.c @@ -51,10 +51,10 @@ } #define assert_null(variable) \ - assert_equal_int(variable, NULL) + assert_equal_int(variable, nullptr) #define assert_not_null(variable) \ - assert_not_equal_int(variable, NULL) + assert_not_equal_int(variable, nullptr) #define invoke_test(name) \ @@ -70,7 +70,7 @@ printf("%sfailed%s\n", console_red, console_normal); \ if(error) { \ free(error); \ - error = NULL; \ + error = nullptr; \ } \ } \ @@ -236,10 +236,47 @@ testresult test_built_in_and() { cond1->value.number->value = 0; result = eval_expr(form, create_empty_environment()); + assert_no_error(error); + assert_not_null(result); + assert_equal_int(result->type, Ast_Node_Type_Nil); + + return pass; +} + +testresult test_built_in_or() { + Ast_Node* _or = create_ast_node_symbol("or"); + Ast_Node* cond1 = create_ast_node_nil(); + Ast_Node* cond2 = create_ast_node_string("asd"); + Ast_Node* nil = create_ast_node_nil(); + Ast_Node* form = create_ast_node_pair( + _or, + create_ast_node_pair( + cond1, + create_ast_node_pair( + cond2, nil))); + Ast_Node* result; + + // a true case + result = eval_expr(form, create_empty_environment()); + assert_no_error(error); assert_not_null(result); assert_equal_int(result->type, Ast_Node_Type_Number); - assert_equal_double(result->value.number->value, 0); + assert_equal_double(result->value.number->value, 1); + + // a false case + cond2 = create_ast_node_nil(); + form = create_ast_node_pair( + _or, + create_ast_node_pair( + cond1, + create_ast_node_pair( + cond2, nil))); + result = eval_expr(form, create_empty_environment()); + + assert_no_error(error); + assert_not_null(result); + assert_equal_int(result->type, Ast_Node_Type_Nil); return pass; } @@ -254,5 +291,6 @@ void run_all_tests() { invoke_test(test_built_in_divide); invoke_test(test_built_in_if); invoke_test(test_built_in_and); + invoke_test(test_built_in_or); }