Author: jonathan
Date: Fri Jun 8 06:37:48 2007
New Revision: 18876
Modified:
trunk/include/parrot/pmc.h
trunk/src/pmc/pmcproxy.pmc
trunk/t/pmc/pmcproxy.t
Log:
[PDD17] Fill in most of the methods of the PMCProxy PMC. Add a methods slot
where we'll eventually hang a hash of methods in the PMC, so they can be
introspected. Add a test to test inspecting the name and namespace of the PMC
through PMCProxy.
Modified: trunk/include/parrot/pmc.h
==============================================================================
--- trunk/include/parrot/pmc.h (original)
+++ trunk/include/parrot/pmc.h Fri Jun 8 06:37:48 2007
@@ -68,6 +68,7 @@
PMC *_namespace; /* The namespace it's linked to, if any. */
PMC *parents; /* Proxy PMCs of any immediate parent classes. */
PMC *all_parents; /* Cached list of ourself and all parents, in MRO
order. */
+ PMC *methods; /* PMC's non-vtable methods. Hash of method names to
invokables. */
} Parrot_PMCProxy;
/* Macro to access underlying structure of a PMCProxy PMC. */
Modified: trunk/src/pmc/pmcproxy.pmc
==============================================================================
--- trunk/src/pmc/pmcproxy.pmc (original)
+++ trunk/src/pmc/pmcproxy.pmc Fri Jun 8 06:37:48 2007
@@ -134,6 +134,191 @@
pobject_lives(interp, (PObj*)_pmc->all_parents);
}
+/*
+
+=item C<PMC* inspect_str(STRING *what)>
+
+Provides introspection of a specific piece of information about the PMC. The
+available information is:
+
+=over 8
+
+=item name
+
+String PMC containing the name of the PMC
+
+=item namespce
+
+NameSpace PMC of the the namespace attached to the PMC
+
+=item methods
+
+Hash keyed on method name, value is an invokable PMC
+
+=item parents
+
+Array of PMCProxy PMCs representing the direct parents of this class.
+
+=back
+
+=cut
+
+*/
+ PMC* inspect_str(STRING *what)
+ {
+ Parrot_PMCProxy *_pmc = PARROT_PMCPROXY(SELF);
+
+ /* What should we return? */
+ PMC *found = PMCNULL;
+
+ if (string_equal(interp, what, CONST_STRING(interp, "name")) == 0) {
+ found = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, found, _pmc->name);
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "namespace"))
== 0) {
+ /* Should not clone this. */
+ return _pmc->_namespace;
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "methods"))
== 0) {
+ found = _pmc->methods;
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "parents"))
== 0) {
+ found = _pmc->parents;
+ }
+ else {
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "Unknown introspection value '%S'", what);
+ }
+
+ /* Clone and return. */
+ return PMC_IS_NULL(found) ? PMCNULL : VTABLE_clone(interp, found);
+ }
+
+/*
+
+=item C<PMC* inspect()>
+
+Returns a Hash describing the PMC, with key/value pairs as described in
+inspect_str.
+
+=cut
+
+*/
+ PMC* inspect()
+ {
+ /* Create a hash, then use inspect_str to get all of the data to
+ * fill it up with. */
+ PMC *metadata = pmc_new(interp, enum_class_Hash);
+ VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp,
"name"),
+ VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "name")));
+ VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp,
"namespace"),
+ VTABLE_inspect_str(interp, SELF, CONST_STRING(interp,
"namespace")));
+ VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp,
"methods"),
+ VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "methods")));
+ VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp,
"parents"),
+ VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "parents")));
+ return metadata;
+ }
+
+/*
+
+=item C<STRING* name()>
+
+Gets the name of the PMC.
+
+=cut
+
+*/
+ PCCMETHOD void name() {
+ Parrot_PMCProxy *_pmc = PARROT_PMCPROXY(SELF);
+ STRING *ret_name = _pmc->name;
+ PCCRETURN(STRING *ret_name);
+ }
+
+/*
+
+=item C<void pmc_namespace()>
+
+Gets the namespace that this class is attached to.
+
+=cut
+
+*/
+ PCCMETHOD void pmc_namespace() {
+ Parrot_PMCProxy *_pmc = PARROT_PMCPROXY(SELF);
+ PMC *ret_namespace = _pmc->_namespace;
+ PCCRETURN(PMC *ret_namespace);
+ }
+
+/*
+
+=item C<void new(PMC *args)>
+
+Creates an instance of the PMC.
+
+=cut
+
+*/
+ PCCMETHOD void new(PMC *args :optional, int got_args :opt_flag) {
+ Parrot_PMCProxy *_pmc = PARROT_PMCPROXY(SELF);
+ PMC *created;
+ if (got_args)
+ created = pmc_new_init(interp, _pmc->id, args);
+ else
+ created = pmc_new(interp, _pmc->id);
+ PCCRETURN(PMC *created);
+ }
+
+/*
+
+=item C<void methods()>
+
+Return a hash where the keys are method names and the values are methods.
+
+=cut
+
+*/
+ PCCMETHOD void methods() {
+ PMC *ret_methods = VTABLE_inspect_str(interp, SELF,
CONST_STRING(interp, "methods"));
+ PCCRETURN(PMC *ret_methods);
+ }
+
+/*
+
+=item C<void parents()>
+
+Return the parents array PMC.
+
+=cut
+
+*/
+ PCCMETHOD void parents() {
+ PMC *ret_parents = VTABLE_inspect_str(interp, SELF,
CONST_STRING(interp, "parents"));
+ PCCRETURN(PMC *ret_parents);
+ }
+
+/*
+
+=item C<void inspect(STRING *what :optional)>
+
+Gets all introspection data for the PMC or, if the optional string
+parameter is supplied, a particular item of introspection data.
+
+=cut
+
+*/
+ PCCMETHOD void inspect(STRING *what :optional, int got_what :opt_flag) {
+ PMC *found;
+
+ /* Just delegate to the appropriate vtable method. */
+ if (got_what)
+ found = VTABLE_inspect_str(interp, SELF, what);
+ else
+ found = VTABLE_inspect(interp, SELF);
+
+ PCCRETURN(PMC *found);
+ }
+
} /* END pmclass */
/*
Modified: trunk/t/pmc/pmcproxy.t
==============================================================================
--- trunk/t/pmc/pmcproxy.t (original)
+++ trunk/t/pmc/pmcproxy.t Fri Jun 8 06:37:48 2007
@@ -6,7 +6,7 @@
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 2;
+use Parrot::Test tests => 3;
=head1 NAME
@@ -60,6 +60,36 @@
ok 2 - isa $P0, 'PMCProxy'
OUT
+pir_output_is( <<'CODE', <<'OUT', 'Proxy PMC supplies name, namespace' );
+.sub 'test' :main
+push_eh nok_1
+ $P0 = get_class 'NameSpace'
+ clear_eh
+ goto ok_1
+nok_1:
+ print "not "
+ok_1:
+ print "ok 1 - get_class returned something\n"
+
+ $S1 = $P0.'name'()
+ print $S1
+ print "\n"
+ print "ok 2 - got name\n"
+
+ $P1 = $P0.'pmc_namespace'()
+ $S1 = $P1
+ print $S1
+ print "\n"
+ print "ok 3 - got namespace\n"
+.end
+CODE
+ok 1 - get_class returned something
+NameSpace
+ok 2 - got name
+NameSpace
+ok 3 - got namespace
+OUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4