Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

278 lines (191 sloc) 6.363 kb
/*
Copyright (C) 2010-2014, Parrot Foundation.
=head1 NAME
src/pmc/oplib.pmc - OpLib PMC
=head1 DESCRIPTION
The PMC provides introspection on the opcodes contained in a library.
=cut
*/
#include "parrot/parrot.h"
#include "parrot/oplib/core_ops.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass OpLib auto_attrs {
ATTR op_lib_t *oplib;
/*
=head2 Vtable functions
=over 4
=item C<void init()>
Throws an error. OpLib requires an argument to init. See C<init_pmc>.
=cut
*/
VTABLE void init() :no_wb {
UNUSED(SELF)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_INVALID_OPERATION,
"OpLib must be initialized with an oplib name");
}
/*
=item C<void init_pmc(PMC *name_pmc)>
Initializes the OpLib with information about an oplib.
=cut
*/
VTABLE void init_pmc(PMC *name_pmc) {
STRING * const name = VTABLE_get_string(INTERP, name_pmc);
char * const name_cstr = Parrot_str_to_cstring(INTERP, name);
op_lib_t *oplib = NULL;
if (STREQ(name_cstr, PARROT_CORE_OPLIB_NAME)) {
oplib = PARROT_CORE_OPLIB_INIT(INTERP, 1);
}
else {
int i;
for (i = 0; i < INTERP->n_libs; i++) {
if (STREQ(name_cstr, INTERP->all_op_libs[i]->name)) {
oplib = INTERP->all_op_libs[i];
break;
}
}
}
Parrot_str_free_cstring(name_cstr);
if (!oplib)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_LIBRARY_NOT_LOADED,
"Could not find oplib `%S'", name);
SET_ATTR_oplib(INTERP, SELF, oplib);
}
/*
=item C<INTVAL get_integer_keyed_str(STRING *name)>
=item C<INTVAL get_integer_keyed(PMC *key)>
=item C<PMC* get_pmc_keyed_str(STRING *name)>
=item C<PMC* get_pmc_keyed(PMC *key)>
Look up an op number given the name of the op. First we look for the
specific name, then the more general short name.
The VTABLEs that return integers return -1 when an opcode could not be found.
The VTABLEs that return PMCs throw exceptions instead.
=cut
*/
VTABLE INTVAL get_integer_keyed_str(STRING *name) :no_wb {
const op_lib_t *oplib;
char * const cstr = Parrot_str_to_cstring(INTERP, name);
INTVAL num;
GET_ATTR_oplib(INTERP, SELF, oplib);
num = oplib->_op_code(INTERP, cstr, 1);
Parrot_str_free_cstring(cstr);
return num;
}
VTABLE INTVAL get_integer_keyed(PMC *key) :no_wb {
STRING * const str_key = Parrot_key_string(INTERP, key);
return SELF.get_integer_keyed_str(str_key);
}
VTABLE PMC* get_pmc_keyed_str(STRING *name) :no_wb {
const INTVAL num = STATICSELF.get_integer_keyed_str(name);
if (num == -1)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"Opcode: Opcode %S not found", name);
return STATICSELF.get_pmc_keyed_int(num);
}
VTABLE PMC* get_pmc_keyed(PMC *key) :no_wb {
STRING * const strkey = VTABLE_get_string(INTERP, key);
return VTABLE_get_pmc_keyed_str(INTERP, SELF, strkey);
}
/*
=item C<PMC* get_pmc_keyed_int(INTVAL value)>
Returns an C<Opcode> PMC for a given opcode number. To find an opcode number
from a name, see C<get_integer_keyed_str()> above.
=cut
*/
VTABLE PMC* get_pmc_keyed_int(INTVAL value) :no_wb {
op_lib_t *oplib;
GET_ATTR_oplib(INTERP, SELF, oplib);
if (value >= oplib->op_count ||
value < 0) {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"OpLib `%s': Opcode index %d out of bounds", oplib->name, value);
}
else {
PMC * const op = Parrot_pmc_new_noinit(INTERP, enum_class_Opcode);
VTABLE_set_integer_native(INTERP, op, value);
VTABLE_set_pointer(INTERP, op, &oplib->op_info_table[value]);
return op;
}
}
/*
=item C<INTVAL elements()>
=item C<INTVAL get_integer()>
Returns the number of opcodes in the library.
=cut
*/
VTABLE INTVAL elements() :no_wb {
const op_lib_t *oplib;
GET_ATTR_oplib(INTERP, SELF, oplib);
return oplib->op_count;
}
VTABLE INTVAL get_integer() :no_wb {
return STATICSELF.elements();
}
/*
=item C<void* get_pointer()>
Returns the C<op_lib_t> pointer for the opcode library.
=cut
*/
VTABLE void* get_pointer() :no_wb {
op_lib_t *oplib;
GET_ATTR_oplib(INTERP, SELF, oplib);
return oplib;
}
/*
=back
=head2 Methods
=over 4
=item C<PMC *op_family(STRING *shortname)>
Returns an array of C<Opcode> PMCs for all the opcodes in the library that
share the given short name.
=cut
*/
METHOD op_family(STRING *shortname) :no_wb {
char * const sname = Parrot_str_to_cstring(INTERP, shortname);
const op_lib_t *oplib;
op_info_t *table;
PMC *result = PMCNULL;
INTVAL i;
GET_ATTR_oplib(INTERP, SELF, oplib);
table = oplib->op_info_table;
for (i = 0; i < oplib->op_count; ++i) {
if (strcmp(table[i].name, sname) == 0) {
if (PMC_IS_NULL(result))
result = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
VTABLE_push_pmc(INTERP, result, SELF.get_pmc_keyed_int(i));
}
}
Parrot_str_free_cstring(sname);
RETURN(PMC *result);
}
/*
=item C<PMC *version()>
Returns an array containing the two bytecode version numbers (bc_major, bc_minor)
of the library.
=cut
*/
METHOD version() :no_wb {
const op_lib_t *oplib;
PMC * const version_array = Parrot_pmc_new_init_int(INTERP,
enum_class_FixedIntegerArray, 2);
GET_ATTR_oplib(INTERP, SELF, oplib);
VTABLE_set_integer_keyed_int(INTERP, version_array,
0, oplib->bc_major_version);
VTABLE_set_integer_keyed_int(INTERP, version_array,
1, oplib->bc_minor_version);
RETURN(PMC *version_array);
}
}
/*
=back
=head1 SEE ALSO
F<src/pmc/opcode.pmc>
=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.