Index: ops/var.ops
===================================================================
RCS file: /cvs/public/parrot/ops/var.ops,v
retrieving revision 1.20
diff -u -r1.20 var.ops
--- ops/var.ops	5 Jul 2004 13:49:30 -0000	1.20
+++ ops/var.ops	1 Aug 2004 16:09:33 -0000
@@ -352,6 +352,76 @@
     goto ADDRESS(next);
 }
 
+=item B<find_or_create_global>(out PMC, in STR)
+
+Find the global named $2 and store it in $1. If the global doesn't
+exist, it is created and set to undef.
+
+=item B<find_global>(out PMC, in STR, in STR)
+
+Find the global named $3 in namespace $2 and store it in $1. If the
+global doesn't exist, it is created and set to undef.
+
+=item B<find_global>(out PMC, in PMC, in STR)
+
+Find the global named $3 in the namespace specified by the key in $2
+and store it in $1. If the global doesn't exist, it is created and set
+to undef.
+
+=cut
+
+op find_or_create_global(out PMC, in STR) {
+    opcode_t * next;
+    if (!$2)
+	internal_exception(1, "Tried to get null global.");
+
+    next = expr NEXT();
+    $1 = Parrot_get_or_create_global(interpreter, NULL, $2, next);
+    goto ADDRESS(next);
+}
+
+op find_or_create_global(out PMC, in STR, in STR) {
+    opcode_t * next;
+    if (!$2)
+	internal_exception(1, "Tried to get null class.");
+    if (!$3)
+	internal_exception(1, "Tried to get null global.");
+
+    next = expr NEXT();
+    $1 = Parrot_get_or_create_global(interpreter, $2, $3, next);
+    goto ADDRESS(next);
+}
+
+op find_or_create_global(out PMC, in PMC, in STR) {
+    /* XXX: All globals should go through an API */
+    opcode_t * next;
+    PMC * globals = interpreter->globals->stash_hash;
+    PMC * stash = NULL; /* -O unit warn */
+    PMC * value = NULL;
+    if (!$2)
+	internal_exception(1, "Tried to get null global.");
+    if (!$3)
+	internal_exception(1, "Tried to get null global.");
+
+    next = expr NEXT();
+    if (!VTABLE_exists_keyed(interpreter, globals, $2)) {
+	stash = pmc_new(interpreter, enum_class_PerlUndef);
+	VTABLE_set_pmc_keyed(interpreter, globals, $2, stash);
+    }
+    else {
+	stash = VTABLE_get_pmc_keyed(interpreter, globals, $2);
+    }
+    if (!VTABLE_exists_keyed_str(interpreter, stash, $3)) {
+	value = pmc_new(interpreter, enum_class_PerlUndef);
+	VTABLE_set_pmc_keyed_str(interpreter,stash,$3,value);
+	$1 = value;
+    }
+    else {
+	$1 = VTABLE_get_pmc_keyed_str(interpreter, stash, $3);
+    }
+    goto ADDRESS(next);
+}
+
 =back
 
 =cut
Index: include/parrot/global.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/global.h,v
retrieving revision 1.3
diff -u -r1.3 global.h
--- include/parrot/global.h	5 Jul 2004 13:49:27 -0000	1.3
+++ include/parrot/global.h	1 Aug 2004 16:09:33 -0000
@@ -15,6 +15,8 @@
 
 PMC *Parrot_find_global(Interp *, STRING *class, STRING *name);
 PMC *Parrot_get_global(Interp *, STRING *class,  STRING *name, void *next);
+PMC *Parrot_get_or_create_global(Interp *, STRING *class,
+                                 STRING *name, void *next);
 PMC *Parrot_global_namespace(Interp *, PMC *globals, STRING *ns);
 void Parrot_store_global(Interp *, STRING *class, STRING *globalname, PMC *pmc);
 
Index: src/global.c
===================================================================
RCS file: /cvs/public/parrot/src/global.c,v
retrieving revision 1.3
diff -u -r1.3 global.c
--- src/global.c	5 Jul 2004 13:49:33 -0000	1.3
+++ src/global.c	1 Aug 2004 16:09:34 -0000
@@ -112,6 +112,18 @@
     return pmc_new(interpreter, enum_class_Undef);
 }
 
+PMC *
+Parrot_get_or_create_global(Parrot_Interp interpreter, STRING *class,
+        STRING *name, void *next)
+{
+    PMC *g = Parrot_find_global(interpreter, class, name);
+    if (g)
+        return g;
+    g = pmc_new(interpreter, enum_class_Undef);
+    Parrot_store_global(interpreter, class, name, g);
+    return g;
+}
+
 /*
 
 =item C<PMC* Parrot_global_namespace(Interp *, PMC *globals, STRING *ns)>
Index: t/op/globals.t
===================================================================
RCS file: /cvs/public/parrot/t/op/globals.t,v
retrieving revision 1.8
diff -u -r1.8 globals.t
--- t/op/globals.t	8 Mar 2004 00:19:58 -0000	1.8
+++ t/op/globals.t	1 Aug 2004 16:09:34 -0000
@@ -12,11 +12,12 @@
 
 =head1 DESCRIPTION
 
-Tests the C<store_global> and C<find_global> operations.
+Tests the C<store_global>, C<find_global>, and C<find_or_create_global>
+operations.
 
 =cut
 
-use Parrot::Test tests => 3;
+use Parrot::Test tests => 4;
 
 output_is(<<'CODE', '12', "Fetch and store");
 	new P0, .PerlInt
@@ -53,3 +54,18 @@
 ok 2
 OUT
 
+output_is(<<'CODE', <<OUT, "Create new global");
+	new P1, .Integer
+	assign P1, 23
+	find_or_create_global P2, "st0r3"
+	setref P2, P1
+
+	find_global P3, "st0r3"
+	deref P4, P3
+
+	print P4
+	print "\n"
+	end
+CODE
+23
+OUT
