cvsuser 03/07/04 05:08:50
Modified: . MANIFEST MANIFEST.detailed embed.c
Added: classes sarray.pmc
t/pmc sarray.t
Log:
sarray.pmc, tests, use it for argv
Revision Changes Path
1.363 +11 -9 parrot/MANIFEST
Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.362
retrieving revision 1.363
diff -u -w -r1.362 -r1.363
--- MANIFEST 3 Jul 2003 10:16:00 -0000 1.362
+++ MANIFEST 4 Jul 2003 12:08:47 -0000 1.363
@@ -50,6 +50,7 @@
classes/perlundef.pmc
classes/pmc2c.pl
classes/pointer.pmc
+classes/sarray.pmc
classes/scalar.pmc
classes/scratchpad.pmc
classes/sub.pmc
@@ -1337,15 +1338,15 @@
languages/BASIC/compiler/COMP_parsefuncs.pm
languages/BASIC/compiler/COMP_parser.pm
languages/BASIC/compiler/COMP_toker.pm
-languages/BASIC/compiler/RT_aggregates.pasm
-languages/BASIC/compiler/RT_builtins.pasm
-languages/BASIC/compiler/RT_debugger.pasm
-languages/BASIC/compiler/RT_initialize.pasm
-languages/BASIC/compiler/RT_io.pasm
-languages/BASIC/compiler/RT_platform.pasm
-languages/BASIC/compiler/RT_platform_ANSIscreen.pasm
-languages/BASIC/compiler/RT_platform_win32.pasm
-languages/BASIC/compiler/RT_support.pasm
+languages/BASIC/compiler/RT_aggregates.imc
+languages/BASIC/compiler/RT_builtins.imc
+languages/BASIC/compiler/RT_debugger.imc
+languages/BASIC/compiler/RT_initialize.imc
+languages/BASIC/compiler/RT_io.imc
+languages/BASIC/compiler/RT_platform.imc
+languages/BASIC/compiler/RT_platform_ANSIscreen.imc
+languages/BASIC/compiler/RT_platform_win32.imc
+languages/BASIC/compiler/RT_support.imc
languages/BASIC/compiler/compile.pl
languages/BASIC/compiler/readme.bas
languages/BASIC/compiler/samples/conn4.bas
@@ -1846,6 +1847,7 @@
t/pmc/perlstring.t
t/pmc/pmc.t
t/pmc/prop.t
+t/pmc/sarray.t
t/pmc/scratchpad.t
t/pmc/sub.t
t/src/basic.t
1.35 +11 -9 parrot/MANIFEST.detailed
Index: MANIFEST.detailed
===================================================================
RCS file: /cvs/public/parrot/MANIFEST.detailed,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -w -r1.34 -r1.35
--- MANIFEST.detailed 3 Jul 2003 15:09:54 -0000 1.34
+++ MANIFEST.detailed 4 Jul 2003 12:08:47 -0000 1.35
@@ -49,6 +49,7 @@
[] classes/perlundef.pmc
[] classes/pmc2c.pl
[] classes/pointer.pmc
+[] classes/sarray.pmc
[] classes/scalar.pmc
[] classes/scratchpad.pmc
[] classes/sub.pmc
@@ -1336,15 +1337,15 @@
[BASIC] languages/BASIC/compiler/COMP_parsefuncs.pm
[BASIC] languages/BASIC/compiler/COMP_parser.pm
[BASIC] languages/BASIC/compiler/COMP_toker.pm
-[BASIC] languages/BASIC/compiler/RT_aggregates.pasm
-[BASIC] languages/BASIC/compiler/RT_builtins.pasm
-[BASIC] languages/BASIC/compiler/RT_debugger.pasm
-[BASIC] languages/BASIC/compiler/RT_initialize.pasm
-[BASIC] languages/BASIC/compiler/RT_io.pasm
-[BASIC] languages/BASIC/compiler/RT_platform.pasm
-[BASIC] languages/BASIC/compiler/RT_platform_ANSIscreen.pasm
-[BASIC] languages/BASIC/compiler/RT_platform_win32.pasm
-[BASIC] languages/BASIC/compiler/RT_support.pasm
+[BASIC] languages/BASIC/compiler/RT_aggregates.imc
+[BASIC] languages/BASIC/compiler/RT_builtins.imc
+[BASIC] languages/BASIC/compiler/RT_debugger.imc
+[BASIC] languages/BASIC/compiler/RT_initialize.imc
+[BASIC] languages/BASIC/compiler/RT_io.imc
+[BASIC] languages/BASIC/compiler/RT_platform.imc
+[BASIC] languages/BASIC/compiler/RT_platform_ANSIscreen.imc
+[BASIC] languages/BASIC/compiler/RT_platform_win32.imc
+[BASIC] languages/BASIC/compiler/RT_support.imc
[BASIC] languages/BASIC/compiler/compile.pl
[BASIC] languages/BASIC/compiler/readme.bas
[BASIC] languages/BASIC/compiler/samples/conn4.bas
@@ -1845,6 +1846,7 @@
[] t/pmc/perlstring.t
[] t/pmc/pmc.t
[] t/pmc/prop.t
+[] t/pmc/sarray.t
[] t/pmc/scratchpad.t
[] t/pmc/sub.t
[] t/src/basic.t
1.72 +5 -4 parrot/embed.c
Index: embed.c
===================================================================
RCS file: /cvs/public/parrot/embed.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -w -r1.71 -r1.72
--- embed.c 2 Jul 2003 13:37:36 -0000 1.71
+++ embed.c 4 Jul 2003 12:08:47 -0000 1.72
@@ -1,7 +1,7 @@
/* embed.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: embed.c,v 1.71 2003/07/02 13:37:36 leo Exp $
+ * $Id: embed.c,v 1.72 2003/07/04 12:08:47 leo Exp $
* Overview:
* The Parrot embedding interface.
* Data Structure and Algorithms:
@@ -269,10 +269,11 @@
argc);
}
- userargv = pmc_new_noinit(interpreter, enum_class_PerlArray);
+ userargv = pmc_new_noinit(interpreter, enum_class_SArray);
/* immediately anchor pmc to root set */
interpreter->pmc_reg.registers[0] = userargv;
VTABLE_init(interpreter, userargv);
+ VTABLE_set_integer_native(interpreter, userargv, argc);
for (i = 0; i < argc; i++) {
/* Run through argv, adding everything to @ARGS. */
1.1 parrot/classes/sarray.pmc
Index: sarray.pmc
===================================================================
/* sarray.pmc
* Copyright: (When this is determined...it will go here)
* CVS Info
* $Id: sarray.pmc,v 1.1 2003/07/04 12:08:49 leo Exp $
* Overview:
* These are the vtable functions for the SArray base class
* Data Structure and Algorithms:
* SArray data are kept in an malloced array of HASH_ENTRY's
* entry 0 = start_idx (for shift)
* entry 1 = end_idx (for push)
* entry 2... data
* History:
* Initial version 2003.07.04 by leo
* Notes:
* This is the Simple (or Static) Array class for parameter
* passing according to pdd03.
* - SArrays are fixed size, implying:
* - The first operation on it must be setting its size.
* - only the most important vtable meths are implemented
* References:
* docs/pdds/pdd03_calling_conventions.pod
*/
#include "parrot/parrot.h"
pmclass SArray {
void init () {
SELF->cache.int_val = 0;
}
void mark () {
HASH_ENTRY *e;
int i, start, end;
if (!PMC_data(SELF))
return;
e = (HASH_ENTRY *) PMC_data(SELF);
start = e[0].val.int_val;
end = e[1].val.int_val;
for (i = start; i < end; i++) {
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + i);
switch (e->type) {
case enum_hash_string:
pobject_lives(INTERP, (PObj *)e->val.string_val);
break;
case enum_hash_pmc:
pobject_lives(INTERP, (PObj *)e->val.pmc_val);
break;
default:
break;
}
}
}
void destroy () {
free(PMC_data(SELF));
PMC_data(SELF) = NULL;
}
STRING* name() {
return whoami;
}
void clone (PMC *dest) {
HASH_ENTRY *e, *d;
int i, start, end;
INTVAL size;
PMC * np;
if (!PMC_data(SELF))
return;
size = SELF->cache.int_val;
dest->cache.int_val = size;
PMC_data(dest) = mem_sys_allocate_zeroed((2 + size) *
sizeof(HASH_ENTRY));
e = (HASH_ENTRY *) PMC_data(SELF);
d = (HASH_ENTRY *) PMC_data(dest);
start = e[0].val.int_val;
end = e[1].val.int_val;
d[0].val.int_val = start;
d[1].val.int_val = end;
for (i = start; i < end; i++) {
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + i);
d = (HASH_ENTRY *) PMC_data(dest) + (2 + i);
d->type = e->type;
switch (e->type) {
case enum_hash_int:
d->val.int_val = e->val.int_val;
break;
case enum_hash_num:
d->val.num_val = e->val.num_val;
break;
case enum_hash_string:
d->val.string_val = string_copy(INTERP, e->val.string_val);
break;
case enum_hash_pmc:
np = pmc_new_noinit(interpreter,
e->val.pmc_val->vtable->base_type);
d->val.pmc_val = np;
VTABLE_clone(INTERP, e->val.pmc_val, np);
break;
default:
break;
}
}
PObj_custom_mark_destroy_SETALL(dest);
}
INTVAL get_bool () {
INTVAL size = DYNSELF.elements();
return (INTVAL)(size != 0);
}
INTVAL elements () {
HASH_ENTRY *e;
if (!PMC_data(SELF))
return 0;
e = (HASH_ENTRY *) PMC_data(SELF);
return e[1].val.int_val - e[0].val.int_val;
}
INTVAL get_integer () {
return DYNSELF.elements();
}
INTVAL get_integer_keyed_int (INTVAL* key) {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (*key < 0) {
*key += e[1].val.int_val;
}
if (*key < e[0].val.int_val || *key >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
if (e->type != enum_hash_int)
internal_exception(OUT_OF_BOUNDS, "SArray: Not an integer!\n");
return e->val.int_val;
}
INTVAL shift_integer() {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (e[0].val.int_val >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + e[0].val.int_val++);
if (e->type != enum_hash_int)
internal_exception(OUT_OF_BOUNDS, "SArray: Not an integer!\n");
return e->val.int_val;
}
FLOATVAL get_number_keyed_int (INTVAL* key) {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (*key < 0) {
*key += e[1].val.int_val;
}
if (*key < e[0].val.int_val || *key >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
if (e->type != enum_hash_num)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a num!\n");
return e->val.num_val;
}
FLOATVAL shift_float() {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (e[0].val.int_val >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + e[0].val.int_val++);
if (e->type != enum_hash_num)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a num!\n");
return e->val.num_val;
}
STRING* get_string_keyed_int (INTVAL* key) {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (*key < 0) {
*key += e[1].val.int_val;
}
if (*key < e[0].val.int_val || *key >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
if (e->type != enum_hash_string)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a string!\n");
return e->val.string_val;
}
STRING* shift_string() {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (e[0].val.int_val >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + e[0].val.int_val++);
if (e->type != enum_hash_string)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a string!\n");
return e->val.string_val;
}
PMC* get_pmc_keyed_int (INTVAL* key) {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (*key < 0) {
*key += e[1].val.int_val;
}
if (*key < e[0].val.int_val || *key >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
if (e->type != enum_hash_pmc)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a pmc!\n");
return e->val.pmc_val;
}
PMC* shift_pmc() {
HASH_ENTRY *e = (HASH_ENTRY *) PMC_data(SELF);
if (e[0].val.int_val >= e[1].val.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + e[0].val.int_val++);
if (e->type != enum_hash_pmc)
internal_exception(OUT_OF_BOUNDS, "SArray: Not a pmc!\n");
return e->val.pmc_val;
}
void set_integer (PMC* value) {
INTVAL size = VTABLE_get_integer(INTERP,value);
SELF.set_integer_native(size);
}
void set_integer_native (INTVAL size) {
if (SELF->cache.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray: Can't resize!\n");
SELF->cache.int_val = size;
PMC_data(SELF) = mem_sys_allocate_zeroed((2 + size) *
sizeof(HASH_ENTRY));
PObj_custom_mark_destroy_SETALL(SELF);
}
void set_integer_keyed_int (INTVAL* key, INTVAL value) {
HASH_ENTRY *e;
if (*key < 0 || *key >= SELF->cache.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
e->type = enum_hash_int;
e->val.int_val = value;
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
if (*key >= e->val.int_val)
e->val.int_val = *key + 1;
}
void push_integer (INTVAL value) {
HASH_ENTRY *e;
INTVAL nextix;
if (!PMC_data(SELF))
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
nextix = e->val.int_val;
DYNSELF.set_integer_keyed_int(&nextix, value);
}
void set_number_keyed_int (INTVAL* key, FLOATVAL value) {
HASH_ENTRY *e;
if (*key < 0 || *key >= SELF->cache.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
e->type = enum_hash_num;
e->val.num_val = value;
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
if (*key >= e->val.int_val)
e->val.int_val = *key + 1;
}
void push_float (FLOATVAL value) {
HASH_ENTRY *e;
INTVAL nextix;
if (!PMC_data(SELF))
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
nextix = e->val.int_val;
DYNSELF.set_number_keyed_int(&nextix, value);
}
void set_string_keyed_int (INTVAL* key, STRING* value) {
HASH_ENTRY *e;
if (*key < 0 || *key >= SELF->cache.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
e->type = enum_hash_string;
e->val.string_val = value;
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
if (*key >= e->val.int_val)
e->val.int_val = *key + 1;
}
void push_string (STRING* value) {
HASH_ENTRY *e;
INTVAL nextix;
if (!PMC_data(SELF))
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
nextix = e->val.int_val;
DYNSELF.set_string_keyed_int(&nextix, value);
}
void set_pmc_keyed_int (INTVAL* key, PMC* src, INTVAL* src_key) {
HASH_ENTRY *e;
if (*key < 0 || *key >= SELF->cache.int_val)
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + (2 + *key);
e->type = enum_hash_pmc;
if (src_key)
src = VTABLE_get_pmc_keyed_int(INTERP, src, src_key);
e->val.pmc_val = src;
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
if (*key >= e->val.int_val)
e->val.int_val = *key + 1;
}
void push_pmc (PMC* value) {
HASH_ENTRY *e;
INTVAL nextix;
if (!PMC_data(SELF))
internal_exception(OUT_OF_BOUNDS, "SArray index out of bounds!\n");
e = (HASH_ENTRY *) PMC_data(SELF) + 1;
nextix = e->val.int_val;
DYNSELF.set_pmc_keyed_int(&nextix, value, NULL);
}
}
1.1 parrot/t/pmc/sarray.t
Index: sarray.t
===================================================================
#! perl -w
use Parrot::Test tests => 10;
use Test::More;
output_is(<<'CODE', <<'OUTPUT', "Setting sarray size");
new P0, .SArray
set I0, P0
eq I0, 0, OK_1
print "not "
OK_1: print "ok 1\n"
set P0, 1
set P0[0], 100
set I0, P0
eq I0, 1, OK_2
print "not "
OK_2: print "ok 2\n"
end
CODE
ok 1
ok 2
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "attempt resize");
new P0, .SArray
set P0, 1
set P0[0], 100
set I0, P0
eq I0, 1, OK_1
print "not "
OK_1: print "ok 1\n"
set P0, 2
end
CODE
ok 1
SArray: Can't resize!
OUTPUT
# '
output_is(<<'CODE', <<'OUTPUT', "indexed access");
new P0, .SArray
set P0, 3
set P0[0], 100
set P0[1], 200
set P0[2], 300
set I0, P0[0]
eq I0, 100, ok1
print "not "
ok1: print "ok 1\n"
set I0, P0[1]
eq I0, 200, ok2
print "not "
ok2: print "ok 2\n"
set I0, P0[2]
eq I0, 300, ok3
print "not "
ok3: print "ok 3\n"
set I0, P0[-1]
eq I0, 300, ok4
print "not "
ok4: print "ok 4\n"
set I0, P0[-2]
eq I0, 200, ok5
print "not "
ok5: print "ok 5\n"
set I0, P0[-3]
eq I0, 100, ok6
print "not "
ok6: print "ok 6\n"
end
CODE
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "push");
new P0, .SArray
set P0, 3
push P0, 100
push P0, 200
push P0, 300
set I0, P0[0]
eq I0, 100, ok1
print "not "
ok1: print "ok 1\n"
set I0, P0[1]
eq I0, 200, ok2
print "not "
ok2: print "ok 2\n"
set I0, P0[2]
eq I0, 300, ok3
print "not "
ok3: print "ok 3\n"
set I0, P0[-1]
eq I0, 300, ok4
print "not "
ok4: print "ok 4\n"
set I0, P0[-2]
eq I0, 200, ok5
print "not "
ok5: print "ok 5\n"
set I0, P0[-3]
eq I0, 100, ok6
print "not "
ok6: print "ok 6\n"
end
CODE
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "push / indexed");
new P0, .SArray
set P0, 3
push P0, 100
set P0[1], 200
push P0, 300
set I0, P0[0]
eq I0, 100, ok1
print "not "
ok1: print "ok 1\n"
set I0, P0[1]
eq I0, 200, ok2
print "not "
ok2: print "ok 2\n"
set I0, P0[2]
eq I0, 300, ok3
print "not "
ok3: print "ok 3\n"
set I0, P0[-1]
eq I0, 300, ok4
print "not "
ok4: print "ok 4\n"
set I0, P0[-2]
eq I0, 200, ok5
print "not "
ok5: print "ok 5\n"
set I0, P0[-3]
eq I0, 100, ok6
print "not "
ok6: print "ok 6\n"
end
CODE
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "mixed indexed");
new P0, .SArray
set P0, 4
set P0[0], 1000
set N0, 222.22
set P0[1], N0
set S0, "string\n"
set P0[2], S0
new P1, .PerlUndef
set P1, 42
set P0[3], P1
set I0, P0[0]
eq I0, 1000, ok1
print "not "
ok1: print "ok 1\n"
set N1, P0[1]
eq N0, N1, ok2
print "not "
ok2: print "ok 2\n"
set S1, P0[2]
print S1
set P3, P0[3]
print P3
print "\n"
end
CODE
ok 1
ok 2
string
42
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "mixed push");
new P0, .SArray
set P0, 4
push P0, 1000
set N0, 222.22
push P0, N0
set S0, "string\n"
push P0, S0
new P1, .PerlUndef
set P1, 42
push P0, P1
set I0, P0[0]
eq I0, 1000, ok1
print "not "
ok1: print "ok 1\n"
set N1, P0[1]
eq N0, N1, ok2
print "not "
ok2: print "ok 2\n"
set S1, P0[2]
print S1
set P3, P0[3]
print P3
print "\n"
end
CODE
ok 1
ok 2
string
42
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "mixed push - clone");
new P2, .SArray
set P2, 4
push P2, 1000
set N0, 222.22
push P2, N0
set S0, "string\n"
push P2, S0
new P1, .PerlUndef
set P1, 42
push P2, P1
clone P0, P2
set I0, P0[0]
eq I0, 1000, ok1
print "not "
ok1: print "ok 1\n"
set N1, P0[1]
eq N0, N1, ok2
print "not "
ok2: print "ok 2\n"
set S1, P0[2]
print S1
set P3, P0[3]
print P3
print "\n"
end
CODE
ok 1
ok 2
string
42
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "shift_integer");
new P0, .SArray
set P0, 3
set P0[0], 100
set P0[1], 200
set P0[2], 300
shift I0, P0
eq I0, 100, ok1
print "not "
ok1: print "ok 1\n"
set I0, P0
eq I0, 2, ok2
ok2: print "ok 2\n"
shift I0, P0
eq I0, 200, ok3
print "not "
ok3: print "ok 3\n"
set I0, P0
eq I0, 1, ok4
ok4: print "ok 4\n"
shift I0, P0
eq I0, 300, ok5
print "not "
ok5: print "ok 5\n"
set I0, P0
eq I0, 0, ok6
ok6: print "ok 6\n"
end
CODE
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
OUTPUT
output_is(<<'CODE', <<'OUTPUT', "mixed shift");
new P0, .SArray
set P0, 4
push P0, 1000
set N0, 222.22
push P0, N0
set S0, "string\n"
push P0, S0
new P1, .PerlUndef
set P1, 42
push P0, P1
shift I0, P0
eq I0, 1000, ok1
print "not "
ok1: print "ok 1\n"
shift N1, P0
eq N0, N1, ok2
print "not "
ok2: print "ok 2\n"
shift S1, P0
print S1
shift P3, P0
print P3
print "\n"
end
CODE
ok 1
ok 2
string
42
OUTPUT