1
0
Fork 0
lesson-lisp/src/eval.c

86 lines
2.0 KiB
C

#include "eval.h"
#include "builtins.h"
#include "lexer.h"
#include "parser.h"
#include "syntax.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
static struct Object *eval_list(struct Object *object);
struct Object *eval_str(const char *const str)
{
assert(str);
Tokens tokens = Tokens_new();
assert(tokens);
Lexer lexer = Lexer_new(tokens);
assert(lexer);
for (const char *chr = str; *chr; ++chr) {
Lexer_lex(lexer, *chr);
}
Lexer_lex(lexer, '\n');
LEXER_DELETE(lexer);
assert(Tokens_top(tokens));
struct Object *const program = parse(tokens);
TOKENS_DELETE(tokens);
return eval(program);
}
struct Object *eval(struct Object *const object)
{
// NULL is an empty list, can't eval
assert(object);
// SYMBOL performs lookup
if (Object_is_symbol(object)) {
struct Object *const procedure = builtins_get(object->s);
assert(procedure);
return procedure;
}
// Almost everything evaluates to itself
if (!Object_is_pair(object)) return object;
struct Object *const func_expr = object->pair.car;
struct Object *const args = object->pair.cdr;
if (Object_is_symbol(func_expr)) {
if (strcmp(func_expr->s, "begin") == 0) return syntax_begin(args);
if (strcmp(func_expr->s, "quote") == 0) return syntax_quote(args);
if (strcmp(func_expr->s, "if") == 0) return syntax_if(args);
}
struct Object *const func = eval(func_expr);
assert(Object_is_procedure(func));
struct Object *const evaluated_args = eval_list(args);
return Object_procedure_call(func, evaluated_args);
}
struct Object *eval_list(struct Object *const object)
{
assert(OBJECT_IS_LIST_HEAD(object));
if (OBJECT_IS_NULL(object)) return NULL;
if (OBJECT_IS_NULL(object->pair.car)) {
return Object_new_pair(
NULL,
eval_list(object->pair.cdr)
);
} else {
return Object_new_pair(
eval(object->pair.car),
eval_list(object->pair.cdr)
);
}
}