This commit is contained in:
NunoSempere 2023-05-07 12:49:22 -04:00
parent 1dfba9f4a1
commit 2f9edb67e6

View File

@ -17,7 +17,7 @@ int VERBOSE = 0;
printf("\n@ %s (%d): ", __FILE__, __LINE__); \ printf("\n@ %s (%d): ", __FILE__, __LINE__); \
printf(__VA_ARGS__); \ printf(__VA_ARGS__); \
} else { \ } else { \
printf("%s", "\n"); \ printf("%s", "\n"); \
printf(__VA_ARGS__); \ printf(__VA_ARGS__); \
} \ } \
} while (0) } while (0)
@ -54,21 +54,21 @@ int LARGEST_LISPVAL = LISPVAL_QEXPR; // for checking out of bounds.
typedef struct lispval { typedef struct lispval {
int type; int type;
// Basic types // Basic types
double num; double num;
char* err; char* err;
char* sym; char* sym;
// Functions // Functions
// Built-in // Built-in
lispbuiltin builtin_func; lispbuiltin builtin_func;
char* builtin_func_name; char* builtin_func_name;
// User-defined // User-defined
lispenv* env; lispenv* env;
lispval* variables; lispval* variables;
lispval* manipulation; lispval* manipulation;
// Expression // Expression
int count; int count;
struct lispval** cell; // list of lisval* struct lispval** cell; // list of lisval*
} lispval; } lispval;
@ -131,15 +131,16 @@ lispval* lispval_builtin_func(lispbuiltin func, char* builtin_func_name)
} }
lispenv* new_lispenv(); lispenv* new_lispenv();
lispval* lispval_lambda_func(lispval* variables, lispval* manipulation){ lispval* lispval_lambda_func(lispval* variables, lispval* manipulation)
lispval* v = malloc(sizeof(lispval)); {
v->type = LISPVAL_USER_FUNC; lispval* v = malloc(sizeof(lispval));
v->builtin_func = NULL; v->type = LISPVAL_USER_FUNC;
v->env = new_lispenv(); v->builtin_func = NULL;
v->variables = variables; v->env = new_lispenv();
v->manipulation = manipulation; v->variables = variables;
// unclear how to garbage-collect this. Maybe add to a list and collect at the end? v->manipulation = manipulation;
return v; // unclear how to garbage-collect this. Maybe add to a list and collect at the end?
return v;
} }
lispval* lispval_sexpr(void) lispval* lispval_sexpr(void)
@ -205,13 +206,13 @@ void delete_lispval(lispval* v)
printfln("Freed sym"); printfln("Freed sym");
break; break;
case LISPVAL_BUILTIN_FUNC: case LISPVAL_BUILTIN_FUNC:
if (v->builtin_func_name != NULL){ if (v->builtin_func_name != NULL) {
if (VERBOSE){ if (VERBOSE) {
printfln("Freeing builtin func"); printfln("Freeing builtin func");
} }
free(v->builtin_func_name); free(v->builtin_func_name);
v->builtin_func_name = NULL; v->builtin_func_name = NULL;
} }
if (v != NULL) if (v != NULL)
free(v); free(v);
if (VERBOSE) if (VERBOSE)
@ -223,18 +224,18 @@ void delete_lispval(lispval* v)
case LISPVAL_USER_FUNC: case LISPVAL_USER_FUNC:
if (VERBOSE) if (VERBOSE)
printfln("Freeing user-defined func"); printfln("Freeing user-defined func");
if (v->env != NULL){ if (v->env != NULL) {
free(v->env); free(v->env);
v->env = NULL; v->env = NULL;
} }
if (v->variables != NULL){ if (v->variables != NULL) {
free(v->variables); free(v->variables);
v->variables = NULL; v->variables = NULL;
} }
if (v->manipulation != NULL){ if (v->manipulation != NULL) {
free(v->manipulation); free(v->manipulation);
v->manipulation = NULL; v->manipulation = NULL;
} }
if (v != NULL) if (v != NULL)
free(v); free(v);
if (VERBOSE) if (VERBOSE)
@ -266,7 +267,6 @@ void delete_lispval(lispval* v)
free(v->cell); free(v->cell);
v->cell = NULL; v->cell = NULL;
if (VERBOSE) if (VERBOSE)
printfln("Freeing the v pointer"); printfln("Freeing the v pointer");
if (v != NULL) if (v != NULL)
@ -295,7 +295,7 @@ lispenv* new_lispenv()
e->count = 0; e->count = 0;
e->syms = NULL; e->syms = NULL;
e->vals = NULL; e->vals = NULL;
e->parent = NULL; e->parent = NULL;
return e; return e;
} }
@ -314,11 +314,9 @@ void destroy_lispenv(lispenv* env)
free(env); free(env);
env = NULL; env = NULL;
// parent is it's own environment // parent is it's own environment
// so it isn't destroyed // so it isn't destroyed
} }
lispval* clone_lispval(lispval* old); lispval* clone_lispval(lispval* old);
lispval* get_from_lispenv(char* sym, lispenv* env) lispval* get_from_lispenv(char* sym, lispenv* env)
{ {
@ -329,12 +327,12 @@ lispval* get_from_lispenv(char* sym, lispenv* env)
} }
} }
if(env->parent != NULL){ if (env->parent != NULL) {
return get_from_lispenv(sym, env->parent); return get_from_lispenv(sym, env->parent);
} else { } else {
return lispval_err("Error: unbound symbol"); return lispval_err("Error: unbound symbol");
} }
// and this explains shadowing! // and this explains shadowing!
} }
void insert_in_lispenv(char* sym, lispval* v, lispenv* env) void insert_in_lispenv(char* sym, lispval* v, lispenv* env)
@ -558,7 +556,7 @@ lispval* clone_lispval(lispval* old)
new = lispval_builtin_func(old->builtin_func, old->builtin_func_name); new = lispval_builtin_func(old->builtin_func, old->builtin_func_name);
break; break;
case LISPVAL_USER_FUNC: case LISPVAL_USER_FUNC:
new = lispval_lambda_func(old->variables, old->manipulation); new = lispval_lambda_func(old->variables, old->manipulation);
break; break;
case LISPVAL_SEXPR: case LISPVAL_SEXPR:
new = lispval_sexpr(); new = lispval_sexpr();
@ -735,7 +733,7 @@ lispval* builtin_def(lispval* v, lispenv* env)
lispval* symbols = source->cell[0]; lispval* symbols = source->cell[0];
lispval* values = source->cell[1]; lispval* values = source->cell[1];
for (int i=0; i < symbols->count; i++) { for (int i = 0; i < symbols->count; i++) {
LISPVAL_ASSERT(symbols->cell[i]->type == LISPVAL_SYM, "Error: in function def, the first list of items should be of type symbol: def { { a b } { 1 2 } }"); LISPVAL_ASSERT(symbols->cell[i]->type == LISPVAL_SYM, "Error: in function def, the first list of items should be of type symbol: def { { a b } { 1 2 } }");
if (VERBOSE) if (VERBOSE)
print_lispval_tree(symbols, 0); print_lispval_tree(symbols, 0);
@ -749,24 +747,25 @@ lispval* builtin_def(lispval* v, lispenv* env)
} }
// A builtin for defining a function // A builtin for defining a function
lispval* builtin_define_lambda(lispval* v, lispenv* env){ lispval* builtin_define_lambda(lispval* v, lispenv* env)
// @ { {x y} { + x y } } {
// def { {plus} {{@ {x y} {+ x y}} }} // @ { {x y} { + x y } }
// (eval plus) 1 2 // def { {plus} {{@ {x y} {+ x y}} }}
// (@ { {x y} { + x y } }) 1 2 // (eval plus) 1 2
LISPVAL_ASSERT( v->count == 2, "Lambda definition requires two arguments; try @ { {x y} { + x y } }"); // (@ { {x y} { + x y } }) 1 2
LISPVAL_ASSERT(v->cell[0]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the first sub-arg be a q-expression; try @ { {x y} { + x y } }"); LISPVAL_ASSERT(v->count == 2, "Lambda definition requires two arguments; try @ { {x y} { + x y } }");
LISPVAL_ASSERT(v->cell[1]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the second sub-arg be a q-expression; try @ { {x y} { + x y } }"); LISPVAL_ASSERT(v->cell[0]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the first sub-arg be a q-expression; try @ { {x y} { + x y } }");
LISPVAL_ASSERT(v->cell[1]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the second sub-arg be a q-expression; try @ { {x y} { + x y } }");
lispval* variables = clone_lispval(v->cell[0]); lispval* variables = clone_lispval(v->cell[0]);
lispval* manipulation = clone_lispval(v->cell[1]); lispval* manipulation = clone_lispval(v->cell[1]);
for(int i=0; i>variables->count; i++){ for (int i = 0; i > variables->count; i++) {
LISPVAL_ASSERT(variables->cell[i]->type == LISPVAL_SYM, "First argument in function definition must only be symbols. Try @ { {x y} { + x y } }"); LISPVAL_ASSERT(variables->cell[i]->type == LISPVAL_SYM, "First argument in function definition must only be symbols. Try @ { {x y} { + x y } }");
} }
lispval* lambda = lispval_lambda_func(variables, manipulation); lispval* lambda = lispval_lambda_func(variables, manipulation);
return lambda; return lambda;
} }
// Simple math ops // Simple math ops
lispval* builtin_math_ops(char* op, lispval* v, lispenv* e) lispval* builtin_math_ops(char* op, lispval* v, lispenv* e)
@ -876,7 +875,7 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
printfln("Evaluating lispval"); printfln("Evaluating lispval");
// Check if this is neither an s-expression nor a symbol; otherwise return as is. // Check if this is neither an s-expression nor a symbol; otherwise return as is.
if (VERBOSE) if (VERBOSE)
printfln("%s", ""); printfln("%s", "");
if (l->type != LISPVAL_SEXPR && l->type != LISPVAL_SYM) if (l->type != LISPVAL_SEXPR && l->type != LISPVAL_SYM)
return l; return l;
@ -886,10 +885,10 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
if (l->type == LISPVAL_SYM) { if (l->type == LISPVAL_SYM) {
// Unclear how I want to structure this so as to not get memory errors. // Unclear how I want to structure this so as to not get memory errors.
lispval* answer = get_from_lispenv(l->sym, env); lispval* answer = get_from_lispenv(l->sym, env);
delete_lispval(l); delete_lispval(l);
// fixes memory bug! I guess that if I just return get_from_lispenv, // fixes memory bug! I guess that if I just return get_from_lispenv,
// then it gets lost along the way? Not sure. // then it gets lost along the way? Not sure.
return answer; return answer;
} }
// Evaluate the children if needed // Evaluate the children if needed
@ -931,7 +930,7 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
// Check if the first element is an operation. // Check if the first element is an operation.
if (VERBOSE) if (VERBOSE)
printfln("Checking is first element is a function"); printfln("Checking is first element is a function");
if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_BUILTIN_FUNC)){ if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_BUILTIN_FUNC)) {
if (VERBOSE) if (VERBOSE)
printfln("Passed check"); printfln("Passed check");
@ -940,15 +939,14 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
if (VERBOSE) if (VERBOSE)
print_lispval_tree(l, 4); print_lispval_tree(l, 4);
// Ok, do this properly now. // Ok, do this properly now.
if (VERBOSE) if (VERBOSE)
printfln("Constructing function and operands"); printfln("Constructing function and operands");
lispval* f = clone_lispval(l->cell[0]); lispval* f = clone_lispval(l->cell[0]);
lispval* operands = lispval_sexpr(); lispval* operands = lispval_sexpr();
for(int i=1; i<l->count; i++){ for (int i = 1; i < l->count; i++) {
lispval_append_child(operands, l->cell[i]); lispval_append_child(operands, l->cell[i]);
}
}
if (VERBOSE) if (VERBOSE)
printfln("Applying function to operands"); printfln("Applying function to operands");
// lispval* answer = lispval_num(42); // lispval* answer = lispval_num(42);
@ -956,7 +954,7 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
if (VERBOSE) if (VERBOSE)
printfln("Applied function to operands"); printfln("Applied function to operands");
if (VERBOSE) if (VERBOSE)
printfln("Cleaning up"); printfln("Cleaning up");
delete_lispval(f); delete_lispval(f);
delete_lispval(operands); delete_lispval(operands);
@ -966,10 +964,10 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
return answer; return answer;
} }
if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_USER_FUNC)) { if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_USER_FUNC)) {
// Do something with user-defined functions here // Do something with user-defined functions here
return lispval_err("Error: User-defined functions not yet implemented"); return lispval_err("Error: User-defined functions not yet implemented");
} }
return l; return l;
} }
@ -978,19 +976,19 @@ int modify_verbosity(char* command)
{ {
if (strcmp("VERBOSE=0", command) == 0) { if (strcmp("VERBOSE=0", command) == 0) {
VERBOSE = 0; VERBOSE = 0;
return 1; return 1;
} }
if (strcmp("VERBOSE=1", command) == 0) { if (strcmp("VERBOSE=1", command) == 0) {
VERBOSE = 1; VERBOSE = 1;
printfln("VERBOSE=1"); printfln("VERBOSE=1");
return 1; return 1;
} }
if (strcmp("VERBOSE=2", command) == 0) { if (strcmp("VERBOSE=2", command) == 0) {
printfln("VERBOSE=2"); printfln("VERBOSE=2");
VERBOSE = 2; VERBOSE = 2;
return 1; return 1;
} }
return 0; return 0;
} }
// Main // Main
@ -1039,16 +1037,16 @@ int main(int argc, char** argv)
if (VERBOSE) if (VERBOSE)
printfln("\n"); printfln("\n");
// Initialize a repl // Initialize a repl
int loop = 1; int loop = 1;
while (loop) { while (loop) {
char* input = readline("mumble> "); char* input = readline("mumble> ");
if (input == NULL) { if (input == NULL) {
break; break;
} else { } else {
if(modify_verbosity(input)){ if (modify_verbosity(input)) {
continue; continue;
} }
/* Attempt to Parse the user Input */ /* Attempt to Parse the user Input */
mpc_result_t result; mpc_result_t result;
if (mpc_parse("<stdin>", input, Mumble, &result)) { if (mpc_parse("<stdin>", input, Mumble, &result)) {
@ -1091,7 +1089,7 @@ int main(int argc, char** argv)
//if(VERBOSE) printfln("Deleting this lispval:"); //if(VERBOSE) printfln("Deleting this lispval:");
// if(VERBOSE) print_lispval_tree(l,2); // if(VERBOSE) print_lispval_tree(l,2);
// delete_lispval(l); // delete_lispval(l);
// if(VERBOSE) printfln("Deleted that ^ lispval"); // if(VERBOSE) printfln("Deleted that ^ lispval");
// ^ I do not understand how the memory in l is freed. // ^ I do not understand how the memory in l is freed.
// delete the ast // delete the ast
@ -1109,9 +1107,9 @@ int main(int argc, char** argv)
input = NULL; input = NULL;
} }
// Clear the history // Clear the history
rl_uninitialize(); rl_uninitialize();
// rl_free_line_state(); // rl_free_line_state();
// Clean up environment // Clean up environment
destroy_lispenv(env); destroy_lispenv(env);