format
This commit is contained in:
parent
1dfba9f4a1
commit
2f9edb67e6
192
src/mumble.c
192
src/mumble.c
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user