1
0
Fork 0

Do not eval in functions

This commit is contained in:
Alex Kotov 2023-05-04 21:50:02 +04:00
parent 79bc0867b4
commit b0ca9965cf
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
3 changed files with 93 additions and 110 deletions

View file

@ -8,8 +8,6 @@
#include <stdlib.h>
#include <string.h>
// Evaluation
static struct Object *func_eval(struct Object *args);
// Basic data structures
static struct Object *func_cons(struct Object *args);
static struct Object *func_quote(struct Object *args);
@ -32,8 +30,6 @@ static struct Object *func_newline(struct Object *args);
static struct Object *func_sum(struct Object *args);
static struct Object builtins[] = {
// Evaluation
{ .type = TYPE_PROCEDURE, .procedure = { "eval", func_eval } },
// Basic data structures
{ .type = TYPE_PROCEDURE, .procedure = { "cons", func_cons } },
{ .type = TYPE_PROCEDURE, .procedure = { "quote", func_quote } },
@ -57,7 +53,7 @@ static struct Object builtins[] = {
{ .type = TYPE_PROCEDURE, .procedure = { NULL, NULL } },
};
static struct Object *builtins_get(const char *name)
struct Object *builtins_get(const char *name)
{
for (size_t index = 0; builtins[index].procedure.name; ++index) {
if (strcmp(name, builtins[index].procedure.name) == 0) {
@ -68,38 +64,6 @@ static struct Object *builtins_get(const char *name)
abort();
}
struct Object *builtins_eval(struct Object *program)
{
// NULL is an empty list, can't eval
assert(program);
// Almost everything evaluates to itself
if (program->type != TYPE_PAIR && program->type != TYPE_SYMBOL) {
return program;
}
// Symbols are variable names, but we can't lookup
assert(program->type != TYPE_SYMBOL);
// The first item of pair should be an symbol - a function name
assert(program->pair.a && program->pair.a->type == TYPE_SYMBOL);
return builtins_get(program->pair.a->s)->procedure.func(program->pair.b);
}
/**************
* Evaluation *
**************/
struct Object *func_eval(struct Object *const args)
{
assert(args);
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
return builtins_eval(args->pair.a);
}
/*************************
* Basic data structures *
*************************/
@ -114,8 +78,8 @@ struct Object *func_cons(struct Object *const args)
assert(args->pair.b->pair.a);
assert(args->pair.b->pair.b == NULL);
struct Object *const car = builtins_eval(args->pair.a);
struct Object *const cdr = builtins_eval(args->pair.b->pair.a);
struct Object *const car = args->pair.a;
struct Object *const cdr = args->pair.b->pair.a;
return Object_new_pair(car, cdr);
}
@ -140,7 +104,7 @@ struct Object *func_booleanQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_BOOLEAN);
}
@ -150,7 +114,7 @@ struct Object *func_charQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_CHAR);
}
@ -160,7 +124,7 @@ struct Object *func_nullQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object == NULL);
}
@ -170,7 +134,7 @@ struct Object *func_numberQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_NUMBER);
}
@ -180,7 +144,7 @@ struct Object *func_pairQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_PAIR);
}
@ -190,7 +154,7 @@ struct Object *func_stringQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_STRING);
}
@ -200,7 +164,7 @@ struct Object *func_symbolQN(struct Object *args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
return Object_new_boolean(object && object->type == TYPE_SYMBOL);
}
@ -214,7 +178,7 @@ struct Object *func_and(struct Object *args)
while (args) {
assert(args->type == TYPE_PAIR);
result = builtins_eval(args->pair.a);
result = args->pair.a;
if (IS_FALSE(result)) break;
args = args->pair.b;
}
@ -228,7 +192,7 @@ struct Object *func_or(struct Object *args)
while (args) {
assert(args->type == TYPE_PAIR);
result = builtins_eval(args->pair.a);
result = args->pair.a;
if (!IS_FALSE(result)) break;
args = args->pair.b;
}
@ -248,7 +212,7 @@ struct Object *func_display(struct Object *const args)
assert(args->type == TYPE_PAIR);
assert(args->pair.b == NULL);
struct Object *const object = builtins_eval(args->pair.a);
struct Object *const object = args->pair.a;
if (!object) {
printf("()");

View file

@ -3,6 +3,6 @@
#include "object.h"
struct Object *builtins_eval(struct Object *args);
struct Object *builtins_get(const char *name);
#endif

139
main.c
View file

@ -30,6 +30,25 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
static struct Object *eval(struct Object *program)
{
// NULL is an empty list, can't eval
assert(program);
// Almost everything evaluates to itself
if (program->type != TYPE_PAIR && program->type != TYPE_SYMBOL) {
return program;
}
// Symbols are variable names, but we can't lookup
assert(program->type != TYPE_SYMBOL);
// The first item of pair should be an symbol - a function name
assert(program->pair.a && program->pair.a->type == TYPE_SYMBOL);
return builtins_get(program->pair.a->s)->procedure.func(program->pair.b);
}
void run()
{
char chr;
@ -53,7 +72,7 @@ void run()
Object_print(program, 0);
printf("\n=== OUTPUT =======\n");
struct Object *const result = builtins_eval(program);
struct Object *const result = eval(program);
printf("\n\n=== RESULT =======\n");
Object_print(result, 0);
@ -78,16 +97,16 @@ void test()
// #t
// #t
assert(builtins_eval(sharp_true) == sharp_true);
assert(eval(sharp_true) == sharp_true);
// 123
// 123
assert(builtins_eval(num_123) == num_123);
assert(eval(num_123) == num_123);
// (quote foo)
// 'foo
assert(
builtins_eval(
eval(
Object_build_list(2, Object_new_symbol("quote"), sym_foo)
) == sym_foo
);
@ -95,7 +114,7 @@ void test()
// (quote #t)
// #t
assert(
builtins_eval(
eval(
Object_build_list(2, Object_new_symbol("quote"), sharp_true)
) == sharp_true
);
@ -103,7 +122,7 @@ void test()
// (quote ())
// '()
assert(
builtins_eval(
eval(
Object_build_list(2, Object_new_symbol("quote"), NULL)
) == NULL
);
@ -111,7 +130,7 @@ void test()
// (quote 123)
// 123
assert(
builtins_eval(
eval(
Object_build_list(2, Object_new_symbol("quote"), num_123)
) == num_123
);
@ -120,7 +139,7 @@ void test()
// #t
{
struct Object *const result =
builtins_eval(Object_build_list(1, Object_new_symbol("and")));
eval(Object_build_list(1, Object_new_symbol("and")));
assert(IS_TRUE(result));
}
@ -128,14 +147,14 @@ void test()
// #f
{
struct Object *const result =
builtins_eval(Object_build_list(1, Object_new_symbol("or")));
eval(Object_build_list(1, Object_new_symbol("or")));
assert(IS_FALSE(result));
}
// (and #t)
// #t
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("and"),
Object_new_boolean(true)
@ -146,7 +165,7 @@ void test()
// (and 123)
// 123
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("and"),
num_123
@ -157,7 +176,7 @@ void test()
// (or #t)
// #t
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("or"),
Object_new_boolean(true)
@ -168,7 +187,7 @@ void test()
// (or 123)
// 123
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("or"),
num_123
@ -179,7 +198,7 @@ void test()
// (and #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("and"),
Object_new_boolean(false)
@ -190,7 +209,7 @@ void test()
// (or #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
2,
Object_new_symbol("or"),
Object_new_boolean(false)
@ -201,7 +220,7 @@ void test()
// (and #t #t)
// #t
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
Object_new_boolean(true),
@ -213,7 +232,7 @@ void test()
// (and 123 456)
// 456
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
num_123,
@ -225,7 +244,7 @@ void test()
// (and #f #t)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
Object_new_boolean(false),
@ -237,7 +256,7 @@ void test()
// (and #f 123)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
Object_new_boolean(false),
@ -249,7 +268,7 @@ void test()
// (and #t #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
Object_new_boolean(true),
@ -261,7 +280,7 @@ void test()
// (and 123 #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
num_123,
@ -273,7 +292,7 @@ void test()
// (and #f #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("and"),
Object_new_boolean(false),
@ -285,7 +304,7 @@ void test()
// (or #t #t)
// #t
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
Object_new_boolean(true),
@ -297,7 +316,7 @@ void test()
// (or 123 456)
// 123
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
num_123,
@ -309,7 +328,7 @@ void test()
// (or #f #t)
// #t
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
Object_new_boolean(false),
@ -321,7 +340,7 @@ void test()
// (or #f 123)
// 123
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
Object_new_boolean(false),
@ -333,7 +352,7 @@ void test()
// (or 123 #f)
// 123
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
num_123,
@ -345,7 +364,7 @@ void test()
// (or #f #f)
// #f
{
struct Object *const result = builtins_eval(Object_build_list(
struct Object *const result = eval(Object_build_list(
3,
Object_new_symbol("or"),
Object_new_boolean(false),
@ -363,7 +382,7 @@ void test_booleanQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
NULL
@ -373,7 +392,7 @@ void test_booleanQN()
// (boolean? #t)
// #t
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_boolean(true)
@ -382,7 +401,7 @@ void test_booleanQN()
// (boolean? #f)
// #t
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_boolean(false)
@ -391,7 +410,7 @@ void test_booleanQN()
// (boolean? #\n)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_char('\n')
@ -400,7 +419,7 @@ void test_booleanQN()
// (boolean? 'foo)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_build_list(
@ -413,7 +432,7 @@ void test_booleanQN()
// (boolean? "foo")
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_string("foo")
@ -422,7 +441,7 @@ void test_booleanQN()
// (boolean? 123)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_number(123)
@ -433,7 +452,7 @@ void test_booleanQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("boolean?"),
Object_new_pair(Object_new_number(123), Object_new_number(456))
@ -450,7 +469,7 @@ void test_charQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
NULL
@ -460,7 +479,7 @@ void test_charQN()
// (char? #t)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_boolean(true)
@ -469,7 +488,7 @@ void test_charQN()
// (char? #f)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_boolean(false)
@ -478,7 +497,7 @@ void test_charQN()
// (char? #\n)
// #t
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_char('\n')
@ -487,7 +506,7 @@ void test_charQN()
// (char? 'foo)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_build_list(
@ -500,7 +519,7 @@ void test_charQN()
// (char? "foo")
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_string("foo")
@ -509,7 +528,7 @@ void test_charQN()
// (char? 123)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_number(123)
@ -520,7 +539,7 @@ void test_charQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("char?"),
Object_new_pair(Object_new_number(123), Object_new_number(456))
@ -537,7 +556,7 @@ void test_nullQN()
// #t
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
NULL
@ -547,7 +566,7 @@ void test_nullQN()
// (null? #t)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_boolean(true)
@ -556,7 +575,7 @@ void test_nullQN()
// (null? #f)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_boolean(false)
@ -565,7 +584,7 @@ void test_nullQN()
// (null? #\n)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_char('\n')
@ -574,7 +593,7 @@ void test_nullQN()
// (null? 'foo)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_build_list(
@ -587,7 +606,7 @@ void test_nullQN()
// (null? "foo")
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_string("foo")
@ -596,7 +615,7 @@ void test_nullQN()
// (null? 123)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_number(123)
@ -607,7 +626,7 @@ void test_nullQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("null?"),
Object_new_pair(Object_new_number(123), Object_new_number(456))
@ -624,7 +643,7 @@ void test_numberQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
NULL
@ -634,7 +653,7 @@ void test_numberQN()
// (number? #t)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_boolean(true)
@ -643,7 +662,7 @@ void test_numberQN()
// (number? #f)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_boolean(false)
@ -652,7 +671,7 @@ void test_numberQN()
// (number? #\n)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_char('\n')
@ -661,7 +680,7 @@ void test_numberQN()
// (number? 'foo)
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_build_list(
@ -674,7 +693,7 @@ void test_numberQN()
// (number? "foo")
// #f
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_string("foo")
@ -683,7 +702,7 @@ void test_numberQN()
// (number? 123)
// #t
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_number(123)
@ -694,7 +713,7 @@ void test_numberQN()
// #f
// TODO
/*
result = builtins_eval(Object_build_list(
result = eval(Object_build_list(
2,
Object_new_symbol("number?"),
Object_new_pair(Object_new_number(123), Object_new_number(456))