4 * Copyright (C) 2008 Vincent Geddes
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "st-primitives.h"
26 #include "st-machine.h"
28 #include "st-large-integer.h"
31 #include "st-object.h"
32 #include "st-behavior.h"
33 #include "st-context.h"
34 #include "st-method.h"
35 #include "st-symbol.h"
36 #include "st-character.h"
37 #include "st-dictionary.h"
38 #include "st-unicode.h"
39 #include "st-compiler.h"
40 #include "st-handle.h"
52 #define ST_PRIMITIVE_FAIL(machine) \
53 machine->success = false
57 set_success (st_machine
*machine
, bool success
)
59 machine
->success
= machine
->success
&& success
;
63 pop_integer (st_machine
*machine
)
65 st_oop object
= ST_STACK_POP (machine
);
67 if (ST_LIKELY (st_object_is_smi (object
)))
68 return st_smi_value (object
);
70 ST_PRIMITIVE_FAIL (machine
);
75 pop_integer32 (st_machine
*machine
)
77 st_oop object
= ST_STACK_POP (machine
);
79 if (ST_LIKELY (st_object_is_smi (object
)))
80 return st_smi_value (object
);
81 else if (st_object_class (object
) == ST_LARGE_INTEGER_CLASS
)
82 return (int) mp_get_int (st_large_integer_value (object
));
84 ST_PRIMITIVE_FAIL (machine
);
89 SmallInteger_add (st_machine
*machine
)
91 int y
= pop_integer (machine
);
92 int x
= pop_integer (machine
);
95 if (ST_LIKELY (machine
->success
)) {
97 if (((result
<< 1) ^ (result
<< 2)) >= 0) {
98 ST_STACK_PUSH (machine
, st_smi_new (result
));
101 ST_PRIMITIVE_FAIL (machine
);
105 ST_STACK_UNPOP (machine
, 2);
109 SmallInteger_sub (st_machine
*machine
)
111 int y
= pop_integer (machine
);
112 int x
= pop_integer (machine
);
116 if (ST_LIKELY (machine
->success
)) {
118 if (((result
<< 1) ^ (result
<< 2)) >= 0) {
119 ST_STACK_PUSH (machine
, st_smi_new (result
));
122 ST_PRIMITIVE_FAIL (machine
);
126 ST_STACK_UNPOP (machine
, 2);
130 SmallInteger_lt (st_machine
*machine
)
132 int y
= pop_integer (machine
);
133 int x
= pop_integer (machine
);
136 if (ST_LIKELY (machine
->success
)) {
137 result
= (x
< y
) ? ST_TRUE
: ST_FALSE
;
138 ST_STACK_PUSH (machine
, result
);
142 ST_STACK_UNPOP (machine
, 2);
146 SmallInteger_gt (st_machine
*machine
)
148 int y
= pop_integer (machine
);
149 int x
= pop_integer (machine
);
152 if (ST_LIKELY (machine
->success
)) {
153 result
= (x
> y
) ? ST_TRUE
: ST_FALSE
;
154 ST_STACK_PUSH (machine
, result
);
158 ST_STACK_UNPOP (machine
, 2);
162 SmallInteger_le (st_machine
*machine
)
164 int y
= pop_integer (machine
);
165 int x
= pop_integer (machine
);
168 if (ST_LIKELY (machine
->success
)) {
169 result
= (x
<= y
) ? ST_TRUE
: ST_FALSE
;
170 ST_STACK_PUSH (machine
, result
);
174 ST_STACK_UNPOP (machine
, 2);
178 SmallInteger_ge (st_machine
*machine
)
180 int y
= pop_integer (machine
);
181 int x
= pop_integer (machine
);
184 if (ST_LIKELY (machine
->success
)) {
185 result
= (x
>= y
) ? ST_TRUE
: ST_FALSE
;
186 ST_STACK_PUSH (machine
, result
);
190 ST_STACK_UNPOP (machine
, 2);
194 SmallInteger_eq (st_machine
*machine
)
196 int y
= pop_integer (machine
);
197 int x
= pop_integer (machine
);
200 if (ST_LIKELY (machine
->success
)) {
201 result
= (x
== y
) ? ST_TRUE
: ST_FALSE
;
202 ST_STACK_PUSH (machine
, result
);
206 ST_STACK_UNPOP (machine
, 2);
210 SmallInteger_ne (st_machine
*machine
)
212 int y
= pop_integer (machine
);
213 int x
= pop_integer (machine
);
216 if (ST_LIKELY (machine
->success
)) {
217 result
= (x
!= y
) ? ST_TRUE
: ST_FALSE
;
218 ST_STACK_PUSH (machine
, result
);
222 ST_STACK_UNPOP (machine
, 2);
226 SmallInteger_mul (st_machine
*machine
)
228 int y
= pop_integer (machine
);
229 int x
= pop_integer (machine
);
232 if (machine
->success
) {
234 if (result
>= ST_SMALL_INTEGER_MIN
&& result
<= ST_SMALL_INTEGER_MAX
) {
235 ST_STACK_PUSH (machine
, st_smi_new ((int) result
));
238 ST_PRIMITIVE_FAIL (machine
);
242 ST_STACK_UNPOP (machine
, 2);
247 SmallInteger_div (st_machine
*machine
)
249 int y
= pop_integer (machine
);
250 int x
= pop_integer (machine
);
253 if (ST_LIKELY (machine
->success
)) {
255 if (y
!= 0 && x
% y
== 0) {
256 result
= st_smi_new (x
/ y
);
257 ST_STACK_PUSH (machine
, result
);
260 ST_PRIMITIVE_FAIL (machine
);
264 ST_STACK_UNPOP (machine
, 2);
268 SmallInteger_intDiv (st_machine
*machine
)
270 int y
= pop_integer (machine
);
271 int x
= pop_integer (machine
);
274 if (ST_LIKELY (machine
->success
)) {
277 result
= st_smi_new (x
/ y
);
278 ST_STACK_PUSH (machine
, result
);
281 ST_PRIMITIVE_FAIL (machine
);
285 ST_STACK_UNPOP (machine
, 2);
289 SmallInteger_mod (st_machine
*machine
)
291 int y
= pop_integer (machine
);
292 int x
= pop_integer (machine
);
295 if (ST_LIKELY (machine
->success
)) {
296 result
= st_smi_new (x
% y
);
297 ST_STACK_PUSH (machine
, result
);
301 ST_STACK_UNPOP (machine
, 2);
305 SmallInteger_bitOr (st_machine
*machine
)
307 int y
= pop_integer (machine
);
308 int x
= pop_integer (machine
);
309 st_oop result
= ST_NIL
;
311 if (ST_LIKELY (machine
->success
)) {
312 result
= st_smi_new (x
| y
);
313 ST_STACK_PUSH (machine
, result
);
317 ST_STACK_UNPOP (machine
, 2);
321 SmallInteger_bitXor (st_machine
*machine
)
323 int y
= pop_integer (machine
);
324 int x
= pop_integer (machine
);
327 if (ST_LIKELY (machine
->success
)) {
328 result
= st_smi_new (x
^ y
);
329 ST_STACK_PUSH (machine
, result
);
333 ST_STACK_UNPOP (machine
, 2);
337 SmallInteger_bitAnd (st_machine
*machine
)
339 int y
= pop_integer (machine
);
340 int x
= pop_integer (machine
);
341 st_oop result
= ST_NIL
;
343 if (ST_LIKELY (machine
->success
)) {
344 result
= st_smi_new (x
& y
);
345 ST_STACK_PUSH (machine
, result
);
349 ST_STACK_UNPOP (machine
, 2);
353 SmallInteger_bitShift (st_machine
*machine
)
355 int y
= pop_integer (machine
);
356 int x
= pop_integer (machine
);
357 st_oop result
= ST_NIL
;
359 if (ST_LIKELY (machine
->success
)) {
361 result
= st_smi_new (x
<< y
);
363 result
= st_smi_new (x
>> (-y
));
365 result
= st_smi_new (x
);
367 ST_STACK_PUSH (machine
, result
);
371 ST_STACK_UNPOP (machine
, 2);
375 SmallInteger_asFloat (st_machine
*machine
)
377 int x
= pop_integer (machine
);
378 st_oop result
= ST_NIL
;
380 if (ST_LIKELY (machine
->success
)) {
381 result
= st_float_new ((double) x
);
382 ST_STACK_PUSH (machine
, result
);
386 ST_STACK_UNPOP (machine
, 1);
390 SmallInteger_asLargeInteger (st_machine
*machine
)
392 int receiver
= pop_integer (machine
);
396 mp_init_set (&value
, abs (receiver
));
399 mp_neg (&value
, &value
);
401 result
= st_large_integer_new (&value
);
402 ST_STACK_PUSH (machine
, result
);
405 #define VALUE(oop) (&(ST_LARGE_INTEGER(oop)->value))
407 /* useful macros to avoid duplication of error-handling code */
409 #define OP_PROLOGUE \
414 #define BINARY_OP(op, a, b) \
416 result = op (VALUE (a), VALUE (b), &value);
418 #define BINARY_DIV_OP(op, a, b) \
420 result = op (VALUE (a), VALUE (b), &value, NULL);
422 #define UNARY_OP(op, a) \
424 result = op (VALUE (a), &value);
428 pop_large_integer (st_machine
*machine
)
430 st_oop object
= ST_STACK_POP (machine
);
432 set_success (machine
, st_object_class (object
) == ST_LARGE_INTEGER_CLASS
);
438 LargeInteger_add (st_machine
*machine
)
440 st_oop b
= pop_large_integer (machine
);
441 st_oop a
= pop_large_integer (machine
);
444 if (!machine
->success
) {
445 ST_STACK_UNPOP (machine
, 2);
449 BINARY_OP (mp_add
, a
, b
);
451 result
= st_large_integer_new (&value
);
452 ST_STACK_PUSH (machine
, result
);
456 LargeInteger_sub (st_machine
*machine
)
458 st_oop b
= pop_large_integer (machine
);
459 st_oop a
= pop_large_integer (machine
);
462 if (!machine
->success
) {
463 ST_STACK_UNPOP (machine
, 2);
467 BINARY_OP (mp_sub
, a
, b
);
469 result
= st_large_integer_new (&value
);
470 ST_STACK_PUSH (machine
, result
);
474 LargeInteger_mul (st_machine
*machine
)
476 st_oop b
= pop_large_integer (machine
);
477 st_oop a
= pop_large_integer (machine
);
480 if (!machine
->success
) {
481 ST_STACK_UNPOP (machine
, 2);
485 BINARY_OP (mp_mul
, a
, b
);
487 result
= st_large_integer_new (&value
);
488 ST_STACK_PUSH (machine
, result
);
492 LargeInteger_div (st_machine
*machine
)
494 st_oop b
= pop_large_integer (machine
);
495 st_oop a
= pop_large_integer (machine
);
496 mp_int quotient
, remainder
;
499 if (!machine
->success
) {
500 ST_STACK_UNPOP (machine
, 2);
504 mp_init_multi ("ient
, &remainder
, NULL
);
505 mp_div (VALUE (a
), VALUE (b
), "ient
, &remainder
);
510 mp_radix_size (&remainder
, 10, &size
);
511 str
= st_malloc (size
);
512 mp_toradix (&remainder
, str
, 10);
514 if (mp_cmp_d (&remainder
, 0) == MP_EQ
) {
515 result
= st_large_integer_new ("ient
);
516 ST_STACK_PUSH (machine
, result
);
517 mp_clear (&remainder
);
519 set_success (machine
, false);
520 ST_STACK_UNPOP (machine
, 2);
521 mp_clear_multi ("ient
, &remainder
, NULL
);
526 LargeInteger_intDiv (st_machine
*machine
)
528 st_oop b
= pop_large_integer (machine
);
529 st_oop a
= pop_large_integer (machine
);
532 if (!machine
->success
) {
533 ST_STACK_UNPOP (machine
, 2);
537 BINARY_DIV_OP (mp_div
, a
, b
);
539 result
= st_large_integer_new (&value
);
540 ST_STACK_PUSH (machine
, result
);
544 LargeInteger_mod (st_machine
*machine
)
546 st_oop b
= pop_large_integer (machine
);
547 st_oop a
= pop_large_integer (machine
);
550 if (!machine
->success
) {
551 ST_STACK_UNPOP (machine
, 2);
555 BINARY_OP (mp_mod
, a
, b
);
557 result
= st_large_integer_new (&value
);
558 ST_STACK_PUSH (machine
, result
);
562 LargeInteger_gcd (st_machine
*machine
)
564 st_oop b
= pop_large_integer (machine
);
565 st_oop a
= pop_large_integer (machine
);
568 if (!machine
->success
) {
569 ST_STACK_UNPOP (machine
, 2);
573 BINARY_OP (mp_gcd
, a
, b
);
575 result
= st_large_integer_new (&value
);
576 ST_STACK_PUSH (machine
, result
);
580 LargeInteger_lcm (st_machine
*machine
)
582 st_oop b
= pop_large_integer (machine
);
583 st_oop a
= pop_large_integer (machine
);
586 if (!machine
->success
) {
587 ST_STACK_UNPOP (machine
, 2);
591 BINARY_OP (mp_lcm
, a
, b
);
593 result
= st_large_integer_new (&value
);
594 ST_STACK_PUSH (machine
, result
);
598 LargeInteger_eq (st_machine
*machine
)
600 st_oop b
= pop_large_integer (machine
);
601 st_oop a
= pop_large_integer (machine
);
605 if (!machine
->success
) {
606 ST_STACK_UNPOP (machine
, 2);
610 relation
= mp_cmp (VALUE (a
), VALUE (b
));
611 result
= (relation
== MP_EQ
) ? ST_TRUE
: ST_FALSE
;
612 ST_STACK_PUSH (machine
, result
);
616 LargeInteger_ne (st_machine
*machine
)
618 st_oop b
= pop_large_integer (machine
);
619 st_oop a
= pop_large_integer (machine
);
623 if (!machine
->success
) {
624 ST_STACK_UNPOP (machine
, 2);
628 relation
= mp_cmp (VALUE (a
), VALUE (b
));
629 result
= (relation
== MP_EQ
) ? ST_FALSE
: ST_TRUE
;
630 ST_STACK_PUSH (machine
, result
);
634 LargeInteger_lt (st_machine
*machine
)
636 st_oop b
= pop_large_integer (machine
);
637 st_oop a
= pop_large_integer (machine
);
641 if (!machine
->success
) {
642 ST_STACK_UNPOP (machine
, 2);
646 relation
= mp_cmp (VALUE (a
), VALUE (b
));
647 result
= (relation
== MP_LT
) ? ST_TRUE
: ST_FALSE
;
648 ST_STACK_PUSH (machine
, result
);
652 LargeInteger_gt (st_machine
*machine
)
654 st_oop b
= pop_large_integer (machine
);
655 st_oop a
= pop_large_integer (machine
);
660 if (!machine
->success
) {
661 ST_STACK_UNPOP (machine
, 2);
665 relation
= mp_cmp (VALUE (a
), VALUE (b
));
666 result
= (relation
== MP_GT
) ? ST_TRUE
: ST_FALSE
;
667 ST_STACK_PUSH (machine
, result
);
671 LargeInteger_le (st_machine
*machine
)
673 st_oop b
= pop_large_integer (machine
);
674 st_oop a
= pop_large_integer (machine
);
678 if (!machine
->success
) {
679 ST_STACK_UNPOP (machine
, 2);
683 relation
= mp_cmp (VALUE (a
), VALUE (b
));
684 result
= (relation
== MP_LT
|| relation
== MP_EQ
) ? ST_TRUE
: ST_FALSE
;
685 ST_STACK_PUSH (machine
, result
);
689 LargeInteger_ge (st_machine
*machine
)
691 st_oop b
= pop_large_integer (machine
);
692 st_oop a
= pop_large_integer (machine
);
696 if (!machine
->success
) {
697 ST_STACK_UNPOP (machine
, 2);
701 relation
= mp_cmp (VALUE (a
), VALUE (b
));
702 result
= (relation
== MP_GT
|| relation
== MP_EQ
) ? ST_TRUE
: ST_FALSE
;
703 ST_STACK_PUSH (machine
, result
);
707 LargeInteger_squared (st_machine
*machine
)
709 st_oop receiver
= pop_large_integer (machine
);
712 if (!machine
->success
) {
713 ST_STACK_UNPOP (machine
, 1);
717 UNARY_OP (mp_sqr
, receiver
);
719 result
= st_large_integer_new (&value
);
720 ST_STACK_PUSH (machine
, result
);
724 LargeInteger_bitOr (st_machine
*machine
)
726 st_oop b
= pop_large_integer (machine
);
727 st_oop a
= pop_large_integer (machine
);
730 if (!machine
->success
) {
731 ST_STACK_UNPOP (machine
, 2);
735 BINARY_OP (mp_or
, a
, b
);
737 result
= st_large_integer_new (&value
);
738 ST_STACK_PUSH (machine
, result
);
742 LargeInteger_bitAnd (st_machine
*machine
)
744 st_oop b
= pop_large_integer (machine
);
745 st_oop a
= pop_large_integer (machine
);
748 if (!machine
->success
) {
749 ST_STACK_UNPOP (machine
, 2);
753 BINARY_OP (mp_and
, a
, b
);
755 result
= st_large_integer_new (&value
);
756 ST_STACK_PUSH (machine
, result
);
760 LargeInteger_bitXor (st_machine
*machine
)
762 st_oop b
= pop_large_integer (machine
);
763 st_oop a
= pop_large_integer (machine
);
766 if (!machine
->success
) {
767 ST_STACK_UNPOP (machine
, 2);
771 BINARY_OP (mp_xor
, a
, b
);
773 result
= st_large_integer_new (&value
);
774 ST_STACK_PUSH (machine
, result
);
778 LargeInteger_bitShift (st_machine
*machine
)
780 int displacement
= pop_integer32 (machine
);
781 st_oop receiver
= pop_large_integer (machine
);
785 if (!machine
->success
) {
786 ST_STACK_UNPOP (machine
, 2);
792 if (displacement
>= 0)
793 mp_mul_2d (VALUE (receiver
), displacement
, &value
);
795 mp_div_2d (VALUE (receiver
), abs (displacement
), &value
, NULL
);
797 result
= st_large_integer_new (&value
);
798 ST_STACK_PUSH (machine
, result
);
801 #define ST_DIGIT_RADIX (1L << DIGIT_BIT)
805 LargeInteger_asFloat (st_machine
*machine
)
807 st_oop receiver
= pop_large_integer (machine
);
813 m
= st_large_integer_value (receiver
);
815 ST_STACK_PUSH (machine
, st_float_new (0));
820 result
= DIGIT (m
, i
);
822 result
= (result
* ST_DIGIT_RADIX
) + DIGIT (m
, i
);
824 if (m
->sign
== MP_NEG
)
827 ST_STACK_PUSH (machine
, st_float_new (result
));
831 LargeInteger_printStringBase (st_machine
*machine
)
833 int radix
= pop_integer (machine
);
834 st_oop x
= pop_large_integer (machine
);
838 if (radix
< 2 || radix
> 36)
839 set_success (machine
, false);
841 if (machine
->success
) {
842 string
= st_large_integer_to_string (x
, radix
);
843 result
= st_string_new (string
);
846 if (machine
->success
)
847 ST_STACK_PUSH (machine
, result
);
849 ST_STACK_UNPOP (machine
, 2);
853 LargeInteger_hash (st_machine
*machine
)
855 st_oop receiver
= ST_STACK_POP (machine
);
862 value
= st_large_integer_value (receiver
);
863 c
= (const char *) value
->dp
;
864 len
= value
->used
* sizeof (mp_digit
);
867 for(unsigned int i
= 0; i
< len
; i
++)
869 hash
= ((hash
<< 5) + hash
) + c
[i
];
876 ST_STACK_PUSH (machine
, st_smi_new (result
));
881 pop_float (st_machine
*machine
)
883 st_oop object
= ST_STACK_POP (machine
);
885 set_success (machine
, st_object_class (object
) == ST_FLOAT_CLASS
);
891 Float_add (st_machine
*machine
)
893 st_oop y
= pop_float (machine
);
894 st_oop x
= pop_float (machine
);
895 st_oop result
= ST_NIL
;
897 if (machine
->success
)
898 result
= st_float_new (st_float_value (x
) + st_float_value (y
));
900 if (machine
->success
)
901 ST_STACK_PUSH (machine
, result
);
903 ST_STACK_UNPOP (machine
, 2);
907 Float_sub (st_machine
*machine
)
909 st_oop y
= pop_float (machine
);
910 st_oop x
= pop_float (machine
);
911 st_oop result
= ST_NIL
;
913 if (machine
->success
)
914 result
= st_float_new (st_float_value (x
) - st_float_value (y
));
916 if (machine
->success
)
917 ST_STACK_PUSH (machine
, result
);
919 ST_STACK_UNPOP (machine
, 2);
923 Float_lt (st_machine
*machine
)
925 st_oop y
= pop_float (machine
);
926 st_oop x
= pop_float (machine
);
927 st_oop result
= ST_NIL
;
929 if (machine
->success
)
930 result
= isless (st_float_value (x
), st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
932 if (machine
->success
)
933 ST_STACK_PUSH (machine
, result
);
935 ST_STACK_UNPOP (machine
, 2);
939 Float_gt (st_machine
*machine
)
941 st_oop y
= pop_float (machine
);
942 st_oop x
= pop_float (machine
);
943 st_oop result
= ST_NIL
;
945 if (machine
->success
)
946 result
= isgreater (st_float_value (x
), st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
948 if (machine
->success
)
949 ST_STACK_PUSH (machine
, result
);
951 ST_STACK_UNPOP (machine
, 2);
955 Float_le (st_machine
*machine
)
957 st_oop y
= pop_float (machine
);
958 st_oop x
= pop_float (machine
);
959 st_oop result
= ST_NIL
;
961 if (machine
->success
)
962 result
= islessequal (st_float_value (x
), st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
964 if (machine
->success
)
965 ST_STACK_PUSH (machine
, result
);
967 ST_STACK_UNPOP (machine
, 2);
971 Float_ge (st_machine
*machine
)
973 st_oop y
= pop_float (machine
);
974 st_oop x
= pop_float (machine
);
975 st_oop result
= ST_NIL
;
977 if (machine
->success
)
978 result
= isgreaterequal (st_float_value (x
), st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
980 if (machine
->success
)
981 ST_STACK_PUSH (machine
, result
);
983 ST_STACK_UNPOP (machine
, 2);
987 Float_eq (st_machine
*machine
)
989 st_oop y
= pop_float (machine
);
990 st_oop x
= pop_float (machine
);
991 st_oop result
= ST_NIL
;
993 if (machine
->success
)
994 result
= (st_float_value (x
) == st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
996 if (machine
->success
)
997 ST_STACK_PUSH (machine
, result
);
999 ST_STACK_UNPOP (machine
, 2);
1003 Float_ne (st_machine
*machine
)
1005 st_oop y
= pop_float (machine
);
1006 st_oop x
= pop_float (machine
);
1007 st_oop result
= ST_NIL
;
1009 if (machine
->success
)
1010 result
= (st_float_value (x
) != st_float_value (y
)) ? ST_TRUE
: ST_FALSE
;
1012 if (machine
->success
)
1013 ST_STACK_PUSH (machine
, result
);
1015 ST_STACK_UNPOP (machine
, 2);
1019 Float_mul (st_machine
*machine
)
1021 st_oop y
= pop_float (machine
);
1022 st_oop x
= pop_float (machine
);
1023 st_oop result
= ST_NIL
;
1025 if (machine
->success
)
1026 result
= st_float_new (st_float_value (x
) * st_float_value (y
));
1028 if (machine
->success
)
1029 ST_STACK_PUSH (machine
, result
);
1031 ST_STACK_UNPOP (machine
, 2);
1035 Float_div (st_machine
*machine
)
1037 st_oop y
= pop_float (machine
);
1038 st_oop x
= pop_float (machine
);
1039 st_oop result
= ST_NIL
;
1041 set_success (machine
, y
!= 0);
1043 if (machine
->success
)
1044 result
= st_float_new (st_float_value (x
) / st_float_value (y
));
1046 if (machine
->success
)
1047 ST_STACK_PUSH (machine
, result
);
1049 ST_STACK_UNPOP (machine
, 2);
1053 Float_sin (st_machine
*machine
)
1055 st_oop receiver
= ST_STACK_POP (machine
);
1059 value
= st_float_value (receiver
);
1061 result
= st_float_new (sin (value
));
1063 if (machine
->success
)
1064 ST_STACK_PUSH (machine
, result
);
1066 ST_STACK_UNPOP (machine
, 1);
1070 Float_cos (st_machine
*machine
)
1072 st_oop receiver
= ST_STACK_POP (machine
);
1076 value
= st_float_value (receiver
);
1078 result
= st_float_new (cos (value
));
1080 if (machine
->success
)
1081 ST_STACK_PUSH (machine
, result
);
1083 ST_STACK_UNPOP (machine
, 1);
1087 Float_tan (st_machine
*machine
)
1089 st_oop receiver
= ST_STACK_POP (machine
);
1093 value
= st_float_value (receiver
);
1095 result
= st_float_new (tan (value
));
1097 if (machine
->success
)
1098 ST_STACK_PUSH (machine
, result
);
1100 ST_STACK_UNPOP (machine
, 1);
1104 Float_arcSin (st_machine
*machine
)
1106 st_oop receiver
= ST_STACK_POP (machine
);
1110 value
= st_float_value (receiver
);
1112 result
= st_float_new (asin (value
));
1114 if (machine
->success
)
1115 ST_STACK_PUSH (machine
, result
);
1117 ST_STACK_UNPOP (machine
, 1);
1121 Float_arcCos (st_machine
*machine
)
1123 st_oop receiver
= ST_STACK_POP (machine
);
1127 value
= st_float_value (receiver
);
1129 result
= st_float_new (acos (value
));
1131 if (machine
->success
)
1132 ST_STACK_PUSH (machine
, result
);
1134 ST_STACK_UNPOP (machine
, 1);
1138 Float_arcTan (st_machine
*machine
)
1140 st_oop receiver
= ST_STACK_POP (machine
);
1144 value
= st_float_value (receiver
);
1146 result
= st_float_new (atan (value
));
1148 if (machine
->success
)
1149 ST_STACK_PUSH (machine
, result
);
1151 ST_STACK_UNPOP (machine
, 1);
1155 Float_sqrt (st_machine
*machine
)
1157 st_oop receiver
= ST_STACK_POP (machine
);
1161 value
= st_float_value (receiver
);
1163 result
= st_float_new (sqrt (value
));
1165 if (machine
->success
)
1166 ST_STACK_PUSH (machine
, result
);
1168 ST_STACK_UNPOP (machine
, 1);
1172 Float_log (st_machine
*machine
)
1174 st_oop receiver
= ST_STACK_POP (machine
);
1178 value
= st_float_value (receiver
);
1180 result
= st_float_new (log10 (value
));
1182 if (machine
->success
)
1183 ST_STACK_PUSH (machine
, result
);
1185 ST_STACK_UNPOP (machine
, 1);
1189 Float_ln (st_machine
*machine
)
1191 st_oop receiver
= ST_STACK_POP (machine
);
1195 value
= st_float_value (receiver
);
1197 result
= st_float_new (log (value
));
1199 if (machine
->success
)
1200 ST_STACK_PUSH (machine
, result
);
1202 ST_STACK_UNPOP (machine
, 1);
1206 Float_exp (st_machine
*machine
)
1208 st_oop receiver
= ST_STACK_POP (machine
);
1212 value
= st_float_value (receiver
);
1214 result
= st_float_new (exp (value
));
1216 if (machine
->success
)
1217 ST_STACK_PUSH (machine
, result
);
1219 ST_STACK_UNPOP (machine
, 1);
1223 Float_truncated (st_machine
*machine
)
1225 st_oop receiver
= ST_STACK_POP (machine
);
1228 result
= (int) trunc (st_float_value (receiver
));
1230 ST_STACK_PUSH (machine
, st_smi_new (result
));
1234 Float_fractionPart (st_machine
*machine
)
1236 st_oop receiver
= ST_STACK_POP (machine
);
1237 double frac_part
, int_part
;
1240 frac_part
= modf (st_float_value (receiver
), &int_part
);
1242 result
= st_float_new (frac_part
);
1244 ST_STACK_PUSH (machine
, result
);
1248 Float_integerPart (st_machine
*machine
)
1250 st_oop receiver
= ST_STACK_POP (machine
);
1254 modf (st_float_value (receiver
), &int_part
);
1256 result
= st_smi_new ((int) int_part
);
1257 ST_STACK_PUSH (machine
, result
);
1261 Float_hash (st_machine
*machine
)
1263 st_oop receiver
= ST_STACK_POP (machine
);
1264 unsigned int hash
= 0;
1269 value
= st_float_value (receiver
);
1272 value
= fabs (value
);
1274 c
= (unsigned char *) & value
;
1275 for (int i
= 0; i
< sizeof (double); i
++) {
1276 hash
= (hash
* 971) ^ c
[i
];
1284 ST_STACK_PUSH (machine
, st_smi_new (result
));
1288 Float_printStringBase (st_machine
*machine
)
1290 int base
= pop_integer(machine
);
1291 st_oop receiver
= ST_STACK_POP (machine
);
1295 if (!machine
->success
||
1296 !st_object_is_heap (receiver
) ||
1297 st_object_format (receiver
) != ST_FORMAT_FLOAT
) {
1298 machine
->success
= false;
1299 ST_STACK_UNPOP (machine
, 2);
1303 /* ignore base for the time being */
1304 tmp
= st_strdup_printf ("%g", st_float_value (receiver
));
1305 string
= st_string_new (tmp
);
1308 ST_STACK_PUSH (machine
, string
);
1312 Object_error (st_machine
*machine
)
1318 traceback
= ST_STACK_POP (machine
);
1319 message
= ST_STACK_POP (machine
);
1320 receiver
= ST_STACK_POP (machine
);
1322 if (!st_object_is_heap (traceback
) ||
1323 st_object_format (traceback
) != ST_FORMAT_BYTE_ARRAY
) {
1324 /* can't resume execution in this prim */
1328 if (!st_object_is_heap (message
) ||
1329 st_object_format (message
) != ST_FORMAT_BYTE_ARRAY
) {
1330 /* can't resume execution in this prim */
1334 printf ("An error occurred during program execution\n");
1335 printf ("message: %s\n\n", st_byte_array_bytes (message
));
1337 printf ("Traceback:\n");
1338 puts (st_byte_array_bytes (traceback
));
1340 /* set success to false to signal error */
1341 machine
->success
= false;
1342 longjmp (machine
->main_loop
, 0);
1346 Object_class (st_machine
*machine
)
1350 object
= ST_STACK_POP (machine
);
1352 ST_STACK_PUSH (machine
, st_object_class (object
));
1356 Object_identityHash (st_machine
*machine
)
1361 object
= ST_STACK_POP (machine
);
1363 if (st_object_is_smi (object
))
1364 hash
= st_smi_hash (object
);
1365 else if (st_object_is_character (object
))
1366 hash
= st_character_hash (object
);
1368 st_object_set_hashed (object
, true);
1369 hash
= st_identity_hashtable_hash (memory
->ht
, object
);
1371 ST_STACK_PUSH (machine
, st_smi_new (hash
));
1375 Object_copy (st_machine
*machine
)
1382 (void) ST_STACK_POP (machine
);
1384 if (!st_object_is_heap (machine
->message_receiver
)) {
1385 ST_STACK_PUSH (machine
, machine
->message_receiver
);
1389 switch (st_object_format (machine
->message_receiver
)) {
1391 case ST_FORMAT_OBJECT
:
1393 class = ST_OBJECT_CLASS (machine
->message_receiver
);
1394 size
= st_smi_value (ST_BEHAVIOR_INSTANCE_SIZE (class));
1395 copy
= st_object_new (class);
1396 st_oops_copy (ST_OBJECT_FIELDS (copy
),
1397 ST_OBJECT_FIELDS (machine
->message_receiver
),
1402 case ST_FORMAT_ARRAY
:
1404 size
= st_smi_value (ST_ARRAYED_OBJECT (machine
->message_receiver
)->size
);
1405 copy
= st_object_new_arrayed (ST_OBJECT_CLASS (machine
->message_receiver
), size
);
1406 st_oops_copy (ST_ARRAY (copy
)->elements
,
1407 ST_ARRAY (machine
->message_receiver
)->elements
,
1411 case ST_FORMAT_BYTE_ARRAY
:
1413 size
= st_smi_value (ST_ARRAYED_OBJECT (machine
->message_receiver
)->size
);
1414 copy
= st_object_new_arrayed (ST_OBJECT_CLASS (machine
->message_receiver
), size
);
1415 memcpy (st_byte_array_bytes (copy
),
1416 st_byte_array_bytes (machine
->message_receiver
),
1420 case ST_FORMAT_FLOAT_ARRAY
:
1422 size
= st_smi_value (st_arrayed_object_size (machine
->message_receiver
));
1423 copy
= st_object_new_arrayed (ST_OBJECT_CLASS (machine
->message_receiver
), size
);
1424 memcpy (st_float_array_elements (copy
),
1425 st_float_array_elements (machine
->message_receiver
),
1426 sizeof (double) * size
);
1430 case ST_FORMAT_WORD_ARRAY
:
1432 size
= st_smi_value (st_arrayed_object_size (machine
->message_receiver
));
1433 copy
= st_object_new_arrayed (ST_OBJECT_CLASS (machine
->message_receiver
), size
);
1434 memcpy (st_word_array_elements (copy
),
1435 st_word_array_elements (machine
->message_receiver
),
1436 sizeof (st_uint
) * size
);
1439 case ST_FORMAT_FLOAT
:
1441 copy
= st_object_new (ST_FLOAT_CLASS
);
1442 st_float_set_value (copy
, st_float_value (machine
->message_receiver
));
1445 case ST_FORMAT_LARGE_INTEGER
:
1450 copy
= st_object_new (ST_LARGE_INTEGER_CLASS
);
1452 result
= mp_init_copy (st_large_integer_value (copy
),
1453 st_large_integer_value (machine
->message_receiver
));
1454 if (result
!= MP_OKAY
)
1458 case ST_FORMAT_HANDLE
:
1460 copy
= st_object_new (ST_HANDLE_CLASS
);
1461 ST_HANDLE_VALUE (copy
) = ST_HANDLE_VALUE (machine
->message_receiver
);
1463 case ST_FORMAT_CONTEXT
:
1464 case ST_FORMAT_INTEGER_ARRAY
:
1466 /* not implemented yet */
1470 ST_STACK_PUSH (machine
, copy
);
1474 Object_equivalent (st_machine
*machine
)
1476 st_oop y
= ST_STACK_POP (machine
);
1477 st_oop x
= ST_STACK_POP (machine
);
1479 ST_STACK_PUSH (machine
, ((x
== y
) ? ST_TRUE
: ST_FALSE
));
1483 lookup_method (st_oop
class, st_oop selector
)
1486 st_oop parent
= class;
1489 while (parent
!= ST_NIL
) {
1490 method
= st_dictionary_at (ST_BEHAVIOR_METHOD_DICTIONARY (parent
), selector
);
1491 if (method
!= ST_NIL
)
1493 parent
= ST_BEHAVIOR_SUPERCLASS (parent
);
1500 Object_perform (st_machine
*machine
)
1505 st_uint selector_index
;
1507 selector
= machine
->message_selector
;
1508 machine
->message_selector
= machine
->stack
[machine
->sp
- machine
->message_argcount
];
1509 receiver
= machine
->message_receiver
;
1511 set_success (machine
, st_object_is_symbol (machine
->message_selector
));
1512 method
= lookup_method (st_object_class (receiver
), machine
->message_selector
);
1513 set_success (machine
, st_method_get_arg_count (method
) == (machine
->message_argcount
- 1));
1515 if (machine
->success
) {
1516 selector_index
= machine
->sp
- machine
->message_argcount
;
1518 st_oops_move (machine
->stack
+ selector_index
,
1519 machine
->stack
+ selector_index
+ 1,
1520 machine
->message_argcount
- 1);
1523 machine
->message_argcount
-= 1;
1524 machine
->new_method
= method
;
1525 st_machine_execute_method (machine
);
1528 machine
->message_selector
= selector
;
1533 Object_perform_withArguments (st_machine
*machine
)
1541 array
= ST_STACK_POP (machine
);
1543 set_success (machine
, st_object_format (array
) == ST_FORMAT_ARRAY
);
1545 if (ST_OBJECT_CLASS (machine
->context
) == ST_BLOCK_CONTEXT_CLASS
)
1546 method
= ST_METHOD_CONTEXT_METHOD (ST_BLOCK_CONTEXT_HOME (machine
->context
));
1548 method
= ST_METHOD_CONTEXT_METHOD (machine
->context
);
1550 array_size
= st_smi_value (st_arrayed_object_size (array
));
1551 set_success (machine
, (machine
->sp
+ array_size
- 1) < 32);
1553 if (machine
->success
) {
1555 selector
= machine
->message_selector
;
1556 machine
->message_selector
= ST_STACK_POP (machine
);
1557 receiver
= ST_STACK_PEEK (machine
);
1558 machine
->message_argcount
= array_size
;
1560 set_success (machine
, st_object_is_symbol (machine
->message_selector
));
1562 st_oops_copy (machine
->stack
+ machine
->sp
,
1563 st_array_elements (array
),
1566 machine
->sp
+= array_size
;
1568 method
= lookup_method (st_object_class (receiver
), machine
->message_selector
);
1569 set_success (machine
, st_method_get_arg_count (method
) == array_size
);
1571 if (machine
->success
) {
1572 machine
->new_method
= method
;
1573 st_machine_execute_method (machine
);
1575 machine
->sp
-= machine
->message_argcount
;
1576 ST_STACK_PUSH (machine
, machine
->message_selector
);
1577 ST_STACK_PUSH (machine
, array
);
1578 machine
->message_argcount
= 2;
1579 machine
->message_selector
= selector
;
1583 ST_STACK_UNPOP (machine
, 1);
1588 Behavior_new (st_machine
*machine
)
1594 class = ST_STACK_POP (machine
);
1596 switch (st_smi_value (ST_BEHAVIOR_FORMAT (class))) {
1597 case ST_FORMAT_OBJECT
:
1598 instance
= st_object_allocate (class);
1600 case ST_FORMAT_CONTEXT
:
1601 /* not implemented */
1604 case ST_FORMAT_FLOAT
:
1605 instance
= st_float_allocate (class);
1607 case ST_FORMAT_LARGE_INTEGER
:
1608 instance
= st_large_integer_allocate (class, NULL
);
1610 case ST_FORMAT_HANDLE
:
1611 instance
= st_handle_allocate (class);
1614 /* should not reach */
1618 ST_STACK_PUSH (machine
, instance
);
1622 Behavior_newSize (st_machine
*machine
)
1629 size
= pop_integer32 (machine
);
1630 class = ST_STACK_POP (machine
);
1632 switch (st_smi_value (ST_BEHAVIOR_FORMAT (class))) {
1633 case ST_FORMAT_ARRAY
:
1634 instance
= st_array_allocate (class, size
);
1636 case ST_FORMAT_BYTE_ARRAY
:
1637 instance
= st_byte_array_allocate (class, size
);
1639 case ST_FORMAT_WORD_ARRAY
:
1640 instance
= st_word_array_allocate (class, size
);
1642 case ST_FORMAT_FLOAT_ARRAY
:
1643 instance
= st_float_array_allocate (class, size
);
1645 case ST_FORMAT_INTEGER_ARRAY
:
1646 /* not implemented */
1650 /* should not reach */
1654 ST_STACK_PUSH (machine
, instance
);
1658 Behavior_compile (st_machine
*machine
)
1660 st_compiler_error error
;
1664 string
= ST_STACK_POP (machine
);
1665 receiver
= ST_STACK_POP (machine
);
1666 if (!st_object_is_heap (string
) ||
1667 st_object_format (string
) != ST_FORMAT_BYTE_ARRAY
) {
1668 machine
->success
= false;
1669 ST_STACK_UNPOP (machine
, 2);
1673 if (!st_compile_string (receiver
,
1674 (char *) st_byte_array_bytes (string
),
1676 machine
->success
= false;
1677 ST_STACK_UNPOP (machine
, 2);
1681 ST_STACK_PUSH (machine
, receiver
);
1685 SequenceableCollection_size (st_machine
*machine
)
1689 object
= ST_STACK_POP (machine
);
1691 ST_STACK_PUSH (machine
, st_arrayed_object_size (object
));
1695 Array_at (st_machine
*machine
)
1697 int index
= pop_integer32 (machine
);
1698 st_oop receiver
= ST_STACK_POP (machine
);
1700 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1701 set_success (machine
, false);
1702 ST_STACK_UNPOP (machine
, 2);
1706 ST_STACK_PUSH (machine
, st_array_at (receiver
, index
));
1710 Array_at_put (st_machine
*machine
)
1712 st_oop object
= ST_STACK_POP (machine
);
1713 int index
= pop_integer32 (machine
);
1714 st_oop receiver
= ST_STACK_POP (machine
);
1716 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1717 set_success (machine
, false);
1718 ST_STACK_UNPOP (machine
, 3);
1722 st_array_at_put (receiver
, index
, object
);
1723 ST_STACK_PUSH (machine
, object
);
1727 ByteArray_at (st_machine
*machine
)
1729 int index
= pop_integer32 (machine
);
1730 st_oop receiver
= ST_STACK_POP (machine
);
1733 if (!machine
->success
) {
1734 ST_STACK_UNPOP (machine
, 2);
1738 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1739 set_success (machine
, false);
1740 ST_STACK_UNPOP (machine
, 2);
1744 result
= st_smi_new (st_byte_array_at (receiver
, index
));
1746 ST_STACK_PUSH (machine
, result
);
1750 ByteArray_at_put (st_machine
*machine
)
1752 int byte
= pop_integer (machine
);
1753 int index
= pop_integer32 (machine
);
1754 st_oop receiver
= ST_STACK_POP (machine
);
1756 if (!machine
->success
) {
1757 ST_STACK_UNPOP (machine
, 3);
1761 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1762 set_success (machine
, false);
1763 ST_STACK_UNPOP (machine
, 3);
1767 st_byte_array_at_put (receiver
, index
, byte
);
1769 ST_STACK_PUSH (machine
, st_smi_new (byte
));
1773 ByteArray_hash (st_machine
*machine
)
1775 st_oop receiver
= ST_STACK_POP (machine
);
1778 hash
= st_byte_array_hash (receiver
);
1780 ST_STACK_PUSH (machine
, st_smi_new (hash
));
1784 ByteString_at (st_machine
*machine
)
1786 int index
= pop_integer32 (machine
);
1787 st_oop receiver
= ST_STACK_POP (machine
);
1791 if (ST_UNLIKELY (!machine
->success
)) {
1792 ST_STACK_UNPOP (machine
, 2);
1796 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1797 set_success (machine
, false);
1798 ST_STACK_UNPOP (machine
, 2);
1802 character
= st_character_new (st_byte_array_at (receiver
, index
));
1804 ST_STACK_PUSH (machine
, character
);
1808 ByteString_at_put (st_machine
*machine
)
1810 st_oop character
= ST_STACK_POP (machine
);
1811 int index
= pop_integer32 (machine
);
1812 st_oop receiver
= ST_STACK_POP (machine
);
1814 if (!machine
->success
) {
1815 ST_STACK_UNPOP (machine
, 3);
1819 set_success (machine
, st_object_class (character
) == ST_CHARACTER_CLASS
);
1821 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1822 set_success (machine
, false);
1823 ST_STACK_UNPOP (machine
, 3);
1827 st_byte_array_at_put (receiver
, index
, (st_uchar
) st_character_value (character
));
1829 ST_STACK_PUSH (machine
, character
);
1834 ByteString_size (st_machine
*machine
)
1839 receiver
= ST_STACK_POP (machine
);
1841 size
= st_arrayed_object_size (receiver
);
1843 /* TODO: allow size to go into a LargeInteger on overflow */
1844 ST_STACK_PUSH (machine
, size
);
1848 ByteString_compare (st_machine
*machine
)
1850 st_oop argument
= ST_STACK_POP (machine
);
1851 st_oop receiver
= ST_STACK_POP (machine
);
1854 if (st_object_format (argument
) != ST_FORMAT_BYTE_ARRAY
)
1855 set_success (machine
, false);
1857 if (machine
->success
)
1858 order
= strcmp ((const char *) st_byte_array_bytes (receiver
),
1859 (const char *) st_byte_array_bytes (argument
));
1861 if (machine
->success
)
1862 ST_STACK_PUSH (machine
, st_smi_new (order
));
1864 ST_STACK_UNPOP (machine
, 2);
1868 WideString_at (st_machine
*machine
)
1870 int index
= pop_integer32 (machine
);
1871 st_oop receiver
= ST_STACK_POP (machine
);
1875 if (!machine
->success
) {
1876 ST_STACK_UNPOP (machine
, 2);
1880 if (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
))) {
1881 set_success (machine
, false);
1882 ST_STACK_UNPOP (machine
, 2);
1886 c
= st_word_array_at (receiver
, index
);
1888 ST_STACK_PUSH (machine
, st_character_new (c
));
1892 WideString_at_put (st_machine
*machine
)
1894 st_oop character
= ST_STACK_POP (machine
);
1895 int index
= pop_integer32 (machine
);
1896 st_oop receiver
= ST_STACK_POP (machine
);
1900 if (!machine
->success
) {
1901 ST_STACK_UNPOP (machine
, 3);
1905 set_success (machine
, st_object_class (character
) == ST_CHARACTER_CLASS
);
1907 if (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
))) {
1908 set_success (machine
, false);
1909 ST_STACK_UNPOP (machine
, 3);
1913 st_word_array_at_put (receiver
, index
, character
);
1915 ST_STACK_PUSH (machine
, character
);
1919 WordArray_at (st_machine
*machine
)
1925 index
= pop_integer32 (machine
);
1926 receiver
= ST_STACK_POP (machine
);
1928 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1929 set_success (machine
, false);
1930 ST_STACK_UNPOP (machine
, 2);
1934 element
= st_word_array_at (receiver
, index
);
1936 ST_STACK_PUSH (machine
, st_smi_new (element
));
1940 WordArray_at_put (st_machine
*machine
)
1942 int value
= pop_integer (machine
);
1943 int index
= pop_integer32 (machine
);
1944 st_oop receiver
= ST_STACK_POP (machine
);
1946 if (!machine
->success
) {
1947 ST_STACK_UNPOP (machine
, 3);
1951 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1952 set_success (machine
, false);
1953 ST_STACK_UNPOP (machine
, 3);
1957 st_word_array_at_put (receiver
, index
, value
);
1959 ST_STACK_PUSH (machine
, st_smi_new (value
));
1963 FloatArray_at (st_machine
*machine
)
1969 index
= pop_integer32 (machine
);
1970 receiver
= ST_STACK_POP (machine
);
1972 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1973 set_success (machine
, false);
1974 ST_STACK_UNPOP (machine
, 2);
1978 element
= st_float_array_at (receiver
, index
);
1979 ST_STACK_PUSH (machine
, st_float_new (element
));
1983 FloatArray_at_put (st_machine
*machine
)
1985 st_oop flt
= ST_STACK_POP (machine
);
1986 int index
= pop_integer32 (machine
);
1987 st_oop receiver
= ST_STACK_POP (machine
);
1989 set_success (machine
, st_object_is_heap (flt
) &&
1990 st_object_format (flt
) == ST_FORMAT_FLOAT
);
1992 if (ST_UNLIKELY (index
< 1 || index
> st_smi_value (st_arrayed_object_size (receiver
)))) {
1993 set_success (machine
, false);
1994 ST_STACK_UNPOP (machine
, 3);
1998 if (!machine
->success
) {
1999 ST_STACK_UNPOP (machine
, 3);
2003 st_float_array_at_put (receiver
, index
, st_float_value (flt
));
2004 ST_STACK_PUSH (machine
, flt
);
2008 BlockContext_value (st_machine
*machine
)
2014 block
= machine
->message_receiver
;
2015 argcount
= st_smi_value (ST_BLOCK_CONTEXT_ARGCOUNT (block
));
2016 if (ST_UNLIKELY (argcount
!= machine
->message_argcount
)) {
2017 machine
->success
= false;
2021 st_oops_copy (ST_BLOCK_CONTEXT_STACK (block
),
2022 machine
->stack
+ machine
->sp
- argcount
,
2024 machine
->sp
-= machine
->message_argcount
+ 1;
2026 ST_CONTEXT_PART_IP (block
) = ST_BLOCK_CONTEXT_INITIALIP (block
);
2027 ST_CONTEXT_PART_SP (block
) = st_smi_new (argcount
);
2028 ST_CONTEXT_PART_SENDER (block
) = machine
->context
;
2030 st_machine_set_active_context (machine
, block
);
2034 BlockContext_valueWithArguments (st_machine
*machine
)
2040 block
= machine
->message_receiver
;
2041 values
= ST_STACK_PEEK (machine
);
2043 if (st_object_class (values
) != ST_ARRAY_CLASS
) {
2044 set_success (machine
, false);
2048 argcount
= st_smi_value (ST_BLOCK_CONTEXT_ARGCOUNT (block
));
2049 if (argcount
!= st_smi_value (st_arrayed_object_size (values
))) {
2050 set_success (machine
, false);
2054 st_oops_copy (ST_BLOCK_CONTEXT_STACK (block
),
2055 ST_ARRAY (values
)->elements
,
2058 machine
->sp
-= machine
->message_argcount
+ 1;
2060 ST_CONTEXT_PART_IP (block
) = ST_BLOCK_CONTEXT_INITIALIP (block
);
2061 ST_CONTEXT_PART_SP (block
) = st_smi_new (argcount
);
2062 ST_CONTEXT_PART_SENDER (block
) = machine
->context
;
2064 st_machine_set_active_context (machine
, block
);
2068 System_exitWithResult (st_machine
*machine
)
2070 /* set success to true to signal that everything was alright */
2071 machine
->success
= true;
2072 longjmp (machine
->main_loop
, 0);
2076 Character_value (st_machine
*machine
)
2078 st_oop receiver
= ST_STACK_POP (machine
);
2080 ST_STACK_PUSH (machine
, st_smi_new (st_character_value (receiver
)));
2084 Character_characterFor (st_machine
*machine
)
2089 value
= pop_integer (machine
);
2090 receiver
= ST_STACK_POP (machine
);
2092 if (machine
->success
)
2093 ST_STACK_PUSH (machine
, st_character_new (value
));
2095 ST_STACK_UNPOP (machine
, 2);
2099 FileStream_open (st_machine
*machine
)
2107 mode
= pop_integer32 (machine
);
2108 filename
= ST_STACK_POP (machine
);
2109 if (st_object_format (filename
) != ST_FORMAT_BYTE_ARRAY
) {
2110 machine
->success
= false;
2111 ST_STACK_UNPOP (machine
, 2);
2120 machine
->success
= false;
2121 ST_STACK_UNPOP (machine
, 2);
2125 str
= st_byte_array_bytes (filename
);
2127 fd
= open (str
, O_WRONLY
| O_CREAT
, 0644);
2129 fprintf (stderr
, strerror (errno
));
2130 machine
->success
= false;
2131 ST_STACK_UNPOP (machine
, 2);
2138 (void) ST_STACK_POP (machine
);
2140 handle
= st_object_new (ST_HANDLE_CLASS
);
2141 ST_HANDLE_VALUE (handle
) = fd
;
2143 ST_STACK_PUSH (machine
, handle
);
2147 FileStream_close (st_machine
*machine
)
2152 handle
= ST_STACK_POP (machine
);
2153 fd
= ST_HANDLE_VALUE (handle
);
2155 if (close (fd
) < 0) {
2156 machine
->success
= false;
2157 ST_STACK_UNPOP (machine
, 1);
2161 /* leave receiver on stack */
2166 FileStream_write (st_machine
*machine
)
2175 array
= ST_STACK_POP (machine
);
2176 handle
= ST_STACK_POP (machine
);
2177 if (st_object_format (array
) != ST_FORMAT_BYTE_ARRAY
) {
2178 machine
->success
= false;
2179 ST_STACK_UNPOP (machine
, 1);
2182 if (st_object_format (handle
) != ST_FORMAT_HANDLE
) {
2183 machine
->success
= false;
2184 ST_STACK_UNPOP (machine
, 2);
2188 fd
= ST_HANDLE_VALUE (handle
);
2189 buffer
= st_byte_array_bytes (array
);
2190 size
= st_smi_value (st_arrayed_object_size (array
));
2193 while (total
< size
) {
2194 count
= write (fd
, buffer
+ total
, size
- total
);
2196 machine
->success
= false;
2197 ST_STACK_UNPOP (machine
, 2);
2203 /* leave receiver on stack */
2207 FileStream_seek (st_machine
*machine
)
2209 /* not implemented yet */
2214 FileStream_read (st_machine
*machine
)
2216 /* not implemented yet */
2220 const struct st_primitive st_primitives
[] = {
2221 { "SmallInteger_add", SmallInteger_add
},
2222 { "SmallInteger_sub", SmallInteger_sub
},
2223 { "SmallInteger_lt", SmallInteger_lt
},
2224 { "SmallInteger_gt", SmallInteger_gt
},
2225 { "SmallInteger_le", SmallInteger_le
},
2226 { "SmallInteger_ge", SmallInteger_ge
},
2227 { "SmallInteger_eq", SmallInteger_eq
},
2228 { "SmallInteger_ne", SmallInteger_ne
},
2229 { "SmallInteger_mul", SmallInteger_mul
},
2230 { "SmallInteger_div", SmallInteger_div
},
2231 { "SmallInteger_intDiv", SmallInteger_intDiv
},
2232 { "SmallInteger_mod", SmallInteger_mod
},
2233 { "SmallInteger_bitOr", SmallInteger_bitOr
},
2234 { "SmallInteger_bitXor", SmallInteger_bitXor
},
2235 { "SmallInteger_bitAnd", SmallInteger_bitAnd
},
2236 { "SmallInteger_bitShift", SmallInteger_bitShift
},
2237 { "SmallInteger_asFloat", SmallInteger_asFloat
},
2238 { "SmallInteger_asLargeInteger", SmallInteger_asLargeInteger
},
2240 { "LargeInteger_add", LargeInteger_add
},
2241 { "LargeInteger_sub", LargeInteger_sub
},
2242 { "LargeInteger_lt", LargeInteger_lt
},
2243 { "LargeInteger_gt", LargeInteger_gt
},
2244 { "LargeInteger_le", LargeInteger_le
},
2245 { "LargeInteger_ge", LargeInteger_ge
},
2246 { "LargeInteger_eq", LargeInteger_eq
},
2247 { "LargeInteger_ne", LargeInteger_ne
},
2248 { "LargeInteger_mul", LargeInteger_mul
},
2249 { "LargeInteger_div", LargeInteger_div
},
2250 { "LargeInteger_intDiv", LargeInteger_intDiv
},
2251 { "LargeInteger_mod", LargeInteger_mod
},
2252 { "LargeInteger_gcd", LargeInteger_gcd
},
2253 { "LargeInteger_lcm", LargeInteger_lcm
},
2254 { "LargeInteger_squared", LargeInteger_squared
},
2255 { "LargeInteger_bitOr", LargeInteger_bitOr
},
2256 { "LargeInteger_bitXor", LargeInteger_bitXor
},
2257 { "LargeInteger_bitAnd", LargeInteger_bitAnd
},
2258 { "LargeInteger_bitShift", LargeInteger_bitShift
},
2259 { "LargeInteger_printStringBase", LargeInteger_printStringBase
},
2260 { "LargeInteger_asFloat", LargeInteger_asFloat
},
2261 { "LargeInteger_hash", LargeInteger_hash
},
2263 { "Float_add", Float_add
},
2264 { "Float_sub", Float_sub
},
2265 { "Float_lt", Float_lt
},
2266 { "Float_gt", Float_gt
},
2267 { "Float_le", Float_le
},
2268 { "Float_ge", Float_ge
},
2269 { "Float_eq", Float_eq
},
2270 { "Float_ne", Float_ne
},
2271 { "Float_mul", Float_mul
},
2272 { "Float_div", Float_div
},
2273 { "Float_exp", Float_exp
},
2274 { "Float_sin", Float_sin
},
2275 { "Float_cos", Float_cos
},
2276 { "Float_tan", Float_tan
},
2277 { "Float_arcSin", Float_arcSin
},
2278 { "Float_arcCos", Float_arcCos
},
2279 { "Float_arcTan", Float_arcTan
},
2280 { "Float_ln", Float_ln
},
2281 { "Float_log", Float_log
},
2282 { "Float_sqrt", Float_sqrt
},
2283 { "Float_truncated", Float_truncated
},
2284 { "Float_fractionPart", Float_fractionPart
},
2285 { "Float_integerPart", Float_integerPart
},
2286 { "Float_hash", Float_hash
},
2287 { "Float_printStringBase", Float_printStringBase
},
2289 { "Object_error", Object_error
},
2290 { "Object_class", Object_class
},
2291 { "Object_identityHash", Object_identityHash
},
2292 { "Object_copy", Object_copy
},
2293 { "Object_equivalent", Object_equivalent
},
2294 { "Object_perform", Object_perform
},
2295 { "Object_perform_withArguments", Object_perform_withArguments
},
2297 { "Behavior_new", Behavior_new
},
2298 { "Behavior_newSize", Behavior_newSize
},
2299 { "Behavior_compile", Behavior_compile
},
2302 { "SequenceableCollection_size", SequenceableCollection_size
},
2304 { "Array_at", Array_at
},
2305 { "Array_at_put", Array_at_put
},
2307 { "ByteArray_at", ByteArray_at
},
2308 { "ByteArray_at_put", ByteArray_at_put
},
2309 { "ByteArray_hash", ByteArray_hash
},
2311 { "ByteString_at", ByteString_at
},
2312 { "ByteString_at_put", ByteString_at_put
},
2313 { "ByteString_size", ByteString_size
},
2314 { "ByteString_compare", ByteString_compare
},
2316 { "WideString_at", WideString_at
},
2317 { "WideString_at_put", WideString_at_put
},
2319 { "WordArray_at", WordArray_at
},
2320 { "WordArray_at_put", WordArray_at_put
},
2322 { "FloatArray_at", FloatArray_at
},
2323 { "FloatArray_at_put", FloatArray_at_put
},
2325 { "System_exitWithResult", System_exitWithResult
},
2327 { "Character_value", Character_value
},
2328 { "Character_characterFor", Character_characterFor
},
2330 { "BlockContext_value", BlockContext_value
},
2331 { "BlockContext_valueWithArguments", BlockContext_valueWithArguments
},
2333 { "FileStream_open", FileStream_open
},
2334 { "FileStream_close", FileStream_close
},
2335 { "FileStream_read", FileStream_read
},
2336 { "FileStream_write", FileStream_write
},
2337 { "FileStream_seek", FileStream_seek
},
2341 /* returns 0 if there no primitive function corresponding
2342 * to the given name */
2344 st_primitive_index_for_name (const char *name
)
2346 st_assert (name
!= NULL
);
2347 for (int i
= 0; i
< ST_N_ELEMENTS (st_primitives
); i
++)
2348 if (streq (name
, st_primitives
[i
].name
))