Added symbols and errors into the union for lval
This commit is contained in:
parent
da94105307
commit
072b628341
8 changed files with 29 additions and 30 deletions
|
@ -12,6 +12,9 @@ typedef lval* (*lbuiltin) (lenv*, lval*);
|
||||||
typedef union typeval {
|
typedef union typeval {
|
||||||
long num;
|
long num;
|
||||||
double dec;
|
double dec;
|
||||||
|
// Error and symbols contain string data
|
||||||
|
char* err;
|
||||||
|
char* sym;
|
||||||
} TypeVal;
|
} TypeVal;
|
||||||
|
|
||||||
// A lispy value can either be a number, error, symbol, or an expression
|
// A lispy value can either be a number, error, symbol, or an expression
|
||||||
|
@ -19,10 +22,6 @@ struct lval {
|
||||||
int type;
|
int type;
|
||||||
TypeVal data;
|
TypeVal data;
|
||||||
|
|
||||||
// Error and symbols contain string data
|
|
||||||
char* err;
|
|
||||||
char* sym;
|
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
lbuiltin builtin;
|
lbuiltin builtin;
|
||||||
lenv* env;
|
lenv* env;
|
||||||
|
|
|
@ -62,8 +62,8 @@ int lval_eq(lval* x, lval* y) {
|
||||||
case LVAL_DOUBLE: return (x->data.dec == y->data.dec);
|
case LVAL_DOUBLE: return (x->data.dec == y->data.dec);
|
||||||
|
|
||||||
// Compare string values
|
// Compare string values
|
||||||
case LVAL_ERR: return (strcmp(x->err, y->err) == 0);
|
case LVAL_ERR: return (strcmp(x->data.err, y->data.err) == 0);
|
||||||
case LVAL_SYM: return (strcmp(x->sym, y->sym) == 0);
|
case LVAL_SYM: return (strcmp(x->data.sym, y->data.sym) == 0);
|
||||||
|
|
||||||
// If builtin compare, otherwise compare formals and body
|
// If builtin compare, otherwise compare formals and body
|
||||||
case LVAL_FUN:
|
case LVAL_FUN:
|
||||||
|
|
|
@ -43,7 +43,7 @@ lval* lenv_get(lenv* e, lval* k) {
|
||||||
for (int i = 0; i < e->count; i++) {
|
for (int i = 0; i < e->count; i++) {
|
||||||
// Check if the stored string matches the symbol string
|
// Check if the stored string matches the symbol string
|
||||||
// If it does, return a copy of hte value
|
// If it does, return a copy of hte value
|
||||||
if (strcmp(e->syms[i], k->sym) == 0) {
|
if (strcmp(e->syms[i], k->data.sym) == 0) {
|
||||||
return lval_copy(e->vals[i]);
|
return lval_copy(e->vals[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ lval* lenv_get(lenv* e, lval* k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no symbol found and no parent, return error
|
// If no symbol found and no parent, return error
|
||||||
return lval_err("Unbounded symbol %s", k->sym);
|
return lval_err("Unbounded symbol %s", k->data.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lenv_put(lenv* e, lval* k, lval* v) {
|
void lenv_put(lenv* e, lval* k, lval* v) {
|
||||||
|
@ -63,7 +63,7 @@ void lenv_put(lenv* e, lval* k, lval* v) {
|
||||||
for (int i = 0; i < e->count; i++) {
|
for (int i = 0; i < e->count; i++) {
|
||||||
// If a variable is found, delete the item at that position
|
// If a variable is found, delete the item at that position
|
||||||
// Then replace it with the data provided by the user
|
// Then replace it with the data provided by the user
|
||||||
if (strcmp(e->syms[i], k->sym) == 0) {
|
if (strcmp(e->syms[i], k->data.sym) == 0) {
|
||||||
lval_del(e->vals[i]);
|
lval_del(e->vals[i]);
|
||||||
e->vals[i] = lval_copy(v);
|
e->vals[i] = lval_copy(v);
|
||||||
return;
|
return;
|
||||||
|
@ -77,8 +77,8 @@ void lenv_put(lenv* e, lval* k, lval* v) {
|
||||||
|
|
||||||
// Copy contents of lval and symbol string
|
// Copy contents of lval and symbol string
|
||||||
e->vals[e->count - 1] = lval_copy(v);
|
e->vals[e->count - 1] = lval_copy(v);
|
||||||
e->syms[e->count - 1] = (char*) malloc(strlen(k->sym) + 1);
|
e->syms[e->count - 1] = (char*) malloc(strlen(k->data.sym) + 1);
|
||||||
strcpy(e->syms[e->count - 1], k->sym);
|
strcpy(e->syms[e->count - 1], k->data.sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lenv_def(lenv* e, lval* k, lval* v) {
|
void lenv_def(lenv* e, lval* k, lval* v) {
|
||||||
|
@ -252,7 +252,7 @@ lval* lval_call(lenv* e, lval* f, lval* a) {
|
||||||
// Pop the first symbol from the formals
|
// Pop the first symbol from the formals
|
||||||
lval* sym = lval_pop(f->formals, 0);
|
lval* sym = lval_pop(f->formals, 0);
|
||||||
|
|
||||||
if (strcmp(sym->sym, "&") == 0) {
|
if (strcmp(sym->data.sym, "&") == 0) {
|
||||||
// Ensure '&' is followed by another symbol
|
// Ensure '&' is followed by another symbol
|
||||||
if (f->formals->count != 1) {
|
if (f->formals->count != 1) {
|
||||||
lval_del(a);
|
lval_del(a);
|
||||||
|
@ -282,7 +282,7 @@ lval* lval_call(lenv* e, lval* f, lval* a) {
|
||||||
|
|
||||||
// If '&' remains in formal list bind to empty list
|
// If '&' remains in formal list bind to empty list
|
||||||
if (f->formals->count > 0 &&
|
if (f->formals->count > 0 &&
|
||||||
strcmp(f->formals->cell[0]->sym, "&") == 0) {
|
strcmp(f->formals->cell[0]->data.sym, "&") == 0) {
|
||||||
// Check to ensure that & is no passed invalidly
|
// Check to ensure that & is no passed invalidly
|
||||||
if (f->formals->count != 2) {
|
if (f->formals->count != 2) {
|
||||||
return lval_err("Function format invalid."
|
return lval_err("Function format invalid."
|
||||||
|
|
|
@ -13,13 +13,13 @@ lval* lval_err(char* fmt, ...) {
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
|
|
||||||
// Allocate 512 bytes of space
|
// Allocate 512 bytes of space
|
||||||
v->err = (char *) malloc(512);
|
v->data.err = (char *) malloc(512);
|
||||||
|
|
||||||
//printf the error string with a maximum of 511 characters
|
//printf the error string with a maximum of 511 characters
|
||||||
vsnprintf(v->err, 511, fmt, va);
|
vsnprintf(v->data.err, 511, fmt, va);
|
||||||
|
|
||||||
// Reallocate to the number of actual bytes
|
// Reallocate to the number of actual bytes
|
||||||
v->err = realloc(v->err, strlen(v->err) + 1);
|
v->data.err = realloc(v->data.err, strlen(v->data.err) + 1);
|
||||||
|
|
||||||
// Cleanup our va list
|
// Cleanup our va list
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
|
@ -58,11 +58,11 @@ lval* lval_take(lval* v, int i) {
|
||||||
lval* lval_eval_sexpr(lenv* e, lval* v) {
|
lval* lval_eval_sexpr(lenv* e, lval* v) {
|
||||||
// No argument functions
|
// No argument functions
|
||||||
if (v->count == 1 && v->cell[0]->type == LVAL_SYM) {
|
if (v->count == 1 && v->cell[0]->type == LVAL_SYM) {
|
||||||
if (strcmp(v->cell[0]->sym, "exit") == 0) { return v; }
|
if (strcmp(v->cell[0]->data.sym, "exit") == 0) { return v; }
|
||||||
lval* x = lenv_get(e, v->cell[0]);
|
lval* x = lenv_get(e, v->cell[0]);
|
||||||
if (x->type == LVAL_FUN) {
|
if (x->type == LVAL_FUN) {
|
||||||
lval_del(x);
|
lval_del(x);
|
||||||
if (strcmp(v->cell[0]->sym, "ls") == 0) {
|
if (strcmp(v->cell[0]->data.sym, "ls") == 0) {
|
||||||
lval_del(v);
|
lval_del(v);
|
||||||
return builtin_ls(e, lval_sexpr());
|
return builtin_ls(e, lval_sexpr());
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ void flval_print(FILE* stream, lval* v) {
|
||||||
|
|
||||||
case LVAL_DOUBLE: fprintf(stream, "%lf", v->data.dec); break;
|
case LVAL_DOUBLE: fprintf(stream, "%lf", v->data.dec); break;
|
||||||
|
|
||||||
case LVAL_ERR: fprintf(stream, "Error: %s", v->err); break;
|
case LVAL_ERR: fprintf(stream, "Error: %s", v->data.err); break;
|
||||||
|
|
||||||
case LVAL_SYM: fprintf(stream, "%s", v->sym); break;
|
case LVAL_SYM: fprintf(stream, "%s", v->data.sym); break;
|
||||||
|
|
||||||
case LVAL_SEXPR: flval_expr_print(stream, v, '(', ')'); break;
|
case LVAL_SEXPR: flval_expr_print(stream, v, '(', ')'); break;
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ 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;
|
||||||
v->sym = (char *) malloc(strlen(s) + 1);
|
v->data.sym = (char *) malloc(strlen(s) + 1);
|
||||||
strcpy(v->sym, s);
|
strcpy(v->data.sym, s);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +72,8 @@ void lval_del(lval* v) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Free the string data
|
// Free the string data
|
||||||
case LVAL_ERR: free(v->err); break;
|
case LVAL_ERR: free(v->data.err); break;
|
||||||
case LVAL_SYM: free(v->sym); break;
|
case LVAL_SYM: free(v->data.sym); break;
|
||||||
|
|
||||||
// Delete all elements inside SEXPR or QEXPR
|
// Delete all elements inside SEXPR or QEXPR
|
||||||
case LVAL_QEXPR:
|
case LVAL_QEXPR:
|
||||||
|
@ -112,11 +112,11 @@ lval* lval_copy(lval* v) {
|
||||||
|
|
||||||
// Copy strings using malloc and strcpy
|
// Copy strings using malloc and strcpy
|
||||||
case LVAL_ERR:
|
case LVAL_ERR:
|
||||||
x->err = (char*) malloc(strlen(v->err) + 1);
|
x->data.err = (char*) malloc(strlen(v->data.err) + 1);
|
||||||
strcpy(x->err, v->err); break;
|
strcpy(x->data.err, v->data.err); break;
|
||||||
case LVAL_SYM:
|
case LVAL_SYM:
|
||||||
x->sym = (char*) malloc(strlen(v->sym) + 1);
|
x->data.sym = (char*) malloc(strlen(v->data.sym) + 1);
|
||||||
strcpy(x->sym, v->sym); break;
|
strcpy(x->data.sym, v->data.sym); break;
|
||||||
|
|
||||||
// Copy lists by copying each sub-expression
|
// Copy lists by copying each sub-expression
|
||||||
case LVAL_SEXPR:
|
case LVAL_SEXPR:
|
||||||
|
|
4
prompt.c
4
prompt.c
|
@ -85,8 +85,8 @@ int main (int argc, char** argv) {
|
||||||
lval_println(result);
|
lval_println(result);
|
||||||
// mpc_ast_print(r.output);
|
// mpc_ast_print(r.output);
|
||||||
mpc_ast_delete(r.output);
|
mpc_ast_delete(r.output);
|
||||||
if ((result->type == LVAL_SEXPR && result->count > 0 && strcmp(result->cell[0]->sym, "exit") == 0) ||
|
if ((result->type == LVAL_SEXPR && result->count > 0 && strcmp(result->cell[0]->data.sym, "exit") == 0) ||
|
||||||
(result->type == LVAL_SYM && strcmp(result->sym, "exit") == 0))
|
(result->type == LVAL_SYM && strcmp(result->data.sym, "exit") == 0))
|
||||||
{ lval_del(result); free(input); break; }
|
{ lval_del(result); free(input); break; }
|
||||||
lval_del(result);
|
lval_del(result);
|
||||||
|
|
||||||
|
|
Reference in a new issue