Skip to content

Instantly share code, notes, and snippets.

@soasme
Last active June 18, 2019 03:44
Show Gist options
  • Save soasme/87618e90cfa600c6eabd5d9386a48281 to your computer and use it in GitHub Desktop.
Save soasme/87618e90cfa600c6eabd5d9386a48281 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef enum {
MONDAY_OK,
MONDAY_ERR,
MONDAY_RET,
MONDAY_BRK,
MONDAY_CON,
} ReturnCode;
typedef enum {
MONDAY_STR,
MONDAY_INT,
MONDAY_FLOAT,
MONDAY_DICT,
MONDAY_LIST,
MONDAY_BOOL,
MONDAY_SYM,
MONDAY_SEXPR,
} MondayTokenType;
struct MondayInterp; /* forward declaration. */
struct MondayToken;
struct MondayFrame;
struct MondayFunction;
struct MondayVar;
typedef char* String;
struct MondayInterp {
int nestingLevel;
struct MondayFrame* callframe;
struct MondayFunction* functions;
String result;
};
struct MondayToken {
MondayTokenType type;
union {
long i;
double f;
bool b;
String s;
void* p;
} data;
struct MondayToken** cells;
};
struct MondayFrame {
struct MondayVar* vars;
struct MondayFrame* parent;
};
typedef ReturnCode (*UserFunction)(struct MondayInterp*, int argc, char **argv, void *privateData);
struct MondayFunction {
char *name;
UserFunction func;
void *privateData;
struct MondayFunction* next;
};
struct MondayVar {
char *name, *val;
struct MondayVar *next;
};
struct MondayToken* mondayIntToken(long x) {
struct MondayToken* t = malloc(sizeof(struct MondayToken));
t->type = MONDAY_INT;
t->data.i = x;
t->cells = NULL;
return t;
}
struct MondayToken* mondayStrToken(String s) {
struct MondayToken* t = malloc(sizeof(struct MondayToken));
t->type = MONDAY_STR;
t->data.s = strdup(s);
t->cells = NULL;
return t;
}
struct MondayToken* mondaySymToken(String s) {
struct MondayToken* t = malloc(sizeof(struct MondayToken));
t->type = MONDAY_SYM;
t->data.s = strdup(s);
t->cells = NULL;
return t;
}
struct MondayToken* mondaySexprToken(void) {
struct MondayToken* t = malloc(sizeof(struct MondayToken));
t->type = MONDAY_SEXPR;
t->data.i = 0;
t->cells = NULL;
return t;
}
struct MondayToken* mondaySexprAdd(struct MondayToken* s, struct MondayToken* cell) {
s->data.i++;
s->cells = realloc(s->cells, sizeof(struct MondayToken*) * s->data.i);
s->cells[s->data.i-1] = cell;
return s;
}
void mondayFreeToken(struct MondayToken* t) {
switch(t->type) {
case MONDAY_INT:
break;
case MONDAY_STR:
free(t->data.s); break;
case MONDAY_SYM:
free(t->data.s); break;
case MONDAY_SEXPR:
for (int i = 0; i < t->data.i; i++) {
mondayFreeToken(t->cells[i]);
}
break;
default: break; /* TODO */
}
free(t);
}
ReturnCode mondayParse(String src) {
return MONDAY_OK;
}
ReturnCode mondayInitInterp(struct MondayInterp* i) {
i->nestingLevel = 0;
i->callframe = malloc(sizeof(struct MondayFrame));
i->callframe->vars = NULL;
i->callframe->parent = NULL;
i->functions = NULL;
i->result = strdup("");
return MONDAY_OK;
}
struct MondayFunction* mondayGetFunction(struct MondayInterp* i, String name) {
struct MondayFunction* f = i->functions;
while (f) {
if (strcmp(f->name, name) == 0) return f;
f = f->next;
}
return NULL;
}
void mondaySetResult(struct MondayInterp* i, String s) {
free(i->result);
i->result = strdup(s);
}
ReturnCode mondayArityException(struct MondayInterp* i, char* name) {
char buf[1024];
snprintf(buf, 1024, "ArityException: %s", name);
mondaySetResult(i, buf);
return MONDAY_ERR;
}
ReturnCode mondayUndefinedException(struct MondayInterp* i, char* name) {
char buf[1024];
snprintf(buf, 1024, "UndefinedException: %s", name);
mondaySetResult(i, buf);
return MONDAY_ERR;
}
struct MondayVar* mondayGetVar(struct MondayInterp* i, String name) {
struct MondayVar* v = i->callframe->vars;
while (v) {
if (strcmp(name, v->name) == 0) return v;
v = v->next;
}
return NULL;
}
ReturnCode mondaySetVar(struct MondayInterp* i, String name, String val) {
struct MondayVar* v = mondayGetVar(i, name);
if (v) {
free(v->val);
v->val = strdup(val);
} else {
v = malloc(sizeof(*v));
v->name = strdup(name);
v->val = strdup(val);
v->next = i->callframe->vars;
i->callframe->vars = v;
}
return MONDAY_OK;
}
ReturnCode mondayRegisterFunction(struct MondayInterp* i, String name, UserFunction func, void* privateData) {
struct MondayFunction* f = mondayGetFunction(i, name);
if (f) free(f); // already defined function. Free it first.
f = malloc(sizeof(*f));
f->name = strdup(name);
f->func = func;
f->privateData = privateData;
f->next = i->functions;
i->functions = f;
return MONDAY_OK;
}
ReturnCode mondayEvalToken(struct MondayInterp* i, struct MondayToken* t) {
char buf[64];
struct MondayVar* var;
struct MondayFunction* f;
char** argv;
switch (t->type) {
case MONDAY_STR: i->result = strdup(t->data.s); break;
case MONDAY_INT:
snprintf(buf, 64, "%ld", t->data.i);
i->result = strdup(buf); break;
case MONDAY_SYM:
var = mondayGetVar(i, t->data.s);
if (!var) return mondayUndefinedException(i, t->data.s);
i->result = strdup(var->val); break;
case MONDAY_SEXPR:
argv = malloc(sizeof(char*) * t->data.i);
f = mondayGetFunction(i, t->cells[0]->data.s);
for(int j = 1; j < t->data.i; j++) {
mondayEvalToken(i, t->cells[j]);
argv[j] = strdup(i->result);
}
f->func(i, t->data.i, argv, NULL);
break;
default: break;
}
return MONDAY_OK;
}
ReturnCode mondayBuiltinLet(struct MondayInterp* i, int argc, char **argv, void *p) {
if (argc != 3) return mondayArityException(i, argv[0]);
mondaySetVar(i, argv[1], argv[2]);
mondaySetResult(i, argv[2]);
return MONDAY_OK;
}
ReturnCode mondayBuiltinPuts(struct MondayInterp* i, int argc, char **argv, void *p) {
if (argc != 2) return mondayArityException(i, argv[0]);
printf("%s\n", argv[1]);
mondaySetResult(i, "");
return MONDAY_OK;
}
ReturnCode mondayBuiltinCall(struct MondayInterp* i, int argc, char **argv, void *p) {
struct MondayFrame* frm = malloc(sizeof(*frm));
frm->vars = NULL;
frm->parent = i->callframe;
i->callframe = frm;
/*mondaySetCallArgs(i, frm, p[0]);
mondayEval(i, p[1]);
mondayDropFrame(i);*/
return MONDAY_OK;
}
ReturnCode mondayBuiltinProc(struct MondayInterp* i, int argc, char **argv, void *p) {
if (argc != 4) return mondayArityException(i, argv[0]);
String *procdata = malloc(sizeof(String)*2);
procdata[0] = strdup(argv[2]); /* proc args */
procdata[1] = strdup(argv[3]); /* proc body */
return mondayRegisterFunction(i, argv[1], mondayBuiltinCall, procdata);
}
ReturnCode mondayRegisterBuiltins(struct MondayInterp* i) {
mondayRegisterFunction(i, "let", mondayBuiltinLet, NULL);
mondayRegisterFunction(i, "puts", mondayBuiltinPuts, NULL);
return MONDAY_OK;
}
int main(int argc, char **argv) {
struct MondayInterp interp;
mondayInitInterp(&interp);
mondayRegisterBuiltins(&interp);
struct MondayToken* t;
t = mondayIntToken(1);
mondayEvalToken(&interp, t);
printf("> 1\n%s\n", interp.result);
mondayFreeToken(t);
t = mondayStrToken("hello world");
mondayEvalToken(&interp, t);
printf("> \"hello world\"\n%s\n", interp.result);
mondayFreeToken(t);
struct MondayToken* l = mondaySexprToken();
mondaySexprAdd(l, mondaySymToken("let"));
mondaySexprAdd(l, mondayStrToken("name"));
mondaySexprAdd(l, mondayStrToken("Monday"));
printf("> let(\"name\", \"Monday\")\n");
mondayEvalToken(&interp, t);
mondayFreeToken(l);
t = mondaySymToken("name");
mondayEvalToken(&interp, t);
printf("> name\n%s\n", interp.result);
mondayFreeToken(t);
struct MondayToken* s = mondaySexprToken();
mondaySexprAdd(s, mondaySymToken("puts"));
mondaySexprAdd(s, mondayStrToken("hello world"));
printf("> puts(\"hello world\")\n");
mondayEvalToken(&interp, s);
printf("%s\n", interp.result);
mondayFreeToken(s);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment