Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added class method functionality and a File.fd method.

  • Loading branch information...
commit 2a896965e7c6c71fdb76db3e8b7c5007517d2f21 1 parent f426707
@orangea orangea authored
View
9 core/file.c
@@ -44,6 +44,14 @@ PN potion_file_new(Potion *P, PN cl, PN self, PN path, PN modestr) {
return self;
}
+PN potion_file_with_fd(Potion *P, PN cl, PN self, PN fd) {
+ struct PNFile *file = (struct PNFile *)potion_object_new(P, PN_NIL, PN_VTABLE(PN_TFILE));
+ file->fd = PN_INT(fd);
+ file->path = PN_NIL;
+ file->mode = fcntl(file->fd, F_GETFL) | O_ACCMODE;
+ return (PN)file;
+}
+
PN potion_file_close(Potion *P, PN cl, PN self) {
close(((struct PNFile *)self)->fd);
((struct PNFile *)self)->fd = -1;
@@ -116,6 +124,7 @@ void potion_file_init(Potion *P) {
potion_method(P->lobby, "read", potion_lobby_read, 0);
potion_type_constructor_is(file_vt, PN_FUNC(potion_file_new, "path=S,mode=S"));
+ potion_class_method(file_vt, "fd", potion_file_with_fd, "fd=N");
potion_method(file_vt, "string", potion_file_string, 0);
potion_method(file_vt, "close", potion_file_close, 0);
potion_method(file_vt, "read", potion_file_read, "n=N");
View
6 core/gc.c
@@ -382,10 +382,11 @@ void *potion_mark_minor(Potion *P, const struct PNObject *ptr) {
GC_MINOR_UPDATE(((struct PNFile *)ptr)->path);
break;
case PN_TVTABLE:
- GC_MINOR_UPDATE(((struct PNVtable *)ptr)->parent);
+ GC_MINOR_UPDATE(PN_VTABLE(((struct PNVtable *)ptr)->parent));
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->name);
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->ivars);
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->methods);
+ GC_MINOR_UPDATE(((struct PNVtable *)ptr)->meta);
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->ctor);
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->call);
GC_MINOR_UPDATE(((struct PNVtable *)ptr)->callset);
@@ -475,10 +476,11 @@ void *potion_mark_major(Potion *P, const struct PNObject *ptr) {
GC_MAJOR_UPDATE(((struct PNFile *)ptr)->path);
break;
case PN_TVTABLE:
- GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->parent);
+ GC_MAJOR_UPDATE(PN_VTABLE(((struct PNVtable *)ptr)->parent));
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->name);
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->ivars);
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->methods);
+ GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->meta);
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->ctor);
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->call);
GC_MAJOR_UPDATE(((struct PNVtable *)ptr)->callset);
View
1  core/internal.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include "potion.h"
#include "internal.h"
+#include "table.h"
#include "gc.h"
PN PN_allocate, PN_break, PN_call, PN_class, PN_compile, PN_continue, PN_def,
View
53 core/objmodel.c
@@ -61,14 +61,29 @@ PN potion_no_call(Potion *P, PN cl, PN self) {
return self;
}
+void potion_add_metaclass(Potion *P, vPN(Vtable) vt) {
+ struct PNVtable *meta = vt->meta = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
+ meta->type = PN_FLEX_SIZE(P->vts) + PN_TNIL;
+ PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
+ PN_FLEX_SIZE(P->vts)++;
+ meta->name = PN_NIL;
+ meta->parent = PN_TVTABLE;
+ meta->methods = (struct PNTable *)potion_table_empty(P);
+ meta->ctor = PN_FUNC(potion_no_call, 0);
+ PN_VTABLE(meta->type) = (PN)meta;
+ meta->meta = PN_NIL;
+ PN_TOUCH(P->vts);
+}
+
PN potion_type_new(Potion *P, PNType t, PN self) {
vPN(Vtable) vt = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
vt->type = t;
vt->name = PN_NIL;
- vt->parent = self;
+ vt->parent = self ? ((struct PNVtable *)self)->type : 0;
vt->methods = (struct PNTable *)potion_table_empty(P);
vt->ctor = PN_FUNC(potion_no_call, 0);
PN_VTABLE(t) = (PN)vt;
+ potion_add_metaclass(P, vt);
return (PN)vt;
}
@@ -107,6 +122,7 @@ PN potion_class(Potion *P, PN cl, PN self, PN ivars) {
PN pvars = ((struct PNVtable *)parent)->ivars;
PNType t = PN_FLEX_SIZE(P->vts) + PN_TNIL;
PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
+ PN_FLEX_SIZE(P->vts)++;
self = potion_type_new(P, t, parent);
if (PN_IS_TUPLE(pvars)) {
if (!PN_IS_TUPLE(ivars)) ivars = PN_TUP0();
@@ -119,7 +135,6 @@ PN potion_class(Potion *P, PN cl, PN self, PN ivars) {
cl = ((struct PNVtable *)parent)->ctor;
((struct PNVtable *)self)->ctor = cl;
- PN_FLEX_SIZE(P->vts)++;
PN_TOUCH(P->vts);
return self;
}
@@ -232,13 +247,17 @@ PN potion_bind(Potion *P, PN rcv, PN msg) {
PN vt = PN_NIL;
PNType t = PN_TYPE(rcv);
if (!PN_TYPECHECK(t)) return PN_NIL;
- vt = PN_VTABLE(t);
- while (PN_IS_PTR(vt)) {
+ if (t == PN_TVTABLE && !PN_IS_METACLASS(rcv)) {
+ vt = (PN)((struct PNVtable *)rcv)->meta;
+ } else {
+ vt = PN_VTABLE(t);
+ }
+ while (1) {
closure = ((msg == PN_lookup) && (t == PN_TVTABLE))
? potion_lookup(P, 0, vt, msg)
: potion_send(vt, PN_lookup, msg);
- if (closure) break;
- vt = ((struct PNVtable *)vt)->parent;
+ if (closure || !((struct PNVtable *)vt)->parent) break;
+ vt = PN_VTABLE(((struct PNVtable *)vt)->parent);
}
return closure;
}
@@ -315,17 +334,26 @@ PN potion_object_send(Potion *P, PN cl, PN self, PN method) {
PN potion_object_new(Potion *P, PN cl, PN self) {
vPN(Vtable) vt = (struct PNVtable *)self;
+ if (PN_IS_METACLASS(vt)) // TODO: error
+ return PN_NIL;
+ if (vt->type == PN_TVTABLE) // TODO: error
+ return PN_NIL;
return (PN)PN_ALLOC_N(vt->type, struct PNObject,
potion_type_size(P, (struct PNObject *)self) - sizeof(struct PNObject) + vt->ivlen * sizeof(PN));
}
+PN potion_get_metaclass(Potion *P, PN cl, vPN(Vtable) self) {
+ return (PN)self->meta;
+}
+
static PN potion_lobby_self(Potion *P, PN cl, PN self) {
return self;
}
PN potion_lobby_string(Potion *P, PN cl, PN self) {
PN str = ((struct PNVtable *)self)->name;
- return (void *)str != NULL ? str : potion_str(P, "<class>");
+ return (void *)str != PN_NIL ? str :
+ PN_IS_METACLASS(self) ? potion_str(P, "<metaclass>") : potion_str(P, "<class>");
}
PN potion_lobby_kind(Potion *P, PN cl, PN self) {
@@ -377,7 +405,10 @@ void potion_object_init(Potion *P) {
static void potion_init_class_reference(Potion *P, PN name, PN vt) {
potion_send(P->lobby, PN_def, name, vt);
- ((vPN(Vtable))vt)->name = name;
+ ((struct PNVtable *)vt)->name = name;
+ char meta_str[strlen("<metaclass: >") + PN_STR_LEN(name) + 1];
+ sprintf(meta_str, "<metaclass: %s>", PN_STR_PTR(name));
+ ((struct PNVtable *)vt)->meta->name = potion_str(P, meta_str);
}
void potion_lobby_init(Potion *P) {
@@ -402,7 +433,11 @@ void potion_lobby_init(Potion *P) {
potion_init_class_reference(P, potion_str(P, "Continuation"), PN_VTABLE(PN_TCONT));
P->call = P->callset = PN_FUNC(potion_no_call, 0);
- potion_type_call_is(PN_VTABLE(PN_TVTABLE), PN_FUNC(potion_object_new, 0));
+
+ PN mixin_vt = PN_VTABLE(PN_TVTABLE);
+ potion_type_call_is(mixin_vt, PN_FUNC(potion_object_new, 0));
+ potion_method(mixin_vt, "meta", potion_get_metaclass, 0);
+
potion_method(P->lobby, "about", potion_about, 0);
potion_method(P->lobby, "here", potion_callcc, 0);
potion_method(P->lobby, "exit", potion_exit, 0);
View
3  core/potion.h
@@ -109,6 +109,7 @@ struct PNVtable;
#define PN_IS_DECIMAL(v) (PN_IS_PTR(v) && PN_TYPE(v) == PN_TNUMBER)
#define PN_IS_PROTO(v) (PN_TYPE(v) == PN_TPROTO)
#define PN_IS_REF(v) (PN_TYPE(v) == PN_TWEAK)
+#define PN_IS_METACLASS(v) (((struct PNVtable *)v)->meta == PN_NIL)
#define PN_NUM(i) ((PN)((((long)(i))<<1) + PN_FNUMBER))
#define PN_INT(x) ((long)((long)(x))>>1)
@@ -518,6 +519,8 @@ static inline struct PNData *potion_data_alloc(Potion *P, int siz) {
#define potion_method(RCV, MSG, FN, SIG) \
potion_send(RCV, PN_def, potion_str(P, MSG), PN_FUNC(FN, SIG))
+#define potion_class_method(RCV, MSG, FN, SIG) \
+ potion_send(((struct PNVtable *)(RCV))->meta, PN_def, potion_str(P, MSG), PN_FUNC(FN, SIG))
extern PN PN_allocate, PN_break, PN_call, PN_class, PN_compile,
PN_continue, PN_def, PN_delegated, PN_else, PN_elsif, PN_if,
View
4 core/table.h
@@ -17,12 +17,12 @@ typedef PN (*PN_IVAR_FUNC)(PNUniq hash);
struct PNVtable {
PN_OBJECT_HEADER
- PN parent;
- PNType type;
+ PNType parent, type;
PN name;
int ivlen;
PN ivars;
vPN(Table) methods;
+ vPN(Vtable) meta;
PN ctor, call, callset;
PN_MCACHE_FUNC mcache;
PN_IVAR_FUNC ivfunc;
Please sign in to comment.
Something went wrong with that request. Please try again.