okay
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
(/ (+ 1 (- 100 7 3)) 2)
|
||||||
@@ -19,7 +19,7 @@ if %errorlevel% == 0 (
|
|||||||
move %exeName% ..\%binDir%\ > NUL
|
move %exeName% ..\%binDir%\ > NUL
|
||||||
pushd ..\%binDir%
|
pushd ..\%binDir%
|
||||||
echo ---------- Running ----------
|
echo ---------- Running ----------
|
||||||
call timecmd %exeName%
|
call timecmd %exeName% test.lsp
|
||||||
del %exeName% /S /Q > NUL
|
del %exeName% /S /Q > NUL
|
||||||
popd
|
popd
|
||||||
) else (
|
) else (
|
||||||
|
|||||||
@@ -54,9 +54,10 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* message;
|
create_error(Error_Type_Symbol_Not_Defined, create_ast_node_nil());
|
||||||
asprintf(&message, "Symbol not defined: %s\n", sym->identifier);
|
/* char* message; */
|
||||||
panic(message);
|
/* asprintf(&message, "Symbol not defined: %s\n", sym->identifier); */
|
||||||
|
/* panic(message); */
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ typedef enum {
|
|||||||
Error_Type_Not_A_Function,
|
Error_Type_Not_A_Function,
|
||||||
Error_Type_Not_Yet_Implemented,
|
Error_Type_Not_Yet_Implemented,
|
||||||
Error_Type_Syntax_Error,
|
Error_Type_Syntax_Error,
|
||||||
|
Error_Type_Unexpected_Eof,
|
||||||
Error_Type_Unknown_Error,
|
Error_Type_Unknown_Error,
|
||||||
} Error_Type;
|
} Error_Type;
|
||||||
|
|
||||||
@@ -40,6 +41,8 @@ char* Error_Type_to_string(Error_Type type) {
|
|||||||
case Error_Type_Type_Missmatch: return "Type Missmatch";
|
case Error_Type_Type_Missmatch: return "Type Missmatch";
|
||||||
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
|
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
|
||||||
case Error_Type_Syntax_Error: return "Syntax Error";
|
case Error_Type_Syntax_Error: return "Syntax Error";
|
||||||
|
case Error_Type_Unexpected_Eof: return "Unexpected EOF";
|
||||||
default: return "Unknown Error";
|
default: return "Unknown Error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -43,6 +43,8 @@ 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); \
|
||||||
|
log_error(); \
|
||||||
|
exit(1); \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +58,6 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
case Ast_Node_Type_Number:
|
case Ast_Node_Type_Number:
|
||||||
case Ast_Node_Type_String:
|
case Ast_Node_Type_String:
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
case Ast_Node_Type_Pair: {
|
case Ast_Node_Type_Pair: {
|
||||||
Ast_Node* operator = eval_expr(node->value.pair->first, env);
|
Ast_Node* operator = eval_expr(node->value.pair->first, env);
|
||||||
Ast_Node* operands = node->value.pair->rest;
|
Ast_Node* operands = node->value.pair->rest;
|
||||||
@@ -81,9 +82,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
} else if (string_equal("if", operator_name)) {
|
} else if (string_equal("if", operator_name)) {
|
||||||
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) {
|
||||||
if (!error)
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Node* condition = operands->value.pair->first;
|
Ast_Node* condition = operands->value.pair->first;
|
||||||
@@ -144,7 +143,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
report_error(Error_Type_Unknown_Error);
|
report_error(Error_Type_Not_A_Function);
|
||||||
}
|
}
|
||||||
#undef report_error
|
#undef report_error
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-1
@@ -57,10 +57,11 @@ char* read_entire_file (char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate our buffer to that size. */
|
/* Allocate our buffer to that size. */
|
||||||
fileContent = malloc(sizeof(char) * (bufsize));
|
fileContent = malloc(sizeof(char) * (bufsize) +1);
|
||||||
|
|
||||||
/* Read the entire file into memory. */
|
/* Read the entire file into memory. */
|
||||||
size_t newLen = fread(fileContent, sizeof(char), bufsize, fp);
|
size_t newLen = fread(fileContent, sizeof(char), bufsize, fp);
|
||||||
|
fileContent[bufsize-1] = '\0';
|
||||||
if ( ferror( fp ) != 0 ) {
|
if ( ferror( fp ) != 0 ) {
|
||||||
fputs("Error reading file", stderr);
|
fputs("Error reading file", stderr);
|
||||||
}
|
}
|
||||||
@@ -72,3 +73,35 @@ char* read_entire_file (char* filename) {
|
|||||||
return fileContent;
|
return fileContent;
|
||||||
/* Don't forget to call free() later! */
|
/* Don't forget to call free() later! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* read_line() {
|
||||||
|
char * line = malloc(100), * linep = line;
|
||||||
|
size_t lenmax = 100, len = lenmax;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if(line == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = fgetc(stdin);
|
||||||
|
if(c == EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(--len == 0) {
|
||||||
|
len = lenmax;
|
||||||
|
char * linen = realloc(linep, lenmax *= 2);
|
||||||
|
|
||||||
|
if(linen == NULL) {
|
||||||
|
free(linep);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
line = linen + (line - linep);
|
||||||
|
linep = linen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*line++ = c) == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*line = '\0';
|
||||||
|
return linep;
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,9 +77,14 @@ void print(Ast_Node* node) {
|
|||||||
Ast_Node* head = node;
|
Ast_Node* head = node;
|
||||||
printf("(");
|
printf("(");
|
||||||
|
|
||||||
while (1) {
|
// NOTE(Felix): We cold do a while true here, however in case
|
||||||
|
// we want to print a broken list (for logging the error) we
|
||||||
|
// should do mo checks.
|
||||||
|
while (head) {
|
||||||
print(head->value.pair->first);
|
print(head->value.pair->first);
|
||||||
head = head->value.pair->rest;
|
head = head->value.pair->rest;
|
||||||
|
if (!head)
|
||||||
|
return;
|
||||||
if (head->type != Ast_Node_Type_Pair)
|
if (head->type != Ast_Node_Type_Pair)
|
||||||
break;
|
break;
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
|||||||
+38
-9
@@ -17,16 +17,45 @@
|
|||||||
#include "./testing.c"
|
#include "./testing.c"
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char *argv[]) {
|
||||||
/* if (argc > 1) { */
|
if (argc > 1) {
|
||||||
/* char* fileContent = read_entire_file(argv[1]); */
|
char* fileContent = read_entire_file(argv[1]);
|
||||||
/* if (fileContent) { */
|
if (fileContent) {
|
||||||
/* printf("File: %s\n", fileContent); */
|
Ast_Node_Array_List* program = parse_program(fileContent);
|
||||||
/* } */
|
if (error) {
|
||||||
/* } else { */
|
log_error();
|
||||||
/* printf("No source provided.\n"); */
|
exit(1);
|
||||||
/* } */
|
}
|
||||||
|
Environment* env = create_empty_environment();
|
||||||
|
Ast_Node* result = create_ast_node_nil();
|
||||||
|
for (int i = 0; i < program->next_index; ++i) {
|
||||||
|
result = eval_expr(program->data[i], env);
|
||||||
|
if (error) {
|
||||||
|
log_error();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(result);
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
printf("The file could not be read\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
run_all_tests();
|
||||||
|
|
||||||
|
printf("Welcome to the lispy interpreter.\n");
|
||||||
|
char* line;
|
||||||
|
Environment* env = create_empty_environment();
|
||||||
|
Ast_Node* parsed, * evaluated;
|
||||||
|
while (true) {
|
||||||
|
printf(">");
|
||||||
|
line = read_line();
|
||||||
|
parsed = parse_single_expression(line);
|
||||||
|
evaluated = eval_expr(parsed, env);
|
||||||
|
print(evaluated);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
run_all_tests();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -196,6 +196,11 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eat_until_code(text, index_in_text);
|
eat_until_code(text, index_in_text);
|
||||||
|
if (text[(*index_in_text)] == '\0') {
|
||||||
|
create_error(Error_Type_Unexpected_Eof, expression);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (text[(*index_in_text)] == ')') {
|
if (text[(*index_in_text)] == ')') {
|
||||||
head->value.pair->rest = create_ast_node_nil();
|
head->value.pair->rest = create_ast_node_nil();
|
||||||
@@ -237,8 +242,10 @@ Ast_Node_Array_List* parse_program(char* text) {
|
|||||||
while (text[index_in_text] != '\0') {
|
while (text[index_in_text] != '\0') {
|
||||||
switch (text[index_in_text]) {
|
switch (text[index_in_text]) {
|
||||||
case '(': {
|
case '(': {
|
||||||
append_to_Ast_Node_Array_List(
|
Ast_Node* parsed = parse_expression(text, &index_in_text);
|
||||||
program, parse_expression(text, &index_in_text));
|
if (error)
|
||||||
|
return nullptr;
|
||||||
|
append_to_Ast_Node_Array_List(program, parsed);
|
||||||
} break;
|
} break;
|
||||||
case ';': {
|
case ';': {
|
||||||
eat_comment_line(text, &index_in_text);
|
eat_comment_line(text, &index_in_text);
|
||||||
@@ -249,8 +256,9 @@ Ast_Node_Array_List* parse_program(char* text) {
|
|||||||
++index_in_text;
|
++index_in_text;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
create_error(Error_Type_Syntax_Error, nullptr);
|
|
||||||
/* syntax error */
|
/* syntax error */
|
||||||
|
create_error(Error_Type_Syntax_Error, create_ast_node_nil());
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
(+ 1 (- 100 7) 3)
|
|
||||||
|
|
||||||
(defun unpack (&rest args)
|
|
||||||
(car args))
|
|
||||||
(unpack '(1 2))
|
|
||||||
|
|
||||||
(defun add (&rest args)
|
|
||||||
(if args
|
|
||||||
(+ (first args)
|
|
||||||
(apply 'add 'args)))
|
|
||||||
0)
|
|
||||||
|
|
||||||
(add 2 123 99)
|
|
||||||
@@ -15,9 +15,12 @@
|
|||||||
|
|
||||||
** DONE if
|
** DONE if
|
||||||
CLOSED: [2018-09-18 Di 12:14]
|
CLOSED: [2018-09-18 Di 12:14]
|
||||||
** TODO and (short circuiting)
|
** DONE and (short circuiting)
|
||||||
** TODO or
|
CLOSED: [2018-10-05 Fr 22:21]
|
||||||
** TODO not
|
** DONE or
|
||||||
|
CLOSED: [2018-10-05 Fr 22:21]
|
||||||
|
** DONE not
|
||||||
|
CLOSED: [2018-10-05 Fr 22:21]
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(not 1) ;; == (not . (1 . nil))
|
(not 1) ;; == (not . (1 . nil))
|
||||||
(not (expression 1 3)) ;; == (not . ((expression . (1 . (3 . nil))) . nil))
|
(not (expression 1 3)) ;; == (not . ((expression . (1 . (3 . nil))) . nil))
|
||||||
@@ -34,16 +37,12 @@
|
|||||||
|
|
||||||
** TODO load (import)
|
** TODO load (import)
|
||||||
** TODO define
|
** TODO define
|
||||||
|
|
||||||
** TODO lambda
|
** TODO lambda
|
||||||
** TODO progn
|
** TODO progn
|
||||||
|
|
||||||
** TODO eval
|
** TODO eval
|
||||||
** TODO quote
|
** TODO quote
|
||||||
|
|
||||||
** TODO print
|
** TODO print
|
||||||
** TODO read
|
** TODO read
|
||||||
|
|
||||||
** TODO help
|
** TODO help
|
||||||
|
|
||||||
* Types
|
* Types
|
||||||
|
|||||||
Reference in New Issue
Block a user