Archived
1
0
Fork 0

Finished implementing the environment

This commit is contained in:
Brandon Rozek 2018-06-09 19:30:24 -04:00
parent e5d5aee39e
commit faf8a22331
7 changed files with 211 additions and 55 deletions

View file

@ -1,4 +1,64 @@
#include "environment.h" #include "environment.h"
#include <stdlib.h>
#include "error.h"
#include "expressions.h"
#include "operations.h"
lenv* lenv_new(void) {
lenv* e = (lenv*) malloc(sizeof(lenv));
e->count = 0;
e->syms = NULL;
e->vals = NULL;
return e;
}
void lenv_del(lenv* e) {
for (int i = 0; i < e->count; i++) {
free(e->syms[i]);
lval_del(e->vals[i]);
}
free(e->syms);
free(e->vals);
free(e);
}
lval* lenv_get(lenv* e, lval* k) {
// Iterate over all items in environment
for (int i = 0; i < e->count; i++) {
// Check if the stored string matches the symbol string
// If it does, return a copy of hte value
if (strcmp(e->syms[i], k->sym) == 0) {
return lval_copy(e->vals[i]);
}
}
// If no symbol found return error
return lval_err("unbounded symbol!");
}
void lenv_put(lenv* e, lval* k, lval* v) {
// Iterate over all items in the environment
// This is to see if the variables already exist
for (int i = 0; i < e->count; i++) {
// If a variable is found, delete the item at that position
// Then replace it with the data provided by the user
if (strcmp(e->syms[i], k->sym) == 0) {
lval_del(e->vals[i]);
e->vals[i] = lval_copy(v);
return;
}
}
// If no existing entry is found, allocate space for new entry
e->count++;
e->vals = realloc(e->vals, sizeof(lval*) * e->count);
e->syms = realloc(e->syms, sizeof(char*) * e->count);
// Copy contents of lval and symbol string
e->vals[e->count - 1] = lval_copy(v);
e->syms[e->count - 1] = (char*) malloc(strlen(k->sym) + 1);
strcpy(e->syms[e->count - 1], k->sym);
}
lval* lval_fun(lbuiltin func) { lval* lval_fun(lbuiltin func) {
lval* v = malloc(sizeof(lval)); lval* v = malloc(sizeof(lval));
@ -6,3 +66,31 @@ lval* lval_fun(lbuiltin func) {
v->fun = func; v->fun = func;
return v; return v;
} }
void lenv_add_builtin(lenv* e, char* name, lbuiltin func) {
lval* k = lval_sym(name);
lval* v = lval_fun(func);
lenv_put(e, k, v);
lval_del(k); lval_del(v);
}
void lenv_add_builtins(lenv* e) {
// List functions
lenv_add_builtin(e, "list", builtin_list);
lenv_add_builtin(e, "head", builtin_head);
lenv_add_builtin(e, "tail", builtin_tail);
lenv_add_builtin(e, "eval", builtin_eval);
lenv_add_builtin(e, "join", builtin_join);
lenv_add_builtin(e, "len", builtin_len);
lenv_add_builtin(e, "cons", builtin_cons);
// Mathematical Functions
lenv_add_builtin(e, "+", builtin_add);
lenv_add_builtin(e, "-", builtin_sub);
lenv_add_builtin(e, "*", builtin_mul);
lenv_add_builtin(e, "/", builtin_div);
lenv_add_builtin(e, "^", builtin_pow);
lenv_add_builtin(e, "%", builtin_mod);
lenv_add_builtin(e, "min", builtin_min);
lenv_add_builtin(e, "max", builtin_max);
}

View file

@ -2,6 +2,24 @@
#define LVAL_ENVIRONMENT #define LVAL_ENVIRONMENT
#include "base.h" #include "base.h"
struct lenv {
int count;
char** syms;
lval** vals;
};
lenv* lenv_new(void);
void lenv_del(lenv* e);
// Obtain a variable from the environment
// e is the environment
// k is the symbol
lval* lenv_get(lenv* e, lval* k);
void lenv_put(lenv* e, lval* k, lval* v);
lval* lval_fun(lbuiltin func); lval* lval_fun(lbuiltin func);
void lenv_add_builtin(lenv* e, char* name, lbuiltin func);
void lenv_add_builtins(lenv* e);
#endif #endif

View file

@ -54,10 +54,10 @@ lval* lval_take(lval* v, int i) {
return x; return x;
} }
lval* lval_eval_sexpr(lval* v) { lval* lval_eval_sexpr(lenv* e, lval* v) {
// Evaluate children // Evaluate children
for (int i = 0; i < v->count; i++) { for (int i = 0; i < v->count; i++) {
v->cell[i] = lval_eval(v->cell[i]); v->cell[i] = lval_eval(e, v->cell[i]);
} }
// Error checking [If there's an error, return it] // Error checking [If there's an error, return it]
@ -73,19 +73,19 @@ lval* lval_eval_sexpr(lval* v) {
// Ensure first element is a symbol otherwise // Ensure first element is a symbol otherwise
lval* f = lval_pop(v, 0); lval* f = lval_pop(v, 0);
if (f->type != LVAL_SYM) { if (f->type != LVAL_FUN) {
printf("The type of f is %d\n", f->type);
lval_del(f); lval_del(v); lval_del(f); lval_del(v);
return lval_err("S-expression does not start with symbol"); return lval_err("S-expression does not start with function");
} }
lval* result = builtin(v, f->sym); // If so call the function and return result
lval* result = f->fun(e, v);
lval_del(f); lval_del(f);
return result; return result;
} }
lval* builtin_headn(lval* a, int n) { lval* builtin_headn(lenv* e, lval* a, int n) {
LASSERT(a, a->count == 1, "Function 'head' passed too many arguments") LASSERT(a, a->count == 1, "Function 'head' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'head' passed incorrect type") LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'head' passed incorrect type")
LASSERT(a, a->cell[0]->count != 0, "Function 'head' passed {}") LASSERT(a, a->cell[0]->count != 0, "Function 'head' passed {}")
@ -95,20 +95,20 @@ lval* builtin_headn(lval* a, int n) {
return v; return v;
} }
lval* builtin_head(lval* a) { lval* builtin_head(lenv* e, lval* a) {
return builtin_headn(a, 1); return builtin_headn(e, a, 1);
} }
lval* builtin_init(lval* a) { lval* builtin_init(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'init' passed too many arguments") LASSERT(a, a->count == 1, "Function 'init' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'init' passed incorrect type") LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'init' passed incorrect type")
LASSERT(a, a->cell[0]->count != 0, "Function 'init' passed {}") LASSERT(a, a->cell[0]->count != 0, "Function 'init' passed {}")
return builtin_headn(a, a->cell[0]->count - 1); return builtin_headn(e, a, a->cell[0]->count - 1);
} }
lval* builtin_tail(lval* a) { lval* builtin_tail(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'tail' passed too many arguments") LASSERT(a, a->count == 1, "Function 'tail' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'tail' passed incorrect type") LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'tail' passed incorrect type")
LASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed {}") LASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed {}")
@ -118,21 +118,21 @@ lval* builtin_tail(lval* a) {
return v; return v;
} }
lval* builtin_list(lval* a) { lval* builtin_list(lenv* e, lval* a) {
a->type = LVAL_QEXPR; a->type = LVAL_QEXPR;
return a; return a;
} }
lval* builtin_eval(lval* a) { lval* builtin_eval(lenv* e, lval* a) {
LASSERT(a, a->count == 1, "Function 'eval' passed too many arguments") LASSERT(a, a->count == 1, "Function 'eval' passed too many arguments")
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'eval' passed incorrect type") LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'eval' passed incorrect type")
lval* x = lval_take(a, 0); lval* x = lval_take(a, 0);
x->type = LVAL_SEXPR; x->type = LVAL_SEXPR;
return lval_eval(x); return lval_eval(e, x);
} }
lval* lval_join(lval* x, lval* y) { lval* lval_join(lenv* e, lval* x, lval* y) {
// For each cell in 'y' add it to 'x' // For each cell in 'y' add it to 'x'
while (y->count) { while (y->count) {
x = lval_add(x, lval_pop(y, 0)); x = lval_add(x, lval_pop(y, 0));
@ -143,7 +143,7 @@ lval* lval_join(lval* x, lval* y) {
return x; return x;
} }
lval* builtin_join(lval* a) { lval* builtin_join(lenv* e, lval* a) {
for (int i = 0 ; i < a->count; i++) { for (int i = 0 ; i < a->count; i++) {
LASSERT(a, a->cell[i]->type == LVAL_QEXPR, "Function 'join' passed incorrect type") LASSERT(a, a->cell[i]->type == LVAL_QEXPR, "Function 'join' passed incorrect type")
} }
@ -151,14 +151,14 @@ lval* builtin_join(lval* a) {
lval* x = lval_pop(a, 0); lval* x = lval_pop(a, 0);
while (a->count) { while (a->count) {
x = lval_join(x, lval_pop(a, 0)); x = lval_join(e, x, lval_pop(a, 0));
} }
lval_del(a); lval_del(a);
return x; return x;
} }
lval* builtin_len(lval* a) { lval* builtin_len(lenv* e, lval* a) {
LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'len' passed incorrect type") LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'len' passed incorrect type")
lval* x = lval_long(a->cell[0]->count); lval* x = lval_long(a->cell[0]->count);
@ -166,14 +166,14 @@ lval* builtin_len(lval* a) {
return x; return x;
} }
lval* builtin_cons(lval* a) { lval* builtin_cons(lenv* e, lval* a) {
LASSERT(a, a->cell[0]->type != LVAL_QEXPR, "Function 'cons' passed incorrect type on first argument") LASSERT(a, a->cell[0]->type != LVAL_QEXPR, "Function 'cons' passed incorrect type on first argument")
LASSERT(a, a->cell[1]->type == LVAL_QEXPR, "Function 'cons' passed incorrect type on second argument") LASSERT(a, a->cell[1]->type == LVAL_QEXPR, "Function 'cons' passed incorrect type on second argument")
LASSERT(a, a->count == 2, "Function 'cons' passed an incorrect number of arguments") LASSERT(a, a->count == 2, "Function 'cons' passed an incorrect number of arguments")
lval* x = lval_qexpr(); lval* x = lval_qexpr();
x = lval_add(x, lval_pop(a, 0)); x = lval_add(x, lval_pop(a, 0));
x = lval_join(x, lval_pop(a, 0)); x = lval_join(e, x, lval_pop(a, 0));
lval_del(a); lval_del(a);

View file

@ -1,6 +1,7 @@
#ifndef LVAL_EXPRESSIONS #ifndef LVAL_EXPRESSIONS
#define LVAL_EXPRESSIONS #define LVAL_EXPRESSIONS
#include "base.h" #include "base.h"
#include "environment.h"
// Constructors for the SEXPR and QEXPR data type // Constructors for the SEXPR and QEXPR data type
lval* lval_sexpr(void); lval* lval_sexpr(void);
@ -20,7 +21,7 @@ lval* lval_take(lval* v, int i);
/* ----------------------------------------------------*/ /* ----------------------------------------------------*/
// Adds the ability to evalutate each expression in the group // Adds the ability to evalutate each expression in the group
lval* lval_eval_sexpr(lval* v); lval* lval_eval_sexpr(lenv* e, lval* v);
/* /*
QEXPR Operations QEXPR Operations
@ -32,15 +33,15 @@ lval* lval_eval_sexpr(lval* v);
Len: Takes a Q-Expression and returns the length of the Q-Expression Len: Takes a Q-Expression and returns the length of the Q-Expression
Init: Takes a Q-Expression and returns a Q-Expression with only the last element removed Init: Takes a Q-Expression and returns a Q-Expression with only the last element removed
*/ */
lval* builtin_headn(lval* a, int n); lval* builtin_headn(lenv* e, lval* a, int n);
lval* builtin_head(lval* a); lval* builtin_head(lenv* e, lval* a);
lval* builtin_init(lval* a); lval* builtin_init(lenv* e, lval* a);
lval* builtin_tail(lval* a); lval* builtin_tail(lenv* e, lval* a);
lval* builtin_list(lval* a); lval* builtin_list(lenv* e, lval* a);
lval* builtin_eval(lval* a); lval* builtin_eval(lenv* e, lval* a);
lval* lval_join(lval* x, lval* y); lval* lval_join(lenv* e, lval* x, lval* y);
lval* builtin_join(lval* a); lval* builtin_join(lenv* e, lval* a);
lval* builtin_len(lval* a); lval* builtin_len(lenv* e, lval* a);
lval* builtin_cons(lval* a); lval* builtin_cons(lenv* e, lval* a);
#endif #endif

View file

@ -4,6 +4,8 @@
#include "expressions.h" #include "expressions.h"
#include "operations.h" #include "operations.h"
lval* builtin_op(lenv* e, lval* v, char* sym);
lval* lval_sym(char* s) { lval* lval_sym(char* s) {
lval* v = (lval *) malloc(sizeof(lval)); lval* v = (lval *) malloc(sizeof(lval));
v->type = LVAL_SYM; v->type = LVAL_SYM;
@ -42,9 +44,15 @@ lval* lval_read(mpc_ast_t* t) {
} }
lval* lval_eval(lval* v) { lval* lval_eval(lenv* e, lval* v) {
if (v->type == LVAL_SYM) {
lval* x = lenv_get(e, v);
lval_del(v);
return x;
}
// Evauluate sexpressions // Evauluate sexpressions
if (v->type == LVAL_SEXPR) { return lval_eval_sexpr(v); } if (v->type == LVAL_SEXPR) { return lval_eval_sexpr(e, v); }
// All other lval types remail the same // All other lval types remail the same
return v; return v;
@ -108,4 +116,34 @@ lval* lval_copy(lval* v) {
return x; return x;
} }
lval* builtin_add(lenv* e, lval* a) {
return builtin_op(e, a, "+");
}
lval* builtin_sub(lenv* e, lval* a) {
return builtin_op(e, a, "-");
}
lval* builtin_mul(lenv* e, lval* a) {
return builtin_op(e, a, "*");
}
lval* builtin_div(lenv* e, lval* a) {
return builtin_op(e, a, "/");
}
lval* builtin_pow(lenv* e, lval* a) {
return builtin_op(e, a, "^");
}
lval* builtin_mod(lenv* e, lval* a) {
return builtin_op(e, a, "%");
}
lval* builtin_min(lenv* e, lval* a) {
return builtin_op(e, a, "min");
}
lval* builtin_max(lenv* e, lval* a) {
return builtin_op(e, a, "max");
}

View file

@ -3,6 +3,7 @@
#include "../mpc.h" #include "../mpc.h"
#include "base.h" #include "base.h"
#include "environment.h"
// Constructor for symbol data type // Constructor for symbol data type
lval* lval_sym(char* s); lval* lval_sym(char* s);
@ -12,8 +13,20 @@ lval* lval_sym(char* s);
copy, and delete lval structures copy, and delete lval structures
*/ */
lval* lval_read(mpc_ast_t* t); lval* lval_read(mpc_ast_t* t);
lval* lval_eval(lval* v); lval* lval_eval(lenv* e, lval* v);
void lval_del(lval* v); void lval_del(lval* v);
lval* lval_copy(lval* v); lval* lval_copy(lval* v);
// Math libraries
lval* builtin_add(lenv* e, lval* a);
lval* builtin_sub(lenv* e, lval* a);
lval* builtin_mul(lenv* e, lval* a);
lval* builtin_div(lenv* e, lval* a);
lval* builtin_pow(lenv* e, lval* a);
lval* builtin_mod(lenv* e, lval* a);
lval* builtin_min(lenv* e, lval* a);
lval* builtin_max(lenv* e, lval* a);
#endif #endif

View file

@ -33,7 +33,7 @@ void add_history(char* unused) {}
double max(double x, double y); double max(double x, double y);
double min(double x, double y); double min(double x, double y);
lval* builtin_op(lval* v, char* op); lval* builtin_op(lenv* e, lval* v, char* op);
int main (int argc, char** argv) { int main (int argc, char** argv) {
@ -65,6 +65,9 @@ int main (int argc, char** argv) {
puts("Lispy Version 0.0.0.0.1"); puts("Lispy Version 0.0.0.0.1");
puts("Press Ctrl+c to Exit\n"); puts("Press Ctrl+c to Exit\n");
lenv* e = lenv_new();
lenv_add_builtins(e);
// In a never ending loop // In a never ending loop
while (1) { while (1) {
// Output prompt and query // Output prompt and query
@ -78,7 +81,7 @@ int main (int argc, char** argv) {
if (mpc_parse("<stdin>", input, Lispy, &r)) { if (mpc_parse("<stdin>", input, Lispy, &r)) {
// Evualuate the expression and print its output // Evualuate the expression and print its output
// lval result = eval(r.output); // lval result = eval(r.output);
lval* result = lval_eval(lval_read(r.output)); lval* result = lval_eval(e, lval_read(r.output));
lval_println(result); lval_println(result);
lval_del(result); lval_del(result);
// mpc_ast_print(r.output); // mpc_ast_print(r.output);
@ -112,12 +115,7 @@ double min(double x, double y) {
return y; return y;
} }
lval* builtin_op(lenv* e, lval* a, char* op) {
lval* builtin_op(lval* a, char* op) {
// Ensure all arguments are numbers // Ensure all arguments are numbers
for (int i = 0; i < a->count; i++) { for (int i = 0; i < a->count; i++) {
if (a->cell[i]->type != LVAL_LONG && a->cell[i]->type != LVAL_DOUBLE) { if (a->cell[i]->type != LVAL_LONG && a->cell[i]->type != LVAL_DOUBLE) {
@ -157,18 +155,18 @@ lval* builtin_op(lval* a, char* op) {
return x; return x;
} }
lval* builtin(lval* a, char* func) { lval* builtin(lenv* e, lval* a, char* func) {
if (strcmp("list", func) == 0) { return builtin_list(a); } if (strcmp("list", func) == 0) { return builtin_list(e, a); }
if (strcmp("head", func) == 0) { return builtin_head(a); } if (strcmp("head", func) == 0) { return builtin_head(e, a); }
if (strcmp("tail", func) == 0) { return builtin_tail(a); } if (strcmp("tail", func) == 0) { return builtin_tail(e, a); }
if (strcmp("join", func) == 0) { return builtin_join(a); } if (strcmp("join", func) == 0) { return builtin_join(e, a); }
if (strcmp("eval", func) == 0) { return builtin_eval(a); } if (strcmp("eval", func) == 0) { return builtin_eval(e, a); }
if (strcmp("len", func) == 0) { return builtin_len(a); } if (strcmp("len", func) == 0) { return builtin_len(e, a); }
if (strcmp("init", func) == 0) { return builtin_init(a); } if (strcmp("init", func) == 0) { return builtin_init(e, a); }
if (strcmp("cons", func) == 0) { return builtin_cons(a); } if (strcmp("cons", func) == 0) { return builtin_cons(e, a); }
if (strstr("+-/*^%", func)) { return builtin_op(a, func); } if (strstr("+-/*^%", func)) { return builtin_op(e, a, func); }
if (strcmp("min", func) == 0) { return builtin_op(a, func); } if (strcmp("min", func) == 0) { return builtin_op(e, a, func); }
if (strcmp("max", func) == 0) { return builtin_op(a, func); } if (strcmp("max", func) == 0) { return builtin_op(e, a, func); }
lval_del(a); lval_del(a);
return lval_err("Unknown Function!"); return lval_err("Unknown Function!");