148 lines
3.4 KiB
C
148 lines
3.4 KiB
C
#include "enums.h"
|
|
#include "object.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static struct Object *new(const enum Type type)
|
|
{
|
|
struct Object *const object = malloc(sizeof(struct Object));
|
|
assert(object);
|
|
memset(object, 0, sizeof(struct Object));
|
|
object->type = type;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_procedure(
|
|
const char *const name,
|
|
struct Object *(*const func)(struct Object *args)
|
|
) {
|
|
struct Object *const object = new(TYPE_PROCEDURE);
|
|
object->procedure.name = NULL;
|
|
if (name && name[0]) {
|
|
object->procedure.name = malloc(strlen(name) + 1);
|
|
assert(object->procedure.name);
|
|
strcpy(object->procedure.name, name);
|
|
}
|
|
object->procedure.func = func;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_pair(struct Object *const a, struct Object *const b)
|
|
{
|
|
struct Object *const object = new(TYPE_PAIR);
|
|
object->pair.a = a;
|
|
object->pair.b = b;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_boolean(const bool boolean)
|
|
{
|
|
struct Object *const object = new(TYPE_BOOLEAN);
|
|
object->boolean = boolean;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_char(const char chr)
|
|
{
|
|
struct Object *const object = new(TYPE_CHAR);
|
|
object->chr = chr;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_symbol(const char *const s)
|
|
{
|
|
struct Object *const object = new(TYPE_SYMBOL);
|
|
object->s = malloc(strlen(s) + 1);
|
|
assert(object->s);
|
|
strcpy(object->s, s);
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_string(const char *const s)
|
|
{
|
|
struct Object *const object = new(TYPE_STRING);
|
|
object->s = malloc(strlen(s) + 1);
|
|
assert(object->s);
|
|
strcpy(object->s, s);
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_new_number(const int64_t i)
|
|
{
|
|
struct Object *const object = new(TYPE_NUMBER);
|
|
object->i = i;
|
|
return object;
|
|
}
|
|
|
|
struct Object *Object_build_list(int count, ...)
|
|
{
|
|
assert(count > 0);
|
|
va_list va;
|
|
va_start(va, count);
|
|
|
|
struct Object *last = NULL;
|
|
struct Object *list = Object_new_pair(va_arg(va, struct Object*), last);
|
|
--count;
|
|
|
|
while (count-- > 0) {
|
|
struct Object *new_pair =
|
|
Object_new_pair(va_arg(va, struct Object*), NULL);
|
|
|
|
if (last) {
|
|
last->pair.b = new_pair;
|
|
last = new_pair;
|
|
} else {
|
|
last = new_pair;
|
|
list->pair.b = last;
|
|
}
|
|
}
|
|
|
|
va_end(va);
|
|
return list;
|
|
}
|
|
|
|
void Object_print(struct Object *const self, const unsigned indent)
|
|
{
|
|
for (unsigned index = 0; index < indent; ++index) {
|
|
printf(" ");
|
|
}
|
|
|
|
if (!self) {
|
|
printf("NULL\n");
|
|
return;
|
|
}
|
|
|
|
printf("%s:", Type_to_str(self->type));
|
|
|
|
switch (self->type) {
|
|
case TYPE_PROCEDURE:
|
|
if (self->procedure.name) {
|
|
printf("#<procedure:%s>\n", self->procedure.name);
|
|
} else {
|
|
printf("#<procedure>\n");
|
|
}
|
|
break;
|
|
case TYPE_PAIR:
|
|
printf("\n");
|
|
Object_print(self->pair.a, indent + 1);
|
|
Object_print(self->pair.b, indent + 1);
|
|
break;
|
|
case TYPE_BOOLEAN:
|
|
printf("%s\n", self->boolean ? "#t" : "#f");
|
|
break;
|
|
case TYPE_CHAR:
|
|
printf("%c\n", self->chr);
|
|
break;
|
|
case TYPE_SYMBOL:
|
|
case TYPE_STRING:
|
|
printf("%s\n", self->s);
|
|
break;
|
|
case TYPE_NUMBER:
|
|
printf("%li\n", self->i);
|
|
break;
|
|
}
|
|
}
|