Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 18dd1479df
Fetching contributors…

Cannot retrieve contributors at this time

427 lines (300 sloc) 10.767 kB
/*
Copyright (C) 2001-2008, Parrot Foundation.
$Id$
=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
*/
pmclass PackfileConstantTable auto_attrs extends PackfileSegment {
/* ResizablePMCArray for storing constants */
ATTR PMC *constants;
/* ResizableIntegerArray for storing constant types */
ATTR PMC *types;
/*
=item C<init>
Create empty PackfileConstantTable.
=cut
*/
VTABLE void init() {
Parrot_PackfileConstantTable_attributes * attrs =
PMC_data_typed(SELF, Parrot_PackfileConstantTable_attributes*);
attrs->constants = pmc_new(interp, enum_class_ResizablePMCArray);
attrs->types = 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() {
Parrot_PackfileConstantTable_attributes * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
Parrot_gc_mark_PMC_alive(interp, attrs->constants);
Parrot_gc_mark_PMC_alive(interp, attrs->types);
SUPER();
}
/*
=item C<set_pointer>
Set pointer to underlying PackFile_ConstTable
=cut
*/
VTABLE void set_pointer(void * pointer) {
Parrot_PackfileConstantTable_attributes * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
const PackFile_ConstTable * const table =
(const PackFile_ConstTable *)(pointer);
const PackFile_Constant * val;
opcode_t i;
/* Preallocate required amount of memory */
VTABLE_set_integer_native(interp, attrs->constants, table->const_count);
VTABLE_set_integer_native(interp, attrs->types, table->const_count);
for (i = 0; i < table->const_count; ++i) {
val = table->constants[i];
switch (val->type) {
case PFC_NONE:
break;
case PFC_NUMBER:
SELF.set_number_keyed_int(i, val->u.number);
break;
case PFC_STRING:
SELF.set_string_keyed_int(i, val->u.string);
break;
case PFC_KEY:
/* fall through */
case PFC_PMC:
SELF.set_pmc_keyed_int(i, val->u.key);
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_MALFORMED_PACKFILE,
"Unknown PackFile constant type: %d", val->type);
}
}
}
/*
=item C<void *get_pointer()>
=cut
*/
VTABLE void *get_pointer() {
Parrot_PackfileConstantTable_attributes * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
PackFile_ConstTable * pftable =
mem_allocate_zeroed_typed(PackFile_ConstTable);
PackFile_Constant * value;
opcode_t i;
pftable->base.type = PF_CONST_SEG;
/* Copy all constanst with respect of type */
pftable->const_count = VTABLE_get_integer(interp, attrs->constants);
pftable->constants = mem_allocate_n_typed(pftable->const_count,
PackFile_Constant*);
for (i = 0; i < pftable->const_count; ++i) {
value = PackFile_Constant_new(interp);
value->type = VTABLE_get_integer_keyed_int(interp, attrs->types, i);
switch (value->type) {
case PFC_NONE:
break;
case PFC_NUMBER:
value->u.number = VTABLE_get_number_keyed_int(interp,
attrs->constants, i);
break;
case PFC_STRING:
value->u.string = VTABLE_get_string_keyed_int(interp,
attrs->constants, i);
break;
case PFC_KEY:
case PFC_PMC:
value->u.key = VTABLE_get_pmc_keyed_int(interp,
attrs->constants, i);
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_MALFORMED_PACKFILE,
"Unknown PackFile constant type: %d", value->type);
}
pftable->constants[i] = value;
}
return pftable;
}
/*
=item C<INTVAL elements()>
Get the number of elements in the array.
=cut
*/
VTABLE INTVAL elements() {
return VTABLE_elements(interp,
PARROT_PACKFILECONSTANTTABLE(SELF)->constants);
}
/*
=item C<FLOATVAL get_number_keyed_int(INTVAL index)>
Fetch a numeric constant. An exception is thrown if the given constant isn't
numeric.
=cut
*/
VTABLE FLOATVAL get_number_keyed_int(INTVAL index) {
return VTABLE_get_number_keyed_int(interp,
PARROT_PACKFILECONSTANTTABLE(SELF)->constants, index);
}
/*
=item C<STRING *get_string_keyed_int(INTVAL index)>
Fetch a string constant. An exception is thrown if the given constant isn't
a string.
=cut
*/
VTABLE STRING *get_string_keyed_int(INTVAL index) {
return VTABLE_get_string_keyed_int(interp,
PARROT_PACKFILECONSTANTTABLE(SELF)->constants, index);
}
/*
=item C<PMC *get_pmc_keyed_int(INTVAL index)>
Fetch a PMC constant. An exception is thrown if the given constant isn't a PMC.
=cut
*/
VTABLE PMC *get_pmc_keyed_int(INTVAL index) {
return VTABLE_get_pmc_keyed_int(interp,
PARROT_PACKFILECONSTANTTABLE(SELF)->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 * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_number_keyed_int(interp, attrs->constants, index, value);
VTABLE_set_integer_keyed_int(interp, attrs->types, index, PFC_NUMBER);
}
/*
=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 * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
VTABLE_set_string_keyed_int(interp, attrs->constants, index, value);
VTABLE_set_integer_keyed_int(interp, attrs->types, index, PFC_STRING);
}
/*
=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 * attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
opcode_t type = VTABLE_isa(interp, value,
Parrot_str_new_constant(interp, "Key"))
? PFC_KEY
: PFC_PMC;
VTABLE_set_pmc_keyed_int(interp, attrs->constants, index, value);
VTABLE_set_integer_keyed_int(interp, attrs->types, index, type);
}
/*
=item C<INTVAL get_type(INTVAL index)>
Get the type of the specified constant. Possible type IDs:
=over 4
=item 0x00 - No constant
=item 0x6E - Number constant
=item 0x73 - String constant
=item 0x70 - PMC constant
=item 0x6B - Key constant
=back
=cut
*/
METHOD get_type(INTVAL index) {
INTVAL rv = VTABLE_get_integer_keyed_int(interp,
PARROT_PACKFILECONSTANTTABLE(SELF)->types, index);
RETURN(INTVAL rv);
}
/*
=item C<INTVAL get_or_create_constant()>
Get or create constant for passed value.
=cut
*/
MULTI INTVAL get_or_create_constant(STRING *value) {
Parrot_PackfileConstantTable_attributes *attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
INTVAL num = VTABLE_elements(interp, attrs->types);
INTVAL i;
STRING *str;
for (i=0; i < num; ++i) {
INTVAL type = VTABLE_get_integer_keyed_int(interp, attrs->types, i);
if (type != PFC_STRING)
continue;
str = VTABLE_get_string_keyed_int(interp, attrs->constants, i);
if (Parrot_str_equal(interp, value, str))
return i;
}
/* Constant not found. Add new one */
VTABLE_set_string_keyed_int(interp, SELF, i, value);
return i;
}
MULTI INTVAL get_or_create_constant(FLOATVAL value) {
Parrot_PackfileConstantTable_attributes *attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
INTVAL num = VTABLE_elements(interp, attrs->types);
INTVAL i;
FLOATVAL val;
for (i=0; i < num; ++i) {
INTVAL type = VTABLE_get_integer_keyed_int(interp, attrs->types, i);
if (type != PFC_NUMBER)
continue;
val = VTABLE_get_number_keyed_int(interp, attrs->constants, i);
if (FLOAT_IS_ZERO(fabs(val - value)))
return i;
}
/* Constant not found. Add new one */
VTABLE_set_number_keyed_int(interp, SELF, i, value);
return i;
}
MULTI INTVAL get_or_create_constant(PMC *value) {
Parrot_PackfileConstantTable_attributes *attrs =
PARROT_PACKFILECONSTANTTABLE(SELF);
INTVAL num = VTABLE_elements(interp, attrs->types);
INTVAL i;
PMC *val;
INTVAL val_type = value->vtable->base_type == enum_class_Key
? PFC_KEY
: PFC_PMC;
for (i=0; i < num; ++i) {
INTVAL type = VTABLE_get_integer_keyed_int(interp, attrs->types, i);
if (type != val_type)
continue;
val = VTABLE_get_pmc_keyed_int(interp, attrs->constants, i);
if (VTABLE_is_equal(INTERP, value, val))
return i;
}
/* Constant not found. Add new one */
VTABLE_set_pmc_keyed_int(interp, SELF, i, value);
return i;
}
/*
=item C<METHOD type()>
Set segment type.
=cut
*/
METHOD type() {
RETURN(INTVAL PF_CONST_SEG);
}
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.