Skip to content

Commit fcd90db

Browse files
committed
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.
1 parent 22f49c1 commit fcd90db

File tree

4 files changed

+246
-3
lines changed

4 files changed

+246
-3
lines changed

src/6model/reprs/P6bigint.c

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/* This is the implementation of the P6bigint representation, which holds a
2+
* libtommath big integer. */
3+
4+
#define PARROT_IN_EXTENSION
5+
#include "parrot/parrot.h"
6+
#include "parrot/extend.h"
7+
#include "../sixmodelobject.h"
8+
#include "P6bigint.h"
9+
10+
/* This representation's function pointer table. */
11+
static REPROps *this_repr;
12+
13+
/* Some functions we have to get references to. */
14+
static PMC * (* wrap_object_func) (PARROT_INTERP, void *obj);
15+
static PMC * (* create_stable_func) (PARROT_INTERP, REPROps *REPR, PMC *HOW);
16+
17+
/* Creates a new type object of this representation, and associates it with
18+
* the given HOW. */
19+
static PMC * type_object_for(PARROT_INTERP, PMC *HOW) {
20+
/* Create new object instance. */
21+
P6bigintInstance *obj = mem_allocate_zeroed_typed(P6bigintInstance);
22+
23+
/* Build an STable. */
24+
PMC *st_pmc = create_stable_func(interp, this_repr, HOW);
25+
STable *st = STABLE_STRUCT(st_pmc);
26+
27+
/* Create type object and point it back at the STable. */
28+
obj->common.stable = st_pmc;
29+
st->WHAT = wrap_object_func(interp, obj);
30+
PARROT_GC_WRITE_BARRIER(interp, st_pmc);
31+
32+
/* Flag it as a type object. */
33+
PObj_flag_SET(private0, st->WHAT);
34+
35+
return st->WHAT;
36+
}
37+
38+
/* Creates a new instance based on the type object. */
39+
static PMC * instance_of(PARROT_INTERP, PMC *WHAT) {
40+
P6bigintInstance *obj = mem_allocate_zeroed_typed(P6bigintInstance);
41+
obj->common.stable = STABLE_PMC(WHAT);
42+
mp_init(&obj->i);
43+
mp_zero(&obj->i);
44+
return wrap_object_func(interp, obj);
45+
}
46+
47+
/* Checks if a given object is defined (from the point of view of the
48+
* representation). */
49+
static INTVAL defined(PARROT_INTERP, PMC *obj) {
50+
return !PObj_flag_TEST(private0, obj);
51+
}
52+
53+
/* Helper to die because this type doesn't support attributes. */
54+
PARROT_DOES_NOT_RETURN
55+
static void die_no_attrs(PARROT_INTERP) {
56+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
57+
"P6bigint representation does not support attribute storage");
58+
}
59+
60+
/* Gets the current value for an attribute. */
61+
static PMC * get_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
62+
die_no_attrs(interp);
63+
return PMCNULL;
64+
}
65+
static INTVAL get_attribute_int(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
66+
die_no_attrs(interp);
67+
return 0;
68+
}
69+
static FLOATVAL get_attribute_num(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
70+
die_no_attrs(interp);
71+
return 0.0;
72+
}
73+
static STRING * get_attribute_str(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
74+
die_no_attrs(interp);
75+
return NULL;
76+
}
77+
static void * get_attribute_ref(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) {
78+
die_no_attrs(interp);
79+
return NULL;
80+
}
81+
82+
/* Binds the given value to the specified attribute. */
83+
static void bind_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
84+
die_no_attrs(interp);
85+
}
86+
static void bind_attribute_int(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, INTVAL value) {
87+
die_no_attrs(interp);
88+
}
89+
static void bind_attribute_num(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, FLOATVAL value) {
90+
die_no_attrs(interp);
91+
}
92+
static void bind_attribute_str(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint, STRING *value) {
93+
die_no_attrs(interp);
94+
}
95+
96+
/* Gets the hint for the given attribute ID. */
97+
static INTVAL hint_for(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name) {
98+
return NO_HINT;
99+
}
100+
101+
/* Clones the current object; simply copies the value. */
102+
static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) {
103+
P6bigintInstance *obj = mem_allocate_zeroed_typed(P6bigintInstance);
104+
obj->common.stable = STABLE_PMC(to_clone);
105+
mp_init_copy(&obj->i, &((P6bigintInstance *)PMC_data(to_clone))->i);
106+
return wrap_object_func(interp, obj);
107+
}
108+
109+
/* Used with boxing. Sets an integer value, for representations that can hold
110+
* one. */
111+
static void set_int(PARROT_INTERP, PMC *obj, INTVAL value) {
112+
mp_set_int(&((P6bigintInstance *)PMC_data(obj))->i, value);
113+
}
114+
115+
/* Used with boxing. Gets an integer value, for representations that can
116+
* hold one. */
117+
static INTVAL get_int(PARROT_INTERP, PMC *obj) {
118+
return mp_get_int(&((P6bigintInstance *)PMC_data(obj))->i);
119+
}
120+
121+
/* Used with boxing. Sets a floating point value, for representations that can
122+
* hold one. */
123+
static void set_num(PARROT_INTERP, PMC *obj, FLOATVAL value) {
124+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
125+
"P6bigint cannot box a native num");
126+
}
127+
128+
/* Used with boxing. Gets a floating point value, for representations that can
129+
* hold one. */
130+
static FLOATVAL get_num(PARROT_INTERP, PMC *obj) {
131+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
132+
"P6bigint cannot unbox to a native num");
133+
}
134+
135+
/* Used with boxing. Sets a string value, for representations that can hold
136+
* one. */
137+
static void set_str(PARROT_INTERP, PMC *obj, STRING *value) {
138+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
139+
"P6bigint cannot box a native string");
140+
}
141+
142+
/* Used with boxing. Gets a string value, for representations that can hold
143+
* one. */
144+
static STRING * get_str(PARROT_INTERP, PMC *obj) {
145+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
146+
"P6bigint cannot unbox to a native string");
147+
}
148+
149+
/* This Parrot-specific addition to the API is used to mark an object. */
150+
static void gc_mark(PARROT_INTERP, PMC *obj) {
151+
P6bigintInstance *instance = (P6bigintInstance *)PMC_data(obj);
152+
if (!PMC_IS_NULL(instance->common.stable))
153+
Parrot_gc_mark_PMC_alive(interp, instance->common.stable);
154+
if (!PMC_IS_NULL(instance->common.sc))
155+
Parrot_gc_mark_PMC_alive(interp, instance->common.sc);
156+
}
157+
158+
/* This Parrot-specific addition to the API is used to free an object. */
159+
static void gc_free(PARROT_INTERP, PMC *obj) {
160+
mp_clear(&((P6bigintInstance *)PMC_data(obj))->i);
161+
mem_sys_free(PMC_data(obj));
162+
PMC_data(obj) = NULL;
163+
}
164+
165+
/* Gets the storage specification for this representation. */
166+
static storage_spec get_storage_spec(PARROT_INTERP, STable *st) {
167+
storage_spec spec;
168+
spec.inlineable = STORAGE_SPEC_INLINED;
169+
spec.bits = sizeof(mp_int) * 8;
170+
spec.boxed_primitive = STORAGE_SPEC_BP_INT;
171+
spec.can_box = STORAGE_SPEC_CAN_BOX_INT;
172+
return spec;
173+
}
174+
175+
/* Checks if an attribute has been initialized. */
176+
static INTVAL is_attribute_initialized(PARROT_INTERP, PMC *Object, PMC *ClassHandle, STRING *Name, INTVAL Hint) {
177+
die_no_attrs(interp);
178+
}
179+
180+
/* Initializes the P6bigint representation. */
181+
REPROps * P6bigint_initialize(PARROT_INTERP,
182+
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
183+
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW)) {
184+
/* Stash away functions passed wrapping functions. */
185+
wrap_object_func = wrap_object_func_ptr;
186+
create_stable_func = create_stable_func_ptr;
187+
188+
/* Allocate and populate the representation function table. */
189+
this_repr = mem_allocate_typed(REPROps);
190+
this_repr->type_object_for = type_object_for;
191+
this_repr->instance_of = instance_of;
192+
this_repr->defined = defined;
193+
this_repr->get_attribute = get_attribute;
194+
this_repr->get_attribute_int = get_attribute_int;
195+
this_repr->get_attribute_num = get_attribute_num;
196+
this_repr->get_attribute_str = get_attribute_str;
197+
this_repr->get_attribute_ref = get_attribute_ref;
198+
this_repr->bind_attribute = bind_attribute;
199+
this_repr->bind_attribute_int = bind_attribute_int;
200+
this_repr->bind_attribute_num = bind_attribute_num;
201+
this_repr->bind_attribute_str = bind_attribute_str;
202+
this_repr->hint_for = hint_for;
203+
this_repr->clone = repr_clone;
204+
this_repr->set_int = set_int;
205+
this_repr->get_int = get_int;
206+
this_repr->set_num = set_num;
207+
this_repr->get_num = get_num;
208+
this_repr->set_str = set_str;
209+
this_repr->get_str = get_str;
210+
this_repr->gc_mark = gc_mark;
211+
this_repr->gc_free = gc_free;
212+
this_repr->gc_mark_repr = NULL;
213+
this_repr->gc_free_repr = NULL;
214+
this_repr->get_storage_spec = get_storage_spec;
215+
this_repr->is_attribute_initialized = is_attribute_initialized;
216+
return this_repr;
217+
}

src/6model/reprs/P6bigint.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef P6BIGINT_H_GUARD
2+
#define P6BIGINT_H_GUARD
3+
4+
#include "tommath.h"
5+
6+
/* This is how an instance with the P6bigint representation looks. */
7+
typedef struct {
8+
/* The commonalities all objects have. */
9+
SixModelObjectCommonalities common;
10+
11+
/* Big integer storage slot. */
12+
mp_int i;
13+
} P6bigintInstance;
14+
15+
/* Initializes the P6bigint REPR. */
16+
REPROps * P6bigint_initialize(PARROT_INTERP,
17+
PMC * (* wrap_object_func_ptr) (PARROT_INTERP, void *obj),
18+
PMC * (* create_stable_func_ptr) (PARROT_INTERP, REPROps *REPR, PMC *HOW));
19+
20+
#endif

src/ops/nqp_bigint.ops

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ BEGIN_OPS_PREAMBLE
44
#include "parrot/parrot.h"
55
#include "parrot/extend.h"
66
#include "parrot/dynext.h"
7+
#include "../6model/sixmodelobject.h"
8+
#include "../6model/reprs/P6bigint.h"
79

810
END_OPS_PREAMBLE
911

1012
inline op nqp_bigint_setup() :base_core {
11-
13+
/* Register the bigint representation. */
14+
REGISTER_DYNAMIC_REPR(interp,
15+
Parrot_str_new_constant(interp, "P6bigint"),
16+
P6bigint_initialize);
1217
}

tools/build/Makefile.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ $(OPS_DIR)/$(OPS)$(LOAD_EXT): $(OPS_DIR)/$(OPS_SOURCE) $(DYNPMC)
442442

443443
$(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT): $(OPS_DIR)/$(BIGINT_OPS_SOURCE)
444444
cd $(OPS_DIR) && $(OPS2C) C --dynamic $(BIGINT_OPS_SOURCE)
445-
cd $(OPS_DIR) && $(CC) -c @cc_o_out@$(BIGINT_OPS)$(O) $(CINCLUDES) $(CFLAGS) $(BIGINT_OPS).c
445+
cd $(OPS_DIR) && $(CC) -c @cc_o_out@$(BIGINT_OPS)$(O) $(CINCLUDES) -I../../3rdparty/libtommath $(CFLAGS) $(BIGINT_OPS).c
446446
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bncore$(O) -I. $(CFLAGS) bncore.c
447447
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_error$(O) -I. $(CFLAGS) bn_error.c
448448
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_fast_mp_invmod$(O) -I. $(CFLAGS) bn_fast_mp_invmod.c
@@ -562,7 +562,8 @@ $(OPS_DIR)/$(BIGINT_OPS)$(LOAD_EXT): $(OPS_DIR)/$(BIGINT_OPS_SOURCE)
562562
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_mul_high_digs$(O) -I. $(CFLAGS) bn_s_mp_mul_high_digs.c
563563
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_sqr$(O) -I. $(CFLAGS) bn_s_mp_sqr.c
564564
cd 3rdparty/libtommath && $(CC) -c @cc_o_out@bn_s_mp_sub$(O) -I. $(CFLAGS) bn_s_mp_sub.c
565-
cd $(OPS_DIR) && $(LD) @ld_out@$(BIGINT_OPS)$(LOAD_EXT) $(BIGINT_OPS)$(O) ../../3rdparty/libtommath/*$(O) $(LINKARGS)
565+
cd src/6model/reprs && $(CC) -c @cc_o_out@P6bigint$(O) -I../../../$(PMC_DIR) -I../../../3rdparty/libtommath $(CINCLUDES) $(CFLAGS) P6bigint.c
566+
cd $(OPS_DIR) && $(LD) @ld_out@$(BIGINT_OPS)$(LOAD_EXT) $(BIGINT_OPS)$(O) ../../3rdparty/libtommath/*$(O) ../6model/reprs/P6bigint$(O) $(LINKARGS)
566567

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

0 commit comments

Comments
 (0)