Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

451 lines (311 sloc) 12.379 kb
/*
Copyright (C) 2001-2014, Parrot Foundation.
=head1 NAME
src/pmc/packfileconstanttable.pmc - PackfileConstantTable PMC
=head1 DESCRIPTION
This class implements a PackfileConstantTable object, a segment of the .pbc
data file used for storing constants of various types. (int, string, PMC)
See packfile.pmc for the toplevel Packfile interface, see packfilesegment.pmc
for the list of common methods every packfile segment pmc must implement; see
PDD13 for the design spec.
=head2 Methods
=over 4
=cut
*/
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass PackfileConstantTable auto_attrs extends PackfileSegment {
/* ResizableXArray for storing constants */
ATTR PMC *num_constants;
ATTR PMC *str_constants;
ATTR PMC *pmc_constants;
ATTR PMC *tag_map;
/*
=item C<init>
Create empty PackfileConstantTable.
=cut
*/
VTABLE void init() {
Parrot_PackfileConstantTable_attributes * const attrs =
PMC_data_typed(SELF, Parrot_PackfileConstantTable_attributes*);
attrs->num_constants = Parrot_pmc_new(INTERP, enum_class_ResizableFloatArray);
attrs->str_constants = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
attrs->pmc_constants = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
attrs->tag_map = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
PObj_custom_mark_SET(SELF);
PMC_data(SELF) = attrs;
}
/*
=item C<void mark()>
Marks the object as live.
=cut
*/
VTABLE void mark() :no_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
Parrot_gc_mark_PMC_alive(INTERP, attrs->num_constants);
Parrot_gc_mark_PMC_alive(INTERP, attrs->str_constants);
Parrot_gc_mark_PMC_alive(INTERP, attrs->pmc_constants);
Parrot_gc_mark_PMC_alive(INTERP, attrs->tag_map);
SUPER();
}
/*
=item C<set_pointer>
Set pointer to underlying PackFile_ConstTable
=cut
*/
VTABLE void set_pointer(void * pointer) {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
const PackFile_ConstTable * const table =
(const PackFile_ConstTable *)(pointer);
opcode_t i;
/* Preallocate required amount of memory */
VTABLE_set_integer_native(INTERP, attrs->num_constants, table->num.const_count);
VTABLE_set_integer_native(INTERP, attrs->str_constants, table->str.const_count);
VTABLE_set_integer_native(INTERP, attrs->pmc_constants, table->pmc.const_count);
VTABLE_set_integer_native(INTERP, attrs->tag_map, table->ntags * 2);
for (i = 0; i < table->num.const_count; i++)
SELF.set_number_keyed_int(i, table->num.constants[i]);
for (i = 0; i < table->str.const_count; i++)
SELF.set_string_keyed_int(i, table->str.constants[i]);
for (i = 0; i < table->pmc.const_count; i++)
SELF.set_pmc_keyed_int(i, table->pmc.constants[i]);
for (i = 0; i < table->ntags; i++) {
const INTVAL ptr = i * 2;
VTABLE_set_integer_keyed_int(INTERP, attrs->tag_map, ptr, table->tag_map[i].tag_idx);
VTABLE_set_integer_keyed_int(INTERP, attrs->tag_map, ptr, table->tag_map[i].const_idx);
}
}
/*
=item C<void *get_pointer()>
=cut
*/
VTABLE void *get_pointer() :no_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
PackFile_ConstTable * const pftable =
mem_gc_allocate_zeroed_typed(INTERP, PackFile_ConstTable);
opcode_t i;
const int tag_elts = VTABLE_elements(INTERP, attrs->tag_map);
pftable->base.type = PF_CONST_SEG;
/* Copy all constanst with respect of type */
pftable->num.const_count = VTABLE_get_integer(INTERP, attrs->num_constants);
pftable->str.const_count = VTABLE_get_integer(INTERP, attrs->str_constants);
pftable->pmc.const_count = VTABLE_get_integer(INTERP, attrs->pmc_constants);
pftable->num.constants = mem_gc_allocate_n_typed(INTERP,
pftable->num.const_count, FLOATVAL);
pftable->str.constants = mem_gc_allocate_n_typed(INTERP,
pftable->str.const_count, STRING *);
pftable->pmc.constants = mem_gc_allocate_n_typed(INTERP,
pftable->pmc.const_count, PMC *);
for (i = 0; i < pftable->num.const_count; i++)
pftable->num.constants[i] =
VTABLE_get_number_keyed_int(INTERP, attrs->num_constants, i);
for (i = 0; i < pftable->str.const_count; i++)
pftable->str.constants[i] =
VTABLE_get_string_keyed_int(INTERP, attrs->str_constants, i);
for (i = 0; i < pftable->pmc.const_count; i++)
pftable->pmc.constants[i] =
VTABLE_get_pmc_keyed_int(INTERP, attrs->pmc_constants, i);
for (i = 0; i < tag_elts; i += 2) {
Parrot_pf_tag_constant(interp, pftable,
VTABLE_get_integer_keyed_int(INTERP, attrs->tag_map, i),
VTABLE_get_integer_keyed_int(INTERP, attrs->tag_map, i + 1));
}
return pftable;
}
/*
=item C<INTVAL num_count()>
=item C<INTVAL str_count()>
=item C<INTVAL pmc_count()>
Get the number of constants.
=cut
*/
METHOD INTVAL num_count() :no_wb {
const INTVAL ret = VTABLE_elements(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->num_constants);
RETURN(INTVAL ret);
}
METHOD INTVAL str_count() :no_wb {
const INTVAL ret = VTABLE_elements(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->str_constants);
RETURN(INTVAL ret);
}
METHOD INTVAL pmc_count() :no_wb {
const INTVAL ret = VTABLE_elements(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->pmc_constants);
RETURN(INTVAL ret);
}
/*
=item C<FLOATVAL get_number_keyed_int(INTVAL index)>
Fetch a numeric constant.
=cut
*/
VTABLE FLOATVAL get_number_keyed_int(INTVAL index) :no_wb {
return VTABLE_get_number_keyed_int(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->num_constants, index);
}
/*
=item C<STRING *get_string_keyed_int(INTVAL index)>
Fetch a string constant.
=cut
*/
VTABLE STRING *get_string_keyed_int(INTVAL index) :no_wb {
return VTABLE_get_string_keyed_int(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->str_constants, index);
}
/*
=item C<PMC *get_pmc_keyed_int(INTVAL index)>
Fetch a PMC constant.
=cut
*/
VTABLE PMC *get_pmc_keyed_int(INTVAL index) :no_wb {
return VTABLE_get_pmc_keyed_int(INTERP,
PARROT_PACKFILECONSTANTTABLE(SELF)->pmc_constants, index);
}
/*
=item C<void set_number_keyed_int(INTVAL index, FLOATVAL value)>
Set the constant to the given number.
=cut
*/
VTABLE void set_number_keyed_int(INTVAL index, FLOATVAL value) {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_number_keyed_int(INTERP, attrs->num_constants, index, value);
}
/*
=item C<void set_string_keyed_int(INTVAL index, STRING *value)>
Set the constant to the given string.
=cut
*/
VTABLE void set_string_keyed_int(INTVAL index, STRING *value) {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_string_keyed_int(INTERP, attrs->str_constants, index, value);
}
/*
=item C<void set_pmc_keyed_int(INTVAL index, PMC *value)>
Set the constant to the given PMC (or key).
=cut
*/
VTABLE void set_pmc_keyed_int(INTVAL index, PMC *value) {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_pmc_keyed_int(INTERP, attrs->pmc_constants, index, value);
}
VTABLE void push_float(FLOATVAL val) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_number_keyed_int(INTERP, SELF,
VTABLE_get_integer(INTERP, attrs->num_constants),
val);
}
VTABLE void push_string(STRING *val) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_string_keyed_int(INTERP, SELF,
VTABLE_get_integer(INTERP, attrs->str_constants),
val);
}
VTABLE void push_pmc(PMC *val) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_pmc_keyed_int(INTERP, SELF,
VTABLE_get_integer(INTERP, attrs->pmc_constants),
val);
}
/*
=item C<void set_main(INTVAL index)>
Set the :main flag in a Sub in the constant table.
Experimental. Use with care. There is no way to set the
private flags from PIR, so we need something like this.
If something goes wrong, blame NotFound.
=cut
*/
METHOD set_main(INTVAL index) {
PMC * const mainsub = SELF.get_pmc_keyed_int(index);
if (mainsub->vtable->base_type != enum_class_Sub)
Parrot_ex_throw_from_c_noargs(INTERP,
EXCEPTION_INVALID_OPERATION,
"Attempt to set main flag in a non Sub");
SUB_FLAG_flag_SET(PF_MAIN, mainsub);
}
/*
=item C<INTVAL get_or_create_constant()>
Get or create constant for passed value.
=cut
*/
MULTI INTVAL get_or_create_constant(STRING *value) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
const INTVAL num = VTABLE_elements(INTERP, attrs->str_constants);
INTVAL i;
for (i=0; i < num; ++i) {
STRING * const str = VTABLE_get_string_keyed_int(INTERP, attrs->str_constants, i);
if (STRING_equal(INTERP, value, str))
return i;
}
/* Constant not found. Add new one */
SELF.set_string_keyed_int(i, value);
return i;
}
MULTI INTVAL get_or_create_constant(FLOATVAL value) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
const INTVAL num = VTABLE_elements(INTERP, attrs->num_constants);
INTVAL i;
for (i=0; i < num; ++i) {
const FLOATVAL val = VTABLE_get_number_keyed_int(INTERP, attrs->num_constants, i);
if (FLOAT_IS_ZERO(fabs(val - value)))
return i;
}
/* Constant not found. Add new one */
SELF.set_number_keyed_int(i, value);
return i;
}
MULTI INTVAL get_or_create_constant(PMC *value) :manual_wb {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
const INTVAL num = VTABLE_elements(INTERP, attrs->pmc_constants);
INTVAL i;
for (i=0; i < num; ++i) {
PMC * const val = VTABLE_get_pmc_keyed_int(INTERP, attrs->pmc_constants, i);
if (VTABLE_is_equal(INTERP, value, val))
return i;
}
/* Constant not found. Add new one */
SELF.set_pmc_keyed_int(i, value);
return i;
}
/*
=item C<METHOD type()>
Set segment type.
=cut
*/
METHOD type() :no_wb {
RETURN(INTVAL PF_CONST_SEG);
}
/*
=item C<METHOD add_tag_mapping(INTVAL pmc_idx, INTVAL str_idx)>
Add a string->pmc tag mapping
*/
METHOD add_tag_mapping(INTVAL pmc_idx, INTVAL str_idx) {
Parrot_PackfileConstantTable_attributes * const attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
INTVAL idx = VTABLE_elements(INTERP, attrs->tag_map);
VTABLE_set_integer_keyed_int(INTERP, attrs->tag_map, idx, pmc_idx);
VTABLE_set_integer_keyed_int(INTERP, attrs->tag_map, idx, str_idx);
}
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.