allow lambda at first element of a list
previously, lambda wasn't evaluated if it was the first element of a list. it should be possible to evaluate calls like ((lm (x) (add x 1)) 55) -> now.
This commit is contained in:
parent
6b8812f467
commit
02d3d783c9
71
tokenize.l
71
tokenize.l
|
@ -1,4 +1,4 @@
|
|||
/* llm - litle lisp machine:
|
||||
/* llm - litle lisp machinery:
|
||||
*
|
||||
* Copyright (c) 2019 Christian Barthel <bch@online.de>
|
||||
* All rights reserved.
|
||||
|
@ -36,10 +36,12 @@
|
|||
%{
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _XOPEN_SOURCE 600
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
|
||||
struct token;
|
||||
struct token {
|
||||
int type;
|
||||
|
@ -138,7 +140,8 @@ reassure(int promised, const char *fmt, ...)
|
|||
}
|
||||
|
||||
void
|
||||
debug_token(struct token *x, int indent) {
|
||||
debug_token(struct token *x, int indent)
|
||||
{
|
||||
for (int i = 0; i < indent; i++) putc(' ', stderr);
|
||||
fprintf(stderr, "%d: (%p)", x->type, x);
|
||||
if (x->type == NUM) fprintf(stderr, "%d @ %p", x->v.num, x);
|
||||
|
@ -209,10 +212,15 @@ make_env(char *name, struct ast *a)
|
|||
}
|
||||
|
||||
int token_is_num(struct token *t) {return t->type == NUM;}
|
||||
|
||||
int token_is_sym(struct token *t) {return t->type == SYM;}
|
||||
|
||||
int token_is_str(struct token *t) {return t->type == STR;}
|
||||
|
||||
int token_is_bool(struct token *t) {return t->type == BOOL;}
|
||||
int token_is_internal(struct token *t) {
|
||||
|
||||
int token_is_internal(struct token *t)
|
||||
{
|
||||
if (strcmp(t->v.str, "def") == 0) return 1;
|
||||
else if (strcmp(t->v.str, "lm") == 0) return 1;
|
||||
else if (strcmp(t->v.str, "if") == 0) return 1;
|
||||
|
@ -231,7 +239,9 @@ int token_is_internal(struct token *t) {
|
|||
* care must be taken when entering a new sub-list (b),
|
||||
* because the processing in the upper level must continue
|
||||
* where the sub-list ended, i.e. "c" must be the next
|
||||
* token on this level.
|
||||
* token on this level. I've solved this with a global
|
||||
* variable `next` and reset the current symbol after
|
||||
* creating a sublist.
|
||||
*/
|
||||
struct token *next;
|
||||
struct ast*
|
||||
|
@ -592,28 +602,43 @@ bind_args(struct token *args,
|
|||
struct ast *
|
||||
eval_fn_call(struct ast *a, struct env *e)
|
||||
{
|
||||
reassure((AST_TOK == a->type) &&
|
||||
a->v.token->type == SYM,
|
||||
"%s: expected SYM, is: %d",
|
||||
__func__, a->type);
|
||||
|
||||
struct ast *fnargs_values = a->next;
|
||||
struct ast *fnargs_values;
|
||||
struct ast *fn_head;
|
||||
struct ast *fn_body;
|
||||
|
||||
fnargs_values = a->next;
|
||||
fprintf(stderr, "fnargs: %d\n", fnargs_values->type);
|
||||
fprintf(stderr, "fnargs: %d\n", fnargs_values->type);
|
||||
reassure(fnargs_values != NULL,
|
||||
"%s: expected RPAR or function args", __func__);
|
||||
/* XXX fprintf(stderr, "eval args: %d\n", fnargs_values->v.token->type); */
|
||||
|
||||
char *fnstr = a->v.token->v.str;
|
||||
struct ast *fn = lookup(e, fnstr);
|
||||
fprintf(stderr, "_lookup: %s\n", fnstr);
|
||||
reassure(fn != NULL && fn->type == AST_LIST,
|
||||
"%s: lookup on `%s` failed", __func__, fnstr);
|
||||
if (a->type == AST_TOK) {
|
||||
reassure((AST_TOK == a->type) &&
|
||||
a->v.token->type == SYM,
|
||||
"%s: expected SYM, is: %d",
|
||||
__func__, a->type);
|
||||
/* XXX fprintf(stderr, "eval args: %d\n", fnargs_values->v.token->type); */
|
||||
|
||||
struct ast *fn_head = fn->v.list;
|
||||
struct ast *fn_body = fn->next->next;
|
||||
|
||||
fprintf(stderr, "fnbody: %d, %p\n", fn_body->type, fn_body->v.list);
|
||||
fprintf(stderr, "fnbody: %d, %d\n", fn_body->v.list->type, fn_body->v.list->v.token->type);
|
||||
fprintf(stderr, "fnbody: %s\n", fn_body->v.list->v.token->v.str);
|
||||
char *fnstr = a->v.token->v.str;
|
||||
struct ast *fn = lookup(e, fnstr);
|
||||
fprintf(stderr, "_lookup: %s\n", fnstr);
|
||||
reassure(fn != NULL && fn->type == AST_LIST,
|
||||
"%s: lookup on `%s` failed", __func__, fnstr);
|
||||
|
||||
fn_head = fn->v.list;
|
||||
fn_body = fn->next->next;
|
||||
|
||||
fprintf(stderr, "fnbody: %d, %p\n", fn_body->type, fn_body->v.list);
|
||||
fprintf(stderr, "fnbody: %d, %d\n", fn_body->v.list->type, fn_body->v.list->v.token->type);
|
||||
fprintf(stderr, "fnbody: %s\n", fn_body->v.list->v.token->v.str);
|
||||
} else if (a->type == AST_LIST) { /* direct lambda? */
|
||||
fprintf(stderr, "looks like a list..\n");
|
||||
|
||||
//debug_ast(a->v.list->next->next, 0);
|
||||
fn_head = a->v.list;
|
||||
fn_body = a->v.list->next->next;
|
||||
|
||||
}
|
||||
|
||||
reassure(fn_body != NULL && fn_body->type == AST_LIST,
|
||||
"%s: expected function body as list", __func__);
|
||||
|
@ -636,7 +661,7 @@ eval_fn_call(struct ast *a, struct env *e)
|
|||
|
||||
reassure(newenv != NULL,
|
||||
"%s: setup for newenv failed", __func__);
|
||||
|
||||
fprintf(stderr, "?hier\n");
|
||||
return eval(fn_body, newenv);
|
||||
/* fnargs: (), (a), (a b), (a b c), ... */
|
||||
/* fprintf(stderr, "args: %d %s\n", fnargs->type, ""); */
|
||||
|
|
Loading…
Reference in New Issue