Просмотр исходного кода

Added some convenience types + impemented and + or

master
FelixBrendel 7 лет назад
Родитель
Сommit
12a200534f
10 измененных файлов: 102 добавлений и 29 удалений
  1. +3
    -2
      src/.dir-locals.el
  2. +1
    -1
      src/ast.c
  3. +0
    -1
      src/built_ins.c
  4. +4
    -4
      src/env.c
  5. +1
    -1
      src/error.c
  6. +43
    -11
      src/eval.c
  7. +6
    -3
      src/helpers.c
  8. +1
    -1
      src/io.c
  9. +1
    -1
      src/parse.c
  10. +42
    -4
      src/testing.c

+ 3
- 2
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)))))

+ 1
- 1
src/ast.c Просмотреть файл

@@ -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;
} }




+ 0
- 1
src/built_ins.c Просмотреть файл

@@ -50,4 +50,3 @@ Ast_Node* built_in_divide(Ast_Node* operands) {
} }
return create_ast_node_number(quotient); return create_ast_node_number(quotient);
} }


+ 4
- 4
src/env.c Просмотреть файл

@@ -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->values = NULL;
env->keys = nullptr;
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
src/error.c Просмотреть файл

@@ -18,7 +18,7 @@ Error* error;
void delete_error() { void delete_error() {
if (error) { if (error) {
free(error); free(error);
error = NULL;
error = nullptr;
} }
} }




+ 43
- 11
src/eval.c Просмотреть файл

@@ -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) \
create_error(_type, node); \
return NULL
#define report_error(_type) { \
create_error(_type, node); \
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("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 { } 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
src/helpers.c Просмотреть файл

@@ -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
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_Warning: prefix = "WARNING"; break;
case Log_Level_Info: prefix = "INFO"; break; case Log_Level_Info: prefix = "INFO"; break;
case Log_Level_Debug: prefix = "DEBUG"; break; case Log_Level_Debug: prefix = "DEBUG"; break;
default: return;
default: return;
} }
printf("%s: %s\n",prefix, message); printf("%s: %s\n",prefix, message);
} }


+ 1
- 1
src/parse.c Просмотреть файл

@@ -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
src/testing.c Просмотреть файл

@@ -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);


} }

Загрузка…
Отмена
Сохранить