Explorar el Código

added error types and stuff

master
Felix Brendel hace 7 años
padre
commit
4c33538e8a
Se han modificado 8 ficheros con 157 adiciones y 108 borrados
  1. +1
    -1
      .dir-locals.el
  2. +16
    -16
      ast.c
  3. +25
    -25
      built_ins.c
  4. +39
    -2
      error.c
  5. +32
    -28
      eval.c
  6. +28
    -26
      io.c
  7. +6
    -9
      testing.c
  8. +10
    -1
      todo.org

+ 1
- 1
.dir-locals.el Ver fichero

@@ -1,2 +1,2 @@
((nil . ((eval . (flycheck-mode 0))
((c-mode . ((eval . (flycheck-mode 0))
(eval . (rainbow-mode 0))))) (eval . (rainbow-mode 0)))))

+ 16
- 16
ast.c Ver fichero

@@ -8,7 +8,7 @@ typedef enum {
Ast_Node_Type_Number, Ast_Node_Type_Number,
Ast_Node_Type_String, Ast_Node_Type_String,


Ast_Node_Type_Cons_Cell,
Ast_Node_Type_Pair,
Ast_Node_Type_Function, Ast_Node_Type_Function,
Ast_Node_Type_Built_In_Function, Ast_Node_Type_Built_In_Function,
} Ast_Node_Type; } Ast_Node_Type;
@@ -32,16 +32,16 @@ typedef struct {
typedef struct { typedef struct {
struct Ast_Node* first; struct Ast_Node* first;
struct Ast_Node* rest; struct Ast_Node* rest;
} Cons_Cell;
} Pair;


typedef struct { typedef struct {
Cons_Cell* regular_params;
Cons_Cell* keyword_params;
Pair* regular_params;
Pair* keyword_params;
} Lambda_List; } Lambda_List;


typedef struct { typedef struct {
Lambda_List* parameters; Lambda_List* parameters;
Cons_Cell* form;
Pair* form;
} Function; } Function;


typedef struct { typedef struct {
@@ -51,12 +51,12 @@ typedef struct {
struct Ast_Node { struct Ast_Node {
Ast_Node_Type type; Ast_Node_Type type;
union { union {
Symbol* symbol;
Keyword* keyword;
Number* number;
String* string;
Cons_Cell* cons_cell;
Function* function;
Symbol* symbol;
Keyword* keyword;
Number* number;
String* string;
Pair* pair;
Function* function;
Built_In_Function* built_in_function; Built_In_Function* built_in_function;
} value; } value;
}; };
@@ -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.cons_cell = NULL;
node->value.pair = NULL;
return node; return node;
} }


@@ -106,9 +106,9 @@ Ast_Node* create_ast_node_built_in_function(char* identifier) {


Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) { Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) {
Ast_Node* node = new(Ast_Node); Ast_Node* node = new(Ast_Node);
node->type = Ast_Node_Type_Cons_Cell;
node->value.cons_cell = new(Cons_Cell);
node->value.cons_cell->first = first;
node->value.cons_cell->rest = rest;
node->type = Ast_Node_Type_Pair;
node->value.pair = new(Pair);
node->value.pair->first = first;
node->value.pair->rest = rest;
return node; return node;
} }

+ 25
- 25
built_ins.c Ver fichero

@@ -1,52 +1,52 @@
Ast_Node* built_in_add(Ast_Node* operands) { Ast_Node* built_in_add(Ast_Node* operands) {
double sum = 0; double sum = 0;
while (operands->type == Ast_Node_Type_Cons_Cell) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
sum += operands->value.cons_cell->first->value.number->value;
operands = operands->value.cons_cell->rest;
while (operands->type == Ast_Node_Type_Pair) {
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); return create_ast_node_number(sum);
} }


Ast_Node* built_in_substract(Ast_Node* operands) { Ast_Node* built_in_substract(Ast_Node* operands) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
double difference = operands->value.cons_cell->first->value.number->value;
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
double difference = operands->value.pair->first->value.number->value;


operands = operands->value.cons_cell->rest;
while (operands->type == Ast_Node_Type_Cons_Cell) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);


difference -= operands->value.cons_cell->first->value.number->value;
operands = operands->value.cons_cell->rest;
difference -= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
} }
return create_ast_node_number(difference); return create_ast_node_number(difference);
} }


Ast_Node* built_in_multiply(Ast_Node* operands) { Ast_Node* built_in_multiply(Ast_Node* operands) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
double product = operands->value.cons_cell->first->value.number->value;
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
double product = operands->value.pair->first->value.number->value;


operands = operands->value.cons_cell->rest;
while (operands->type == Ast_Node_Type_Cons_Cell) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);


product *= operands->value.cons_cell->first->value.number->value;
operands = operands->value.cons_cell->rest;
product *= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
} }
return create_ast_node_number(product); return create_ast_node_number(product);
} }


Ast_Node* built_in_divide(Ast_Node* operands) { Ast_Node* built_in_divide(Ast_Node* operands) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
double quotient = operands->value.cons_cell->first->value.number->value;
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
double quotient = operands->value.pair->first->value.number->value;


operands = operands->value.cons_cell->rest;
while (operands->type == Ast_Node_Type_Cons_Cell) {
assert_type(operands->value.cons_cell->first, Ast_Node_Type_Number);
operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);


quotient /= operands->value.cons_cell->first->value.number->value;
operands = operands->value.cons_cell->rest;
quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
} }
return create_ast_node_number(quotient); return create_ast_node_number(quotient);
} }

+ 39
- 2
error.c Ver fichero

@@ -1,6 +1,43 @@
typedef enum {
Error_Type_Ill_Formed_List,
Error_Type_Wrong_Number_Of_Arguments,
Error_Type_Type_Missmatch,
Error_Type_Symbol_Not_Defined,
Error_Type_Not_A_Function,
Error_Type_Not_Yet_Implemented,
Error_Type_Unknown_Error,
} Error_Type;

typedef struct { typedef struct {
char* message;
Ast_Node* location;
Error_Type type;
Ast_Node* location;
} Error; } Error;


Error* error; Error* error;

void delete_error() {
if (error) {
free(error);
error = NULL;
}
}

void create_error(Error_Type type, Ast_Node* location) {
delete_error();

error = new(Error);
error->type = type;
error->location = location;
}

char* Error_Type_to_string(Error_Type type) {
switch (type) {
case Error_Type_Ill_Formed_List: return "Ill formed list";
case Error_Type_Not_A_Function: return "Not a function";
case Error_Type_Symbol_Not_Defined: return "Symbol not defined";
case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments";
case Error_Type_Type_Missmatch: return "Type Missmatch";
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
case Error_Type_Unknown_Error: return "Unknown Error";
}
}

+ 32
- 28
eval.c Ver fichero

@@ -7,24 +7,29 @@
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); int is_truthy (Ast_Node* expression, Environment* env);


int list_length(Ast_Node* node) {
if (node->type != Ast_Node_Type_Pair) {
create_error(Error_Type_Type_Missmatch, node);
return 0;
}

return 1;
}

void eval_operands(Ast_Node* operands, Environment* env) { void eval_operands(Ast_Node* operands, Environment* env) {
while (!error) { while (!error) {
if (operands->type == Ast_Node_Type_Cons_Cell) {
operands->value.cons_cell->first = eval_expr(operands->value.cons_cell->first, env);
operands = operands->value.cons_cell->rest;
if (operands->type == Ast_Node_Type_Pair) {
operands->value.pair->first = eval_expr(operands->value.pair->first, env);
operands = operands->value.pair->rest;
} else { } else {
return; return;
} }
} }
// if we reach here we got an error
log_error("An error occurred while evaluating operands to a function:");
} }


Ast_Node* eval_expr(Ast_Node* node, Environment* env) { Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
#define report_error(_message) \
error = new(Error); \
error->message = _message; \
error->location = node; \
#define report_error(_type) \
create_error(_type, node); \
return NULL return NULL


Ast_Node* ret = new(Ast_Node); Ast_Node* ret = new(Ast_Node);
@@ -38,15 +43,15 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Ast_Node_Type_String: case Ast_Node_Type_String:
return node; return node;


case Ast_Node_Type_Cons_Cell: {
Ast_Node* operator = eval_expr(node->value.cons_cell->first, env);
Ast_Node* operands = node->value.cons_cell->rest;
case Ast_Node_Type_Pair: {
Ast_Node* operator = eval_expr(node->value.pair->first, env);
Ast_Node* operands = node->value.pair->rest;


// check for built ins functions // check for built ins functions
if (operator->type == Ast_Node_Type_Built_In_Function) { if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier; char* operator_name = operator->value.built_in_function->identifier;
if (string_equal("quote", operator_name)) { if (string_equal("quote", operator_name)) {
return node->value.cons_cell->rest;
return node->value.pair->rest;
} else if (string_equal("+", operator_name)) { } else if (string_equal("+", operator_name)) {
eval_operands(operands, env); eval_operands(operands, env);
return built_in_add(operands); return built_in_add(operands);
@@ -60,25 +65,24 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
eval_operands(operands, env); eval_operands(operands, env);
return built_in_divide(operands); return built_in_divide(operands);
} else if (string_equal("if", operator_name)) { } else if (string_equal("if", operator_name)) {
if (Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->type ||
Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->value.cons_cell->rest->type ||
Ast_Node_Type_Nil != operands->value.cons_cell->rest->value.cons_cell->rest->value.cons_cell->rest->type)
{
report_error("Ill formed if statement");
if (list_length(operands) != 3) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
} }


Ast_Node* then_part = operands->value.cons_cell->rest;
Ast_Node* else_part = then_part->value.cons_cell->rest;
Ast_Node* condition = operands->value.pair->first;
Ast_Node* then_part = operands->value.pair->rest;
Ast_Node* else_part = then_part->value.pair->rest;


if (is_truthy(operands->value.cons_cell->first, env))
return eval_expr(then_part->value.cons_cell->first, env);
if (is_truthy(condition, env))
return eval_expr(then_part->value.pair->first, env);
else else
return eval_expr(else_part->value.cons_cell->first, env);
} else if (string_equal("not", operator_name)) {
} else if (string_equal("and", operator_name)) {
} else if (string_equal("or", operator_name)) {
return eval_expr(else_part->value.pair->first, env);
/* } else if (string_equal("not", operator_name)) { */

/* } else if (string_equal("and", operator_name)) { */
/* } else if (string_equal("or", operator_name)) { */
} else { } else {
report_error("The operator is not yet implemented");
report_error(Error_Type_Not_Yet_Implemented);
} }
} }


@@ -88,7 +92,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
} }


default: default:
report_error("Unknown error");
report_error(Error_Type_Unknown_Error);
} }
#undef report_error #undef report_error
} }


+ 28
- 26
io.c Ver fichero

@@ -1,3 +1,8 @@
#define console_normal "\x1B[0m"
#define console_red "\x1B[31m"
#define console_green "\x1B[32m"
#define console_cyan "\x1B[36m"

typedef enum { typedef enum {
Log_Level_None, Log_Level_None,


@@ -24,11 +29,6 @@ void log_message(Log_Level type, char* message) {
printf("%s: %s\n",prefix, message); printf("%s: %s\n",prefix, message);
} }


void log_error(char* message) {
log_message(Log_Level_Critical, message);
log_message(Log_Level_Critical, error->message);
}



void panic(char* message) { void panic(char* message) {
log_message(Log_Level_Critical, message); log_message(Log_Level_Critical, message);
@@ -36,24 +36,16 @@ void panic(char* message) {
} }




char* Ast_Node_Type_to_string (Ast_Node_Type type) {
char* Ast_Node_Type_to_string(Ast_Node_Type type) {
switch (type) { switch (type) {
case(Ast_Node_Type_Nil):
return "nil";
case(Ast_Node_Type_Number):
return "number";
case(Ast_Node_Type_String):
return "string";
case(Ast_Node_Type_Symbol):
return "symbol";
case(Ast_Node_Type_Keyword):
return "keyword";
case(Ast_Node_Type_Function):
return "function";
case(Ast_Node_Type_Built_In_Function):
return "built-in function";
case(Ast_Node_Type_Cons_Cell):
return "pair";
case(Ast_Node_Type_Nil): return "nil";
case(Ast_Node_Type_Number): return "number";
case(Ast_Node_Type_String): return "string";
case(Ast_Node_Type_Symbol): return "symbol";
case(Ast_Node_Type_Keyword): return "keyword";
case(Ast_Node_Type_Function): return "function";
case(Ast_Node_Type_Built_In_Function): return "built-in function";
case(Ast_Node_Type_Pair): return "pair";
} }
} }


@@ -80,14 +72,14 @@ void print(Ast_Node* node) {
case (Ast_Node_Type_Built_In_Function): { case (Ast_Node_Type_Built_In_Function): {
printf("[built-in-function %s]", node->value.built_in_function->identifier); printf("[built-in-function %s]", node->value.built_in_function->identifier);
} break; } break;
case (Ast_Node_Type_Cons_Cell): {
case (Ast_Node_Type_Pair): {
Ast_Node* head = node; Ast_Node* head = node;
printf("("); printf("(");


while (1) { while (1) {
print(head->value.cons_cell->first);
head = head->value.cons_cell->rest;
if (head->type != Ast_Node_Type_Cons_Cell)
print(head->value.pair->first);
head = head->value.pair->rest;
if (head->type != Ast_Node_Type_Pair)
break; break;
printf(" "); printf(" ");
} }
@@ -101,3 +93,13 @@ void print(Ast_Node* node) {
} break; } break;
} }
} }


void log_error() {
printf("\t%s%s%s\n", console_red,
Error_Type_to_string(error->type),
console_normal);
printf("\t in: %s", console_cyan);
print(error->location);
printf("%s\n", console_normal);
}

+ 6
- 9
testing.c Ver fichero

@@ -1,7 +1,3 @@
#define console_normal "\x1B[0m"
#define console_red "\x1B[31m"
#define console_green "\x1B[32m"

#define epsilon 2.2204460492503131E-16 #define epsilon 2.2204460492503131E-16


#define testresult int #define testresult int
@@ -16,16 +12,18 @@
__FILE__, __LINE__, (type)value, (type)variable) __FILE__, __LINE__, (type)value, (type)variable)


#define print_assert_not_equal_fail(variable, value, type, format) \ #define print_assert_not_equal_fail(variable, value, type, format) \
printf("\n\tAssertion failed for '" #variable "'" \
printf("\n\tAssertion failed for '" #variable "'" \
"\n\t in %s:%d" \ "\n\t in %s:%d" \
"\n\texpected not: " format \ "\n\texpected not: " format \
"\n\tgot anyways: " format "\n", \ "\n\tgot anyways: " format "\n", \
__FILE__, __LINE__, (type)value, (type)variable) __FILE__, __LINE__, (type)value, (type)variable)


/* print_assert_not_equal_fail(error, 0, int, "%d"); \ */
#define assert_no_error(error) \ #define assert_no_error(error) \
if (error) { \ if (error) { \
print_assert_not_equal_fail(error, 0, int, "%d"); \
printf("\t%s%s%s\n", console_red, error->message,console_normal); \
printf("\n\tExpected no error to occur," \
" but an error occured anyways:\n"); \
log_error(); \
return fail; \ return fail; \
} \ } \


@@ -63,13 +61,12 @@
#define invoke_test(name) \ #define invoke_test(name) \
printf("" #name ":"); \ printf("" #name ":"); \
for(int i = 0; i < 45 - strlen(#name); ++i) \ for(int i = 0; i < 45 - strlen(#name); ++i) \
printf(" "); \
printf(" "); \
if (name() == pass) \ if (name() == pass) \
printf("%spassed%s\n", console_green, console_normal); \ printf("%spassed%s\n", console_green, console_normal); \
else { \ else { \
printf("%sfailed%s\n", console_red, console_normal); \ printf("%sfailed%s\n", console_red, console_normal); \
if(error) { \ if(error) { \
log_error("Error while running test" #name); \
free(error); \ free(error); \
error = NULL; \ error = NULL; \
} \ } \


+ 10
- 1
todo.org Ver fichero

@@ -14,9 +14,18 @@


** DONE if ** DONE if
CLOSED: [2018-09-18 Di 12:14] CLOSED: [2018-09-18 Di 12:14]
** TODO and
** TODO and (short circuiting)
** TODO or ** TODO or
** TODO not ** TODO not
#+begin_src emacs-lisp
(not 1) ;; == (not . (1 . nil))
(not (expression 1 3)) ;; == (not . ((expression . (1 . (3 . nil))) . nil))
(not) ;; == (not . nil)
(not 1 2) ;; == (not . (1 . (2 . nil)))
#+end_src

#+RESULTS:
: t


** TODO first (car) ** TODO first (car)
** TODO rest (cdr) ** TODO rest (cdr)


Cargando…
Cancelar
Guardar