Last active
June 18, 2019 03:44
-
-
Save soasme/87618e90cfa600c6eabd5d9386a48281 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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