Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
First cut of a P6bigint REPR, plus bigint library initialization code…
…. With this, we can declare a type with repr('bigint') and have it box/unbox native ints; it's allocating the libtommath big integer under the hood.
  • Loading branch information
jnthn committed Oct 28, 2011
1 parent 22f49c1 commit fcd90db
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 3 deletions.
217 changes: 217 additions & 0 deletions src/6model/reprs/P6bigint.c
@@ -0,0 +1,217 @@
/* This is the implementation of the P6bigint representation, which holds a
* libtommath big integer. */

#define PARROT_IN_EXTENSION
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "../sixmodelobject.h"
#include "P6bigint.h"

/* This representation's function pointer table. */
static REPROps *this_repr;

/* Some functions we have to get references to. */
static PMC * (* wrap_object_func) (PARROT_INTERP, void *obj);
static PMC * (* create_stable_func) (PARROT_INTERP, REPROps *REPR, PMC *HOW);

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

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

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

/* Flag it as a type object. */
PObj_flag_SET(private0, st->WHAT);

return st->WHAT;
}

/* Creates a new instance based on the type object. */
static PMC * instance_of(PARROT_INTERP, PMC *WHAT) {
P6bigintInstance *obj = mem_allocate_zeroed_typed(P6bigintInstance);
obj->common.stable = STABLE_PMC(WHAT);
mp_init(&obj->i);
mp_zero(&obj->i);
return wrap_object_func(interp, obj);
}

/* Checks if a given object is defined (from the point of view of the
* representation). */
static INTVAL defined(PARROT_INTERP, PMC *obj) {
return !PObj_flag_TEST(private0, obj);
}

/* Helper to die because this type doesn't support attributes. */
PARROT_DOES_NOT_RETURN
static void die_no_attrs(PARROT_INTERP) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6bigint representation does not support attribute storage");
}

/* Gets the current value for an attribute. */
static PMC * get_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp);
return PMCNULL;
}
static INTVAL get_attribute_int(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp);
return 0;
}
static FLOATVAL get_attribute_num(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp);
return 0.0;
}
static STRING * get_attribute_str(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp);
return NULL;
}
static void * get_attribute_ref(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp);
return NULL;
}

/* Binds the given value to the specified attribute. */
static void bind_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
die_no_attrs(interp);
}
static void bind_attribute_int(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, INTVAL value) {
die_no_attrs(interp);
}
static void bind_attribute_num(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, FLOATVAL value) {
die_no_attrs(interp);
}
static void bind_attribute_str(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, STRING *value) {
die_no_attrs(interp);
}

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

/* Clones the current object; simply copies the value. */
static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) {
P6bigintInstance *obj = mem_allocate_zeroed_typed(P6bigintInstance);
obj->common.stable = STABLE_PMC(to_clone);
mp_init_copy(&obj->i, &((P6bigintInstance *)PMC_data(to_clone))->i);
return wrap_object_func(interp, obj);
}

/* Used with boxing. Sets an integer value, for representations that can hold
* one. */
static void set_int(PARROT_INTERP, PMC *obj, INTVAL value) {
mp_set_int(&((P6bigintInstance *)PMC_data(obj))->i, value);
}

/* Used with boxing. Gets an integer value, for representations that can
* hold one. */
static INTVAL get_int(PARROT_INTERP, PMC *obj) {
return mp_get_int(&((P6bigintInstance *)PMC_data(obj))->i);
}

/* Used with boxing. Sets a floating point value, for representations that can
* hold one. */
static void set_num(PARROT_INTERP, PMC *obj, FLOATVAL value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6bigint cannot 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 *obj) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6bigint cannot 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 *obj, STRING *value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6bigint cannot box a native string");
}

/* Used with boxing. Gets a string value, for representations that can hold
* one. */
static STRING * get_str(PARROT_INTERP, PMC *obj) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"P6bigint cannot 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 *obj) {
P6bigintInstance *instance = (P6bigintInstance *)PMC_data(obj);
if (!PMC_IS_NULL(instance->common.stable))
Parrot_gc_mark_PMC_alive(interp, instance->common.stable);
if (!PMC_IS_NULL(instance->common.sc))
Parrot_gc_mark_PMC_alive(interp, instance->common.sc);
}

/* This Parrot-specific addition to the API is used to free an object. */
static void gc_free(PARROT_INTERP, PMC *obj) {
mp_clear(&((P6bigintInstance *)PMC_data(obj))->i);
mem_sys_free(PMC_data(obj));
PMC_data(obj) = NULL;
}

/* Gets the storage specification for this representation. */
static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
storage_spec spec;
spec.inlineable = STORAGE_SPEC_INLINED;
spec.bits = sizeof(mp_int) * 8;
spec.boxed_primitive = STORAGE_SPEC_BP_INT;
spec.can_box = STORAGE_SPEC_CAN_BOX_INT;
return spec;
}

/* Checks if an attribute has been initialized. */
static INTVAL is_attribute_initialized(PARROT_INTERP, PMC *Object, PMC *ClassHandle, STRING *Name, INTVAL Hint) {
die_no_attrs(interp);
}

/* Initializes the P6bigint representation. */
REPROps * P6bigint_initialize(PARROT_INTERP,
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW)) {
/* Stash away functions passed wrapping functions. */
wrap_object_func = wrap_object_func_ptr;
create_stable_func = create_stable_func_ptr;

/* Allocate and populate the representation function table. */
this_repr = mem_allocate_typed(REPROps);
this_repr->type_object_for = type_object_for;
this_repr->instance_of = instance_of;
this_repr->defined = defined;
this_repr->get_attribute = get_attribute;
this_repr->get_attribute_int = get_attribute_int;
this_repr->get_attribute_num = get_attribute_num;
this_repr->get_attribute_str = get_attribute_str;
this_repr->get_attribute_ref = get_attribute_ref;
this_repr->bind_attribute = bind_attribute;
this_repr->bind_attribute_int = bind_attribute_int;
this_repr->bind_attribute_num = bind_attribute_num;
this_repr->bind_attribute_str = bind_attribute_str;
this_repr->hint_for = hint_for;
this_repr->clone = repr_clone;
this_repr->set_int = set_int;
this_repr->get_int = get_int;
this_repr->set_num = set_num;
this_repr->get_num = get_num;
this_repr->set_str = set_str;
this_repr->get_str = get_str;
this_repr->gc_mark = gc_mark;
this_repr->gc_free = gc_free;
this_repr->gc_mark_repr = NULL;
this_repr->gc_free_repr = NULL;
this_repr->get_storage_spec = get_storage_spec;
this_repr->is_attribute_initialized = is_attribute_initialized;
return this_repr;
}
20 changes: 20 additions & 0 deletions src/6model/reprs/P6bigint.h
@@ -0,0 +1,20 @@
#ifndef P6BIGINT_H_GUARD
#define P6BIGINT_H_GUARD

#include "tommath.h"

/* This is how an instance with the P6bigint representation looks. */
typedef struct {
/* The commonalities all objects have. */
SixModelObjectCommonalities common;

/* Big integer storage slot. */
mp_int i;
} P6bigintInstance;

/* Initializes the P6bigint REPR. */
REPROps * P6bigint_initialize(PARROT_INTERP,
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW));

#endif
7 changes: 6 additions & 1 deletion src/ops/nqp_bigint.ops
Expand Up @@ -4,9 +4,14 @@ BEGIN_OPS_PREAMBLE
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "parrot/dynext.h"
#include "../6model/sixmodelobject.h"
#include "../6model/reprs/P6bigint.h"

END_OPS_PREAMBLE

inline op nqp_bigint_setup() :base_core {

/* Register the bigint representation. */
REGISTER_DYNAMIC_REPR(interp,
Parrot_str_new_constant(interp, "P6bigint"),
P6bigint_initialize);
}
5 changes: 3 additions & 2 deletions tools/build/Makefile.in
Expand Up @@ -442,7 +442,7 @@ $(OPS_DIR)/$(OPS)$(LOAD_EXT): $(OPS_DIR)/$(OPS_SOURCE) $(DYNPMC)

$(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT): $(OPS_DIR)/$(BIGINT_OPS_SOURCE)
cd $(OPS_DIR) && $(OPS2C) C --dynamic $(BIGINT_OPS_SOURCE)
cd $(OPS_DIR) && $(CC) -c @cc_o_out@$(BIGINT_OPS)$(O) $(CINCLUDES) $(CFLAGS) $(BIGINT_OPS).c
cd $(OPS_DIR) && $(CC) -c @cc_o_out@$(BIGINT_OPS)$(O) $(CINCLUDES) -I../../3rdparty/libtommath $(CFLAGS) $(BIGINT_OPS).c
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bncore$(O) -I. $(CFLAGS) bncore.c
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_error$(O) -I. $(CFLAGS) bn_error.c
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_fast_mp_invmod$(O) -I. $(CFLAGS) bn_fast_mp_invmod.c
Expand Down Expand Up @@ -562,7 +562,8 @@ $(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT): $(OPS_DIR)/$(BIGINT_OPS_SOURCE)
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_mul_high_digs$(O) -I. $(CFLAGS) bn_s_mp_mul_high_digs.c
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_sqr$(O) -I. $(CFLAGS) bn_s_mp_sqr.c
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_sub$(O) -I. $(CFLAGS) bn_s_mp_sub.c
cd $(OPS_DIR) && $(LD) @ld_out@$(BIGINT_OPS)$(LOAD_EXT) $(BIGINT_OPS)$(O) ../../3rdparty/libtommath/*$(O) $(LINKARGS)
cd src/6model/reprs && $(CC) -c @cc_o_out@P6bigint$(O) -I../../../$(PMC_DIR) -I../../../3rdparty/libtommath $(CINCLUDES) $(CFLAGS) P6bigint.c
cd $(OPS_DIR) && $(LD) @ld_out@$(BIGINT_OPS)$(LOAD_EXT) $(BIGINT_OPS)$(O) ../../3rdparty/libtommath/*$(O) ../6model/reprs/P6bigint$(O) $(LINKARGS)

bootstrap-files: $(STAGE2_PBCS) src/stage2/$(CORE_SETTING_NQP)
$(PERL) tools/build/gen-bootstrap.pl src/Regex.pir >src/stage0/Regex-s0.pir
Expand Down

0 comments on commit fcd90db

Please sign in to comment.