summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2010-04-25 23:33:04 +0200
committerJohannes Weiner <hannes@cmpxchg.org>2010-04-25 23:33:04 +0200
commiteed8fdee11187ce4913a2dbf8511e58a49cb2006 (patch)
tree01e91530a0e77d5a6547c5e4d7215ac446e80b6a
parent7ed7df8fce3dbf8b07ada95b556e23815391d756 (diff)
type object
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-rw-r--r--include/sheep/type.h31
-rw-r--r--sheep/Makefile2
-rw-r--r--sheep/core.c48
-rw-r--r--sheep/eval.c14
-rw-r--r--sheep/type.c116
5 files changed, 206 insertions, 5 deletions
diff --git a/include/sheep/type.h b/include/sheep/type.h
new file mode 100644
index 0000000..11f05fc
--- /dev/null
+++ b/include/sheep/type.h
@@ -0,0 +1,31 @@
+/*
+ * include/sheep/type.h
+ *
+ * Copyright (c) 2010 Johannes Weiner <hannes@cmpxchg.org>
+ */
+#ifndef _SHEEP_TYPE_H
+#define _SHEEP_TYPE_H
+
+#include <sheep/object.h>
+#include <sheep/map.h>
+
+struct sheep_vm;
+
+struct sheep_typeobject {
+ sheep_t class;
+ sheep_t *values;
+ struct sheep_map map;
+};
+
+extern const struct sheep_type sheep_typeobject_type;
+
+struct sheep_typeclass {
+ const char *name;
+ const char **names;
+ unsigned int nr_slots;
+};
+
+sheep_t sheep_make_typeclass(struct sheep_vm *, const char *,
+ const char **, unsigned int);
+
+#endif /* _SHEEP_TYPE_H */
diff --git a/sheep/Makefile b/sheep/Makefile
index e1d5a43..17d4721 100644
--- a/sheep/Makefile
+++ b/sheep/Makefile
@@ -1,6 +1,6 @@
libsheep-obj := util.o vector.o map.o code.o gc.o
libsheep-obj += object.o bool.o string.o name.o number.o list.o \
- sequence.o foreign.o function.o alien.o
+ sequence.o foreign.o function.o alien.o type.o
libsheep-obj += unpack.o vm.o module.o read.o parse.o compile.o eval.o core.o
sheep-obj := sheep.o
diff --git a/sheep/core.c b/sheep/core.c
index 4e389e1..72d2820 100644
--- a/sheep/core.c
+++ b/sheep/core.c
@@ -11,6 +11,7 @@
#include <sheep/code.h>
#include <sheep/list.h>
#include <sheep/name.h>
+#include <sheep/type.h>
#include <sheep/util.h>
#include <sheep/map.h>
#include <sheep/gc.h>
@@ -270,6 +271,52 @@ out:
return ret;
}
+/* (type name slotnames*) */
+static int compile_type(struct sheep_compile *compile,
+ struct sheep_function *function,
+ struct sheep_context *context, struct sheep_list *args)
+{
+ const char **slotnames = NULL;
+ unsigned int nr_slots = 0;
+ struct sheep_list *names;
+ unsigned int cslot;
+ const char *name;
+ sheep_t class;
+
+ if (sheep_parse(compile, args, "sR", &name, &names))
+ return -1;
+
+ do {
+ const char *slotname;
+
+ if (__sheep_parse(compile, args, names, "sr", &slotname, &names))
+ goto err;
+
+ slotnames = sheep_realloc(slotnames, sizeof(char *) * ++nr_slots);
+ slotnames[nr_slots - 1] = sheep_strdup(slotname);
+ } while (names->head);
+
+ class = sheep_make_typeclass(compile->vm, name, slotnames, nr_slots);
+
+ cslot = sheep_vm_constant(compile->vm, class);
+ sheep_emit(&function->code, SHEEP_GLOBAL, cslot);
+ sheep_emit(&function->code, SHEEP_DUP, 0);
+ if (context->parent) {
+ cslot = sheep_function_local(function);
+ sheep_emit(&function->code, SHEEP_SET_LOCAL, cslot);
+ } else {
+ cslot = sheep_vm_global(compile->vm);
+ sheep_emit(&function->code, SHEEP_SET_GLOBAL, cslot);
+ }
+ sheep_map_set(context->env, name, (void *)(unsigned long)cslot);
+ return 0;
+err:
+ while (nr_slots--)
+ sheep_free(slotnames[nr_slots]);
+ sheep_free(slotnames);
+ return -1;
+}
+
static int do_compile_chain(struct sheep_compile *compile,
struct sheep_function *function,
struct sheep_context *context,
@@ -445,6 +492,7 @@ void sheep_core_init(struct sheep_vm *vm)
sheep_map_set(&vm->specials, "with", compile_with);
sheep_map_set(&vm->specials, "variable", compile_variable);
sheep_map_set(&vm->specials, "function", compile_function);
+ sheep_map_set(&vm->specials, "type", compile_type);
sheep_map_set(&vm->specials, "or", compile_or);
sheep_map_set(&vm->specials, "and", compile_and);
sheep_map_set(&vm->specials, "if", compile_if);
diff --git a/sheep/eval.c b/sheep/eval.c
index 139aece..6b024a2 100644
--- a/sheep/eval.c
+++ b/sheep/eval.c
@@ -11,6 +11,7 @@
#include <sheep/bool.h>
#include <sheep/code.h>
#include <sheep/name.h>
+#include <sheep/type.h>
#include <sheep/util.h>
#include <sheep/map.h>
#include <sheep/gc.h>
@@ -24,9 +25,9 @@
static sheep_t hash(struct sheep_vm *vm, sheep_t container,
unsigned int key_slot, sheep_t value)
{
- struct sheep_vector *slots;
const char *key, *obj;
struct sheep_map *map;
+ sheep_t *slots;
void *entry;
key = vm->keys[key_slot];
@@ -34,8 +35,13 @@ static sheep_t hash(struct sheep_vm *vm, sheep_t container,
if (sheep_type(container) == &sheep_module_type) {
struct sheep_module *mod = sheep_data(container);
- slots = &vm->globals;
+ slots = (sheep_t *)vm->globals.items;
map = &mod->env;
+ } else if (sheep_type(container) == &sheep_typeobject_type) {
+ struct sheep_typeobject *object = sheep_data(container);
+
+ slots = object->values;
+ map = &object->map;
} else
goto err;
@@ -43,9 +49,9 @@ static sheep_t hash(struct sheep_vm *vm, sheep_t container,
goto err;
if (value)
- slots->items[(unsigned int)entry] = value;
+ slots[(unsigned int)entry] = value;
- return slots->items[(unsigned int)entry];
+ return slots[(unsigned int)entry];
err:
obj = sheep_repr(container);
fprintf(stderr, "can not find %s in %s\n", key, obj);
diff --git a/sheep/type.c b/sheep/type.c
new file mode 100644
index 0000000..4b87d36
--- /dev/null
+++ b/sheep/type.c
@@ -0,0 +1,116 @@
+/*
+ * sheep/type.c
+ *
+ * Copyright (c) 2010 Johannes Weiner <hannes@cmpxchg.org>
+ */
+#include <sheep/object.h>
+#include <sheep/util.h>
+#include <sheep/map.h>
+#include <sheep/gc.h>
+#include <sheep/vm.h>
+#include <stdio.h>
+
+#include <sheep/type.h>
+
+static void typeobject_mark(sheep_t sheep)
+{
+ struct sheep_typeobject *object;
+ struct sheep_typeclass *class;
+ unsigned int i;
+
+ object = sheep_data(sheep);
+ class = sheep_data(object->class);
+
+ sheep_mark(object->class);
+ for (i = 0; i < class->nr_slots; i++)
+ sheep_mark(object->values[i]);
+}
+
+static void typeobject_free(struct sheep_vm *vm, sheep_t sheep)
+{
+ struct sheep_typeobject *object;
+
+ object = sheep_data(sheep);
+ sheep_free(object->values);
+ sheep_map_drain(&object->map);
+ sheep_free(object);
+}
+
+static void typeobject_format(sheep_t sheep, char **bufp, size_t *posp, int repr)
+{
+ struct sheep_typeobject *object;
+
+ object = sheep_data(sheep);
+ sheep_addprintf(bufp, posp, "#<object '%p'>", object);
+}
+
+const struct sheep_type sheep_typeobject_type = {
+ .mark = typeobject_mark,
+ .free = typeobject_free,
+ .format = typeobject_format,
+};
+
+static void typeclass_free(struct sheep_vm *vm, sheep_t sheep)
+{
+ struct sheep_typeclass *class;
+ unsigned int i;
+
+ class = sheep_data(sheep);
+ sheep_free(class->name);
+ for (i = 0; i < class->nr_slots; i++)
+ sheep_free(class->names[i]);
+ sheep_free(class->names);
+ sheep_free(class);
+}
+
+static enum sheep_call typeclass_call(struct sheep_vm *vm, sheep_t callable,
+ unsigned int nr_args, sheep_t *valuep)
+{
+ struct sheep_typeobject *object;
+ struct sheep_typeclass *class;
+
+ class = sheep_data(callable);
+ if (nr_args != class->nr_slots) {
+ fprintf(stderr, "%s has %d slots, %d values given\n",
+ class->name, class->nr_slots, nr_args);
+ return SHEEP_CALL_FAIL;
+ }
+
+ object = sheep_zalloc(sizeof(struct sheep_typeobject));
+ object->class = callable;
+ object->values = sheep_malloc(sizeof(sheep_t *) * class->nr_slots);
+ while (nr_args--) {
+ object->values[nr_args] = sheep_vector_pop(&vm->stack);
+ sheep_map_set(&object->map, class->names[nr_args],
+ (void *)(unsigned long)nr_args);
+ }
+ *valuep = sheep_make_object(vm, &sheep_typeobject_type, object);
+ return SHEEP_CALL_DONE;
+}
+
+static void typeclass_format(sheep_t sheep, char **bufp, size_t *posp, int repr)
+{
+ struct sheep_typeclass *class;
+
+ class = sheep_data(sheep);
+ sheep_addprintf(bufp, posp, "#<type '%s'>", class->name);
+}
+
+const struct sheep_type sheep_typeclass_type = {
+ .free = typeclass_free,
+ .call = typeclass_call,
+ .format = typeclass_format,
+};
+
+sheep_t sheep_make_typeclass(struct sheep_vm *vm, const char *name,
+ const char **names, unsigned int nr_slots)
+{
+ struct sheep_typeclass *class;
+
+ class = sheep_malloc(sizeof(struct sheep_typeclass));
+ class->name = sheep_strdup(name);
+ class->names = names;
+ class->nr_slots = nr_slots;
+
+ return sheep_make_object(vm, &sheep_typeclass_type, class);
+}