Archived
1
0
Fork 0

Made union data type for space efficiency

This commit is contained in:
Brandon Rozek 2018-06-03 12:46:52 -04:00
parent 0144d28002
commit 4d86d79a2f

View file

@ -30,11 +30,15 @@ void add_history(char* unused) {}
#include <editline/readline.h> #include <editline/readline.h>
#endif #endif
typedef union numerr {
long num;
int err;
} NumErr;
// A lispy value can either be a number or an error // A lispy value can either be a number or an error
typedef struct { typedef struct {
int type; int type;
long num; NumErr data;
int err;
} lval; } lval;
// Possible lispy value types // Possible lispy value types
@ -115,17 +119,17 @@ lval eval_op(lval x, char* op, lval y) {
if (x.type == LVAL_ERR) { return x; } if (x.type == LVAL_ERR) { return x; }
if (y.type == LVAL_ERR) { return y; } if (y.type == LVAL_ERR) { return y; }
if (strcmp(op, "+") == 0) { return lval_num(x.num + y.num); } if (strcmp(op, "+") == 0) { return lval_num(x.data.num + y.data.num); }
if (strcmp(op, "-") == 0) { return lval_num(x.num - y.num); } if (strcmp(op, "-") == 0) { return lval_num(x.data.num - y.data.num); }
if (strcmp(op, "*") == 0) { return lval_num(x.num * y.num); } if (strcmp(op, "*") == 0) { return lval_num(x.data.num * y.data.num); }
if (strcmp(op, "/") == 0) { if (strcmp(op, "/") == 0) {
// If you try to divide by zero, report an error // If you try to divide by zero, report an error
return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num / y.num); return y.data.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.data.num / y.data.num);
} }
if (strcmp(op, "min") == 0) { return lval_num(min(x.num, y.num)); } if (strcmp(op, "min") == 0) { return lval_num(min(x.data.num, y.data.num)); }
if (strcmp(op, "max") == 0) { return lval_num(max(x.num, y.num)); } if (strcmp(op, "max") == 0) { return lval_num(max(x.data.num, y.data.num)); }
if (strcmp(op, "^") == 0) { return lval_num(pow(x.num, y.num)); } if (strcmp(op, "^") == 0) { return lval_num(pow(x.data.num, y.data.num)); }
if (strcmp(op, "%") == 0) { return lval_num(fmod(x.num, y.num)); } if (strcmp(op, "%") == 0) { return lval_num(fmod(x.data.num, y.data.num)); }
return lval_err(LERR_BAD_OP); return lval_err(LERR_BAD_OP);
} }
@ -134,7 +138,7 @@ lval eval_uni(lval x, char* op) {
// If it's an error, return it // If it's an error, return it
if (x.type == LVAL_ERR) { return x; } if (x.type == LVAL_ERR) { return x; }
if (strcmp(op, "-") == 0) { return lval_num(-1 * x.num); } if (strcmp(op, "-") == 0) { return lval_num(-1 * x.data.num); }
return lval_err(LERR_BAD_OP); return lval_err(LERR_BAD_OP);
} }
@ -187,32 +191,32 @@ long min(long x, long y) {
lval lval_num(long x) { lval lval_num(long x) {
lval v; lval v;
v.type = LVAL_NUM; v.type = LVAL_NUM;
v.num = x; v.data.num = x;
return v; return v;
} }
lval lval_err(int x) { lval lval_err(int x) {
lval v; lval v;
v.type = LVAL_ERR; v.type = LVAL_ERR;
v.err = x; v.data.err = x;
return v; return v;
} }
void flval_print(FILE* stream, lval v) { void flval_print(FILE* stream, lval v) {
switch (v.type) { switch (v.type) {
// If it's a number, then print it out // If it's a number, then print it out
case LVAL_NUM: fprintf(stream, "%li", v.num); break; case LVAL_NUM: fprintf(stream, "%li", v.data.num); break;
// If it's an error, indicate the error // If it's an error, indicate the error
case LVAL_ERR: case LVAL_ERR:
fprintf(stream, "Error: "); fprintf(stream, "Error: ");
if (v.err == LERR_DIV_ZERO) { if (v.data.err == LERR_DIV_ZERO) {
fprintf(stream, "Division by zero"); fprintf(stream, "Division by zero");
} }
if (v.err == LERR_BAD_OP) { if (v.data.err == LERR_BAD_OP) {
fprintf(stream, "Invalid Operator"); fprintf(stream, "Invalid Operator");
} }
if (v.err == LERR_BAD_NUM) { if (v.data.err == LERR_BAD_NUM) {
fprintf(stream, "Invalid Number"); fprintf(stream, "Invalid Number");
} }
break; break;