2 # Copyright (C) 2001-2010, 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, const char *argv[])
40 Parrot_Interp interp = Parrot_new(NULL);
41 Parrot_Int parrot_reg = 0;
42 Parrot_Int value = 42;
45 /* Interpreter set-up */
47 Parrot_set_intreg(interp, parrot_reg, value);
48 new_value = Parrot_get_intreg(interp, parrot_reg);
50 printf("%d\n", (int)new_value);
51 Parrot_destroy(interp);
60 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_numreg' );
63 #include "parrot/embed.h"
64 #include "parrot/extend.h"
67 main(int argc, const 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 */
76 Parrot_set_numreg(interp, parrot_reg, value);
77 new_value = Parrot_get_numreg(interp, parrot_reg);
79 printf("%.1f\n", (double)new_value);
81 Parrot_destroy(interp);
90 c_output_is( <<'CODE', <<'OUTPUT', 'Parrot_new_string' );
93 #include "parrot/embed.h"
94 #include "parrot/extend.h"
97 main(int argc, const char *argv[])
99 Parrot_Interp interp = Parrot_new(NULL);
100 Parrot_String output;
102 /* Interpreter set-up */
104 output = Parrot_new_string(interp, "Test", 4, "iso-8859-1", 0);
105 Parrot_eprintf(interp, "%S\n", output);
107 Parrot_destroy(interp);
116 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_strreg' );
119 #include "parrot/embed.h"
120 #include "parrot/extend.h"
123 main(int argc, const 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 */
131 value = Parrot_new_string(interp, "Test", 4, "iso-8859-1", 0);
132 Parrot_set_strreg(interp, parrot_reg, value);
134 new_value = Parrot_get_strreg(interp, parrot_reg);
135 Parrot_eprintf(interp, "%S\n", new_value);
137 Parrot_destroy(interp);
146 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_integer' );
149 #include "parrot/embed.h"
150 #include "parrot/extend.h"
153 main(int argc, const char *argv[])
155 Parrot_Interp interp = Parrot_new(NULL);
156 Parrot_Int value = 101010;
158 Parrot_Int type, new_value;
160 /* Interpreter set-up */
162 type = Parrot_PMC_typenum(interp, "Integer");
163 testpmc = Parrot_PMC_new(interp, type);
165 Parrot_PMC_set_integer_native(interp, testpmc, value);
166 new_value = Parrot_PMC_get_integer(interp, testpmc);
168 printf("%ld\n", (long)new_value);
170 Parrot_destroy(interp);
178 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_integer_keyed_int' );
181 #include "parrot/parrot.h"
182 #include "parrot/embed.h"
183 #include "parrot/extend.h"
186 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
188 Parrot_Int type = Parrot_PMC_typenum(interp, "ResizablePMCArray");
189 Parrot_PMC array = Parrot_PMC_new(interp, type);
190 Parrot_Int value = 12345;
192 Parrot_Int new_value;
194 Parrot_PMC_set_integer_keyed_int(interp, array, key, value);
196 new_value = Parrot_PMC_get_integer_keyed_int(interp, array, key);
198 printf("%ld\n", (long)new_value);
203 main(int argc, const char *argv[])
205 Parrot_Interp interp = Parrot_new(NULL);
207 /* Interpreter set-up */
209 Parrot_run_native(interp, the_test);
211 Parrot_destroy(interp);
219 c_output_is( <<'CODE', <<'OUTPUT', 'set/get_pmcreg' );
222 #include "parrot/embed.h"
223 #include "parrot/extend.h"
226 main(int argc, const char *argv[])
228 Parrot_Interp interp = Parrot_new(NULL);
229 Parrot_Int value = -123;
230 Parrot_Int parrot_reg = 31;
231 Parrot_Int type, new_value;
232 Parrot_PMC testpmc, newpmc;
234 /* Interpreter set-up */
236 type = Parrot_PMC_typenum(interp, "Integer");
237 testpmc = Parrot_PMC_new(interp, type);
239 Parrot_PMC_set_integer_native(interp, testpmc, value);
242 Parrot_set_pmcreg(interp, parrot_reg, testpmc);
244 newpmc = Parrot_get_pmcreg(interp, parrot_reg);
245 new_value = Parrot_PMC_get_integer(interp, newpmc);
247 printf("%d\n", (int)new_value);
249 Parrot_destroy(interp);
257 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_number' );
260 #include "parrot/embed.h"
261 #include "parrot/extend.h"
264 main(int argc, const char *argv[])
266 Parrot_Interp interp = Parrot_new(NULL);
267 Parrot_Float value = 3.1415927;
269 Parrot_Float new_value;
272 /* Interpreter set-up */
274 type = Parrot_PMC_typenum(interp, "Float");
275 testpmc = Parrot_PMC_new(interp, type);
277 Parrot_PMC_set_number_native(interp, testpmc, value);
278 new_value = Parrot_PMC_get_number(interp, testpmc);
280 printf("%.7f\n", (double)new_value);
282 Parrot_destroy(interp);
290 c_output_is( <<'CODE', <<'OUTPUT', 'PMC_set/get_string' );
293 #include "parrot/embed.h"
294 #include "parrot/extend.h"
297 main(int argc, const char *argv[])
299 Parrot_Interp interp = Parrot_new(NULL);
301 Parrot_String value, new_value;
304 /* Interpreter set-up */
306 type = Parrot_PMC_typenum(interp, "String");
307 testpmc = Parrot_PMC_new(interp, type);
309 value = Parrot_new_string(interp, "Pumpking", 8, "iso-8859-1", 0);
310 Parrot_PMC_set_string_native(interp, testpmc, value);
311 new_value = Parrot_PMC_get_string(interp, testpmc);
313 Parrot_eprintf(interp, "%S\n", new_value);
315 Parrot_destroy(interp);
323 my ($TEMP, $temp_pasm) = create_tempfile( SUFFIX => '.pasm', UNLINK => 1 );
341 my (undef, $temp_pbc) = create_tempfile( SUFFIX => '.pbc', UNLINK => 1 );
342 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pasm);
344 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub' );
346 #include <parrot/parrot.h>
347 #include <parrot/embed.h>
348 #include <parrot/extend.h>
350 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
353 main(int argc, const char *argv[])
355 Parrot_Interp interp = Parrot_new(NULL);
358 Parrot_run_native(interp, the_test);
360 Parrot_destroy(interp);
365 /* also both the test PASM and the_test() print to stderr
366 * so that buffering in PIO is not an issue */
369 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
371 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
372 Parrot_String name = Parrot_str_new_constant(interp, "_sub1");
375 Parrot_pbc_load(interp, pf);
376 sub = Parrot_ns_find_current_namespace_global(interp, name);
377 Parrot_ext_call(interp, sub, "->");
378 Parrot_eprintf(interp, "back\\n");
380 /* win32 seems to buffer stderr ? */
381 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
383 name = Parrot_str_new_constant(interp, "_sub2");
384 sub = Parrot_ns_find_current_namespace_global(interp, name);
385 arg = Parrot_pmc_new(interp, enum_class_String);
387 Parrot_PMC_set_string_native(interp, arg,
388 Parrot_str_new(interp, "hello ", 0));
390 Parrot_ext_call(interp, sub, "P->", arg);
391 Parrot_eprintf(interp, "back\\n");
402 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub using the unified interface' );
404 #include <parrot/parrot.h>
405 #include <parrot/embed.h>
406 #include <parrot/extend.h>
408 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
411 main(int argc, const char *argv[])
413 Parrot_Interp interp = Parrot_new(NULL);
415 Parrot_run_native(interp, the_test);
417 Parrot_destroy(interp);
422 /* also both the test PASM and the_test() print to stderr
423 * so that buffering in PIO is not an issue */
426 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
428 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
429 Parrot_String name = Parrot_str_new_constant(interp, "_sub1");
432 Parrot_pbc_load(interp, pf);
433 sub = Parrot_ns_find_current_namespace_global(interp, name);
434 Parrot_ext_call(interp, sub, "->");
435 Parrot_eprintf(interp, "back\\n");
437 /* win32 seems to buffer stderr ? */
438 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
440 name = Parrot_str_new_constant(interp, "_sub2");
441 sub = Parrot_ns_find_current_namespace_global(interp, name);
442 arg = Parrot_pmc_new(interp, enum_class_String);
444 Parrot_PMC_set_string_native(interp, arg,
445 Parrot_str_new(interp, "hello ", 0));
447 Parrot_ext_call(interp, sub, "P->", arg);
448 Parrot_eprintf(interp, "back\\n");
459 ($TEMP, my $temp_pir) = create_tempfile( SUFFIX => '.pir', UNLINK => 1 );
474 (undef, $temp_pbc) = create_tempfile( SUFFIX => '.pbc', UNLINK => 1 );
475 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pir);
477 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub and return an integer' );
479 #include <parrot/parrot.h>
480 #include <parrot/embed.h>
481 #include <parrot/extend.h>
483 static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);
486 main(int argc, const char *argv[])
488 Parrot_Interp interp = Parrot_new(NULL);
490 Parrot_run_native(interp, the_test);
492 Parrot_destroy(interp);
497 /* also both the test PASM and the_test() print to stderr
498 * so that buffering in PIO is not an issue */
501 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
503 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
504 Parrot_String name = Parrot_str_new_constant(interp, "foo");
508 Parrot_pbc_load(interp, pf);
509 sub = Parrot_ns_find_current_namespace_global(interp, name);
510 arg = Parrot_pmc_new(interp, enum_class_String);
512 Parrot_PMC_set_string_native(interp, arg,
513 Parrot_str_new(interp, "hello ", 0));
515 Parrot_ext_call(interp, sub, "P->I", arg, &result);
516 Parrot_eprintf(interp, "result %d\\n", result);
517 Parrot_eprintf(interp, "back\\n");
527 ($TEMP, $temp_pasm) = create_tempfile( SUFFIX => '.pasm', UNLINK => 1 );
533 set I1, 0 # Divide by 0 to force exception.
541 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pasm);
543 c_output_is( <<"CODE", <<'OUTPUT', 'call a parrot sub, catch exception' );
545 #include <parrot/parrot.h>
546 #include <parrot/embed.h>
547 #include <parrot/extend.h>
550 the_test(Parrot_Interp, opcode_t *, opcode_t *);
553 main(int argc, const char *argv[])
555 Parrot_Interp interp = Parrot_new(NULL);
557 Parrot_run_native(interp, the_test);
559 Parrot_destroy(interp);
564 /* also both the test PASM and the_test() print to stderr
565 * so that buffering in PIO is not an issue */
568 the_test(PARROT_INTERP, opcode_t *cur_op, opcode_t *start)
570 PackFile *pf = Parrot_pbc_read(interp, "$temp_pbc", 0);
571 Parrot_String name = Parrot_str_new_constant(interp, "_sub1");
573 Parrot_runloop jump_point;
575 Parrot_pbc_load(interp, pf);
576 sub = Parrot_ns_find_current_namespace_global(interp, name);
578 if (setjmp(jump_point.resume)) {
579 Parrot_eprintf(interp, "caught\\n");
582 /* pretend the EH was pushed by the sub call. */
583 interp->current_runloop_id++;
585 Parrot_ex_add_c_handler(interp, &jump_point);
586 Parrot_ext_call(interp, sub, "->");
589 Parrot_eprintf(interp, "back\\n");
599 ($TEMP, $temp_pir) = create_tempfile( SUFFIX => '.pir', UNLINK => 1 );
606 compreg compiler, 'PIR'
611 .local pmc compiled_sub
612 compiled_sub = compiler( code )
618 .sub add :multi( int, int )
627 .sub add :multi( num, num )
639 system(".$PConfig{slash}parrot$PConfig{exe}", '-o', $temp_pbc, $temp_pir);
641 c_output_is( <<"CODE", <<'OUTPUT', 'eval code through a parrot sub - #39669' );
643 #include <parrot/parrot.h>
644 #include <parrot/embed.h>
647 main(int argc, const char *argv[])
649 Parrot_PackFile packfile;
650 const char * code[] = { ".sub foo\\nsay \\"Hello from foo!\\"\\n.end\\n" };
652 Parrot_Interp interp = Parrot_new(NULL);
654 packfile = Parrot_pbc_read( interp, "$temp_pbc", 0 );
657 Parrot_pbc_load( interp, packfile );
658 Parrot_runcode( interp, 1, code );
661 Parrot_destroy( interp );
669 c_output_is( <<'CODE', <<'OUTPUT', 'compile string in a fresh interp - #39986' );
671 #include <parrot/parrot.h>
672 #include <parrot/embed.h>
673 #include <parrot/extend.h>
676 main(int argc, const char *argv[])
678 Parrot_Interp interp = Parrot_new(NULL);
679 const char *code = ".sub foo\nprint\"Hello from foo!\\n\"\n.end\n";
682 Parrot_String code_type, error, foo_name;
685 code_type = Parrot_str_new_constant( interp, "PIR" );
686 retval = Parrot_compile_string( interp, code_type, code, &error );
689 foo_name = Parrot_str_new_constant( interp, "foo" );
690 sub = Parrot_ns_find_current_namespace_global( interp, foo_name );
692 Parrot_ext_call(interp, sub, "->");
694 Parrot_destroy(interp);
702 c_output_is( <<"CODE", <<'OUTPUT', 'call multi sub from C - #41511' );
703 #include <parrot/parrot.h>
704 #include <parrot/embed.h>
705 #include <parrot/extend.h>
708 main(int argc, const char *argv[])
713 Parrot_Interp interp = Parrot_new(NULL);
716 pf = Parrot_pbc_read( interp, "$temp_pbc", 0 );
717 Parrot_pbc_load( interp, pf );
719 sub = Parrot_ns_find_current_namespace_global( interp, Parrot_str_new_constant( interp, "add" ) );
720 Parrot_ext_call(interp, sub, "II->I", 100, 200, &result);
721 printf( "Result is %d.\\n", result );
722 Parrot_destroy(interp);
730 c_output_is( <<"CODE", <<'OUTPUT', 'call multi sub from C - unified interface' );
731 #include <parrot/parrot.h>
732 #include <parrot/embed.h>
733 #include <parrot/extend.h>
736 main(int argc, const char *argv[])
741 Parrot_Interp interp = Parrot_new(NULL);
744 pf = Parrot_pbc_read( interp, "$temp_pbc", 0 );
745 Parrot_pbc_load( interp, pf );
747 sub = Parrot_ns_find_current_namespace_global( interp, Parrot_str_new_constant( interp, "add" ) );
748 Parrot_ext_call( interp, sub, "II->I", 100, 200, &result );
749 printf( "Result is %d.\\n", result );
750 Parrot_destroy(interp);
758 c_output_is( <<'CODE', <<'OUTPUT', 'multiple Parrot_new/Parrot_exit cycles' );
761 #include "parrot/parrot.h"
762 #include "parrot/embed.h"
764 /* this is Parrot_exit without the exit()
765 * it will call Parrot_really_destroy() as an exit handler
767 void interp_cleanup(Parrot_Interp, int);
769 void interp_cleanup(PARROT_INTERP, int status)
771 handler_node_t *node = interp->exit_handler_list;
773 Parrot_block_GC_mark(interp);
774 Parrot_block_GC_sweep(interp);
777 handler_node_t * const next = node->next;
778 (node->function)(interp, status, node->arg);
785 main(int argc, const char *argv[])
787 Parrot_Interp interp;
790 for (i = 1; i <= niter; i++) {
791 printf("Starting interp %d\n", i);
793 interp = Parrot_new(NULL);
795 Parrot_set_flag(interp, PARROT_DESTROY_FLAG);
797 printf("Destroying interp %d\n", i);
799 interp_cleanup(interp, 0);
815 # cperl-indent-level: 4
818 # vim: expandtab shiftwidth=4: