step: get more stuff working with functions.
This commit is contained in:
parent
d072f3e1f6
commit
70a9076dc7
170
src/mumble.c
170
src/mumble.c
|
@ -5,7 +5,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "mpc/mpc.h"
|
#include "mpc/mpc.h"
|
||||||
#define VERBOSE 0
|
#define VERBOSE 2
|
||||||
#define LISPVAL_ASSERT(cond, err) \
|
#define LISPVAL_ASSERT(cond, err) \
|
||||||
if (!(cond)) { \
|
if (!(cond)) { \
|
||||||
return lispval_err(err); \
|
return lispval_err(err); \
|
||||||
|
@ -31,7 +31,7 @@ struct lispenv;
|
||||||
typedef struct lispval lispval;
|
typedef struct lispval lispval;
|
||||||
typedef struct lispenv lispenv;
|
typedef struct lispenv lispenv;
|
||||||
|
|
||||||
typedef lispval*(*lispbuiltin)(lispenv*, lispval*);
|
typedef lispval*(*lispbuiltin)(lispval*, lispenv*);
|
||||||
// this defines the lispbuiltin type
|
// this defines the lispbuiltin type
|
||||||
// which seems to be a pointer to a function which takes in a lispenv*
|
// which seems to be a pointer to a function which takes in a lispenv*
|
||||||
// and a lispval* and returns a lispval*
|
// and a lispval* and returns a lispval*
|
||||||
|
@ -99,13 +99,14 @@ lispval* lispval_sym(char* symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* lispval_func(lispbuiltin func, char* funcname){
|
lispval* lispval_func(lispbuiltin func, char* funcname){
|
||||||
if(VERBOSE) printfln("Allocated sym");
|
if(VERBOSE) printfln("Allocating func name:%s, pointer: %p", funcname, func);
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_FUNC;
|
v->type = LISPVAL_FUNC;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
v->sym = malloc(strlen(funcname) + 1);
|
v->funcname = malloc(strlen(funcname) + 1);
|
||||||
strcpy(v->funcname, funcname);
|
strcpy(v->funcname, funcname);
|
||||||
v->func = func;
|
v->func = func;
|
||||||
|
if(VERBOSE) printfln("Allocated func");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,30 +368,30 @@ void print_lispval_parenthesis(lispval* v)
|
||||||
{
|
{
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case LISPVAL_NUM:
|
case LISPVAL_NUM:
|
||||||
printfln("%f ", v->num);
|
printf("%f ", v->num);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_ERR:
|
case LISPVAL_ERR:
|
||||||
printfln("%s ", v->err);
|
printf("%s ", v->err);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SYM:
|
case LISPVAL_SYM:
|
||||||
printfln("%s ", v->sym);
|
printf("%s ", v->sym);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_FUNC:
|
case LISPVAL_FUNC:
|
||||||
printfln("<function name: %s pointer: %p>", v->funcname, v->func);
|
printf("<function name: %s, pointer: %p> ", v->funcname, v->func);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SEXPR:
|
case LISPVAL_SEXPR:
|
||||||
printfln("( ");
|
printf("( ");
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_parenthesis(v->cell[i]);
|
print_lispval_parenthesis(v->cell[i]);
|
||||||
}
|
}
|
||||||
printfln(") ");
|
printf(") ");
|
||||||
break;
|
break;
|
||||||
case LISPVAL_QEXPR:
|
case LISPVAL_QEXPR:
|
||||||
printfln("{ ");
|
printf("{ ");
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_parenthesis(v->cell[i]);
|
print_lispval_parenthesis(v->cell[i]);
|
||||||
}
|
}
|
||||||
printfln("} ");
|
printf("} ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printfln("Error: unknown lispval type\n");
|
printfln("Error: unknown lispval type\n");
|
||||||
|
@ -458,7 +459,7 @@ lispval* clone_lispval(lispval* old)
|
||||||
|
|
||||||
lispval* pop_lispval(lispval* v, int i)
|
lispval* pop_lispval(lispval* v, int i)
|
||||||
{
|
{
|
||||||
LISPVAL_ASSERT(v->type == LISPVAL_QEXPR || v->type == LISPVAL_SEXPR, "Error: function pop passed too many arguments");
|
LISPVAL_ASSERT(v->type == LISPVAL_QEXPR || v->type == LISPVAL_SEXPR, "Error: function pop wasn't passed a q-expression or an s-expression arguments");
|
||||||
lispval* r = v->cell[i];
|
lispval* r = v->cell[i];
|
||||||
/* Shift memory after the item at "i" over the top */
|
/* Shift memory after the item at "i" over the top */
|
||||||
memmove(&v->cell[i], &v->cell[i + 1],
|
memmove(&v->cell[i], &v->cell[i + 1],
|
||||||
|
@ -482,7 +483,7 @@ lispval* take_lispval(lispval* v, int i)
|
||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
// Ops for q-expressions
|
// Ops for q-expressions
|
||||||
lispval* builtin_head(lispval* v)
|
lispval* builtin_head(lispval* v, lispenv* e)
|
||||||
{
|
{
|
||||||
// printfln("Entering builtin_head with v->count = %d and v->cell[0]->type = %d\n", v->count, v->cell[0]->type);
|
// printfln("Entering builtin_head with v->count = %d and v->cell[0]->type = %d\n", v->count, v->cell[0]->type);
|
||||||
// head { 1 2 3 }
|
// head { 1 2 3 }
|
||||||
|
@ -501,7 +502,7 @@ lispval* builtin_head(lispval* v)
|
||||||
// Returns something that doesn't share pointers with the input: yes.
|
// Returns something that doesn't share pointers with the input: yes.
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* builtin_tail(lispval* v)
|
lispval* builtin_tail(lispval* v, lispenv* env)
|
||||||
{
|
{
|
||||||
// tail { 1 2 3 }
|
// tail { 1 2 3 }
|
||||||
LISPVAL_ASSERT(v->count == 1, "Error: function tail passed too many arguments");
|
LISPVAL_ASSERT(v->count == 1, "Error: function tail passed too many arguments");
|
||||||
|
@ -528,7 +529,7 @@ lispval* builtin_tail(lispval* v)
|
||||||
// Returns something that doesn't share pointers with the input: yes.
|
// Returns something that doesn't share pointers with the input: yes.
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* builtin_list(lispval* v)
|
lispval* builtin_list(lispval* v, lispenv* e)
|
||||||
{
|
{
|
||||||
// list ( 1 2 3 )
|
// list ( 1 2 3 )
|
||||||
LISPVAL_ASSERT(v->count == 1, "Error: function list passed too many arguments");
|
LISPVAL_ASSERT(v->count == 1, "Error: function list passed too many arguments");
|
||||||
|
@ -541,7 +542,7 @@ lispval* builtin_list(lispval* v)
|
||||||
// Returns something that is independent of the input: yes.
|
// Returns something that is independent of the input: yes.
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* builtin_len(lispval* v)
|
lispval* builtin_len(lispval* v, lispenv* e)
|
||||||
{
|
{
|
||||||
// tail { 1 2 3 }
|
// tail { 1 2 3 }
|
||||||
LISPVAL_ASSERT(v->count == 1, "Error: function len passed too many arguments");
|
LISPVAL_ASSERT(v->count == 1, "Error: function len passed too many arguments");
|
||||||
|
@ -571,7 +572,7 @@ lispval* builtin_eval(lispval* v, lispenv* env)
|
||||||
// Returns something that is independent of the input: depends on the output of evaluate_lispval.
|
// Returns something that is independent of the input: depends on the output of evaluate_lispval.
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* builtin_join(lispval* l)
|
lispval* builtin_join(lispval* l, lispenv* e)
|
||||||
{
|
{
|
||||||
// return lispval_err("Error: Join not ready yet.");
|
// return lispval_err("Error: Join not ready yet.");
|
||||||
// join { {1 2} {3 4} }
|
// join { {1 2} {3 4} }
|
||||||
|
@ -594,7 +595,7 @@ lispval* builtin_join(lispval* l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple math ops
|
// Simple math ops
|
||||||
lispval* builtin_math_ops(char* op, lispval* v)
|
lispval* builtin_math_ops(char* op, lispval* v, lispenv* e)
|
||||||
{
|
{
|
||||||
// For now, ensure all args are numbers
|
// For now, ensure all args are numbers
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
|
@ -643,23 +644,40 @@ lispval* builtin_math_ops(char* op, lispval* v)
|
||||||
// Returns something that is independent of the input: yes.
|
// Returns something that is independent of the input: yes.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fit the simple math ops using the above code
|
||||||
|
lispval* builtin_add(lispval* v, lispenv* env) {
|
||||||
|
return builtin_math_ops("+", v, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
lispval* builtin_substract(lispval* v, lispenv* env) {
|
||||||
|
return builtin_math_ops("-", v, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
lispval* builtin_multiply(lispval* v, lispenv* env) {
|
||||||
|
return builtin_math_ops("*", v, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
lispval* builtin_divide(lispval* v, lispenv* env) {
|
||||||
|
return builtin_math_ops("/", v, env);
|
||||||
|
}
|
||||||
|
|
||||||
// Aggregate both math and operations over lists
|
// Aggregate both math and operations over lists
|
||||||
lispval* builtin_functions(char* func, lispval* v, lispenv* env)
|
lispval* builtin_functions(char* func, lispval* v, lispenv* env)
|
||||||
{
|
{
|
||||||
if (strcmp("list", func) == 0) {
|
if (strcmp("list", func) == 0) {
|
||||||
return builtin_list(v);
|
return builtin_list(v, env);
|
||||||
} else if (strcmp("head", func) == 0) {
|
} else if (strcmp("head", func) == 0) {
|
||||||
return builtin_head(v);
|
return builtin_head(v, env);
|
||||||
} else if (strcmp("tail", func) == 0) {
|
} else if (strcmp("tail", func) == 0) {
|
||||||
return builtin_tail(v);
|
return builtin_tail(v, env);
|
||||||
} else if (strcmp("join", func) == 0) {
|
} else if (strcmp("join", func) == 0) {
|
||||||
return builtin_join(v);
|
return builtin_join(v, env);
|
||||||
} else if (strcmp("eval", func) == 0) {
|
} else if (strcmp("eval", func) == 0) {
|
||||||
return builtin_eval(v, env);
|
return builtin_eval(v, env);
|
||||||
} else if (strcmp("len", func) == 0) {
|
} else if (strcmp("len", func) == 0) {
|
||||||
return builtin_len(v);
|
return builtin_len(v, env);
|
||||||
} else if (strstr("+-/*", func)) {
|
} else if (strstr("+-/*", func)) {
|
||||||
return builtin_math_ops(func, v);
|
return builtin_math_ops(func, v, env);
|
||||||
} else {
|
} else {
|
||||||
return lispval_err("Unknown function");
|
return lispval_err("Unknown function");
|
||||||
}
|
}
|
||||||
|
@ -667,30 +685,61 @@ lispval* builtin_functions(char* func, lispval* v, lispenv* env)
|
||||||
// Returns something that is independent of the input: depends on eval
|
// Returns something that is independent of the input: depends on eval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
lispval* f = lispval_func(func, funcname);
|
||||||
|
if(VERBOSE) print_lispval_tree(f, 0);
|
||||||
|
insert_in_lispenv(funcname, f,env);
|
||||||
|
// delete_lispval(f);
|
||||||
|
}
|
||||||
|
void lispenv_add_builtins(lispenv* env){
|
||||||
|
// Math functions
|
||||||
|
lispenv_add_builtin("+", builtin_add, env);
|
||||||
|
lispenv_add_builtin("-", builtin_substract, env);
|
||||||
|
lispenv_add_builtin("*", builtin_multiply, env);
|
||||||
|
lispenv_add_builtin("/", builtin_divide, env);
|
||||||
|
|
||||||
|
//
|
||||||
|
/* List Functions */
|
||||||
|
lispenv_add_builtin("list", builtin_list, env);
|
||||||
|
lispenv_add_builtin("head", builtin_head, env);
|
||||||
|
lispenv_add_builtin("tail", builtin_tail, env);
|
||||||
|
lispenv_add_builtin("eval", builtin_eval, env);
|
||||||
|
lispenv_add_builtin("join", builtin_join, env);
|
||||||
|
}
|
||||||
|
|
||||||
// Evaluate the lispval
|
// Evaluate the lispval
|
||||||
lispval* evaluate_lispval(lispval* l, lispenv* env)
|
lispval* evaluate_lispval(lispval* l, lispenv* env)
|
||||||
{
|
{
|
||||||
|
if(VERBOSE) 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) printfln("");
|
||||||
if (l->type != LISPVAL_SEXPR && l->type != LISPVAL_SYM)
|
if (l->type != LISPVAL_SEXPR && l->type != LISPVAL_SYM)
|
||||||
return l;
|
return l;
|
||||||
|
|
||||||
// Check if this is a symbol
|
// Check if this is a symbol
|
||||||
|
if(VERBOSE) printfln("Checking if this is a symbol");
|
||||||
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.
|
||||||
return get_from_lispenv(l->sym, env);
|
return get_from_lispenv(l->sym, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the children if needed
|
// Evaluate the children if needed
|
||||||
|
if(VERBOSE) printfln("Evaluating children");
|
||||||
for (int i = 0; i < l->count; i++) {
|
for (int i = 0; i < l->count; i++) {
|
||||||
if (l->cell[i]->type == LISPVAL_SEXPR || l->cell[i]->type == LISPVAL_SYM) {
|
if (l->cell[i]->type == LISPVAL_SEXPR || l->cell[i]->type == LISPVAL_SYM) {
|
||||||
// l->cell[i] =
|
// l->cell[i] =
|
||||||
|
if(VERBOSE) printfln("");
|
||||||
lispval* new = evaluate_lispval(l->cell[i], env);
|
lispval* new = evaluate_lispval(l->cell[i], env);
|
||||||
// delete_lispval(l->cell[i]);
|
// delete_lispval(l->cell[i]);
|
||||||
// ^ gave me a "double free" error.
|
// ^ gave me a "double free" error.
|
||||||
l->cell[i] = new;
|
l->cell[i] = new;
|
||||||
|
if(VERBOSE) printfln("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if any are errors.
|
// Check if any are errors.
|
||||||
|
if(VERBOSE) printfln("Checking for errors in children");
|
||||||
lispval* err = NULL;
|
lispval* err = NULL;
|
||||||
for (int i = 0; i < l->count; i++) {
|
for (int i = 0; i < l->count; i++) {
|
||||||
if (l->cell[i]->type == LISPVAL_ERR) {
|
if (l->cell[i]->type == LISPVAL_ERR) {
|
||||||
|
@ -703,23 +752,36 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
|
||||||
delete_lispval(l->cell[i]);
|
delete_lispval(l->cell[i]);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
if(VERBOSE) printfln("Returning error");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the first element is an operation.
|
// Check if the first element is an operation.
|
||||||
|
if(VERBOSE) printfln("Checking is first element is a function");
|
||||||
if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_FUNC)) {
|
if (l->count >= 2 && ((l->cell[0])->type == LISPVAL_FUNC)) {
|
||||||
lispval* temp = clone_lispval(l->cell[0]);
|
if(VERBOSE) printfln("Passed check");
|
||||||
lispval* f = pop_lispval(temp, 0);
|
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;
|
lispval* operands = temp;
|
||||||
|
if(VERBOSE) printfln("Allocated memory");
|
||||||
// lispval* operation = clone_lispval(l->cell[0]);
|
// lispval* operation = 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]);
|
||||||
// }
|
// }
|
||||||
lispval* answer = f->func(env, 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");
|
||||||
// builtin_functions(operation->sym, l, env);
|
// builtin_functions(operation->sym, l, env);
|
||||||
delete_lispval(f);
|
delete_lispval(f);
|
||||||
delete_lispval(operands);
|
delete_lispval(operands);
|
||||||
|
if(VERBOSE) printfln("Returning");
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
|
@ -750,19 +812,30 @@ int main(int argc, char** argv)
|
||||||
",
|
",
|
||||||
Number, Symbol, Sexpr, Qexpr, Expr, Mumble);
|
Number, Symbol, Sexpr, Qexpr, Expr, Mumble);
|
||||||
|
|
||||||
// Initialize a repl
|
// Create an environment
|
||||||
int loop = 1;
|
if(VERBOSE) printfln("Creating lispenv");
|
||||||
while (loop) {
|
lispenv* env = new_lispenv();
|
||||||
char* input = readline("mumble> ");
|
if(VERBOSE) printfln("Created lispenv");
|
||||||
if (input == NULL) {
|
if(VERBOSE) printfln("Adding builtins");
|
||||||
// ^ catches Ctrl+D
|
lispenv_add_builtins(env);
|
||||||
loop = 0;
|
if(VERBOSE) printfln("Added builtins");
|
||||||
} else {
|
if(VERBOSE) printfln("Environment contents: %i", env->count);
|
||||||
/* Attempt to Parse the user Input */
|
if(VERBOSE) printfln(" env->syms[0]: %s", env->syms[0]);
|
||||||
mpc_result_t result;
|
if(VERBOSE) print_lispval_tree(env->vals[0], 2);
|
||||||
if (mpc_parse("<stdin>", input, Mumble, &result)) {
|
if(VERBOSE) printfln("\n");
|
||||||
/* On Success Print the AST */
|
// Initialize a repl
|
||||||
// mpc_ast_print(result.output);
|
int loop = 1;
|
||||||
|
while (loop) {
|
||||||
|
char* input = readline("mumble> ");
|
||||||
|
if (input == NULL) {
|
||||||
|
// ^ catches Ctrl+D
|
||||||
|
loop = 0;
|
||||||
|
} else {
|
||||||
|
/* Attempt to Parse the user Input */
|
||||||
|
mpc_result_t result;
|
||||||
|
if (mpc_parse("<stdin>", input, Mumble, &result)) {
|
||||||
|
/* On Success Print the AST */
|
||||||
|
// mpc_ast_print(result.output);
|
||||||
/* Load AST from output */
|
/* Load AST from output */
|
||||||
mpc_ast_t* ast = result.output;
|
mpc_ast_t* ast = result.output;
|
||||||
|
|
||||||
|
@ -772,7 +845,6 @@ int main(int argc, char** argv)
|
||||||
print_ast(ast, 0);
|
print_ast(ast, 0);
|
||||||
}
|
}
|
||||||
// Evaluate the AST
|
// Evaluate the AST
|
||||||
if(VERBOSE) printfln("\nEvaluating the AST");
|
|
||||||
// lispval result = evaluate_ast(ast);
|
// lispval result = evaluate_ast(ast);
|
||||||
lispval* l = read_lispval(ast);
|
lispval* l = read_lispval(ast);
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
|
@ -782,22 +854,19 @@ int main(int argc, char** argv)
|
||||||
printfln("Parenthesis printing: ");
|
printfln("Parenthesis printing: ");
|
||||||
print_lispval_parenthesis(l);
|
print_lispval_parenthesis(l);
|
||||||
}
|
}
|
||||||
// Create an environment
|
|
||||||
lispenv* env = new_lispenv();
|
|
||||||
|
|
||||||
// Eval the lispval in that environment.
|
// Eval the lispval in that environment.
|
||||||
|
|
||||||
lispval* answer = evaluate_lispval(l, env);
|
lispval* answer = evaluate_lispval(l, env);
|
||||||
{
|
{
|
||||||
printfln("Result: ");
|
if(VERBOSE) printfln("Result: ");
|
||||||
print_lispval_parenthesis(answer);
|
print_lispval_parenthesis(answer);
|
||||||
print_lispval_tree(answer, 0);
|
if(VERBOSE) print_lispval_tree(answer, 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
// ^ I do not understand how the memory in l is freed.
|
// ^ I do not understand how the memory in l is freed.
|
||||||
delete_lispval(answer);
|
delete_lispval(answer);
|
||||||
// delete_lispval(l);
|
// delete_lispval(l);
|
||||||
// Clean up environment
|
|
||||||
destroy_lispenv(env);
|
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise Print the Error */
|
/* Otherwise Print the Error */
|
||||||
mpc_err_print(result.error);
|
mpc_err_print(result.error);
|
||||||
|
@ -811,6 +880,11 @@ int main(int argc, char** argv)
|
||||||
input = NULL;
|
input = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up environment
|
||||||
|
destroy_lispenv(env);
|
||||||
|
// Clean up environment
|
||||||
|
destroy_lispenv(env);
|
||||||
|
|
||||||
/* Undefine and Delete our Parsers */
|
/* Undefine and Delete our Parsers */
|
||||||
mpc_cleanup(6, Number, Symbol, Sexpr, Qexpr, Expr, Mumble);
|
mpc_cleanup(6, Number, Symbol, Sexpr, Qexpr, Expr, Mumble);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user