Skip to content

Instantly share code, notes, and snippets.

@gerdr
Created February 6, 2012 10:01
Show Gist options
  • Save gerdr/1751167 to your computer and use it in GitHub Desktop.
Save gerdr/1751167 to your computer and use it in GitHub Desktop.
Parrot object model refactor proposal
#ifndef PARROT_H_
#define PARROT_H_
#include <stddef.h>
// short names so we don't have to type Parrot_ everywhere
#define PInt Parrot_Int
#define PNum Parrot_Num
// ...
// dynamic type id
enum parrot_value_type_
{
PARROT_FAIL_VALUE,
PARROT_VOID_VALUE,
PARROT_INT_VALUE,
PARROT_NUM_VALUE,
PARROT_STRING_VALUE,
PARROT_OBJECT_VALUE,
PARROT_POINTER_VALUE
};
typedef enum parrot_value_type_ PValueType;
// message ids for new dispatch system
enum parrot_message_id_
{
PARROT_NO_MSG,
PARROT_GET_BY_INT_MSG,
PARROT_SET_BY_INT_MSG,
PARROT_GET_BY_STRING_MSG,
PARROT_SET_BY_STRING_MSG,
// ...
};
typedef enum parrot_message_id_ PMsgId;
// configured types
typedef long long PInt;
typedef double PNum;
// a dynamically typed value
// used for generic data structures
typedef union parrot_value_ PValue;
// a 6model object
typedef struct parrot_object_ PObject;
// internal 6model objects with known structure
typedef struct parrot_interp_ PInterp;
typedef struct parrot_string_ PString;
typedef struct parrot_stable_ PSTable;
typedef struct parrot_array_ PArray;
typedef struct parrot_hash_ PHash;
typedef struct parrot_pointer_hash_ PPointerHash;
// ...
// the 6model representation
typedef struct parrot_repr_ PRepr;
union parrot_value_
{
PValueType type;
struct { PValueType type; PInt value; } as_int;
struct { PValueType type; PNum value; } as_num;
struct { PValueType type; PString *value; } as_string;
struct { PValueType type; PObject *value; } as_object;
struct { PValueType type; void *value; } as_pointer;
};
// every object has this structure as first member
struct parrot_object_
{
PSTable *stable;
// ...
// things like the serialization context and flags need to go here
};
// parrot-level objects implemented in C use the message system instead of the
// current monolithic vtable
// each message has a unique id, which is part of its stable
typedef struct parrot_get_by_int_msg_ PGetByIntMsg;
typedef struct parrot_set_by_int_msg_ PSetByIntMsg;
struct parrot_set_by_int_msg_
{
PObject header;
PInt key;
PValue value;
};
struct parrot_get_by_int_msg_
{
PObject header;
PInt key;
};
// example usage of message-passing from C:
/* PInterp *interp = ...;
PObject *obj = ...;
// messages can be placed on stack
// the initializer takes care of using a correct repr and sets the msg_id
PSetByIntMsg msg = PARROT_INIT_SET_BY_INT_MSG_ON_STACK;
msg.key = 3;
msg.value.type = PARROT_INT_VALUE;
msg.value.as_int.value = 42;
PValue rv = obj->stable.handle_msg(iterp, obj, &msg.header);
switch(rv.type)
{
case PARROT_FAIL_VALUE:
...
}
// the message handler dispatches by message id
switch(args->stable.msg_id)
{
case PARROT_SET_BY_INT_MSG:
...
}
*/
struct parrot_interp_
{
PObject header;
PPointerHash *repr_registry;
// ...
};
struct parrot_repr_
{
// a repr needs no numeric id, so we got rid of it
PString *name;
// the various repr functions, including gc-specifics...
PObject *(*allocate)(PInterp *interp, PSTable *st);
void (*initialize)(PInterp *interp, PSTable *st, void *data);
// ...
// the SixModel_REPROps_* tables get flattened into this as well:
// the additional indirection is unnecessary
};
struct parrot_stable_
{
PObject header;
PRepr *repr;
void *repr_data;
// only != 0 if object is a message
PMsgId msg_id;
// the default handler delegates to the meta-object, ie uses find_method
// to look up a handler method by message name
PValue (*handle_msg)(PInterp *interp, PObject *obj, PObject *msg);
PObject *meta_object;
PObject *type_object;
PObject *method_cache;
PObject **static_method_cache;
size_t static_method_cache_size;
PObject **type_check_cache;
size_t type_check_cache_size;
// ...
};
// meta-object methods need not be virtual
extern PObject *Parrot_find_method(
PInterp *interp, PObject *obj, PString *name, PInt hint);
extern PInt Parrot_type_check(PInterp *interp, PObject *obj, PObject *checkee);
// hide short names in foreign source files
#ifndef PARROT_SOURCE
#undef PInt
#undef PNum
//...
#endif
#endif
@gerdr
Copy link
Author

gerdr commented Feb 6, 2012

the current factoring means that each message needs its own repr, which will probably get quite tedious - some code-generation might come in handy here...

@gerdr
Copy link
Author

gerdr commented Feb 6, 2012

also, wrapper-functions like

PValue Parrot_send_set_by_int_msg(
    PInterp *interp, PObject *obj, PInt key, PValue value);

can make the C interface less bothersome...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment