Skip to content
This repository has been archived by the owner on Feb 3, 2021. It is now read-only.

Commit

Permalink
Start to stub in the P6opaque representation. Doesn't actually comput…
Browse files Browse the repository at this point in the history
…e any slot storage and store attributes yet, but this gets the outline in place.
  • Loading branch information
jnthn committed Sep 20, 2010
1 parent 76d9ad1 commit e80031a
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 2 deletions.
7 changes: 5 additions & 2 deletions build/Makefile.in
Expand Up @@ -142,10 +142,12 @@ OPS_SOURCE = nqp.ops
METAMODEL_SOURCE = src/metamodel/rakudoobject.h src/metamodel/rakudoobject.c \
src/metamodel/repr_registry.h src/metamodel/repr_registry.c \
src/metamodel/knowhow_bootstrapper.h src/metamodel/knowhow_bootstrapper.c \
src/metamodel/reprs/KnowHOWREPR.h src/metamodel/reprs/KnowHOWREPR.c
src/metamodel/reprs/KnowHOWREPR.h src/metamodel/reprs/KnowHOWREPR.c \
src/metamodel/reprs/P6opaque.h src/metamodel/reprs/P6opaque.c

METAMODEL_OBJS = ../metamodel/rakudoobject$(O) ../metamodel/repr_registry$(O) \
../metamodel/knowhow_bootstrapper$(O) ../metamodel/reprs/KnowHOWREPR$(O)
../metamodel/knowhow_bootstrapper$(O) ../metamodel/reprs/KnowHOWREPR$(O) \
../metamodel/reprs/P6opaque$(O)

CLEANUPS = \
*.manifest \
Expand Down Expand Up @@ -323,6 +325,7 @@ $(OPS_DIR)/$(OPS)$(LOAD_EXT): $(OPS_DIR)/$(OPS_SOURCE) $(DYNPMC)
cd src/metamodel && $(CC) -c @cc_o_out@repr_registry$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) repr_registry.c
cd src/metamodel && $(CC) -c @cc_o_out@knowhow_bootstrapper$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) knowhow_bootstrapper.c
cd src/metamodel/reprs && $(CC) -c @cc_o_out@KnowHOWREPR$(O) -I../../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) KnowHOWREPR.c
cd src/metamodel/reprs && $(CC) -c @cc_o_out@P6opaque$(O) -I../../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) P6opaque.c
cd $(OPS_DIR) && $(LD) @ld_out@$(OPS)$(LOAD_EXT) $(OPS)$(O) $(METAMODEL_OBJS) $(LINKARGS)

bootstrap-files: $(STAGE2_PBCS) $(SETTING_NQP)
Expand Down
3 changes: 3 additions & 0 deletions src/metamodel/repr_registry.c
Expand Up @@ -7,6 +7,7 @@
#include "parrot/extend.h"
#include "rakudoobject.h"
#include "reprs/KnowHOWREPR.h"
#include "reprs/P6opaque.h"

/* An array of representations. */
static PMC *repr_registry = NULL;
Expand Down Expand Up @@ -35,6 +36,8 @@ void REPR_initialize_registry(PARROT_INTERP) {
/* Add all representations. */
register_repr(interp, Parrot_str_new_constant(interp, "KnowHOWREPR"),
KnowHOWREPR_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "P6opaque"),
P6opaque_initialize(interp));
}

/* Get a representation's ID from its name. Note that the IDs may change so
Expand Down
203 changes: 203 additions & 0 deletions src/metamodel/reprs/P6opaque.c
@@ -0,0 +1,203 @@
/* This is a first cut implementation of the P6opaque representation.
* Eventually it's going to need to handle native types too, but for now
* this gets us started. */

#define PARROT_IN_EXTENSION
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "../rakudoobject.h"
#include "P6opaque.h"

/* Forward declaration of repr_instance ('cus if we don't, we have to
* forward declare a bunch of other stuff). */
static PMC * repr_instance(PARROT_INTERP);

/* This computes the slot mapping for a type; that is, for single inheritance
* classes it works out an allocation in an array for storing the attributes. */
static void compute_slot_mapping(PARROT_INTERP, PMC *WHAT) {
/* XXX TODO. */
}

/* Creates a new type object of this representation, and associates it with
* the given HOW. */
static PMC * type_object_for(PARROT_INTERP, PMC *self, PMC *HOW) {
/* Create new object instance. */
P6opaqueInstance *obj = mem_allocate_zeroed_typed(P6opaqueInstance);

/* Create a new repr instance. */
PMC *my_repr = repr_instance(interp);

/* Build an STable. */
PMC *st_pmc = create_stable(interp, my_repr, HOW);
STable *st = STABLE_STRUCT(st_pmc);

/* Create type object and point it back at the STable. */
st->WHAT = wrap_object(interp, obj);
obj->common.stable = st_pmc;

return st->WHAT;
}

/* Creates a new instance based on the type object. */
static PMC * instance_of(PARROT_INTERP, PMC *self, PMC *WHAT) {
P6opaqueInstance *obj;

/* Compute slot mapping if we've not already done so. */
REPRP6opaque *repr = P6O_REPR_STRUCT(self);
if (!repr->slot_mapping)
compute_slot_mapping(interp, WHAT);

/* Allocate and set up object instance. */
obj = mem_allocate_zeroed_typed(P6opaqueInstance);
obj->common.stable = STABLE_PMC(WHAT);
obj->slots = mem_sys_allocate(sizeof(PMC *) *
repr->num_slots == 0 ? 1 : repr->num_slots);

return wrap_object(interp, obj);
}

/* Checks if a given object is defined (from the point of view of the
* representation). */
static INTVAL defined(PARROT_INTERP, PMC *self, PMC *obj) {
P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj);
return instance->slots != NULL;
}

/* Gets the current value for an attribute. */
static PMC * get_attribute(PARROT_INTERP, PMC *self, PMC *obj, PMC *class_handle, STRING *name) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque attributes NYI");
}

/* Gets the current value for an attribute, obtained using the given hint.*/
static PMC * get_attribute_with_hint(PARROT_INTERP, PMC *self, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque attributes NYI");
}

/* Binds the given value to the specified attribute. */
static void bind_attribute(PARROT_INTERP, PMC *self, PMC *obj, PMC *class_handle, STRING *name, PMC *value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque attributes NYI");
}

/* Binds the given value to the specified attribute, using the given hint. */
static void bind_attribute_with_hint(PARROT_INTERP, PMC *self, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque attributes NYI");
}

/* Gets the hint for the given attribute ID. */
static INTVAL hint_for(PARROT_INTERP, PMC *self, PMC *class_handle, STRING *name) {
return NO_HINT;
}

/* Used with boxing. Sets an integer value, for representations that can hold
* one. */
static void set_int(PARROT_INTERP, PMC *self, PMC *obj, INTVAL value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet box a native int");
}

/* Used with boxing. Gets an integer value, for representations that can
* hold one. */
static INTVAL get_int(PARROT_INTERP, PMC *self, PMC *obj) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet unbox to a native int");
}

/* Used with boxing. Sets a floating point value, for representations that can
* hold one. */
static void set_num(PARROT_INTERP, PMC *self, PMC *obj, FLOATVAL value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet box a native num");
}

/* Used with boxing. Gets a floating point value, for representations that can
* hold one. */
static FLOATVAL get_num(PARROT_INTERP, PMC *self, PMC *obj) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet unbox to a native num");
}

/* Used with boxing. Sets a string value, for representations that can hold
* one. */
static void set_str(PARROT_INTERP, PMC *self, PMC *obj, STRING *value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet box a native string");
}

/* Used with boxing. Gets a string value, for representations that can hold
* one. */
static STRING * get_str(PARROT_INTERP, PMC *self, PMC *obj) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6opaque cannot yet unbox to a native string");
}

/* This Parrot-specific addition to the API is used to mark an object. */
static void gc_mark(PARROT_INTERP, PMC *self, PMC *obj) {
P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj);

/* Mark STable. */
if (!PMC_IS_NULL(instance->common.stable))
Parrot_gc_mark_PMC_alive(interp, instance->common.stable);

/* If we have slots... */
if (instance->slots) {
/* ...mark the things in those. */
REPRP6opaque *repr = P6O_REPR_STRUCT(self);
INTVAL i;
for (i = 0; i < repr->num_slots; i++)
if (!PMC_IS_NULL(instance->slots[i]))
Parrot_gc_mark_PMC_alive(interp, instance->slots[i]);
}

/* If there's spill storage, mark that. */
if (!PMC_IS_NULL(instance->spill))
Parrot_gc_mark_PMC_alive(interp, instance->spill);
}

/* This Parrot-specific addition to the API is used to free an object. */
static void gc_free(PARROT_INTERP, PMC *self, PMC *obj) {
P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj);
if (instance->slots)
mem_sys_free(instance->slots);
mem_sys_free(instance);
PMC_data(obj) = NULL;
}

/* Sets up an instance of this representation with function pointers in place
* and no allocated slot storage. */
static PMC * repr_instance(PARROT_INTERP) {
REPRP6opaque *repr;
PMC *repr_pmc;

/* Allocate and populate the representation function table. */
repr = mem_allocate_typed(REPRP6opaque);
repr->common.type_object_for = type_object_for;
repr->common.instance_of = instance_of;
repr->common.defined = defined;
repr->common.get_attribute = get_attribute;
repr->common.get_attribute_with_hint = get_attribute_with_hint;
repr->common.bind_attribute = bind_attribute;
repr->common.bind_attribute_with_hint = bind_attribute_with_hint;
repr->common.hint_for = hint_for;
repr->common.set_int = set_int;
repr->common.get_int = get_int;
repr->common.set_num = set_num;
repr->common.get_num = get_num;
repr->common.set_str = set_str;
repr->common.get_str = get_str;
repr->common.gc_mark = gc_mark;
repr->common.gc_free = gc_free;
repr->slot_mapping = PMCNULL;
repr->num_slots = 0;

/* Wrap it in a PMC. */
return wrap_repr(interp, repr);
}

/* Initializes the P6opaque representation. */
PMC * P6opaque_initialize(PARROT_INTERP) {
return repr_instance(interp);
}
43 changes: 43 additions & 0 deletions src/metamodel/reprs/P6opaque.h
@@ -0,0 +1,43 @@
#ifndef P6OPAQUE_H_GUARD
#define P6OPAQUE_H_GUARD

/* This is how an instance with the P6opaque representation looks. The slots
* is an array where we'll store most attributes, so we can look them up by
* index. There's also an unallocated spill-over store for any attributes that
* are added through augment, or in MI cases (e.g. it's lazily allocated on
* demand). */
typedef struct {
/* The commonalities all objects have. */
RakudoObjectCommonalities common;

/* Attribute slot storage. */
PMC **slots;

/* Spill (for MI, dynamically added attributes, etc.) Normally null. */
PMC *spill;
} P6opaqueInstance;

/* A P6opaque REPR instance carries around both a slot mapping with it.
* XXX We waste some memory here in that we're storing the REPR pointer
* table per "instantiation" of the REPR. It's per type rather than per
* instance, so not so bad, but with another level of indirection we
* could probably do a bit better. OTOH, it'd be another level of
* indirection... */
typedef struct {
/* The commonalities shared by all representations. */
REPRCommonalities common;

/* A slot mapping table. */
PMC *slot_mapping;

/* The number of slots we have. */
INTVAL num_slots;
} REPRP6opaque;

/* Handy macro for getting the struct out. */
#define P6O_REPR_STRUCT(p) ((REPRP6opaque *)PMC_data(p))

/* Initializes the P6opaque REPR. */
PMC * P6opaque_initialize(PARROT_INTERP);

#endif

0 comments on commit e80031a

Please sign in to comment.