[TT #871] Add rand as a dynop, with tests
[parrot.git] / src / key.c
blob934c0366d78e0392fa6b74ec6a8f0e96557327dd
1 /*
2 Copyright (C) 2001-2008, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/key.c - Base vtable calling functions
9 =head1 DESCRIPTION
11 The base vtable calling functions.
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/key.h"
23 #include "key.str"
24 #include "pmc/pmc_key.h"
26 /* HEADERIZER HFILE: include/parrot/key.h */
30 =item C<PMC * key_new(PARROT_INTERP)>
32 Returns a new C<Key> PMC.
34 =cut
38 PARROT_EXPORT
39 PARROT_CANNOT_RETURN_NULL
40 PARROT_WARN_UNUSED_RESULT
41 PMC *
42 key_new(PARROT_INTERP)
44 ASSERT_ARGS(key_new)
45 return pmc_new(interp, enum_class_Key);
51 =item C<PMC * key_new_integer(PARROT_INTERP, INTVAL value)>
53 Returns a new integer C<Key> PMC with value C<value>.
55 =cut
59 PARROT_EXPORT
60 PARROT_CANNOT_RETURN_NULL
61 PARROT_WARN_UNUSED_RESULT
62 PMC *
63 key_new_integer(PARROT_INTERP, INTVAL value)
65 ASSERT_ARGS(key_new_integer)
66 PMC * const key = pmc_new(interp, enum_class_Key);
68 PObj_get_FLAGS(key) |= KEY_integer_FLAG;
69 SETATTR_Key_int_key(interp, key, value);
71 return key;
77 =item C<PMC * key_new_number(PARROT_INTERP, FLOATVAL value)>
79 Returns a new number C<Key> PMC with value C<value>.
81 =cut
85 PARROT_EXPORT
86 PARROT_CANNOT_RETURN_NULL
87 PARROT_WARN_UNUSED_RESULT
88 PMC *
89 key_new_number(PARROT_INTERP, FLOATVAL value)
91 ASSERT_ARGS(key_new_number)
92 PMC * const key = pmc_new(interp, enum_class_Key);
94 PObj_get_FLAGS(key) |= KEY_number_FLAG;
95 SETATTR_Key_num_key(interp, key, value);
97 return key;
103 =item C<PMC * key_new_string(PARROT_INTERP, STRING *value)>
105 Returns a new string C<Key> PMC with value C<value>.
107 =cut
111 PARROT_EXPORT
112 PARROT_CANNOT_RETURN_NULL
113 PARROT_WARN_UNUSED_RESULT
114 PMC *
115 key_new_string(PARROT_INTERP, ARGIN(STRING *value))
117 ASSERT_ARGS(key_new_string)
118 PMC * const key = pmc_new(interp, enum_class_Key);
120 PObj_get_FLAGS(key) |= KEY_string_FLAG;
121 SETATTR_Key_str_key(interp, key, value);
123 return key;
129 =item C<PMC * key_new_cstring(PARROT_INTERP, const char *value)>
131 Returns a new string C<Key> PMC with value C<value> converted to a
132 C<STRING>.
134 =cut
138 PARROT_EXPORT
139 PARROT_CANNOT_RETURN_NULL
140 PARROT_WARN_UNUSED_RESULT
141 PMC *
142 key_new_cstring(PARROT_INTERP, ARGIN_NULLOK(const char *value))
144 ASSERT_ARGS(key_new_cstring)
145 return key_new_string(interp, Parrot_str_new(interp, value, 0));
151 =item C<PMC * key_new_pmc(PARROT_INTERP, PMC *value)>
153 Returns a new PMC C<Key> PMC with value C<value>.
155 =cut
159 PARROT_EXPORT
160 PARROT_CANNOT_RETURN_NULL
161 PARROT_WARN_UNUSED_RESULT
162 PMC *
163 key_new_pmc(PARROT_INTERP, ARGIN(PMC *value))
165 ASSERT_ARGS(key_new_pmc)
166 PMC * const key = pmc_new(interp, enum_class_Key);
168 PObj_get_FLAGS(key) |= KEY_pmc_FLAG;
169 Parrot_ex_throw_from_c_args(interp, NULL, 1, "this is broken - see slice.pmc");
175 =item C<void key_set_integer(PARROT_INTERP, PMC *key, INTVAL value)>
177 Set the integer C<value> in C<key>.
179 =cut
183 PARROT_EXPORT
184 void
185 key_set_integer(PARROT_INTERP, ARGMOD(PMC *key), INTVAL value)
187 ASSERT_ARGS(key_set_integer)
188 PObj_get_FLAGS(key) &= ~KEY_type_FLAGS;
189 PObj_get_FLAGS(key) |= KEY_integer_FLAG;
190 SETATTR_Key_int_key(interp, key, value);
192 return;
198 =item C<void key_set_register(PARROT_INTERP, PMC *key, INTVAL value, INTVAL
199 flag)>
201 Set the register C<value> in C<key>.
203 =cut
207 PARROT_EXPORT
208 void
209 key_set_register(PARROT_INTERP, ARGMOD(PMC *key), INTVAL value, INTVAL flag)
211 ASSERT_ARGS(key_set_register)
212 PObj_get_FLAGS(key) &= ~KEY_type_FLAGS;
213 PObj_get_FLAGS(key) |= KEY_register_FLAG | flag;
214 SETATTR_Key_int_key(interp, key, value);
216 return;
222 =item C<void key_set_number(PARROT_INTERP, PMC *key, FLOATVAL value)>
224 Set the number C<value> in C<key>.
226 =cut
230 PARROT_EXPORT
231 void
232 key_set_number(PARROT_INTERP, ARGMOD(PMC *key), FLOATVAL value)
234 ASSERT_ARGS(key_set_number)
235 PObj_get_FLAGS(key) &= ~KEY_type_FLAGS;
236 PObj_get_FLAGS(key) |= KEY_number_FLAG;
237 SETATTR_Key_num_key(interp, key, value);
239 return;
245 =item C<void key_set_string(PARROT_INTERP, PMC *key, STRING *value)>
247 Set the string C<value> in C<key>.
249 =cut
253 PARROT_EXPORT
254 void
255 key_set_string(PARROT_INTERP, ARGMOD(PMC *key), ARGIN(STRING *value))
257 ASSERT_ARGS(key_set_string)
258 PObj_get_FLAGS(key) &= ~KEY_type_FLAGS;
259 PObj_get_FLAGS(key) |= KEY_string_FLAG;
260 SETATTR_Key_str_key(interp, key, value);
262 return;
268 =item C<void key_set_pmc(PARROT_INTERP, PMC *key, PMC *value)>
270 Set the PMC C<value> in C<key>.
272 =cut
276 PARROT_EXPORT
277 void
278 key_set_pmc(PARROT_INTERP, ARGMOD(PMC *key), ARGIN(PMC *value))
280 ASSERT_ARGS(key_set_pmc)
281 PObj_get_FLAGS(key) &= ~KEY_type_FLAGS;
282 PObj_get_FLAGS(key) |= KEY_pmc_FLAG;
285 * XXX leo
286 * what for is this indirection?
288 Parrot_ex_throw_from_c_args(interp, NULL, 1, "this is broken - see slice.pmc");
294 =item C<INTVAL key_type(PARROT_INTERP, const PMC *key)>
296 Returns the type of C<key>.
298 =cut
302 PARROT_EXPORT
303 PARROT_WARN_UNUSED_RESULT
304 INTVAL
305 key_type(SHIM_INTERP, ARGIN(const PMC *key))
307 ASSERT_ARGS(key_type)
308 return (PObj_get_FLAGS(key) & KEY_type_FLAGS) & ~KEY_register_FLAG;
314 =item C<INTVAL key_integer(PARROT_INTERP, PMC *key)>
316 Translates a key value into an integer.
317 Takes an interpreter name and pointer to a key.
318 Returns an integer value corresponding to the key.
320 =cut
324 PARROT_EXPORT
325 PARROT_WARN_UNUSED_RESULT
326 INTVAL
327 key_integer(PARROT_INTERP, ARGIN(PMC *key))
329 ASSERT_ARGS(key_integer)
330 INTVAL int_key;
331 STRING *str_key;
332 FLOATVAL num_key;
334 switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
335 case KEY_integer_FLAG:
336 GETATTR_Key_int_key(interp, key, int_key);
337 return int_key;
338 case KEY_integer_FLAG | KEY_register_FLAG:
339 GETATTR_Key_int_key(interp, key, int_key);
340 return REG_INT(interp, int_key);
342 case KEY_number_FLAG:
343 GETATTR_Key_num_key(interp, key, num_key);
344 return (INTVAL)num_key;
345 case KEY_number_FLAG | KEY_register_FLAG:
346 GETATTR_Key_int_key(interp, key, int_key);
347 return (INTVAL)REG_NUM(interp, int_key);
349 case KEY_pmc_FLAG | KEY_register_FLAG:
351 PMC *reg;
352 GETATTR_Key_int_key(interp, key, int_key);
353 reg = REG_PMC(interp, int_key);
354 return VTABLE_get_integer(interp, reg);
357 case KEY_string_FLAG:
358 GETATTR_Key_str_key(interp, key, str_key);
359 return Parrot_str_to_int(interp, str_key);
360 case KEY_string_FLAG | KEY_register_FLAG:
362 STRING *s_reg;
363 GETATTR_Key_int_key(interp, key, int_key);
364 s_reg = REG_STR(interp, int_key);
365 return Parrot_str_to_int(interp, s_reg);
368 default:
369 break;
372 return VTABLE_get_integer(interp, key);
378 =item C<FLOATVAL key_number(PARROT_INTERP, PMC *key)>
380 Translates a key value into a number.
381 Takes an interpreter name and pointer to a key.
382 Returns a number value corresponding to the key.
383 Throws an exception if the key is not a valid number.
385 =cut
389 PARROT_EXPORT
390 PARROT_WARN_UNUSED_RESULT
391 FLOATVAL
392 key_number(PARROT_INTERP, ARGIN(PMC *key))
394 ASSERT_ARGS(key_number)
395 INTVAL int_key;
396 FLOATVAL num_key;
398 switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
399 case KEY_number_FLAG:
400 GETATTR_Key_num_key(interp, key, num_key);
401 return num_key;
402 case KEY_number_FLAG | KEY_register_FLAG:
403 GETATTR_Key_int_key(interp, key, int_key);
404 return REG_NUM(interp, int_key);
405 case KEY_pmc_FLAG:
406 return VTABLE_get_number(interp, key);
407 case KEY_pmc_FLAG | KEY_register_FLAG:
409 PMC *reg;
410 GETATTR_Key_int_key(interp, key, int_key);
411 reg = REG_PMC(interp, int_key);
412 return VTABLE_get_number(interp, reg);
414 default:
415 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
416 "Key not a number!\n");
423 =item C<STRING * key_string(PARROT_INTERP, PMC *key)>
425 Translates a key value into a string. Takes an interpreter name and pointer to
426 a key. Returns a string value corresponding to the key.
428 =cut
432 PARROT_WARN_UNUSED_RESULT
433 PARROT_CAN_RETURN_NULL
434 STRING *
435 key_string(PARROT_INTERP, ARGIN(PMC *key))
437 ASSERT_ARGS(key_string)
439 switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
440 /* remember to COW strings instead of returning them directly */
441 case KEY_string_FLAG:
443 STRING *s;
444 GETATTR_Key_str_key(interp, key, s);
445 if (s)
446 s = Parrot_str_new_COW(interp, s);
447 return s;
449 case KEY_string_FLAG | KEY_register_FLAG:
451 INTVAL int_key;
452 STRING *s;
453 GETATTR_Key_int_key(interp, key, int_key);
454 s = REG_STR(interp, int_key);
455 if (s)
456 s = Parrot_str_new_COW(interp, s);
457 return s;
459 case KEY_pmc_FLAG | KEY_register_FLAG:
461 INTVAL int_key;
462 PMC *reg;
463 GETATTR_Key_int_key(interp, key, int_key);
464 reg = REG_PMC(interp, int_key);
465 return VTABLE_get_string(interp, reg);
467 case KEY_integer_FLAG:
469 INTVAL int_key;
470 GETATTR_Key_int_key(interp, key, int_key);
471 return Parrot_str_from_int(interp, int_key);
473 case KEY_integer_FLAG | KEY_register_FLAG:
475 INTVAL int_key;
476 GETATTR_Key_int_key(interp, key, int_key);
477 return Parrot_str_from_int(interp, REG_INT(interp, int_key));
479 case KEY_number_FLAG:
481 FLOATVAL num_key;
482 GETATTR_Key_num_key(interp, key, num_key);
483 return Parrot_str_from_num(interp, num_key);
485 case KEY_number_FLAG | KEY_register_FLAG:
487 INTVAL int_key;
488 GETATTR_Key_int_key(interp, key, int_key);
489 return Parrot_str_from_num(interp, REG_NUM(interp, int_key));
491 default:
492 case KEY_pmc_FLAG:
493 return VTABLE_get_string(interp, key);
500 =item C<PMC * key_pmc(PARROT_INTERP, PMC *key)>
502 These functions return the integer/number/string/PMC values of C<key> if
503 possible. Otherwise they throw exceptions.
505 =cut
509 PARROT_EXPORT
510 PARROT_CANNOT_RETURN_NULL
511 PARROT_WARN_UNUSED_RESULT
512 PMC *
513 key_pmc(PARROT_INTERP, ARGIN(PMC *key))
515 ASSERT_ARGS(key_pmc)
516 INTVAL int_key;
518 switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
519 case KEY_pmc_FLAG | KEY_register_FLAG:
520 GETATTR_Key_int_key(interp, key, int_key);
521 return REG_PMC(interp, int_key);
522 default:
523 return key;
530 =item C<PMC * key_next(PARROT_INTERP, PMC *key)>
532 Returns the next key if C<key> is in a sequence of linked keys.
534 =cut
538 PARROT_EXPORT
539 PARROT_CAN_RETURN_NULL
540 PARROT_WARN_UNUSED_RESULT
541 PMC *
542 key_next(PARROT_INTERP, ARGIN(PMC *key))
544 ASSERT_ARGS(key_next)
545 PMC *next_key;
547 if (VTABLE_isa(interp, key, CONST_STRING(interp, "Key")) && key->pmc_ext) {
548 GETATTR_Key_next_key(interp, key, next_key);
549 return next_key;
552 return NULL;
558 =item C<PMC * key_append(PARROT_INTERP, PMC *key1, PMC *key2)>
560 Appends C<key2> to C<key1>.
562 Note that if C<key1> is not the last key in a sequence of linked keys then the
563 last key will be found and C<key2> appended to that.
565 Returns C<key1>.
567 =cut
571 PARROT_EXPORT
572 PARROT_CANNOT_RETURN_NULL
573 PARROT_IGNORABLE_RESULT
574 PMC *
575 key_append(PARROT_INTERP, ARGMOD(PMC *key1), ARGIN(PMC *key2))
577 ASSERT_ARGS(key_append)
578 PMC *tail = key1;
579 PMC *tail_next;
581 GETATTR_Key_next_key(interp, tail, tail_next);
583 while (tail_next) {
584 tail = tail_next;
585 GETATTR_Key_next_key(interp, tail, tail_next);
588 SETATTR_Key_next_key(interp, tail, key2);
590 return key1;
596 =item C<void key_mark(PARROT_INTERP, PMC *key)>
598 Marks C<key> as live.
600 =cut
604 PARROT_EXPORT
605 void
606 key_mark(PARROT_INTERP, ARGIN(PMC *key))
608 ASSERT_ARGS(key_mark)
609 PMC *next_key;
610 const UINTVAL flags = PObj_get_FLAGS(key) & KEY_type_FLAGS;
612 if (flags == KEY_string_FLAG) {
613 STRING *str_key;
614 GETATTR_Key_str_key(interp, key, str_key);
616 /* XXX str_key can be NULL from GETATTR_Key_str_key, */
617 /* so shouldn't be marked. */
618 Parrot_gc_mark_PObj_alive(interp, (PObj *)str_key);
621 /* Mark next key */
622 if ((flags == KEY_string_FLAG) || (flags == KEY_pmc_FLAG)) {
623 GETATTR_Key_next_key(interp, key, next_key);
624 if (next_key)
625 Parrot_gc_mark_PObj_alive(interp, (PObj *)next_key);
633 =item C<STRING * key_set_to_string(PARROT_INTERP, PMC *key)>
635 Translates a series of key values into strings, quoted or bracketed if
636 appropriate. Takes an interpreter name and pointer to a key. Returns a
637 string value corresponding to the key.
639 =cut
643 PARROT_EXPORT
644 PARROT_CANNOT_RETURN_NULL
645 PARROT_WARN_UNUSED_RESULT
646 STRING *
647 key_set_to_string(PARROT_INTERP, ARGIN_NULLOK(PMC *key))
649 ASSERT_ARGS(key_set_to_string)
650 STRING * const semicolon = CONST_STRING(interp, " ; ");
651 STRING * const quote = CONST_STRING(interp, "'");
652 STRING *value = Parrot_str_new(interp, "[ ", 2);
653 PMC *next_key;
654 INTVAL int_key;
655 STRING *str_key;
657 while (key != NULL) {
658 switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
659 case KEY_integer_FLAG:
660 GETATTR_Key_int_key(interp, key, int_key);
661 value = Parrot_str_append(interp, value,
662 Parrot_str_from_int(interp, int_key));
663 break;
664 case KEY_number_FLAG:
665 GETATTR_Key_int_key(interp, key, int_key);
666 value = Parrot_str_append(interp, value,
667 Parrot_str_from_num(interp, (FLOATVAL)int_key));
668 break;
669 case KEY_string_FLAG:
670 GETATTR_Key_str_key(interp, key, str_key);
671 value = Parrot_str_append(interp, value, quote);
672 value = Parrot_str_append(interp, value, str_key);
673 value = Parrot_str_append(interp, value, quote);
674 break;
675 case KEY_pmc_FLAG:
676 value = Parrot_str_append(interp, value,
677 VTABLE_get_string(interp, key));
678 break;
679 case KEY_integer_FLAG | KEY_register_FLAG:
680 GETATTR_Key_int_key(interp, key, int_key);
681 value = Parrot_str_append(interp, value,
682 Parrot_str_from_int(interp,
683 REG_INT(interp, int_key)));
684 break;
685 case KEY_number_FLAG | KEY_register_FLAG:
686 GETATTR_Key_int_key(interp, key, int_key);
687 value = Parrot_str_append(interp, value,
688 Parrot_str_from_num(interp,
689 REG_NUM(interp, int_key)));
690 break;
691 case KEY_string_FLAG | KEY_register_FLAG:
692 value = Parrot_str_append(interp, value, quote);
693 GETATTR_Key_int_key(interp, key, int_key);
694 value = Parrot_str_append(interp, value,
695 REG_STR(interp, int_key));
696 value = Parrot_str_append(interp, value, quote);
697 break;
698 case KEY_pmc_FLAG | KEY_register_FLAG:
700 PMC *reg;
701 GETATTR_Key_int_key(interp, key, int_key);
702 reg = REG_PMC(interp, int_key);
703 value = Parrot_str_append(interp, value,
704 VTABLE_get_string(interp, reg));
706 break;
707 default:
708 value = Parrot_str_append(interp, value, CONST_STRING(interp, "Key type unknown"));
709 break;
712 GETATTR_Key_next_key(interp, key, next_key);
713 if (next_key)
714 value = Parrot_str_append(interp, value, semicolon);
716 GETATTR_Key_next_key(interp, key, key);
719 value = Parrot_str_append(interp, value, Parrot_str_new(interp, " ]", 2));
720 return value;
725 =back
727 =head1 SEE ALSO
729 F<include/parrot/key.h>.
731 =head1 HISTORY
733 Initial version by Jeff G. on 2001.12.05.
735 =cut
741 * Local variables:
742 * c-file-style: "parrot"
743 * End:
744 * vim: expandtab shiftwidth=4: