quote eval define print read
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
((c-mode . ((eval . (company-clang-set-prefix "main.c"))
|
||||||
|
(eval . (flycheck-mode 0))
|
||||||
|
(eval . (rainbow-mode 0))))
|
||||||
|
(nil . ((eval . (progn
|
||||||
|
(defvar context-mode-map (make-sparse-keymap)
|
||||||
|
"Keymap while context-mode is active.")
|
||||||
|
(define-minor-mode context-mode
|
||||||
|
"A temporary minor mode to be activated only specific to a buffer."
|
||||||
|
nil
|
||||||
|
:lighter " Context"
|
||||||
|
context-mode-map)
|
||||||
|
(context-mode 1)
|
||||||
|
|
||||||
|
;; additional scripts
|
||||||
|
(defun save-and-find-test-script-and-compile ()
|
||||||
|
(interactive)
|
||||||
|
(let ((build-script-name "test.bat"))
|
||||||
|
(save-and-find-build-script-and-compile)))
|
||||||
|
(defun save-and-find-run-script-and-compile ()
|
||||||
|
(interactive)
|
||||||
|
(let ((build-script-name "run.bat"))
|
||||||
|
(save-and-find-build-script-and-compile)))
|
||||||
|
(defun save-and-find-debug-script-and-compile ()
|
||||||
|
(interactive)
|
||||||
|
(let ((build-script-name "debug.bat"))
|
||||||
|
(save-and-find-build-script-and-compile)))
|
||||||
|
|
||||||
|
(defhydra hydra-context (context-mode-map "<f2>")
|
||||||
|
"Context Actions:"
|
||||||
|
("b" save-and-find-build-script-and-compile "build" :color blue)
|
||||||
|
("r" save-and-find-run-script-and-compile "run" :color blue)
|
||||||
|
("d" save-and-find-debug-script-and-compile "debug" :color blue)
|
||||||
|
("t" save-and-find-test-script-and-compile "test" :color blue)
|
||||||
|
("q" nil "quit" :color blue))
|
||||||
|
(define-key context-mode-map (kbd "<f2>") 'hydra-context/body)
|
||||||
|
)))))
|
||||||
@@ -4,3 +4,5 @@
|
|||||||
/*.pdb
|
/*.pdb
|
||||||
/.vs/
|
/.vs/
|
||||||
/vs/
|
/vs/
|
||||||
|
/*.exe
|
||||||
|
*.exe
|
||||||
|
|||||||
+12
-1
@@ -1 +1,12 @@
|
|||||||
(/ (+ 1 (- 100 7 3)) 2)
|
((lambda (x) (* x x)) 2)
|
||||||
|
|
||||||
|
(setq a 3)
|
||||||
|
|
||||||
|
(let ((a 10))
|
||||||
|
(let ((b 5))
|
||||||
|
(setq a 4))
|
||||||
|
a)
|
||||||
|
|
||||||
|
|
||||||
|
a
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
@setlocal
|
@setlocal
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
set start=%time%
|
|
||||||
|
|
||||||
set exeName=lisp.exe
|
set exeName=lisp.exe
|
||||||
set binDir=bin
|
set binDir=bin
|
||||||
|
|
||||||
@@ -17,11 +15,6 @@ if %errorlevel% == 0 (
|
|||||||
echo.
|
echo.
|
||||||
if not exist ..\%binDir% mkdir ..\%binDir%
|
if not exist ..\%binDir% mkdir ..\%binDir%
|
||||||
move %exeName% ..\%binDir%\ > NUL
|
move %exeName% ..\%binDir%\ > NUL
|
||||||
pushd ..\%binDir%
|
|
||||||
echo ---------- Running ----------
|
|
||||||
call timecmd %exeName% test.lsp
|
|
||||||
del %exeName% /S /Q > NUL
|
|
||||||
popd
|
|
||||||
) else (
|
) else (
|
||||||
echo.
|
echo.
|
||||||
echo Fucki'n 'ell
|
echo Fucki'n 'ell
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@echo off
|
||||||
|
pushd %~dp0\bin
|
||||||
|
|
||||||
|
call ..\build.bat
|
||||||
|
if %errorlevel% == 0 (
|
||||||
|
echo ---------- Running ----------
|
||||||
|
call timecmd lisp.exe
|
||||||
|
)
|
||||||
|
popd
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
((c-mode . ((eval . (company-clang-set-prefix "main.c"))
|
|
||||||
(eval . (flycheck-mode 0))
|
|
||||||
(eval . (rainbow-mode 0)))))
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
struct Environment {
|
struct Environment {
|
||||||
struct Environment* parent;
|
struct Environment* parent;
|
||||||
int key_count;
|
int capacity;
|
||||||
|
int next_index;
|
||||||
char** keys;
|
char** keys;
|
||||||
Ast_Node* values;
|
Ast_Node* values;
|
||||||
};
|
};
|
||||||
@@ -11,16 +12,37 @@ typedef struct Environment Environment;
|
|||||||
Environment* create_empty_environment() {
|
Environment* create_empty_environment() {
|
||||||
Environment* env = new(Environment);
|
Environment* env = new(Environment);
|
||||||
|
|
||||||
|
int start_capacity = 1;
|
||||||
|
|
||||||
env->parent = nullptr;
|
env->parent = nullptr;
|
||||||
env->key_count = 0;
|
env->capacity = start_capacity;
|
||||||
env->keys = nullptr;
|
env->next_index = 0;
|
||||||
env->values = nullptr;
|
env->keys = (char**)malloc(start_capacity * sizeof(char*));
|
||||||
|
env->values = (Ast_Node*)malloc(start_capacity * sizeof(Ast_Node));
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
|
||||||
|
// NOTE(Felix): right now we are simmply adding the symol at the
|
||||||
|
// back of the list without checking if it already exists but are
|
||||||
|
// also searching for thesymbol from the back, so we will find the
|
||||||
|
// latest defined one first, but a bit messy. Later we should use
|
||||||
|
// a hashmap here. @refactor
|
||||||
|
|
||||||
|
if (env->next_index == env->capacity) {
|
||||||
|
env->capacity *= 2;
|
||||||
|
env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
|
||||||
|
env->values = (Ast_Node*)realloc(env->values, env->capacity * sizeof(Ast_Node));
|
||||||
|
}
|
||||||
|
|
||||||
|
env->keys [env->next_index] = symbol->value.symbol->identifier;
|
||||||
|
env->values[env->next_index] = *value;
|
||||||
|
++env->next_index;
|
||||||
|
}
|
||||||
|
|
||||||
Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
||||||
for (int i = 0; i < env->key_count; ++i)
|
for (int i = env->next_index - 1; i >= 0; --i)
|
||||||
if (string_equal(env->keys[i], sym->identifier))
|
if (string_equal(env->keys[i], sym->identifier))
|
||||||
return env->values+i;
|
return env->values+i;
|
||||||
|
|
||||||
@@ -30,7 +52,7 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
|||||||
char* built_in_names[] = {
|
char* built_in_names[] = {
|
||||||
// Math stuff
|
// Math stuff
|
||||||
"+", "-", "*", "/",
|
"+", "-", "*", "/",
|
||||||
">", "<", "=",
|
">", "<", "=", "<=", ">=",
|
||||||
// Conditional stuff
|
// Conditional stuff
|
||||||
"if", "and", "or", "not",
|
"if", "and", "or", "not",
|
||||||
// Cons stuff
|
// Cons stuff
|
||||||
@@ -40,9 +62,9 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
|
|||||||
"lambda", "progn",
|
"lambda", "progn",
|
||||||
"eval", "quote",
|
"eval", "quote",
|
||||||
"print", "read",
|
"print", "read",
|
||||||
"help"
|
"help", "exit"
|
||||||
};
|
};
|
||||||
int built_in_count = 23;
|
int built_in_count = 26;
|
||||||
|
|
||||||
for (int i = 0; i < built_in_count; ++i) {
|
for (int i = 0; i < built_in_count; ++i) {
|
||||||
if (string_equal(built_in_names[i], sym->identifier)) {
|
if (string_equal(built_in_names[i], sym->identifier)) {
|
||||||
|
|||||||
+11
-8
@@ -7,6 +7,8 @@ typedef enum {
|
|||||||
Error_Type_Not_Yet_Implemented,
|
Error_Type_Not_Yet_Implemented,
|
||||||
Error_Type_Syntax_Error,
|
Error_Type_Syntax_Error,
|
||||||
Error_Type_Unexpected_Eof,
|
Error_Type_Unexpected_Eof,
|
||||||
|
Error_Type_Unbalanced_Parenthesis,
|
||||||
|
Error_Type_Trailing_Garbage,
|
||||||
Error_Type_Unknown_Error,
|
Error_Type_Unknown_Error,
|
||||||
} Error_Type;
|
} Error_Type;
|
||||||
|
|
||||||
@@ -34,15 +36,16 @@ void create_error(Error_Type type, Ast_Node* location) {
|
|||||||
|
|
||||||
char* Error_Type_to_string(Error_Type type) {
|
char* Error_Type_to_string(Error_Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Error_Type_Ill_Formed_List: return "Ill formed list";
|
case Error_Type_Ill_Formed_List: return "Evaluation-error: Ill formed list";
|
||||||
case Error_Type_Not_A_Function: return "Not a function";
|
case Error_Type_Not_A_Function: return "Evaluation-error: Not a function";
|
||||||
case Error_Type_Symbol_Not_Defined: return "Symbol not defined";
|
case Error_Type_Symbol_Not_Defined: return "Evaluation-error: Symbol not defined";
|
||||||
case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments";
|
case Error_Type_Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
|
||||||
case Error_Type_Type_Missmatch: return "Type Missmatch";
|
case Error_Type_Type_Missmatch: return "Evaluation-error: Type Missmatch";
|
||||||
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
|
case Error_Type_Not_Yet_Implemented: return "Evaluation-error: Not yet implemented";
|
||||||
|
case Error_Type_Trailing_Garbage: return "Evaluation-error: Trailing garbage following expression";
|
||||||
case Error_Type_Syntax_Error: return "Syntax Error";
|
case Error_Type_Syntax_Error: return "Syntax Error";
|
||||||
case Error_Type_Unexpected_Eof: return "Unexpected EOF";
|
case Error_Type_Unexpected_Eof: return "Parsing-error: Unexpected EOF";
|
||||||
|
case Error_Type_Unbalanced_Parenthesis: return "Parsing-error: Unbalanced parenthesis";
|
||||||
default: return "Unknown Error";
|
default: return "Unknown Error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+91
-8
@@ -1,9 +1,5 @@
|
|||||||
/* Ast_Node* apply_to_lambda () {} */
|
/* Ast_Node* apply_to_lambda () {} */
|
||||||
|
|
||||||
/* Ast_Node* apply_to_built_in (Ast_Node* function, Ast_Node* arguments) { */
|
|
||||||
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
|
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
|
||||||
bool is_truthy (Ast_Node* expression, Environment* env);
|
bool is_truthy (Ast_Node* expression, Environment* env);
|
||||||
|
|
||||||
@@ -43,10 +39,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) { \
|
#define report_error(_type) { \
|
||||||
create_error(_type, node); \
|
create_error(_type, node); \
|
||||||
log_error(); \
|
|
||||||
exit(1); \
|
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
Ast_Node* ret = new(Ast_Node);
|
Ast_Node* ret = new(Ast_Node);
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
@@ -56,31 +52,112 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
case Ast_Node_Type_Symbol:
|
case Ast_Node_Type_Symbol:
|
||||||
return lookup_symbol(node->value.symbol, env);
|
return lookup_symbol(node->value.symbol, env);
|
||||||
case Ast_Node_Type_Number:
|
case Ast_Node_Type_Number:
|
||||||
|
case Ast_Node_Type_Keyword:
|
||||||
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);
|
||||||
|
if (error) return nullptr;
|
||||||
|
|
||||||
Ast_Node* operands = node->value.pair->rest;
|
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.pair->rest;
|
int operands_length = list_length(operands);
|
||||||
|
if (operands_length != 1) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
return operands->value.pair->first;
|
||||||
|
} else if (string_equal("eval", operator_name)) {
|
||||||
|
int operands_length = list_length(operands);
|
||||||
|
if (operands_length != 1) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
if (error) return nullptr;
|
||||||
|
return eval_expr(operands->value.pair->first, env);
|
||||||
} else if (string_equal("+", operator_name)) {
|
} else if (string_equal("+", operator_name)) {
|
||||||
eval_operands(operands, env);
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
return built_in_add(operands);
|
return built_in_add(operands);
|
||||||
} else if (string_equal("-", operator_name)) {
|
} else if (string_equal("-", operator_name)) {
|
||||||
eval_operands(operands, env);
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
return built_in_substract(operands);
|
return built_in_substract(operands);
|
||||||
} else if (string_equal("*", operator_name)) {
|
} else if (string_equal("*", operator_name)) {
|
||||||
eval_operands(operands, env);
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
return built_in_multiply(operands);
|
return built_in_multiply(operands);
|
||||||
} else if (string_equal("/", operator_name)) {
|
} else if (string_equal("/", operator_name)) {
|
||||||
eval_operands(operands, env);
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
return built_in_divide(operands);
|
return built_in_divide(operands);
|
||||||
|
} else if (string_equal("define", operator_name)) {
|
||||||
|
int operands_length = list_length(operands);
|
||||||
|
if (error) return nullptr;
|
||||||
|
if (operands_length != 2) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Node* symbol = operands->value.pair->first;
|
||||||
|
if (symbol->type != Ast_Node_Type_Symbol)
|
||||||
|
report_error(Error_Type_Type_Missmatch);
|
||||||
|
|
||||||
|
Ast_Node* value = operands->value.pair->rest->value.pair->first;
|
||||||
|
value = eval_expr(value, env);
|
||||||
|
|
||||||
|
define_symbol(symbol, value, env);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
} else if (string_equal("exit", operator_name)) {
|
||||||
|
int operands_length = list_length(operands);
|
||||||
|
if (error) return nullptr;
|
||||||
|
if (operands_length > 1) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operands_length == 1) {
|
||||||
|
Ast_Node* error_code = operands->value.pair->first;
|
||||||
|
if (error_code->type != Ast_Node_Type_Number)
|
||||||
|
report_error(Error_Type_Type_Missmatch);
|
||||||
|
|
||||||
|
exit((int)error_code->value.number->value);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
} else if (string_equal("print", operator_name)) {
|
||||||
|
int operands_length = list_length(operands);
|
||||||
|
if (error) return nullptr;
|
||||||
|
if (operands_length != 1) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
|
print(operands->value.pair->first);
|
||||||
|
printf("\n");
|
||||||
|
return operands->value.pair->first;
|
||||||
|
} else if (string_equal("read", operator_name)) {
|
||||||
|
int operands_length = list_length(operands);
|
||||||
|
if (error) return nullptr;
|
||||||
|
if (operands_length > 1) {
|
||||||
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operands_length == 1) {
|
||||||
|
eval_operands(operands, env);
|
||||||
|
if (error) return nullptr;
|
||||||
|
Ast_Node* prompt = operands->value.pair->first;
|
||||||
|
if (prompt->type == Ast_Node_Type_String)
|
||||||
|
printf("%s", prompt->value.string->value);
|
||||||
|
else
|
||||||
|
print(operands->value.pair->first);
|
||||||
|
}
|
||||||
|
char* line = read_line();
|
||||||
|
return create_ast_node_string(line, (int)strlen(line));
|
||||||
} 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 (error) return nullptr;
|
||||||
if (operands_length != 2 && operands_length != 3) {
|
if (operands_length != 2 && operands_length != 3) {
|
||||||
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
report_error(Error_Type_Wrong_Number_Of_Arguments);
|
||||||
}
|
}
|
||||||
@@ -89,7 +166,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
Ast_Node* then_part = operands->value.pair->rest;
|
Ast_Node* then_part = operands->value.pair->rest;
|
||||||
Ast_Node* else_part = then_part->value.pair->rest;
|
Ast_Node* else_part = then_part->value.pair->rest;
|
||||||
|
|
||||||
if (is_truthy(condition, env))
|
bool truthy = is_truthy(condition, env);
|
||||||
|
if (error) return nullptr;
|
||||||
|
if (truthy)
|
||||||
return eval_expr(then_part->value.pair->first, env);
|
return eval_expr(then_part->value.pair->first, 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);
|
||||||
@@ -102,6 +181,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
report_error(Error_Type_Ill_Formed_List);
|
report_error(Error_Type_Ill_Formed_List);
|
||||||
}
|
}
|
||||||
result &= is_truthy(operands->value.pair->first, env);
|
result &= is_truthy(operands->value.pair->first, env);
|
||||||
|
if (error) return nullptr;
|
||||||
operands = operands->value.pair->rest;
|
operands = operands->value.pair->rest;
|
||||||
|
|
||||||
if (!result) return create_ast_node_nil();
|
if (!result) return create_ast_node_nil();
|
||||||
@@ -116,6 +196,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
report_error(Error_Type_Ill_Formed_List);
|
report_error(Error_Type_Ill_Formed_List);
|
||||||
}
|
}
|
||||||
result |= is_truthy(operands->value.pair->first, env);
|
result |= is_truthy(operands->value.pair->first, env);
|
||||||
|
if (error) return nullptr;
|
||||||
operands = operands->value.pair->rest;
|
operands = operands->value.pair->rest;
|
||||||
|
|
||||||
if (result) return create_ast_node_number(1);;
|
if (result) return create_ast_node_number(1);;
|
||||||
@@ -129,6 +210,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
bool truthy = is_truthy(operands->value.pair->first, env);
|
bool truthy = is_truthy(operands->value.pair->first, env);
|
||||||
|
if (error) return nullptr;
|
||||||
if (truthy)
|
if (truthy)
|
||||||
return create_ast_node_nil();
|
return create_ast_node_nil();
|
||||||
return create_ast_node_number(1);
|
return create_ast_node_number(1);
|
||||||
@@ -150,6 +232,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
|||||||
|
|
||||||
bool 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);
|
||||||
|
if (error) return false;
|
||||||
switch (result->type) {
|
switch (result->type) {
|
||||||
case Ast_Node_Type_Nil: return false;
|
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; */
|
||||||
|
|||||||
+31
-11
@@ -16,14 +16,11 @@
|
|||||||
#include "./eval.c"
|
#include "./eval.c"
|
||||||
#include "./testing.c"
|
#include "./testing.c"
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int interprete_file (char* file_content) {
|
||||||
if (argc > 1) {
|
Ast_Node_Array_List* program = parse_program(file_content);
|
||||||
char* fileContent = read_entire_file(argv[1]);
|
|
||||||
if (fileContent) {
|
|
||||||
Ast_Node_Array_List* program = parse_program(fileContent);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
log_error();
|
log_error();
|
||||||
exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
Environment* env = create_empty_environment();
|
Environment* env = create_empty_environment();
|
||||||
Ast_Node* result = create_ast_node_nil();
|
Ast_Node* result = create_ast_node_nil();
|
||||||
@@ -31,17 +28,15 @@ int main (int argc, char *argv[]) {
|
|||||||
result = eval_expr(program->data[i], env);
|
result = eval_expr(program->data[i], env);
|
||||||
if (error) {
|
if (error) {
|
||||||
log_error();
|
log_error();
|
||||||
exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print(result);
|
print(result);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
return 0;
|
||||||
printf("The file could not be read\n");
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
run_all_tests();
|
|
||||||
|
|
||||||
|
int interprete_stdin () {
|
||||||
printf("Welcome to the lispy interpreter.\n");
|
printf("Welcome to the lispy interpreter.\n");
|
||||||
char* line;
|
char* line;
|
||||||
Environment* env = create_empty_environment();
|
Environment* env = create_empty_environment();
|
||||||
@@ -50,12 +45,37 @@ int main (int argc, char *argv[]) {
|
|||||||
printf(">");
|
printf(">");
|
||||||
line = read_line();
|
line = read_line();
|
||||||
parsed = parse_single_expression(line);
|
parsed = parse_single_expression(line);
|
||||||
|
if (error) {
|
||||||
|
log_error();
|
||||||
|
delete_error();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
evaluated = eval_expr(parsed, env);
|
evaluated = eval_expr(parsed, env);
|
||||||
|
if (error) {
|
||||||
|
log_error();
|
||||||
|
delete_error();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
print(evaluated);
|
print(evaluated);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
if (argc > 1) {
|
||||||
|
char* file_content = read_entire_file(argv[1]);
|
||||||
|
if (file_content) {
|
||||||
|
return interprete_file(file_content);
|
||||||
|
} else {
|
||||||
|
printf("The file could not be read\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
run_all_tests();
|
||||||
|
return interprete_stdin();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-8
@@ -18,10 +18,8 @@ Ast_Node_Array_List* create_Ast_Node_Array_List() {
|
|||||||
void append_to_Ast_Node_Array_List(Ast_Node_Array_List* list, Ast_Node* node) {
|
void append_to_Ast_Node_Array_List(Ast_Node_Array_List* list, Ast_Node* node) {
|
||||||
if (list->next_index == list->length) {
|
if (list->next_index == list->length) {
|
||||||
list->length *= 2;
|
list->length *= 2;
|
||||||
list->data =
|
list->data = (Ast_Node**)realloc(list->data, list->length * sizeof(Ast_Node));
|
||||||
(Ast_Node**)realloc(list->data, list->length * sizeof(Ast_Node));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list->data[list->next_index++] = node;
|
list->data[list->next_index++] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +229,17 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
|
|||||||
|
|
||||||
Ast_Node* parse_single_expression(char* text) {
|
Ast_Node* parse_single_expression(char* text) {
|
||||||
int index_in_text = 0;
|
int index_in_text = 0;
|
||||||
return parse_expression(text, &index_in_text);
|
Ast_Node* result;
|
||||||
|
eat_until_code(text, &index_in_text);
|
||||||
|
if (text[(index_in_text)] == '(')
|
||||||
|
result = parse_expression(text, &index_in_text);
|
||||||
|
else
|
||||||
|
result = parse_atom(text, &index_in_text);
|
||||||
|
eat_until_code(text, &index_in_text);
|
||||||
|
if (text[(index_in_text)] == '\0')
|
||||||
|
return result;
|
||||||
|
create_error(Error_Type_Trailing_Garbage, create_ast_node_nil());
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Node_Array_List* parse_program(char* text) {
|
Ast_Node_Array_List* parse_program(char* text) {
|
||||||
@@ -247,13 +255,11 @@ Ast_Node_Array_List* parse_program(char* text) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
append_to_Ast_Node_Array_List(program, parsed);
|
append_to_Ast_Node_Array_List(program, parsed);
|
||||||
} break;
|
} break;
|
||||||
case ';': {
|
case ';':
|
||||||
eat_comment_line(text, &index_in_text);
|
|
||||||
} break;
|
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
case '\n': {
|
case '\n': {
|
||||||
++index_in_text;
|
eat_until_code(text, &index_in_text);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
/* syntax error */
|
/* syntax error */
|
||||||
|
|||||||
Reference in New Issue
Block a user