Explorar el Código

fixed some bugs and stuff

master
FelixBrendel hace 7 años
padre
commit
2d3892b034
Se han modificado 7 ficheros con 162 adiciones y 66 borrados
  1. +2
    -12
      bin/test.lsp
  2. +1
    -0
      debug.bat
  3. +110
    -46
      src/eval.c
  4. +4
    -4
      src/helpers.c
  5. +2
    -4
      src/main.c
  6. +36
    -0
      src/testing.c
  7. +7
    -0
      todo.org

+ 2
- 12
bin/test.lsp Ver fichero

@@ -1,12 +1,2 @@
((lambda (x) (* x x)) 2)

(setq a 3)

(let ((a 10))
(let ((b 5))
(setq a 4))
a)


a

(define operators (list + - * /))
(print ((first operators) 1 2 3))

+ 1
- 0
debug.bat Ver fichero

@@ -1,3 +1,4 @@
@echo off
pushd %~dp0\vs
start lisp.sln
popd

+ 110
- 46
src/eval.c Ver fichero

@@ -25,15 +25,58 @@ int list_length(Ast_Node* node) {
return 0;
}

void eval_operands(Ast_Node* operands, Environment* env) {
while (!error) {
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;
/**
Copies a list, in that it creates a new list, however the items are
the same as in the original (same pointers). This is neede to copy
a list when evaluating a parameters list, but not wanting to change
the parameters list. This happens if you have someting like:

(define a 10)
(define condition (quote (= a 10)))
(eval condition)
> 1.00000

If we wouldn't copy the parameters list, after calling eval would
be baked into the quoted list. So even after changing a, the result
of (eval condition) would be 1.00000.
**/
Ast_Node* copy_list(Ast_Node* node) {
// we don't copy immutables in here
if (node->type != Ast_Node_Type_Pair) {
return node;
}

Ast_Node* result = new(Ast_Node);
result->type = Ast_Node_Type_Pair;
result->value.pair = new(Pair);

result->value.pair->first = copy_list(node->value.pair->first);
result->value.pair->rest = copy_list(node->value.pair->rest);

return result;
}

Ast_Node* eval_operands(Ast_Node* operands, Environment* env) {
if (operands->type == Ast_Node_Type_Nil) {
return operands;
}

// NOTE(Feilx): Instead of copying and then mutating it, we could
// just build the resulting list on the fly
Ast_Node* evaluated_operands = copy_list(operands);
Ast_Node* current_head = evaluated_operands;
/* print(operands); */
/* printf("\n"); */
/* print(evaluated_operands); */
/* printf("\n"); */
while (current_head->type == Ast_Node_Type_Pair) {
try {
current_head->value.pair->first =
eval_expr(current_head->value.pair->first, env);
}
current_head = current_head->value.pair->rest;
}
return evaluated_operands;
}

Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
@@ -50,7 +93,11 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
ret->type = Ast_Node_Type_Nil;
return ret;
case Ast_Node_Type_Symbol:
return lookup_symbol(node->value.symbol, env);
Ast_Node* symbol;
try {
symbol = lookup_symbol(node->value.symbol, env);
}
return symbol;
case Ast_Node_Type_Number:
case Ast_Node_Type_Keyword:
case Ast_Node_Type_String:
@@ -64,7 +111,6 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
Ast_Node* operands = node->value.pair->rest;
int operands_length;


// check for built ins functions
if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier;
@@ -81,53 +127,62 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}

return eval_expr(operands->value.pair->first, env);
try {
operands = eval_operands(operands, env);
}
/* print(operands); */
Ast_Node* result;
try {
result = eval_expr(operands->value.pair->first, env);
}
return result;
} else if (string_equal("prog", operator_name)) {
if (operands->type == Ast_Node_Type_Nil)
return operands;
while (!error) {
try {
operands->value.pair->first = eval_expr(operands->value.pair->first, env);
}

if (operands->value.pair->rest->type == Ast_Node_Type_Pair)
operands = operands->value.pair->rest;
else {
if (operands->value.pair->rest->type != Ast_Node_Type_Nil)
report_error(Error_Type_Ill_Formed_List);
break;
}
operands = copy_list(operands);
Ast_Node* evaluated_operands;
try {
evaluated_operands = eval_operands(operands, env);
}
return operands->value.pair->first;

// skip to the last evaluated operand and return it,
// we use eval_operands here instead of doing it
// manually, becuase we want to increase code reuse,
// but at the cost that we have to find the end of the
// list again
while (evaluated_operands->value.pair->rest->type == Ast_Node_Type_Pair) {
evaluated_operands = evaluated_operands->value.pair->rest;
}
return evaluated_operands->value.pair->first;
} else if (string_equal("list", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return operands;
} else if (string_equal("=", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return built_in_equals(operands);
} else if (string_equal("+", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return built_in_add(operands);
} else if (string_equal("-", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return built_in_substract(operands);
} else if (string_equal("*", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return built_in_multiply(operands);
} else if (string_equal("/", operator_name)) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
return built_in_divide(operands);
} else if (string_equal("define", operator_name)) {
@@ -143,7 +198,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Type_Missmatch);

Ast_Node* value = operands->value.pair->rest->value.pair->first;
value = eval_expr(value, env);
try {
value = eval_expr(value, env);
}

define_symbol(symbol, value, env);

@@ -156,7 +213,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
Ast_Node_Type type = operands->value.pair->first->type;
switch (type) {
@@ -180,7 +237,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {

if (operands_length == 1) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
Ast_Node* error_code = operands->value.pair->first;
if (error_code->type != Ast_Node_Type_Number)
@@ -198,7 +255,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
print(operands->value.pair->first);
printf("\n");
@@ -213,7 +270,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {

if (operands_length == 1) {
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
Ast_Node* prompt = operands->value.pair->first;
if (prompt->type == Ast_Node_Type_String)
@@ -231,7 +288,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}

return create_ast_node_pair(operands->value.pair->first, operands->value.pair->rest->value.pair->first);
@@ -243,7 +300,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
if (operands->value.pair->first->type == Ast_Node_Type_Nil)
return create_ast_node_nil();
@@ -259,7 +316,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
operands = eval_operands(operands, env);
}
if (operands->value.pair->first->type == Ast_Node_Type_Nil)
return create_ast_node_nil();
@@ -283,11 +340,17 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
try {
truthy = is_truthy(condition, env);
}
Ast_Node* result;
if (truthy)
return eval_expr(then_part->value.pair->first, env);
try{
result = eval_expr(then_part->value.pair->first, env);
}
else if (operands_length == 3)
return eval_expr(else_part->value.pair->first, env);
try {
result = eval_expr(else_part->value.pair->first, env);
}
else return create_ast_node_nil();
return result;

} else if (string_equal("and", operator_name)) {
bool result = true;
@@ -341,7 +404,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {

// assume it's lambda function and evaluate the operands in
// place
eval_operands(operands, env);
operands = eval_operands(operands, env);
}

default:
@@ -351,11 +414,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}

bool is_truthy (Ast_Node* expression, Environment* env) {
Ast_Node* result = eval_expr(expression, env);
if (error) return false;
switch (result->type) {
case Ast_Node_Type_Nil: return false;
/* case Ast_Node_Type_Number: return result->value.number->value != 0; */
default: return true;
Ast_Node* result;
try {
result = eval_expr(expression, env);
}
if (result->type == Ast_Node_Type_Nil)
return false;
return true;

}

+ 4
- 4
src/helpers.c Ver fichero

@@ -12,7 +12,7 @@
if(error) return 0; \
break; \
} \
else label(body,__LINE__):
else label(body,__LINE__):

typedef enum { false, true } bool;

@@ -70,11 +70,11 @@ char* read_entire_file (char* filename) {
}

/* Allocate our buffer to that size. */
fileContent = malloc(sizeof(char) * (bufsize) +1);
fileContent = (char*)calloc(bufsize, sizeof(char));

/* Read the entire file into memory. */
size_t newLen = fread(fileContent, sizeof(char), bufsize, fp);
fileContent[bufsize-1] = '\0';
/* fileContent[bufsize-5] = '\0'; */
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
}
@@ -112,7 +112,7 @@ char* read_line() {
linep = linen;
}

if((*line++ = c) == '\n')
if((*line++ = (char)c) == '\n')
break;
}
*line--; // we dont want the \n actually


+ 2
- 4
src/main.c Ver fichero

@@ -31,8 +31,8 @@ int interprete_file (char* file_content) {
return 1;
}
}
print(result);
printf("\n");
/* print(result); */
/* printf("\n"); */
return 0;
}

@@ -76,6 +76,4 @@ int main (int argc, char *argv[]) {
run_all_tests();
return interprete_stdin();
}

return 0;
}

+ 36
- 0
src/testing.c Ver fichero

@@ -79,6 +79,39 @@
} \
} \

testresult test_eval_operands() {
char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
Ast_Node* operands = parse_single_expression(operands_string);
operands = eval_operands(operands, create_empty_environment());

assert_no_error(error);
assert_equal_int(list_length(operands), 4);

assert_equal_int(operands->type, Ast_Node_Type_Pair);
assert_equal_int(operands->value.pair->first->type, Ast_Node_Type_Number);
assert_equal_int(operands->value.pair->first->value.number->value, 1);

operands = operands->value.pair->rest;

assert_equal_int(operands->type, Ast_Node_Type_Pair);
assert_equal_int(operands->value.pair->first->type, Ast_Node_Type_Number);
assert_equal_int(operands->value.pair->first->value.number->value, 3);

operands = operands->value.pair->rest;

assert_equal_int(operands->type, Ast_Node_Type_Pair);
assert_equal_int(operands->value.pair->first->type, Ast_Node_Type_String);
assert_equal_string(operands->value.pair->first->value.string->value, "okay");

operands = operands->value.pair->rest;

assert_equal_int(operands->type, Ast_Node_Type_Pair);
assert_equal_int(operands->value.pair->first->type, Ast_Node_Type_Keyword);
assert_equal_string(operands->value.pair->first->value.keyword->identifier, "haha");

return pass;
}

testresult test_parse_atom() {
int index_in_text = 0;
char string[] =
@@ -342,6 +375,9 @@ void run_all_tests() {
invoke_test(test_parse_atom);
invoke_test(test_parse_expression);

printf("\n-- Basic evaluating --\n");
invoke_test(test_eval_operands);

printf("\n-- Built ins --\n");
invoke_test(test_built_in_add);
invoke_test(test_built_in_substract);


+ 7
- 0
todo.org Ver fichero

@@ -45,6 +45,13 @@
** TODO progn
** DONE eval
CLOSED: [2018-10-08 Mo 20:28]

(setq condition (quote (= a 10)))
(setq a 10)
(eval condition)
(setq a 11)
(eval condition)

** DONE quote
CLOSED: [2018-10-08 Mo 20:28]



Cargando…
Cancelar
Guardar