Author: particle
Date: Tue May 1 16:41:53 2007
New Revision: 18382
Modified:
trunk/src/pmc/namespace.pmc
trunk/t/pmc/namespace.t
Changes in other areas also in this revision:
Modified:
trunk/docs/pdds/pdd21_namespaces.pod
Log:
[pmc]: added functionality to NameSpace PMC 'export_to' method
~ can now accept a hash argument, which allows an object to be exported with a
different name
~ updated spec, implementation, and tests
Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Tue May 1 16:41:53 2007
@@ -593,35 +593,101 @@
=item C<METHOD void export_to(PMC* dest, PMC* what)>
-Export items from this NameSpace into the C<dest> NameSpace. C<what>
-is an array of (string) names to be exported.
+Export items from this NameSpace into the C<dest> NameSpace. The items to
+export are named in C<what>, which may be an array of strings, a hash, or null.
+If C<what> is an array of strings, interpretation of items in an array follows
+the conventions of the source (exporting) namespace.
+If C<what> is a hash, the keys correspond to the names in the source namespace,
+and the values correspond to the names in the destination namespace.
+if a hash value is null or an empty string, the name in the hash key is used.
+A null C<what> requests the 'default' set of items.
+Any other type passed in C<what> throws an exception.
+
+NOTE: exporting 'default' set of items is not yet implemented.
=cut
*/
METHOD void export_to(PMC* dest, PMC* what) {
- INTVAL i, n;
+ STRING *s_hash = CONST_STRING(interp, "hash");
+ STRING *s_array = CONST_STRING(interp, "array");
if (PMC_IS_NULL(dest)) {
real_exception(interp, NULL, 0,
"destination namespace not specified");
return;
}
+
if (PMC_IS_NULL(what) || !VTABLE_elements(interp, what)) {
real_exception(interp, NULL, 0,
- "exporting default object set not yet specified");
+ "exporting default object set not yet implemented");
return;
}
- n = VTABLE_elements(INTERP, what);
- for (i = 0; i < n; ++i) {
- STRING *name;
- PMC *el;
-
- name = VTABLE_get_string_keyed_int(INTERP, what, i);
- el = VTABLE_get_pmc_keyed_str(INTERP, SELF, name);
- VTABLE_set_pmc_keyed_str(INTERP, dest, name, el);
+ /* if "what" does "hash", we extract string key/value pairs,
+ * lookup the object with the name specified in the key,
+ * and export it with the name specified as value. */
+ if (VTABLE_does(INTERP, what, s_hash)) {
+ PMC * const iter = VTABLE_get_iter(interp, what);
+ const INTVAL n = VTABLE_elements(interp, what);
+ INTVAL i;
+
+ for (i = 0; i < n; ++i) {
+ STRING *src_name;
+ STRING *dest_name;
+ PMC *object;
+
+ src_name = VTABLE_shift_string(interp, iter);
+ if (STRING_IS_NULL(src_name) || STRING_IS_EMPTY(src_name)) {
+ real_exception(interp, NULL, 0, "source object name not
specified");
+ return;
+ }
+
+ dest_name = VTABLE_get_string_keyed_str(interp, what,
src_name);
+ if (STRING_IS_NULL(dest_name) || STRING_IS_EMPTY(dest_name)) {
+ dest_name = src_name;
+ }
+
+ object = VTABLE_get_pmc_keyed_str(interp, SELF, src_name);
+ if (PMC_IS_NULL(object)) {
+ real_exception(interp, NULL, 0,
+ "object '%s' not found in current namespace",
+ string_to_cstring(interp, src_name));
+ return;
+ }
+
+ VTABLE_set_pmc_keyed_str(interp, dest, dest_name, object);
+ }
+ }
+ else if (VTABLE_does(INTERP, what, s_array)) {
+ const INTVAL n = VTABLE_elements(interp, what);
+ INTVAL i;
+
+ for (i = 0; i < n; ++i) {
+ STRING *name;
+ PMC *object;
+
+ name = VTABLE_get_string_keyed_int(interp, what, i);
+ if (STRING_IS_NULL(name) || STRING_IS_EMPTY(name)) {
+ real_exception(interp, NULL, 0, "object name not
specified");
+ return;
+ }
+
+ object = VTABLE_get_pmc_keyed_str(interp, SELF, name);
+ if (PMC_IS_NULL(object)) {
+ real_exception(interp, NULL, 0,
+ "object '%s' not found in current namespace",
+ string_to_cstring(interp, name));
+ return;
+ }
+
+ VTABLE_set_pmc_keyed_str(interp, dest, name, object);
+ }
+ }
+ else {
+ real_exception(interp, NULL, 0,
+ "can't handle argument of type %s",
what->vtable->base_type);
}
}
Modified: trunk/t/pmc/namespace.t
==============================================================================
--- trunk/t/pmc/namespace.t (original)
+++ trunk/t/pmc/namespace.t Tue May 1 16:41:53 2007
@@ -6,7 +6,7 @@
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 56;
+use Parrot::Test tests => 59;
use Parrot::Config;
=head1 NAME
@@ -703,7 +703,7 @@
OUTPUT
pir_output_like(
- <<'CODE', <<'OUTPUT', 'export_to() with null array exports default boject
set !!!UNSPECIFIED!!!' );
+ <<'CODE', <<'OUTPUT', 'export_to() with null exports default object set
!!!UNSPECIFIED!!!' );
.sub 'test' :main
.local pmc nsa, nsb, ar
@@ -717,11 +717,11 @@
.sub 'foo'
.end
CODE
-/^exporting default object set not yet specified\n/
+/^exporting default object set not yet implemented\n/
OUTPUT
pir_output_like(
- <<'CODE', <<'OUTPUT', 'export_to() with empty array exports default boject
set !!!UNSPECIFIED!!!' );
+ <<'CODE', <<'OUTPUT', 'export_to() with empty array exports default object
set !!!UNSPECIFIED!!!' );
.sub 'test' :main
.local pmc nsa, nsb, ar
@@ -735,10 +735,28 @@
.sub 'foo'
.end
CODE
-/^exporting default object set not yet specified\n/
+/^exporting default object set not yet implemented\n/
OUTPUT
-pir_output_is( <<"CODE", <<'OUTPUT', "export_to -- success" );
+pir_output_like(
+ <<'CODE', <<'OUTPUT', 'export_to() with empty hash exports default object
set !!!UNSPECIFIED!!!' );
+.sub 'test' :main
+ .local pmc nsa, nsb, ar
+
+ ar = new .Hash
+ nsa = get_namespace
+ nsb = get_namespace ['B']
+ nsb.'export_to'(nsa, ar)
+.end
+
+.namespace ['B']
+.sub 'foo'
+.end
+CODE
+/^exporting default object set not yet implemented\n/
+OUTPUT
+
+pir_output_is( <<"CODE", <<'OUTPUT', "export_to -- success with array" );
.HLL 'A', ''
.sub main :main
a_foo()
@@ -761,6 +779,54 @@
b_foo
OUTPUT
+pir_output_is( <<"CODE", <<'OUTPUT', "export_to -- success with hash (empty
value)" );
+.HLL 'A', ''
+.sub main :main
+ a_foo()
+ load_bytecode "$temp_b.pir"
+ .local pmc nsr, nsa, nsb, ar
+ ar = new .Hash
+ ar["b_foo"] = ""
+ nsr = get_root_namespace
+ nsa = nsr['a']
+ nsb = nsr['b']
+ nsb."export_to"(nsa, ar)
+ b_foo()
+.end
+
+.sub a_foo
+ print "a_foo\\n"
+.end
+CODE
+a_foo
+b_foo
+OUTPUT
+
+pir_output_like( <<"CODE", <<'OUTPUT', "export_to -- success with hash (and
value)" );
+.HLL 'A', ''
+.sub main :main
+ a_foo()
+ load_bytecode "$temp_b.pir"
+ .local pmc nsr, nsa, nsb, ar
+ ar = new .Hash
+ ar["b_foo"] = "c_foo"
+ nsr = get_root_namespace
+ nsa = nsr['a']
+ nsb = nsr['b']
+ nsb."export_to"(nsa, ar)
+ c_foo()
+ b_foo()
+.end
+
+.sub a_foo
+ print "a_foo\\n"
+.end
+CODE
+/^a_foo
+b_foo
+Null PMC access in invoke\(\)/
+OUTPUT
+
pir_output_is( <<'CODE', <<'OUTPUT', "get_parent" );
.sub main :main
.local pmc ns