6 VERSION = PARROT_VERSION;
10 experimental.ops - Experimental Operations
16 This file contains operations that are in an experimental state. Do not
17 rely upon the existence of the ops in this file when writing production code.
18 No decision has yet been made as to whether they are accepted as regular
19 Parrot ops or not. They are included here for testing purposes only!
23 ###############################################################################
25 =head2 Mathematical operations
27 Implementations of various mathematical operations
33 ########################################
35 =item B<gcd>(out INT, in NUM, in NUM)
37 Greatest Common divisor of $2 and $3.
39 =item B<gcd>(out INT, out INT, out INT, in INT, in INT)
41 Given $4 and $5, it calculates $1, $2 and $3 so that
43 $1 = gcd($4, $5) = $2 * $4 + $3 * $5 (d = gcd(a, b) = x*a + y*b)
47 inline op gcd(out INT, in NUM, in NUM) :advanced_math {
51 FLOATVAL temp2 = fabs($2);
52 FLOATVAL temp3 = fabs($3);
54 while (!FLOAT_IS_ZERO(temp3)) {
55 q = floor((FLOATVAL)temp2/temp3);
64 inline op gcd(out INT, out INT, out INT, in INT, in INT) :advanced_math {
66 INTVAL r0 = $4 < 0 ? -$4 : $4;
67 INTVAL r1 = $5 < 0 ? -$5 : $5;
102 $2 = (INTVAL)(xk * pow(-1, n));
103 $3 = (INTVAL)(yk * pow(-1, n+1));
108 /* correct the sign (can be wrong because we used abs($4) and abs($5) */
110 /* no correction necessary */
112 else if (x + y == -r1) {
116 else if (x - y == r1) {
119 else if (-x + y == r1) {
128 ###############################################################################
130 =head2 Misc other ops
136 =item B<splice>(invar PMC, invar PMC, in INT, in INT)
138 Replace $4 values at offset $3 in aggregate $1 with the PMCs in aggregate $2.
139 The values are put into the aggregate by a shallow copy. If the values would
140 be reused, they have to be B<clone>d.
144 inline op splice(invar PMC, invar PMC, in INT, in INT) {
145 VTABLE_splice(interp, $1, $2, $3, $4);
149 =item B<slice>(out PMC, invar PMC, in KEY)
151 Return a new Iterator PMC $1 for aggregate $2 and Slice PMC $3.
153 =item B<slice>(out PMC, invar PMC, in KEY, inconst INT)
155 Return a new list PMC $1 for aggregate $2 and Slice PMC $3.
157 This is a Python opcode. Range is i <= k < j. $4 must be 1.
158 May change and move to python.ops.
160 =item B<iter>(out PMC, invar PMC)
162 Return a new Iterator PMC $1 for aggregate $2.
166 inline op slice(out PMC, invar PMC, in KEY) :base_core {
167 $1 = VTABLE_slice(interp, $2, $3, 0);
170 inline op slice(out PMC, invar PMC, in KEY, inconst INT) :python {
171 $1 = VTABLE_slice(interp, $2, $3, $4);
174 inline op iter(out PMC, invar PMC) :base_core {
175 $1 = VTABLE_get_iter(interp, $2);
178 ########################################
180 =item B<morph>(invar PMC, in INT)
182 =item B<morph>(invar PMC, in STR)
184 Have $1 turn itself into a PMC of type $2.
188 inline op morph(invar PMC, in INT) {
189 VTABLE_morph(interp, $1, $2);
192 inline op morph(invar PMC, in STR) {
193 INTVAL type = pmc_type(interp, $2);
194 VTABLE_morph(interp, $1, type);
197 =item B<exec>(in STR)
199 Execute the passed-in command. Completely tosses the current process
200 image and replaces it with the command. Doesn't exit (the program
201 ends, after all), though it does throw an exception if something goes
206 inline op exec(in STR) {
207 Parrot_Exec_OS_Command(interp, $1);
211 =item B<classname>(out PMC, invar PMC)
213 Get the class name for the class in $2 and put it in $1. Note that $1 will be
214 a Key PMC that you can use with "new", for example.
218 op classname(out PMC, invar PMC) :object_base {
219 PMC *ns = Parrot_ns_get_name(interp,
220 VTABLE_get_namespace(interp, $2));
221 if (PMC_IS_NULL(ns) || VTABLE_elements(interp, ns) < 2)
223 real_exception(interp, NULL, NO_CLASS,
224 "Attempt to get class name of a non-class.");
232 /* Need to turn list of strings into a key. Note that we are not
233 including the first item in the array, since that is the HLL. */
234 tmp = VTABLE_get_string_keyed_int(interp, ns, 1);
235 $1 = key_tail = key_new_string(interp, tmp);
236 max = VTABLE_elements(interp, ns);
237 for (i = 2; i < max; i++)
239 tmp = VTABLE_get_string_keyed_int(interp, ns, i);
240 key = key_new_string(interp, tmp);
241 key_append(interp, key_tail, key);
249 =head2 More Experimental Ops
255 Break into debugger. Implementation notes:
257 - x86/gcc ... works with gdb
258 - ppc/gcc ... works with gdb, to proceed: gdb> p $pc = $pc + 4
261 For other architectures, this is a C<noop>.
266 #if defined(__GNUC__) && defined(i386)
267 __asm__("int3"); /* opcode 0xcc */
269 #if defined(__GNUC__) && defined(PPC)
270 __asm__("trap"); /* opcode tr 31, 0, 0 */
274 =item B<pow>(out NUM, in NUM, in INT)
276 Set $1 to $2 raised to the power $3.
280 inline op pow(out NUM, in NUM, in INT) :base_core {
304 =item B<new>(out PMC, in INT, in STR)
306 Create a new PMC of the type $2 according to the PMCs string representation
309 BUT SINCE INSTANTIATE WILL PROBABLY DIE, DON'T USE THIS;
310 OR IF YOU NEED THIS (OR INSTANTIATE), TELL CHIP
314 op new(out PMC, in INT, in STR) {
316 if ($2 <= 0 || $2 >= interp->n_vtable_max) {
317 real_exception(interp, 0, NO_CLASS,
318 "Illegal PMC enum (%d) in new", (int)$2);
320 _class = interp->vtables[$2]->pmc_class;
321 $1 = VTABLE_new_from_string(interp, _class, $3, 0);
324 ########################################
326 =item B<add_io_event>(invar PMC, invar PMC, invar PMC, inconst INT)
328 Call the sub $2 for PIO $1 with user data $3 on ready state of $4.
329 RT#42376 The only handled $4 = IO_THR_MSG_ADD_SELECT_RD aka 2 for now.
333 op add_io_event(invar PMC, invar PMC, invar PMC, inconst INT) {
334 Parrot_event_add_io_event(interp, $1, $2, $3, $4);
337 =item B<need_finalize>(invar PMC)
339 The ParrotObject $1 needs the __finalize method during GC.
343 op need_finalize(invar PMC) {
345 if (PObj_is_object_TEST(pmc)) {
346 PObj_get_FLAGS(pmc) |= PObj_need_finalize_FLAG;
350 #########################################
352 =item B<setstdout>(invar PMC)
354 Sets the standard output for a bare C<print> op to go to the supplied ParrotIO
355 PMC. Call C<getstdout> first if you care about retaining the previous PMC.
357 =item B<setstderr>(invar PMC)
359 Sets the standard error for a bare C<printerr> op to go to the supplied
360 ParrotIO PMC. Call C<getstderr> first if you care about retaining the previous
365 inline op setstdout(invar PMC) :base_io {
366 _PIO_STDOUT(interp) = $1;
369 inline op setstderr(invar PMC) :base_io {
370 _PIO_STDERR(interp) = $1;
374 ########################################
376 =item B<runinterp>(invar PMC, in PMC)
378 Invokes the PMC $2 using interp $1.
382 op runinterp(invar PMC, in PMC) {
383 Interp * const new_interp = (Interp *)PMC_data($1);
385 Interp_flags_SET(new_interp, PARROT_EXTERN_CODE_FLAG);
386 pc = (opcode_t *)VTABLE_invoke(new_interp, $2, NULL);
388 Parrot_runops_fromc_args(new_interp, $2, "P");
391 ########################################
393 =item B<substr_r>(out STR, in STR, in INT, in INT)
395 Make $1 refer to the given part of $2, basically like above, but it
396 is reusing the given destination string and does not care if the
397 source string is changed later. This I<is changed> includes
398 also GC runs, which will move the referenced string. This also
399 means that $1 has to be reset before any GC may happen.
401 This opcode should really be just used to quickly refer to a substring of
402 another part, e.g. for printing and is a temporary hack.
408 inline op substr_r(out STR, in STR, in INT, in INT) :base_core {
411 dest = new_string_header(interp, 0);
412 $1 = string_substr(interp, $2, $3, $4, &dest, 1);
415 =item C<find_sub_not_null>(out PMC, in STR)
417 inline op find_sub_not_null(out PMC, in STR) :base_core {
418 PMC *sub = Parrot_find_name_op(interp, $2, expr NEXT());
420 if (PMC_IS_NULL(sub))
421 real_exception(interp, NULL, GLOBAL_NOT_FOUND,
422 "Could not find non-existent sub %Ss", $2);
431 Copyright (C) 2001-2008, The Perl Foundation.
435 This program is free software. It is subject to the same license
436 as the Parrot interp itself.
443 * c-file-style: "parrot"
445 * vim: expandtab shiftwidth=4: