Added some convenience types + impemented and + or
This commit is contained in:
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
((c-mode . ((eval . (flycheck-mode 0))
|
((c-mode . ((eval . (company-clang-set-prefix "main.c"))
|
||||||
|
(eval . (flycheck-mode 0))
|
||||||
(eval . (rainbow-mode 0)))))
|
(eval . (rainbow-mode 0)))))
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ typedef struct Ast_Node Ast_Node;
|
|||||||
Ast_Node* create_ast_node_nil() {
|
Ast_Node* create_ast_node_nil() {
|
||||||
Ast_Node* node = new(Ast_Node);
|
Ast_Node* node = new(Ast_Node);
|
||||||
node->type = Ast_Node_Type_Nil;
|
node->type = Ast_Node_Type_Nil;
|
||||||
node->value.pair = NULL;
|
node->value.pair = nullptr;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ Ast_Node* built_in_divide(Ast_Node* operands) {
|
|||||||
}
|
}
|
||||||
return create_ast_node_number(quotient);
|
return create_ast_node_number(quotient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ typedef struct Environment Environment;
|
|||||||
Environment* create_empty_environment() {
|
Environment* create_empty_environment() {
|
||||||
Environment* env = new(Environment);
|
Environment* env = new(Environment);
|
||||||
|
|
||||||
env->parent = NULL;
|
env->parent = nullptr;
|
||||||
env->key_count = 0;
|
env->key_count = 0;
|
||||||
env->keys = NULL;
|
env->keys = nullptr;
|
||||||
env->values = NULL;
|
env->values = nullptr;
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
@@ -58,5 +58,5 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
|||||||
asprintf(&message, "Symbol not defined: %s\n", sym->identifier);
|
asprintf(&message, "Symbol not defined: %s\n", sym->identifier);
|
||||||
panic(message);
|
panic(message);
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ Error* error;
|
|||||||
void delete_error() {
|
void delete_error() {
|
||||||
if (error) {
|
if (error) {
|
||||||
free(error);
|
free(error);
|
||||||
error = NULL;
|
error = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-10
@@ -5,7 +5,8 @@
|
|||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
|
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) {
|
int list_length(Ast_Node* node) {
|
||||||
if (node->type == Ast_Node_Type_Nil)
|
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) {
|
Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
||||||
#define report_error(_type) \
|
#define report_error(_type) { \
|
||||||
create_error(_type, node); \
|
create_error(_type, node); \
|
||||||
return NULL
|
return nullptr; \
|
||||||
|
}
|
||||||
|
|
||||||
Ast_Node* ret = new(Ast_Node);
|
Ast_Node* ret = new(Ast_Node);
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
@@ -80,7 +82,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
int operands_length = list_length(operands);
|
int operands_length = list_length(operands);
|
||||||
if (operands_length != 2 && operands_length != 3) {
|
if (operands_length != 2 && operands_length != 3) {
|
||||||
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
|
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Node* condition = operands->value.pair->first;
|
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)
|
else if (operands_length == 3)
|
||||||
return eval_expr(else_part->value.pair->first, env);
|
return eval_expr(else_part->value.pair->first, env);
|
||||||
else return create_ast_node_nil();
|
else return create_ast_node_nil();
|
||||||
/* } else if (string_equal("not", operator_name)) { */
|
|
||||||
|
|
||||||
/* } else if (string_equal("and", operator_name)) { */
|
} else if (string_equal("and", operator_name)) {
|
||||||
/* } else if (string_equal("or", 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 {
|
} else {
|
||||||
report_error(Error_Type_Not_Yet_Implemented);
|
report_error(Error_Type_Not_Yet_Implemented);
|
||||||
}
|
}
|
||||||
@@ -112,11 +144,11 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
#undef report_error
|
#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);
|
Ast_Node* result = eval_expr(expression, env);
|
||||||
switch (result->type) {
|
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;
|
case Ast_Node_Type_Number: return result->value.number->value != 0;
|
||||||
default: return 1;
|
default: return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -1,4 +1,7 @@
|
|||||||
#define new(type) (type*)malloc(sizeof(type))
|
#define new(type) (type*)malloc(sizeof(type))
|
||||||
|
#define nullptr NULL
|
||||||
|
|
||||||
|
typedef enum { false, true } bool;
|
||||||
|
|
||||||
int string_equal(char* a, char* b) {
|
int string_equal(char* a, char* b) {
|
||||||
return !strcmp(a, b);
|
return !strcmp(a, b);
|
||||||
@@ -9,7 +12,7 @@ int _vscprintf_so(const char * format, va_list pargs) {
|
|||||||
int retval;
|
int retval;
|
||||||
va_list argcopy;
|
va_list argcopy;
|
||||||
va_copy(argcopy, pargs);
|
va_copy(argcopy, pargs);
|
||||||
retval = vsnprintf(NULL, 0, format, argcopy);
|
retval = vsnprintf(nullptr, 0, format, argcopy);
|
||||||
va_end(argcopy);
|
va_end(argcopy);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -35,9 +38,9 @@ int asprintf(char *strp[], const char *fmt, ...) {
|
|||||||
// asprintf implementation end
|
// asprintf implementation end
|
||||||
|
|
||||||
char* read_entire_file (char* filename) {
|
char* read_entire_file (char* filename) {
|
||||||
char *fileContent = NULL;
|
char *fileContent = nullptr;
|
||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp = fopen(filename, "r");
|
||||||
if (fp != NULL) {
|
if (fp) {
|
||||||
/* Go to the end of the file. */
|
/* Go to the end of the file. */
|
||||||
if (fseek(fp, 0L, SEEK_END) == 0) {
|
if (fseek(fp, 0L, SEEK_END) == 0) {
|
||||||
/* Get the size of the file. */
|
/* Get the size of the file. */
|
||||||
|
|||||||
+1
-1
@@ -8,5 +8,5 @@ Ast_Node* parse_expression(char* expr) {
|
|||||||
// initial state is code
|
// initial state is code
|
||||||
Parser_State current_parser_state = Parser_State_Code;
|
Parser_State current_parser_state = Parser_State_Code;
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-4
@@ -51,10 +51,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define assert_null(variable) \
|
#define assert_null(variable) \
|
||||||
assert_equal_int(variable, NULL)
|
assert_equal_int(variable, nullptr)
|
||||||
|
|
||||||
#define assert_not_null(variable) \
|
#define assert_not_null(variable) \
|
||||||
assert_not_equal_int(variable, NULL)
|
assert_not_equal_int(variable, nullptr)
|
||||||
|
|
||||||
|
|
||||||
#define invoke_test(name) \
|
#define invoke_test(name) \
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
printf("%sfailed%s\n", console_red, console_normal); \
|
printf("%sfailed%s\n", console_red, console_normal); \
|
||||||
if(error) { \
|
if(error) { \
|
||||||
free(error); \
|
free(error); \
|
||||||
error = NULL; \
|
error = nullptr; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
@@ -236,10 +236,47 @@ testresult test_built_in_and() {
|
|||||||
cond1->value.number->value = 0;
|
cond1->value.number->value = 0;
|
||||||
result = eval_expr(form, create_empty_environment());
|
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_no_error(error);
|
||||||
assert_not_null(result);
|
assert_not_null(result);
|
||||||
assert_equal_int(result->type, Ast_Node_Type_Number);
|
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;
|
return pass;
|
||||||
}
|
}
|
||||||
@@ -254,5 +291,6 @@ void run_all_tests() {
|
|||||||
invoke_test(test_built_in_divide);
|
invoke_test(test_built_in_divide);
|
||||||
invoke_test(test_built_in_if);
|
invoke_test(test_built_in_if);
|
||||||
invoke_test(test_built_in_and);
|
invoke_test(test_built_in_and);
|
||||||
|
invoke_test(test_built_in_or);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user