This commit is contained in:
NunoSempere 2023-05-02 20:43:12 -04:00
parent e269917240
commit 59b92a6479

View File

@ -10,7 +10,8 @@
return lispval_err(err); \
}
int VERBOSE = 2;
#define printfln(...) do { \
#define printfln(...) \
do { \
if (VERBOSE == 2) { \
printf("\n@ %s (%d): ", __FILE__, __LINE__); \
printf(__VA_ARGS__); \
@ -58,7 +59,6 @@ typedef struct lispval {
struct lispval** cell; // list of lisval*
} lispval;
enum {
LISPERR_DIV_ZERO,
LISPERR_BAD_OP,
@ -68,7 +68,8 @@ enum {
// Constructors
lispval* lispval_num(double x)
{
if(VERBOSE) printfln("Allocated num");
if (VERBOSE)
printfln("Allocated num");
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_NUM;
v->count = 0;
@ -78,7 +79,8 @@ lispval* lispval_num(double x)
lispval* lispval_err(char* message)
{
if(VERBOSE) printfln("Allocated err");
if (VERBOSE)
printfln("Allocated err");
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_ERR;
v->count = 0;
@ -89,7 +91,8 @@ lispval* lispval_err(char* message)
lispval* lispval_sym(char* symbol)
{
if(VERBOSE) printfln("Allocated sym");
if (VERBOSE)
printfln("Allocated sym");
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_SYM;
v->count = 0;
@ -98,21 +101,25 @@ lispval* lispval_sym(char* symbol)
return v;
}
lispval* lispval_func(lispbuiltin func, char* funcname){
if(VERBOSE) printfln("Allocating func name:%s, pointer: %p", funcname, func);
lispval* lispval_func(lispbuiltin func, char* funcname)
{
if (VERBOSE)
printfln("Allocating func name:%s, pointer: %p", funcname, func);
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_FUNC;
v->count = 0;
v->funcname = malloc(strlen(funcname) + 1);
strcpy(v->funcname, funcname);
v->func = func;
if(VERBOSE) printfln("Allocated func");
if (VERBOSE)
printfln("Allocated func");
return v;
}
lispval* lispval_sexpr(void)
{
if(VERBOSE) printfln("Allocated sexpr");
if (VERBOSE)
printfln("Allocated sexpr");
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_SEXPR;
v->count = 0;
@ -122,7 +129,8 @@ lispval* lispval_sexpr(void)
lispval* lispval_qexpr(void)
{
if(VERBOSE) printfln("Allocated qexpr");
if (VERBOSE)
printfln("Allocated qexpr");
lispval* v = malloc(sizeof(lispval));
v->type = LISPVAL_QEXPR;
v->count = 0;
@ -134,46 +142,62 @@ lispval* lispval_qexpr(void)
void print_lispval_tree(lispval* v, int indent_level);
void delete_lispval(lispval* v)
{
if(v == NULL) return;
if (v == NULL)
return;
// print_lispval_tree(v, 0);
if(VERBOSE) printfln("\nDeleting object of type %i",v->type);
if (VERBOSE)
printfln("\nDeleting object of type %i", v->type);
switch (v->type) {
case LISPVAL_NUM:
if(VERBOSE) printfln("Freeing num");
if (v != NULL) free(v);
if(VERBOSE) printfln("Freed num");
if (VERBOSE)
printfln("Freeing num");
if (v != NULL)
free(v);
if (VERBOSE)
printfln("Freed num");
break;
case LISPVAL_ERR:
if(VERBOSE) printfln("Freeing err");
if (VERBOSE)
printfln("Freeing err");
if (v->err != NULL)
free(v->err);
v->err = NULL;
if (v != NULL) free(v);
if(VERBOSE) printfln("Freed err");
if (v != NULL)
free(v);
if (VERBOSE)
printfln("Freed err");
break;
case LISPVAL_SYM:
if(VERBOSE) printfln("Freeing sym");
if (VERBOSE)
printfln("Freeing sym");
if (v->sym != NULL)
free(v->sym);
v->sym = NULL;
if (v != NULL) free(v);
if(VERBOSE) printfln("Freed sym");
if (v != NULL)
free(v);
if (VERBOSE)
printfln("Freed sym");
break;
case LISPVAL_FUNC:
if(VERBOSE) printfln("Freeing func");
if (VERBOSE)
printfln("Freeing func");
if (v->funcname != NULL)
free(v->funcname);
v->funcname = NULL;
if (v != NULL) free(v);
if(VERBOSE) printfln("Freed func");
if (v != NULL)
free(v);
if (VERBOSE)
printfln("Freed func");
// Don't do anything with v->func for now
// Though we could delete the pointer to the function later
// free(v->func);
break;
case LISPVAL_SEXPR:
case LISPVAL_QEXPR:
if(VERBOSE) printfln("Freeing sexpr|qexpr");
if(v==NULL || v->count !=0) return;
if (VERBOSE)
printfln("Freeing sexpr|qexpr");
if (v == NULL || v->count != 0)
return;
for (int i = 0; i < v->count; i++) {
if (v->cell[i] != NULL)
delete_lispval(v->cell[i]);
@ -183,11 +207,14 @@ void delete_lispval(lispval* v)
if (v->cell != NULL)
free(v->cell);
v->cell = NULL;
if (v != NULL) free(v);
if(VERBOSE) printfln("Freed sexpr|qexpr");
if (v != NULL)
free(v);
if (VERBOSE)
printfln("Freed sexpr|qexpr");
break;
default:
if(VERBOSE) printfln("Error: Unknown expression type for pointer %p of type %i", v, v->type);
if (VERBOSE)
printfln("Error: Unknown expression type for pointer %p of type %i", v, v->type);
}
// v = NULL; this is only our local pointer, sadly.
}
@ -199,7 +226,8 @@ struct lispenv {
lispval** vals; // list of pointers to vals
};
lispenv* new_lispenv(){
lispenv* new_lispenv()
{
lispenv* n = malloc(sizeof(lispenv));
n->count = 0;
n->syms = NULL;
@ -207,7 +235,8 @@ lispenv* new_lispenv(){
return n;
}
void destroy_lispenv(lispenv* env){
void destroy_lispenv(lispenv* env)
{
for (int i = 0; i < env->count; i++) {
free(env->syms[i]);
free(env->vals[i]);
@ -223,7 +252,8 @@ void destroy_lispenv(lispenv* env){
}
lispval* clone_lispval(lispval* old);
lispval* get_from_lispenv(char* sym, lispenv* env){
lispval* get_from_lispenv(char* sym, lispenv* env)
{
for (int i = 0; i < env->count; i++) {
if (strcmp(env->syms[i], sym) == 0) {
return clone_lispval(env->vals[i]);
@ -233,7 +263,8 @@ lispval* get_from_lispenv(char* sym, lispenv* env){
return lispval_err("Error: unbound symbol");
}
void insert_in_lispenv(char* sym, lispval* v, lispenv* env){
void insert_in_lispenv(char* sym, lispval* v, lispenv* env)
{
int found = 0;
for (int i = 0; i < env->count; i++) {
if (strcmp(env->syms[i], sym) == 0) {
@ -364,10 +395,13 @@ void print_lispval_tree(lispval* v, int indent_level)
printfln("Error: unknown lispval type\n");
// printfln("%s", v->sym);
}
if(VERBOSE > 1) printfln("Freeing indent");
if (indent!=NULL) free(indent);
if (VERBOSE > 1)
printfln("Freeing indent");
if (indent != NULL)
free(indent);
indent = NULL;
if(VERBOSE > 1) printfln("Freed indent");
if (VERBOSE > 1)
printfln("Freed indent");
}
void print_lispval_parenthesis(lispval* v)
@ -605,7 +639,8 @@ lispval* builtin_join(lispval* l, lispenv* e)
}
// Define a variable
lispval* builtin_def(lispval* v, lispenv* env){
lispval* builtin_def(lispval* v, lispenv* env)
{
// Takes one argument: def { { a b } { 1 2 } }
lispval* source = v->cell[0];
LISPVAL_ASSERT(v->count == 1, "Error: function def passed too many arguments");
@ -619,9 +654,12 @@ lispval* builtin_def(lispval* v, lispenv* env){
lispval* values = source->cell[1];
for (int i; 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 } }");
if(VERBOSE) print_lispval_tree(symbols, 0);
if(VERBOSE) print_lispval_tree(values, 0);
if(VERBOSE) printf("\n");
if (VERBOSE)
print_lispval_tree(symbols, 0);
if (VERBOSE)
print_lispval_tree(values, 0);
if (VERBOSE)
printf("\n");
insert_in_lispenv(symbols->cell[i]->sym, values->cell[i], env);
}
return lispval_sexpr(); // ()
@ -678,19 +716,23 @@ lispval* builtin_math_ops(char* op, lispval* v, lispenv* e)
}
// Fit the simple math ops using the above code
lispval* builtin_add(lispval* v, lispenv* env) {
lispval* builtin_add(lispval* v, lispenv* env)
{
return builtin_math_ops("+", v, env);
}
lispval* builtin_substract(lispval* v, lispenv* env) {
lispval* builtin_substract(lispval* v, lispenv* env)
{
return builtin_math_ops("-", v, env);
}
lispval* builtin_multiply(lispval* v, lispenv* env) {
lispval* builtin_multiply(lispval* v, lispenv* env)
{
return builtin_math_ops("*", v, env);
}
lispval* builtin_divide(lispval* v, lispenv* env) {
lispval* builtin_divide(lispval* v, lispenv* env)
{
return builtin_math_ops("/", v, env);
}
@ -719,14 +761,18 @@ lispval* builtin_functions(char* func, lispval* v, lispenv* env)
}
// Add builtins to an env
void lispenv_add_builtin(char* funcname, lispbuiltin func, lispenv* env ){
if(VERBOSE) printfln("Adding func: name: %s, pointer: %p", funcname, func);
void lispenv_add_builtin(char* funcname, lispbuiltin func, lispenv* env)
{
if (VERBOSE)
printfln("Adding func: name: %s, pointer: %p", funcname, func);
lispval* f = lispval_func(func, funcname);
if(VERBOSE) print_lispval_tree(f, 0);
if (VERBOSE)
print_lispval_tree(f, 0);
insert_in_lispenv(funcname, f, env);
delete_lispval(f);
}
void lispenv_add_builtins(lispenv* env){
void lispenv_add_builtins(lispenv* env)
{
// Math functions
lispenv_add_builtin("+", builtin_add, env);
lispenv_add_builtin("-", builtin_substract, env);
@ -746,34 +792,41 @@ void lispenv_add_builtins(lispenv* env){
// Evaluate the lispval
lispval* evaluate_lispval(lispval* l, lispenv* env)
{
if(VERBOSE) printfln("Evaluating lispval");
if (VERBOSE)
printfln("Evaluating lispval");
// Check if this is neither an s-expression nor a symbol; otherwise return as is.
if(VERBOSE) printfln("");
if (VERBOSE)
printfln("");
if (l->type != LISPVAL_SEXPR && l->type != LISPVAL_SYM)
return l;
// Check if this is a symbol
if(VERBOSE) printfln("Checking if this is a symbol");
if (VERBOSE)
printfln("Checking if this is a symbol");
if (l->type == LISPVAL_SYM) {
// Unclear how I want to structure this so as to not get memory errors.
return get_from_lispenv(l->sym, env);
}
// Evaluate the children if needed
if(VERBOSE) printfln("Evaluating children");
if (VERBOSE)
printfln("Evaluating children");
for (int i = 0; i < l->count; i++) {
if (l->cell[i]->type == LISPVAL_SEXPR || l->cell[i]->type == LISPVAL_SYM) {
// l->cell[i] =
if(VERBOSE) printfln("");
if (VERBOSE)
printfln("");
lispval* new = evaluate_lispval(l->cell[i], env);
// delete_lispval(l->cell[i]);
// ^ gave me a "double free" error.
l->cell[i] = new;
if(VERBOSE) printfln("");
if (VERBOSE)
printfln("");
}
}
// Check if any are errors.
if(VERBOSE) printfln("Checking for errors in children");
if (VERBOSE)
printfln("Checking for errors in children");
lispval* err = NULL;
for (int i = 0; i < l->count; i++) {
if (l->cell[i]->type == LISPVAL_ERR) {
@ -786,43 +839,56 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
delete_lispval(l->cell[i]);
}
*/
if(VERBOSE) printfln("Returning error");
if (VERBOSE)
printfln("Returning error");
return err;
}
// Check if the first element is an operation.
if(VERBOSE) printfln("Checking is first element is a function");
if (VERBOSE)
printfln("Checking is first element is a function");
if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_FUNC)) {
if(VERBOSE) printfln("Passed check");
if(VERBOSE) printfln("Operating on:");
if(VERBOSE) print_lispval_tree(l, 4);
if (VERBOSE)
printfln("Passed check");
if (VERBOSE)
printfln("Operating on:");
if (VERBOSE)
print_lispval_tree(l, 4);
lispval* temp = clone_lispval(l);
lispval* f = pop_lispval(temp, 0);
// pop is destructive.
lispval* operands = temp;
if(VERBOSE) printfln("Allocated memory");
if (VERBOSE)
printfln("Allocated memory");
// lispval* operation = clone_lispval(l->cell[0]);
// lispval* operands = lispval_sexpr();
// for (int i = 1; i < l->count; i++) {
// lispval_append_child(operands, l->cell[i]);
// }
if(VERBOSE) printfln("Applying function to operands");
if (VERBOSE)
printfln("Applying function to operands");
// lispval* answer = lispval_num(42);
lispval* answer = f->func(operands, env);
if(VERBOSE) printfln("Applied function to operands");
if(VERBOSE) printfln("Cleaning up");
if (VERBOSE)
printfln("Applied function to operands");
if (VERBOSE)
printfln("Cleaning up");
// builtin_functions(operation->sym, l, env);
delete_lispval(f);
delete_lispval(operands);
// delete_lispval(temp);
if(VERBOSE) printfln("Returning");
if (VERBOSE)
printfln("Returning");
return answer;
}
return l;
}
// Increase or decrease verbosity level manually
void modify_verbosity(char* command){
void modify_verbosity(char* command)
{
if (strcmp("VERBOSE=0", command) == 0) {
VERBOSE = 0;
}
@ -862,16 +928,24 @@ int main(int argc, char** argv)
Number, Symbol, Sexpr, Qexpr, Expr, Mumble);
// Create an environment
if(VERBOSE) printfln("Creating lispenv");
if (VERBOSE)
printfln("Creating lispenv");
lispenv* env = new_lispenv();
if(VERBOSE) printfln("Created lispenv");
if(VERBOSE) printfln("Adding builtins");
if (VERBOSE)
printfln("Created lispenv");
if (VERBOSE)
printfln("Adding builtins");
lispenv_add_builtins(env);
if(VERBOSE) printfln("Added builtins");
if(VERBOSE) printfln("Environment contents: %i", env->count);
if(VERBOSE) printfln(" env->syms[0]: %s", env->syms[0]);
if(VERBOSE) print_lispval_tree(env->vals[0], 2);
if(VERBOSE) printfln("\n");
if (VERBOSE)
printfln("Added builtins");
if (VERBOSE)
printfln("Environment contents: %i", env->count);
if (VERBOSE)
printfln(" env->syms[0]: %s", env->syms[0]);
if (VERBOSE)
print_lispval_tree(env->vals[0], 2);
if (VERBOSE)
printfln("\n");
// Initialize a repl
int loop = 1;
while (loop) {
@ -909,13 +983,16 @@ int main(int argc, char** argv)
lispval* answer = evaluate_lispval(l, env);
{
if(VERBOSE) printfln("Result: ");
if (VERBOSE)
printfln("Result: ");
print_lispval_parenthesis(answer);
if(VERBOSE) print_lispval_tree(answer, 0);
if (VERBOSE)
print_lispval_tree(answer, 0);
printf("\n");
}
delete_lispval(answer);
if(VERBOSE > 1) printfln("Answer after deletion: %p", answer);
if (VERBOSE > 1)
printfln("Answer after deletion: %p", answer);
// delete_lispval(answer); // do this twice, just to see.
//if(VERBOSE) printfln("Deleting this lispval:");
// if(VERBOSE) print_lispval_tree(l,2);