eval function calls, 2nd and improved attempt
This commit is contained in:
parent
bc8cbe24e9
commit
712dcfc931
137
tokenize.l
137
tokenize.l
|
@ -86,7 +86,7 @@ enum yytokentype {
|
|||
};
|
||||
|
||||
struct token* make_token(enum yytokentype, int, char*);
|
||||
struct ast* eval(struct ast *a, struct env *e);
|
||||
struct ast* eval(struct ast *a, struct env *e, struct env **w);
|
||||
int yylval;
|
||||
char *yystr;
|
||||
%}
|
||||
|
@ -144,6 +144,10 @@ void
|
|||
debug_token(struct token *x, int indent)
|
||||
{
|
||||
for (int i = 0; i < indent; i++) putc(' ', stderr);
|
||||
if (x == NULL) {
|
||||
fprintf(stderr, "NULL TOKEN\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%d: (%p)", x->type, x);
|
||||
if (x->type == NUM) fprintf(stderr, "%d @ %p", x->v.num, x);
|
||||
if (x->type == STR || x->type == SYM)
|
||||
|
@ -308,11 +312,11 @@ lookup(struct env *e, char *name)
|
|||
if (e == NULL)
|
||||
return NULL;
|
||||
for (struct env *t = e; t != NULL; t = t->next) {
|
||||
fprintf(stderr, "env: %s\n", t->name);
|
||||
/* fprintf(stderr, "env: %s\n", t->name); */
|
||||
if (strcmp(t->name, name) == 0)
|
||||
return t->a;
|
||||
}
|
||||
fprintf(stderr, "====\n");
|
||||
//fprintf(stderr, "====\n");
|
||||
return lookup(e->parent, name);
|
||||
}
|
||||
|
||||
|
@ -321,6 +325,7 @@ struct ast *
|
|||
eval_def(struct ast *a, struct env *e)
|
||||
{
|
||||
a = a->next; /* skip `def` */
|
||||
//debug_ast(a, 0);
|
||||
reassure(a->v.token->type == SYM, /* must be a symbol */
|
||||
"%s: expected SYM, given: %d",
|
||||
__func__, a->v.token->type);
|
||||
|
@ -345,7 +350,7 @@ eval_def(struct ast *a, struct env *e)
|
|||
"%s: %s already assigned in env=%p",
|
||||
__func__, new, e);
|
||||
|
||||
append(e, make_env(new, eval(a->next, e)));
|
||||
append(e, make_env(new, eval(a->next, e, NULL)));
|
||||
|
||||
reassure(a->next->next == NULL,
|
||||
"%s: ended with unexpected token", __func__);
|
||||
|
@ -356,12 +361,13 @@ eval_def(struct ast *a, struct env *e)
|
|||
struct ast *
|
||||
eval_if(struct ast *a, struct env *e)
|
||||
{
|
||||
//debug_ast(a, 0);
|
||||
a = a->next;
|
||||
|
||||
reassure(a != NULL && a->next != NULL,
|
||||
"%s: unexpected NULL", __func__);
|
||||
|
||||
struct ast *condition = eval(a, e);
|
||||
struct ast *condition = eval(a, e, NULL);
|
||||
|
||||
reassure(condition != NULL &&
|
||||
condition->type == AST_TOK &&
|
||||
|
@ -373,9 +379,9 @@ eval_if(struct ast *a, struct env *e)
|
|||
__func__);
|
||||
|
||||
if (condition->v.token->v.num == 1)
|
||||
return eval(a->next, e);
|
||||
return eval(a->next, e, NULL);
|
||||
else
|
||||
return eval(a->next->next, e);
|
||||
return eval(a->next->next, e, NULL);
|
||||
}
|
||||
|
||||
/* (nand <ausdruck::bool> <audsruck::bool>) -> BOOL */
|
||||
|
@ -388,8 +394,8 @@ eval_nand(struct ast *a, struct env *e)
|
|||
a->next->next->next == NULL,
|
||||
"%s: unexpected NULL", __func__);
|
||||
|
||||
struct ast *op1 = eval(a->next, e);
|
||||
struct ast *op2 = eval(a->next->next, e);
|
||||
struct ast *op1 = eval(a->next, e, NULL);
|
||||
struct ast *op2 = eval(a->next->next, e, NULL);
|
||||
|
||||
reassure(op1 != NULL &&
|
||||
op1->type == AST_TOK &&
|
||||
|
@ -416,8 +422,8 @@ eval_add(struct ast *a, struct env *e)
|
|||
a->next->next->next == NULL,
|
||||
"%s: expected 2 operands", __func__);
|
||||
|
||||
struct ast *op1 = eval(a->next, e);
|
||||
struct ast *op2 = eval(a->next->next, e);
|
||||
struct ast *op1 = eval(a->next, e, NULL);
|
||||
struct ast *op2 = eval(a->next->next, e, NULL);
|
||||
|
||||
reassure(op1 != NULL &&
|
||||
op1->type == AST_TOK &&
|
||||
|
@ -443,8 +449,8 @@ eval_lt(struct ast *a, struct env *e)
|
|||
a->next->next->next == NULL,
|
||||
"%s: expected 2 operands", __func__);
|
||||
|
||||
struct ast *op1 = eval(a->next, e);
|
||||
struct ast *op2 = eval(a->next->next, e);
|
||||
struct ast *op1 = eval(a->next, e, NULL);
|
||||
struct ast *op2 = eval(a->next->next, e, NULL);
|
||||
|
||||
reassure(op1 != NULL &&
|
||||
op1->type == AST_TOK &&
|
||||
|
@ -468,7 +474,7 @@ eval_inv(struct ast *a, struct env *e)
|
|||
a->next != NULL &&
|
||||
a->next->next == NULL,
|
||||
"%s: expected one argument", __func__);
|
||||
struct ast *op = eval(a->next, e);
|
||||
struct ast *op = eval(a->next, e, NULL);
|
||||
reassure(op != NULL &&
|
||||
op->type == AST_TOK &&
|
||||
op->v.token->type == NUM &&
|
||||
|
@ -488,7 +494,7 @@ eval_num2bool(struct ast *a, struct env *e)
|
|||
a->next != NULL &&
|
||||
a->next->next == NULL,
|
||||
"%s: expected one operand", __func__);
|
||||
struct ast *op = eval(a->next, e);
|
||||
struct ast *op = eval(a->next, e, NULL);
|
||||
reassure(op != NULL &&
|
||||
op->type == AST_TOK &&
|
||||
op->v.token->type == NUM &&
|
||||
|
@ -501,17 +507,26 @@ eval_num2bool(struct ast *a, struct env *e)
|
|||
}
|
||||
|
||||
struct ast *
|
||||
eval_internal_sym(struct ast *a, struct env *e)
|
||||
eval_internal_sym(struct ast *x, struct env *e)
|
||||
{
|
||||
struct ast *a = x->v.list;
|
||||
if (strcmp(a->v.token->v.str, "def") == 0)
|
||||
return eval_def(a, e);
|
||||
else if (strcmp(a->v.token->v.str, "lm") == 0) {
|
||||
//new->v.token = a->v.token;
|
||||
return x;
|
||||
struct ast *l = make_ast(AST_LIST, NULL);
|
||||
struct ast *head = make_ast(AST_TOK, NULL);
|
||||
l->v.list = head;
|
||||
l->next = a->next;
|
||||
fprintf(stderr, "%p, %p\n", l->next, a->next);
|
||||
l->next->next = a->next->next;
|
||||
//debug_ast(l, 0);
|
||||
head->v.token = a->v.token;
|
||||
//fprintf(stderr, "returning AST:\n");
|
||||
//fprintf(stderr, "------------------------\n");
|
||||
//debug_ast(l, 0);
|
||||
//fprintf(stderr, "------------------------\n");
|
||||
return l;
|
||||
} else if (strcmp(a->v.token->v.str, "if") == 0) {
|
||||
return eval_if(a, e);
|
||||
|
@ -541,13 +556,13 @@ eval_defined_sym(struct ast *a, struct env *e)
|
|||
__func__, a->v.token->v.str);
|
||||
return var;
|
||||
}
|
||||
|
||||
struct env *lastenv;
|
||||
struct env *
|
||||
bind_args(struct token *args,
|
||||
struct ast *fnargs_values, struct env *e)
|
||||
{
|
||||
reassure(args && args->type == LPAR,
|
||||
"%s: first argument", __func__);
|
||||
"%s: first argument: %d %s", __func__, args->type, args->v.str);
|
||||
args = args->next;
|
||||
|
||||
struct ast *a = fnargs_values;
|
||||
|
@ -557,6 +572,7 @@ bind_args(struct token *args,
|
|||
|
||||
newenv->name = strdup("__fn");
|
||||
newenv->parent = e;
|
||||
lastenv = newenv;
|
||||
|
||||
while (t != NULL && t->type != RPAR) {
|
||||
reassure(t != NULL &&
|
||||
|
@ -569,7 +585,7 @@ bind_args(struct token *args,
|
|||
"%s: arg=%s given, but no value present",
|
||||
__func__, t->v.str);
|
||||
|
||||
struct ast *new = eval(a, e);
|
||||
struct ast *new = eval(a, e, NULL);
|
||||
|
||||
append(newenv, make_env(t->v.str, new));
|
||||
|
||||
|
@ -587,11 +603,44 @@ bind_args(struct token *args,
|
|||
}
|
||||
|
||||
struct ast *
|
||||
eval_fn_call(struct ast *a, struct env *e)
|
||||
eval_fn_name(struct ast *a, struct env *e, struct env **w)
|
||||
{
|
||||
if (a->type == AST_LIST) {
|
||||
//fprintf(stderr, "eval list\n");
|
||||
//debug_ast(a, 0);
|
||||
//reassure(0, "not implemented\n");
|
||||
//return eval(a, e, NULL);
|
||||
return a;
|
||||
} else if (a->type == AST_TOK) {
|
||||
//fprintf(stderr, "eval token: %s\n", a->v.token->v.str);
|
||||
struct ast *fn = lookup(e, a->v.token->v.str);
|
||||
return eval(fn, e, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast *
|
||||
eval_fn_call(struct ast *a, struct env *e, struct env **w)
|
||||
{
|
||||
//fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~ eval call\n");
|
||||
|
||||
struct ast *fn = eval_fn_name(a, e, NULL);
|
||||
struct ast *fn_body = fn->v.list->next->next;
|
||||
struct ast *fn_args = fn->v.list->next;
|
||||
struct token *args_head = fn->v.list->v.token->next;
|
||||
struct ast *fn_args_values = a->next;
|
||||
//debug_ast(fn, 0);
|
||||
|
||||
struct env *newenv = bind_args(args_head, fn_args_values, e);
|
||||
return eval(fn_body, newenv, NULL);
|
||||
}
|
||||
|
||||
struct ast *
|
||||
eval_fn_call_old(struct ast *a, struct env *e, struct env **w)
|
||||
{
|
||||
struct ast *fnargs_values;
|
||||
struct ast *fn_head;
|
||||
struct ast *fn_body;
|
||||
struct env *wanted = NULL;
|
||||
|
||||
fnargs_values = a->next;
|
||||
reassure(fnargs_values != NULL,
|
||||
|
@ -605,10 +654,16 @@ eval_fn_call(struct ast *a, struct env *e)
|
|||
|
||||
char *fnstr = a->v.token->v.str;
|
||||
struct ast *fn = lookup(e, fnstr);
|
||||
debug_ast(fn, 0);
|
||||
|
||||
reassure(fn != NULL && fn->type == AST_LIST,
|
||||
"%s: lookup on `%s` failed", __func__, fnstr);
|
||||
|
||||
/* struct ast *fn2 = eval(fn, e, &wanted); */
|
||||
/* fprintf(stderr, "===========\n"); */
|
||||
debug_ast(fn, 0);
|
||||
/* fn_head = fn2->v.list; */
|
||||
/* fn_body = fn2->next->next; */
|
||||
fn_head = fn->v.list;
|
||||
fn_body = fn->next->next;
|
||||
} else if (a->type == AST_LIST
|
||||
|
@ -617,8 +672,8 @@ eval_fn_call(struct ast *a, struct env *e)
|
|||
fn_head = a->v.list;
|
||||
fn_body = a->v.list->next->next;
|
||||
} else {
|
||||
/* xxx */
|
||||
struct ast *fn = eval(a, e);
|
||||
/* */
|
||||
struct ast *fn = eval(a, e, &wanted);
|
||||
fn_head = fn->v.list;
|
||||
fn_body = fn->next->next;
|
||||
}
|
||||
|
@ -639,26 +694,37 @@ eval_fn_call(struct ast *a, struct env *e)
|
|||
"%s: args expected to be a list", __func__);
|
||||
|
||||
struct env *newenv = bind_args(fnargs, fnargs_values, e);
|
||||
if (wanted != NULL) {
|
||||
/* fprintf(stderr, "==lastenv\n"); */
|
||||
/* for (struct env *e = lastenv; e; e=e->next) */
|
||||
/* fprintf(stderr, "e: %s\n", e->name); */
|
||||
|
||||
for (struct env *e = newenv; e; e=e->next)
|
||||
fprintf(stderr, "e: %s\n", e->name);
|
||||
/* fprintf(stderr, "==newenv:\n"); */
|
||||
/* for (struct env *e = newenv; e; e=e->next) */
|
||||
/* fprintf(stderr, "e: %s\n", e->name); */
|
||||
|
||||
newenv->parent = wanted;
|
||||
}
|
||||
if (w != NULL) {
|
||||
*w = newenv;
|
||||
}
|
||||
|
||||
reassure(newenv != NULL,
|
||||
"%s: setup for newenv failed", __func__);
|
||||
return eval(fn_body, newenv);
|
||||
return eval(fn_body, newenv, NULL);
|
||||
}
|
||||
|
||||
struct ast *
|
||||
eval_list(struct ast *a, struct env *e)
|
||||
eval_list(struct ast *a, struct env *e, struct env **w)
|
||||
{
|
||||
if (token_is_internal(a->v.list->v.token))
|
||||
return eval_internal_sym(a->v.list, e);
|
||||
return eval_internal_sym(a, e);
|
||||
else
|
||||
return eval_fn_call(a->v.list, e);
|
||||
return eval_fn_call(a->v.list, e, w);
|
||||
}
|
||||
|
||||
struct ast *
|
||||
eval(struct ast *a, struct env *e)
|
||||
eval(struct ast *a, struct env *e, struct env **w)
|
||||
{
|
||||
if (a == NULL)
|
||||
return NULL;
|
||||
|
@ -678,7 +744,7 @@ eval(struct ast *a, struct env *e)
|
|||
a->v.list->v.token->type == SYM) ||
|
||||
(a->v.list->type == AST_LIST),
|
||||
"%s: expected LIST or TOK", __func__);
|
||||
return eval_list(a, e);
|
||||
return eval_list(a, e, w);
|
||||
default:
|
||||
reassure(0, "%s: wrong AST Type", __func__);
|
||||
}
|
||||
|
@ -689,7 +755,7 @@ void
|
|||
pr(struct ast *a)
|
||||
{
|
||||
if (a == NULL) {
|
||||
fprintf(stderr, "nil %p\n", a);
|
||||
//fprintf(stderr, "nil %p\n", a);
|
||||
return;
|
||||
}
|
||||
switch (a->type) {
|
||||
|
@ -709,6 +775,13 @@ pr(struct ast *a)
|
|||
break;
|
||||
case AST_LIST:
|
||||
printf("#fn\n");
|
||||
struct token *t = a->v.list->v.token;
|
||||
debug_ast(a, 0);
|
||||
while (t != NULL) {
|
||||
printf("%d ", t->type);
|
||||
t = t->next;
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
default:
|
||||
err(1, "don't know how to print");
|
||||
|
@ -745,7 +818,7 @@ int main(void)
|
|||
env->name = "__llm";
|
||||
|
||||
while (1)
|
||||
pr(eval(parse(read_form()), env));
|
||||
pr(eval(parse(read_form()), env, NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue