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

+ 16
- 16
ast.c Ver fichero

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

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

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

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

typedef struct {
@@ -51,12 +51,12 @@ typedef struct {
struct Ast_Node {
Ast_Node_Type type;
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;
} value;
};
@@ -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.cons_cell = NULL;
node->value.pair = NULL;
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* 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;
}

+ 25
- 25
built_ins.c Ver fichero

@@ -1,52 +1,52 @@
Ast_Node* built_in_add(Ast_Node* operands) {
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);
}

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

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

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

+ 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 {
char* message;
Ast_Node* location;
Error_Type type;
Ast_Node* location;
} 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);
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) {
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 {
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) {
#define report_error(_message) \
error = new(Error); \
error->message = _message; \
error->location = node; \
#define report_error(_type) \
create_error(_type, node); \
return NULL

Ast_Node* ret = new(Ast_Node);
@@ -38,15 +43,15 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Ast_Node_Type_String:
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
if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier;
if (string_equal("quote", operator_name)) {
return node->value.cons_cell->rest;
return node->value.pair->rest;
} else if (string_equal("+", operator_name)) {
eval_operands(operands, env);
return built_in_add(operands);
@@ -60,25 +65,24 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
eval_operands(operands, env);
return built_in_divide(operands);
} 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
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 {
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:
report_error("Unknown error");
report_error(Error_Type_Unknown_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 {
Log_Level_None,

@@ -24,11 +29,6 @@ void log_message(Log_Level type, char* 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) {
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) {
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): {
printf("[built-in-function %s]", node->value.built_in_function->identifier);
} break;
case (Ast_Node_Type_Cons_Cell): {
case (Ast_Node_Type_Pair): {
Ast_Node* head = node;
printf("(");

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;
printf(" ");
}
@@ -101,3 +93,13 @@ void print(Ast_Node* node) {
} 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 testresult int
@@ -16,16 +12,18 @@
__FILE__, __LINE__, (type)value, (type)variable)

#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\texpected not: " format \
"\n\tgot anyways: " format "\n", \
__FILE__, __LINE__, (type)value, (type)variable)

/* print_assert_not_equal_fail(error, 0, int, "%d"); \ */
#define assert_no_error(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; \
} \

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


+ 10
- 1
todo.org Ver fichero

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

** DONE if
CLOSED: [2018-09-18 Di 12:14]
** TODO and
** TODO and (short circuiting)
** TODO or
** 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 rest (cdr)


Cargando…
Cancelar
Guardar