2 # Copyright (C) 2001-2009, Parrot Foundation.
7 use lib qw( . lib ../lib ../../lib );
10 use Parrot::Test::Util 'create_tempfile';
19 t/src/extend.t - Parrot Extension API
23 % prove t/src/extend.t
27 Tests the extension API.
31 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_intreg' );
34 #include "parrot/embed.h"
35 #include "parrot/extend.h"
38 main(int argc, char* argv[]) {
39 Parrot_Interp interp = Parrot_new(NULL);
40 Parrot_Int parrot_reg = 0;
41 Parrot_Int value = 42;
44 /* Interpreter set-up */
48 Parrot_set_intreg(interp, parrot_reg, value);
49 new_value = Parrot_get_intreg(interp, parrot_reg);
51 printf("%d\n", (int)new_value);
53 Parrot_exit(interp, 0);
61 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_numreg' );
64 #include "parrot/embed.h"
65 #include "parrot/extend.h"
68 main(int argc, char* argv[]) {
69 Parrot_Interp interp = Parrot_new(NULL);
70 Parrot_Int parrot_reg = 1;
71 Parrot_Float value = 2.5;
72 Parrot_Float new_value;
74 /* Interpreter set-up */
78 Parrot_set_numreg(interp, parrot_reg, value);
79 new_value = Parrot_get_numreg(interp, parrot_reg);
81 printf("%.1f\n", (double)new_value);
83 Parrot_exit(interp, 0);
91 c_output_is( <<'CODE', <<'OUTPUT', 'Parrot_new_string' );
94 #include "parrot/embed.h"
95 #include "parrot/extend.h"
98 main(int argc, char* argv[]) {
99 Parrot_Interp interp = Parrot_new(NULL);
100 Parrot_String output;
102 /* Interpreter set-up */
106 output = Parrot_new_string(interp, "Test", 4, "iso-8859-1", 0);
107 Parrot_eprintf(interp, "%S\n", output);
109 Parrot_exit(interp, 0);
117 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_strreg' );
120 #include "parrot/embed.h"
121 #include "parrot/extend.h"
124 main(int argc, char* argv[]) {
125 Parrot_Interp interp = Parrot_new(NULL);
126 Parrot_Int parrot_reg = 2;
127 Parrot_String value, new_value;
129 /* Interpreter set-up */
133 value = Parrot_new_string(interp, "Test", 4, "iso-8859-1", 0);
134 Parrot_set_strreg(interp, parrot_reg, value);
136 new_value = Parrot_get_strreg(interp, parrot_reg);
137 Parrot_eprintf(interp, "%S\n", new_value);
139 Parrot_exit(interp, 0);
147 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_intval' );
150 #include "parrot/embed.h"
151 #include "parrot/extend.h"
154 main(int argc, char* argv[]) {
155 Parrot_Interp interp = Parrot_new(NULL);
156 Parrot_Int value = 101010;
158 Parrot_Int type, new_value;
160 /* Interpreter set-up */
164 type = Parrot_PMC_typenum(interp, "Integer");
165 testpmc = Parrot_PMC_new(interp, type);
167 Parrot_PMC_set_intval(interp, testpmc, value);
168 new_value = Parrot_PMC_get_intval(interp, testpmc);
170 printf("%ld\n", (long)new_value);
172 Parrot_exit(interp, 0);
179 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_intval_intkey' );
182 #include "parrot/parrot.h"
183 #include "parrot/embed.h"
184 #include "parrot/extend.h"
187 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
189 Parrot_Int type = Parrot_PMC_typenum(interp, "ResizablePMCArray");
190 Parrot_PMC array = Parrot_PMC_new(interp, type);
191 Parrot_Int value = 12345;
193 Parrot_Int new_value;
195 Parrot_PMC_set_intval_intkey(interp, array, key, value);
197 new_value = Parrot_PMC_get_intval_intkey(interp, array, key);
199 printf("%ld\n", (long)new_value);
204 main(int argc, char* argv[]) {
205 Parrot_Interp interp = Parrot_new(NULL);
207 /* Interpreter set-up */
211 Parrot_run_native(interp, the_test);
212 Parrot_exit(interp, 0);
219 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_pmcreg' );
222 #include "parrot/embed.h"
223 #include "parrot/extend.h"
226 main(int argc, char* argv[]) {
227 Parrot_Interp interp = Parrot_new(NULL);
228 Parrot_Int value = -123;
229 Parrot_Int parrot_reg = 31;
230 Parrot_Int type, new_value;
231 Parrot_PMC testpmc, newpmc;
233 /* Interpreter set-up */
237 type = Parrot_PMC_typenum(interp, "Integer");
238 testpmc = Parrot_PMC_new(interp, type);
240 Parrot_PMC_set_intval(interp, testpmc, value);
243 Parrot_set_pmcreg(interp, parrot_reg, testpmc);
245 newpmc = Parrot_get_pmcreg(interp, parrot_reg);
246 new_value = Parrot_PMC_get_intval(interp, newpmc);
248 printf("%d\n", (int)new_value);
250 Parrot_exit(interp, 0);
257 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_numval' );
260 #include "parrot/embed.h"
261 #include "parrot/extend.h"
264 main(int argc, char* argv[]) {
265 Parrot_Interp interp = Parrot_new(NULL);
266 Parrot_Float value = 3.1415927;
268 Parrot_Float new_value;
271 /* Interpreter set-up */
275 type = Parrot_PMC_typenum(interp, "Float");
276 testpmc = Parrot_PMC_new(interp, type);
278 Parrot_PMC_set_numval(interp, testpmc, value);
279 new_value = Parrot_PMC_get_numval(interp, testpmc);
281 printf("%.7f\n", (double)new_value);
283 Parrot_exit(interp, 0);
290 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_string' );
293 #include "parrot/embed.h"
294 #include "parrot/extend.h"
297 main(int argc, char* argv[]) {
298 Parrot_Interp interp = Parrot_new(NULL);
300 Parrot_String value, new_value;
303 /* Interpreter set-up */
307 type = Parrot_PMC_typenum(interp, "String");
308 testpmc = Parrot_PMC_new(interp, type);
310 value = Parrot_new_string(interp, "Pumpking", 8, "iso-8859-1", 0);
311 Parrot_PMC_set_string(interp, testpmc, value);
312 new_value = Parrot_PMC_get_string(interp, testpmc);
314 Parrot_eprintf(interp, "%S\n", new_value);
316 Parrot_exit(interp, 0);
323 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_cstring' );
326 #include "parrot/embed.h"
327 #include "parrot/extend.h"
330 main(int argc, char* argv[]) {
331 Parrot_Interp interp = Parrot_new(NULL);
336 /* Interpreter set-up */
340 type = Parrot_PMC_typenum(interp, "String");
341 testpmc = Parrot_PMC_new(interp, type);
343 Parrot_PMC_set_cstring(interp, testpmc, "Wibble");
344 new_value = Parrot_PMC_get_cstring(interp, testpmc);
346 printf("%s\n", new_value);
348 Parrot_free_cstring(new_value);
350 Parrot_exit(interp, 0);
357 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_cstringn' );
360 #include "parrot/embed.h"
361 #include "parrot/extend.h"
364 main(int argc, char* argv[]) {
365 Parrot_Interp interp = Parrot_new(NULL);
366 Parrot_Int length = 6;
372 /* Interpreter set-up */
376 type = Parrot_PMC_typenum(interp, "String");
377 testpmc = Parrot_PMC_new(interp, type);
379 Parrot_PMC_set_cstringn(interp, testpmc, "Wibble", length);
380 new_value = Parrot_PMC_get_cstringn(interp, testpmc, &new_len);
382 printf("%s\n", new_value);
383 printf("%d\n", (int)(new_len));
385 Parrot_free_cstring(new_value);
387 Parrot_exit(interp, 0);
395 my ($TEMP, $temp_pasm) = create_tempfile( SUFFIX => '.pasm', UNLINK => 1 );
413 my (undef, $temp_pbc) = create_tempfile( SUFFIX => '.pbc', UNLINK => 1 );
414 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pasm);
416 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub' );
418 #include <parrot/parrot.h>
419 #include <parrot/embed.h>
420 #include <parrot/extend.h>
422 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
425 main(int argc, char *argv[])
427 Parrot_Interp interp = Parrot_new(NULL);
431 Parrot_run_native(interp, the_test);
433 Parrot_exit(interp, 0);
437 /* also both the test PASM and the_test() print to stderr
438 * so that buffering in PIO is not an issue */
441 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
443 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
444 STRING *name = Parrot_str_new_constant(interp, "_sub1");
447 Parrot_pbc_load(interp, pf);
448 sub = Parrot_find_global_cur(interp, name);
449 Parrot_call_sub(interp, sub, "v");
450 Parrot_eprintf(interp, "back\\n");
452 /* win32 seems to buffer stderr ? */
453 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
455 name = Parrot_str_new_constant(interp, "_sub2");
456 sub = Parrot_find_global_cur(interp, name);
457 arg = pmc_new(interp, enum_class_String);
459 Parrot_PMC_set_string_native(interp, arg,
460 Parrot_str_new(interp, "hello ", 0));
462 Parrot_call_sub(interp, sub, "vP", arg);
463 Parrot_eprintf(interp, "back\\n");
474 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub using the unified interface' );
476 #include <parrot/parrot.h>
477 #include <parrot/embed.h>
478 #include <parrot/extend.h>
480 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
483 main(int argc, char *argv[])
485 Parrot_Interp interp = Parrot_new(NULL);
489 Parrot_run_native(interp, the_test);
491 Parrot_exit(interp, 0);
495 /* also both the test PASM and the_test() print to stderr
496 * so that buffering in PIO is not an issue */
499 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
501 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
502 STRING *name = Parrot_str_new_constant(interp, "_sub1");
505 Parrot_pbc_load(interp, pf);
506 sub = Parrot_find_global_cur(interp, name);
507 Parrot_ext_call(interp, sub, "->");
508 Parrot_eprintf(interp, "back\\n");
510 /* win32 seems to buffer stderr ? */
511 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
513 name = Parrot_str_new_constant(interp, "_sub2");
514 sub = Parrot_find_global_cur(interp, name);
515 arg = pmc_new(interp, enum_class_String);
517 Parrot_PMC_set_string_native(interp, arg,
518 Parrot_str_new(interp, "hello ", 0));
520 Parrot_ext_call(interp, sub, "P->", arg);
521 Parrot_eprintf(interp, "back\\n");
532 ($TEMP, my $temp_pir) = create_tempfile( SUFFIX => '.pir', UNLINK => 1 );
547 (undef, $temp_pbc) = create_tempfile( SUFFIX => '.pbc', UNLINK => 1 );
548 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pir);
550 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub and return an integer' );
552 #include <parrot/parrot.h>
553 #include <parrot/embed.h>
554 #include <parrot/extend.h>
556 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
559 main(int argc, char *argv[])
561 Parrot_Interp interp = Parrot_new(NULL);
565 Parrot_run_native(interp, the_test);
567 Parrot_exit(interp, 0);
571 /* also both the test PASM and the_test() print to stderr
572 * so that buffering in PIO is not an issue */
575 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
577 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
578 STRING *name = Parrot_str_new_constant(interp, "foo");
582 Parrot_pbc_load(interp, pf);
583 sub = Parrot_find_global_cur(interp, name);
584 arg = pmc_new(interp, enum_class_String);
586 Parrot_PMC_set_string_native(interp, arg,
587 Parrot_str_new(interp, "hello ", 0));
589 Parrot_ext_call(interp, sub, "P->I", arg, &result);
590 Parrot_eprintf(interp, "result %d\\n", result);
591 Parrot_eprintf(interp, "back\\n");
601 ($TEMP, $temp_pasm) = create_tempfile( SUFFIX => '.pasm', UNLINK => 1 );
607 find_lex P2, "no_such_var"
614 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pasm);
616 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub, catch exception' );
618 #include <parrot/parrot.h>
619 #include <parrot/embed.h>
620 #include <parrot/extend.h>
623 the_test(Parrot_Interp, opcode_t *, opcode_t *);
626 main(int argc, char *argv[])
628 Parrot_Interp interp = Parrot_new(NULL);
632 Parrot_run_native(interp, the_test);
634 Parrot_exit(interp, 0);
638 /* also both the test PASM and the_test() print to stderr
639 * so that buffering in PIO is not an issue */
642 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
644 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
645 STRING *name = Parrot_str_new_constant(interp, "_sub1");
647 Parrot_runloop jump_point;
649 Parrot_pbc_load(interp, pf);
650 sub = Parrot_find_global_cur(interp, name);
652 if (setjmp(jump_point.resume)) {
653 Parrot_eprintf(interp, "caught\\n");
656 /* pretend the EH was pushed by the sub call. */
657 interp->current_runloop_id++;
659 Parrot_ex_add_c_handler(interp, &jump_point);
660 Parrot_call_sub(interp, sub, "v");
663 Parrot_eprintf(interp, "back\\n");
673 ($TEMP, $temp_pir) = create_tempfile( SUFFIX => '.pir', UNLINK => 1 );
680 compreg compiler, 'PIR'
685 .local pmc compiled_sub
686 compiled_sub = compiler( code )
692 .sub add :multi( int, int )
701 .sub add :multi( num, num )
713 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pir);
715 c_output_is( <<"CODE", <<'OUTPUT', 'eval code through a parrot sub - #39669' );
717 #include <parrot/parrot.h>
718 #include <parrot/embed.h>
721 main(int argc, char* argv[])
723 Parrot_PackFile packfile;
724 char * code[] = { ".sub foo\\nsay \\"Hello from foo!\\"\\n.end\\n" };
726 Parrot_Interp interp = Parrot_new(NULL);
732 packfile = Parrot_pbc_read( interp, "$temp_pbc", 0 );
739 Parrot_pbc_load( interp, packfile );
740 Parrot_runcode( interp, 1, code );
742 Parrot_destroy( interp );
744 Parrot_exit(interp, 0);
751 c_output_is( <<'CODE', <<'OUTPUT', 'compile string in a fresh interp - #39986' );
753 #include <parrot/parrot.h>
754 #include <parrot/embed.h>
755 #include <parrot/extend.h>
758 main(int argc, char* argv[])
760 Parrot_Interp interp = Parrot_new(NULL);
761 const char *code = ".sub foo\nprint\"Hello from foo!\\n\"\n.end\n";
773 code_type = Parrot_str_new_constant( interp, "PIR" );
774 retval = Parrot_compile_string( interp, code_type, code, &error );
781 foo_name = Parrot_str_new_constant( interp, "foo" );
782 sub = Parrot_find_global_cur( interp, foo_name );
784 retval = (PMC *) Parrot_call_sub( interp, sub, "V", "" );
786 Parrot_exit(interp, 0);
793 c_output_is( <<"CODE", <<'OUTPUT', 'call multi sub from C - #41511' );
794 #include <parrot/parrot.h>
795 #include <parrot/embed.h>
796 #include <parrot/extend.h>
799 main(int argc, char* argv[])
804 Parrot_Interp interp = Parrot_new(NULL);
807 printf( "No interpreter\\n" );
811 pf = Parrot_pbc_read( interp, "$temp_pbc", 0 );
812 Parrot_pbc_load( interp, pf );
814 sub = Parrot_find_global_cur( interp, Parrot_str_new_constant( interp, "add" ) );
815 result = Parrot_call_sub_ret_int( interp, sub, "III", 100, 200 );
816 printf( "Result is %d.\\n", result );
818 Parrot_exit(interp, 0);
825 c_output_is( <<"CODE", <<'OUTPUT', 'call multi sub from C - unified interface' );
826 #include <parrot/parrot.h>
827 #include <parrot/embed.h>
828 #include <parrot/extend.h>
831 main(int argc, char* argv[])
836 Parrot_Interp interp = Parrot_new(NULL);
839 printf( "No interpreter\\n" );
843 pf = Parrot_pbc_read( interp, "$temp_pbc", 0 );
844 Parrot_pbc_load( interp, pf );
846 sub = Parrot_find_global_cur( interp, Parrot_str_new_constant( interp, "add" ) );
847 Parrot_ext_call( interp, sub, "II->I", 100, 200, &result );
848 printf( "Result is %d.\\n", result );
850 Parrot_exit(interp, 0);
857 c_output_is( <<'CODE', <<'OUTPUT', 'multiple Parrot_new/Parrot_exit cycles' );
860 #include "parrot/parrot.h"
861 #include "parrot/embed.h"
863 /* this is Parrot_exit without the exit()
864 * it will call Parrot_really_destroy() as an exit handler
866 void interp_cleanup(Parrot_Interp, int);
868 void interp_cleanup(PARROT_INTERP, int status)
870 handler_node_t *node = interp->exit_handler_list;
872 Parrot_block_GC_mark(interp);
873 Parrot_block_GC_sweep(interp);
876 handler_node_t * const next = node->next;
877 (node->function)(interp, status, node->arg);
884 main(int argc, char *argv[]) {
885 Parrot_Interp interp;
888 for (i = 1; i <= niter; i++) {
889 printf("Starting interp %d\n", i);
891 interp = Parrot_new(NULL);
895 Parrot_set_flag(interp, PARROT_DESTROY_FLAG);
897 printf("Destroying interp %d\n", i);
899 interp_cleanup(interp, 0);
914 # cperl-indent-level: 4
917 # vim: expandtab shiftwidth=4: