2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "PyrKernel.h"
25 #include "PyrObject.h"
26 #include "PyrPrimitive.h"
27 #include "PyrPrimitiveProto.h"
28 #include "PyrSignal.h"
30 #include "PyrSignalPrim.h"
31 #include "PyrFilePrim.h"
32 #include "PyrMathPrim.h"
33 #include "PyrListPrim.h"
35 #include "SC_InlineUnaryOp.h"
36 #include "SC_InlineBinaryOp.h"
37 #include "PyrMessage.h"
38 #include "PyrParseNode.h"
40 #include "PyrKernelProto.h"
41 #include "PyrInterpreter.h"
42 #include "PyrObjectProto.h"
43 #include "PyrArchiverT.h"
44 #include "PyrDeepCopier.h"
45 #include "PyrDeepFreezer.h"
47 #include "InitAlloc.h"
48 #include "SC_LibraryConfig.h"
49 #include "SC_DirUtils.h"
55 # include <sys/param.h>
59 # include "QtCollider.h"
64 extern bool gTraceInterpreter
;
67 void initPatternPrimitives();
70 PrimitiveHandler func
;
73 unsigned char numArgs
;
74 unsigned char varArgs
;
75 unsigned char keyArgs
;
83 extern PrimitiveTable gPrimitiveTable
;
85 extern PyrSlot o_nullframe
;
88 int getPrimitiveNumArgs(int index
)
90 return gPrimitiveTable
.table
[index
].numArgs
;
93 PyrSymbol
* getPrimitiveName(int index
)
95 return gPrimitiveTable
.table
[index
].name
;
98 int slotStrLen(PyrSlot
*slot
) {
100 return slotRawSymbol(slot
)->length
;
101 } else if (isKindOfSlot(slot
, class_string
)) {
102 return slotRawObject(slot
)->size
;
107 int slotStrVal(PyrSlot
*slot
, char *str
, int maxlen
)
110 strncpy(str
, slotRawSymbol(slot
)->name
, maxlen
);
112 } else if (isKindOfSlot(slot
, class_string
)) {
114 len
= sc_min(maxlen
-1, slotRawObject(slot
)->size
);
115 memcpy(str
, slotRawString(slot
)->s
, len
);
122 int slotPStrVal(PyrSlot
*slot
, unsigned char *str
)
125 strncpy((char*)str
+1, slotRawSymbol(slot
)->name
, 255);
126 str
[0] = slotRawSymbol(slot
)->length
;
128 } else if (isKindOfSlot(slot
, class_string
)) {
130 len
= sc_min(255, slotRawObject(slot
)->size
);
131 memcpy(str
+1, slotRawString(slot
)->s
, len
);
138 int instVarAt(struct VMGlobals
*g
, int numArgsPushed
)
146 if (NotObj(a
)) return errWrongType
;
148 PyrObject
*obj
= slotRawObject(a
);
151 index
= slotRawInt(b
);
152 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
153 slotCopy(a
,&obj
->slots
[index
]);
154 } else if (IsSym(b
)) {
155 PyrSlot
*instVarNamesSlot
= &obj
->classptr
->instVarNames
;
156 if (!isKindOfSlot(instVarNamesSlot
, class_symbolarray
)) return errFailed
;
157 PyrSymbolArray
*instVarNames
= slotRawSymbolArray(instVarNamesSlot
);
158 PyrSymbol
**names
= instVarNames
->symbols
;
159 PyrSymbol
*name
= slotRawSymbol(b
);
160 for (int i
=0; i
<instVarNames
->size
; ++i
) {
161 if (names
[i
] == name
) {
162 slotCopy(a
,&obj
->slots
[i
]);
167 } else return errWrongType
;
171 int instVarPut(struct VMGlobals
*g
, int numArgsPushed
)
173 PyrSlot
*a
, *b
, *c
, *slot
;
181 if (NotObj(a
)) return errWrongType
;
182 obj
= slotRawObject(a
);
183 if (obj
->obj_flags
& obj_immutable
) return errImmutableObject
;
186 index
= slotRawInt(b
);
187 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
188 slot
= obj
->slots
+ index
;
190 g
->gc
->GCWrite(obj
, slot
);
191 } else if (IsSym(b
)) {
192 PyrSlot
*instVarNamesSlot
= &obj
->classptr
->instVarNames
;
193 if (!IsObj(instVarNamesSlot
)) return errFailed
;
194 PyrSymbolArray
*instVarNames
= slotRawSymbolArray(instVarNamesSlot
);
195 PyrSymbol
**names
= instVarNames
->symbols
;
196 PyrSymbol
*name
= slotRawSymbol(b
);
197 for (int i
=0; i
<instVarNames
->size
; ++i
) {
198 if (names
[i
] == name
) {
199 slot
= obj
->slots
+ i
;
201 g
->gc
->GCWrite(obj
, slot
);
205 post("WARNING: %s instVarPut '%s' failed.\n", slotRawSymbol(&obj
->classptr
->name
)->name
, name
->name
);
207 } else return errWrongType
;
211 int instVarSize(struct VMGlobals
*g
, int numArgsPushed
)
221 obj
= slotRawObject(a
);
222 if (obj
->obj_format
== obj_notindexed
) {
223 SetInt(a
, obj
->size
);
231 int objectHash(struct VMGlobals
*g
, int numArgsPushed
)
243 int objectClass(struct VMGlobals
*g
, int numArgsPushed
)
249 classobj
= classOfSlot(a
);
250 SetObject(a
, classobj
);
254 int prPrimitiveError(struct VMGlobals
*g
, int numArgsPushed
)
259 slotCopy(a
,&g
->thread
->primitiveError
);
263 int prStackDepth(struct VMGlobals
*g
, int numArgsPushed
);
264 int prStackDepth(struct VMGlobals
*g
, int numArgsPushed
)
269 SetInt(a
, g
->gc
->StackDepth());
273 extern void DumpStack(VMGlobals
*g
, PyrSlot
*sp
);
275 int prDumpStack(struct VMGlobals
*g
, int numArgsPushed
)
281 void DumpDetailedBackTrace(VMGlobals
*g
);
282 int prDumpDetailedBackTrace(struct VMGlobals
*g
, int numArgsPushed
);
283 int prDumpDetailedBackTrace(struct VMGlobals
*g
, int numArgsPushed
)
285 DumpDetailedBackTrace(g
);
289 int prPrimitiveErrorString(struct VMGlobals
*g
, int numArgsPushed
)
296 switch (slotRawInt(&g
->thread
->primitiveError
)) {
297 case errReturn
: str
= "Return (not an error)."; break;
298 case errNone
: str
= "No Error"; break;
299 case errFailed
: str
= "Failed."; break;
300 case errBadPrimitive
: str
= "Bad Primitive."; break;
301 case errWrongType
: str
= "Wrong type."; break;
302 case errIndexNotAnInteger
: str
= "Index not an Integer"; break;
303 case errIndexOutOfRange
: str
= "Index out of range."; break;
304 case errImmutableObject
: str
= "Attempted write to immutable object."; break;
305 case errNotAnIndexableObject
: str
= "Not an indexable object."; break;
306 case errStackOverflow
: str
= "Stack overflow."; break;
307 case errOutOfMemory
: str
= "Out of memory."; break;
308 case errCantCallOS
: str
= "Operation cannot be called from this Process. Try using AppClock instead of SystemClock."; break;
310 default : str
= "Failed.";
312 string
= newPyrString(g
->gc
, str
, 0, true);
313 SetObject(a
, string
);
319 int prPostString(struct VMGlobals
*g
, int numArgsPushed
)
324 //if (NotObj(a)) return errWrongType;
325 // assume it is a string!
326 postText(slotRawString(a
)->s
, slotRawString(a
)->size
);
330 int prPostLine(struct VMGlobals
*g
, int numArgsPushed
)
335 //if (NotObj(a)) return errWrongType;
336 // assume it is a string!
337 postText(slotRawString(a
)->s
, slotRawString(a
)->size
);
342 int prDebugger(struct VMGlobals
*g
, int numArgsPushed
)
354 int prObjectString(struct VMGlobals
*g
, int numArgsPushed
)
362 string
= newPyrString(g
->gc
, slotRawSymbol(a
)->name
, 0, true);
363 SetObject(a
, string
);
365 } else if (postString(a
, str
)) {
366 string
= newPyrString(g
->gc
, str
, 0, true);
367 SetObject(a
, string
);
374 int prFloat_AsStringPrec(struct VMGlobals
*g
, int numArgsPushed
);
375 int prFloat_AsStringPrec(struct VMGlobals
*g
, int numArgsPushed
)
377 PyrSlot
*a
= g
->sp
- 1;
381 int err
= slotIntVal(b
, &precision
);
384 char fmt
[8], str
[256];
385 sprintf(fmt
, "%%.%dg", precision
);
386 sprintf(str
, fmt
, slotRawFloat(a
));
388 PyrString
*string
= newPyrString(g
->gc
, str
, 0, true);
389 SetObject(a
, string
);
394 int prAsCompileString(struct VMGlobals
*g
, int numArgsPushed
);
395 int prAsCompileString(struct VMGlobals
*g
, int numArgsPushed
)
403 int len
= strlen(slotRawSymbol(a
)->name
) + 1;
406 sprintf(str
, "'%s'", slotRawSymbol(a
)->name
);
407 string
= newPyrString(g
->gc
, str
, 0, true);
409 char *str
= (char*)malloc(len
+2);
410 sprintf(str
, "'%s'", slotRawSymbol(a
)->name
);
411 string
= newPyrString(g
->gc
, str
, 0, true);
416 err
= asCompileString(a
, str
);
418 string
= newPyrString(g
->gc
, str
, 0, true);
420 SetObject(a
, string
);
425 int prClassString(struct VMGlobals
*g
, int numArgsPushed
)
432 classobj
= classOfSlot(a
);
433 string
= newPyrString(g
->gc
, slotRawSymbol(&classobj
->name
)->name
, 0, true);
434 SetObject(a
, string
);
439 int prPrimName(struct VMGlobals
*g
, int numArgsPushed
)
445 thread
= slotRawThread(a
);
446 if (slotRawInt(&thread
->primitiveIndex
) <= gPrimitiveTable
.size
) {
447 SetSymbol(a
, gPrimitiveTable
.table
[slotRawInt(&thread
->primitiveIndex
)].name
);
449 SetSymbol(a
, s_none
);
454 int objectIsKindOf(struct VMGlobals
*g
, int numArgsPushed
)
457 PyrClass
*classobj
, *testclass
;
458 int objClassIndex
, testClassIndex
, maxSubclassIndex
;
463 if (NotObj(b
)) return errWrongType
;
464 testclass
= (PyrClass
*)slotRawObject(b
);
465 classobj
= classOfSlot(a
);
468 if (classobj
== testclass
) {
472 classobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
476 // constant time lookup method:
478 objClassIndex
= slotRawInt(&classobj
->classIndex
);
479 testClassIndex
= slotRawInt(&testclass
->classIndex
);
480 maxSubclassIndex
= slotRawInt(&testclass
->maxSubclassIndex
);
482 /*post("%s %s\n", slotRawSymbol(&classobj->name)->name, testclass->name.us->name);
483 post("objClassIndex %d\n", objClassIndex);
484 post("testClassIndex %d\n", testClassIndex);
485 post("maxSubclassIndex %d\n", maxSubclassIndex);*/
487 if (objClassIndex
>= testClassIndex
&& objClassIndex
<= maxSubclassIndex
) {
500 int objectIsMemberOf(struct VMGlobals
*g
, int numArgsPushed
)
503 PyrClass
*classobj
, *testclass
;
508 if (NotObj(b
)) return errWrongType
;
509 testclass
= (PyrClass
*)slotRawObject(b
);
510 classobj
= classOfSlot(a
);
511 if (classobj
== testclass
) {
519 int objectIdentical(struct VMGlobals
*g
, int numArgsPushed
)
533 int objectNotIdentical(struct VMGlobals
*g
, int numArgsPushed
)
548 int basicNewClear(struct VMGlobals
*g
, int numArgsPushed
)
558 if (NotObj(a
)) return errWrongType
;
559 classobj
= (PyrClass
*)slotRawObject(a
);
560 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
561 // create an indexable object
564 size
= (int)slotRawFloat(b
);
565 } else if (NotNil(b
)) return errIndexNotAnInteger
;
568 size
= slotRawInt(b
);
570 if (size
< 0) size
= 0;
574 newobj
= instantiateObject(g
->gc
, classobj
, size
, true, true);
575 SetObject(a
, newobj
);
579 int basicNewCopyArgsToInstanceVars(struct VMGlobals
*g
, int numArgsPushed
);
580 int basicNewCopyArgsToInstanceVars(struct VMGlobals
*g
, int numArgsPushed
)
586 a
= g
->sp
- numArgsPushed
+ 1;
589 if (NotObj(a
)) return errWrongType
;
590 classobj
= (PyrClass
*)slotRawObject(a
);
591 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
592 error("CopyArgs : object has no instance variables.\n");
595 newobj
= instantiateObject(g
->gc
, classobj
, 0, true, true);
596 SetObject(a
, newobj
);
598 int length
= sc_min(numArgsPushed
-1, newobj
->size
);
599 for (int i
=0; i
<length
; ++i
) {
600 slotCopy(&newobj
->slots
[i
],&b
[i
]);
608 int basicNew(struct VMGlobals
*g
, int numArgsPushed
)
618 if (NotObj(a
)) return errWrongType
;
619 classobj
= (PyrClass
*)slotRawObject(a
);
620 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
621 // create an indexable object
624 size
= (int)slotRawFloat(b
);
625 } else if (NotNil(b
)) return errIndexNotAnInteger
;
628 size
= slotRawInt(b
);
630 if (size
< 0) size
= 0;
634 newobj
= instantiateObject(g
->gc
, classobj
, size
, false, true);
635 SetObject(a
, newobj
);
640 bool isClosed(PyrBlock
* fundef
);
641 bool isClosed(PyrBlock
* fundef
)
643 return IsNil(&fundef
->contextDef
) && fundef
->classptr
== class_fundef
;
646 bool isWithinClosed(PyrBlock
* fundef
);
647 bool isWithinClosed(PyrBlock
* fundef
)
650 if (isClosed(fundef
)) return true;
651 fundef
= slotRawBlock(&fundef
->contextDef
);
656 int prFunctionDefAsFunction(struct VMGlobals
*g
, int numArgsPushed
);
657 int prFunctionDefAsFunction(struct VMGlobals
*g
, int numArgsPushed
)
661 if (!isClosed(slotRawBlock(a
))) {
663 error("Only closed FunctionDef may be converted to a Function using asFunction.\n");
667 PyrClosure
* closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
669 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
671 slotCopy(&closure
->block
,a
);
672 slotCopy(&closure
->context
,&slotRawInterpreter(&g
->process
->interpreter
)->context
);
673 SetObject(a
, closure
);
677 int prFunctionDefDumpContexts(struct VMGlobals
*g
, int numArgsPushed
);
678 int prFunctionDefDumpContexts(struct VMGlobals
*g
, int numArgsPushed
)
683 while (slotRawBlock(a
)) {
684 post("%2d context %s %p\n", i
++, slotRawSymbol(&slotRawObject(a
)->classptr
->name
)->name
, slotRawInt(&slotRawBlock(a
)->contextDef
));
685 a
= &slotRawBlock(a
)->contextDef
;
692 int prFunctionDefIsClosed(struct VMGlobals
*g
, int numArgsPushed
);
693 int prFunctionDefIsClosed(struct VMGlobals
*g
, int numArgsPushed
)
696 PyrBlock
*block
= slotRawBlock(a
);
698 SetBool(a
, isClosed(block
));
702 int prFunctionDefIsWithinClosed(struct VMGlobals
*g
, int numArgsPushed
);
703 int prFunctionDefIsWithinClosed(struct VMGlobals
*g
, int numArgsPushed
)
706 PyrBlock
*block
= slotRawBlock(a
);
708 SetBool(a
, isWithinClosed(block
));
713 void reallocStack(struct VMGlobals
*g
, int stackNeeded
, int stackDepth
)
715 //PyrThread *thread = g->thread;
717 int newStackSize
= NEXTPOWEROFTWO(stackNeeded
);
719 PyrObject
* array
= newPyrArray(gc
, newStackSize
, 0, false);
720 memcpy(array
->slots
, gc
->Stack()->slots
, stackDepth
* sizeof(PyrSlot
));
722 gc
->ToBlack(gc
->Stack());
723 g
->sp
= array
->slots
+ stackDepth
- 1;
727 int blockValueArray(struct VMGlobals
*g
, int numArgsPushed
)
732 PyrSlot
*pslot
, *qslot
;
735 //a = g->sp - numArgsPushed + 1;
739 if (slotRawObject(b
)->classptr
== class_array
) {
740 array
= (PyrObject
*)slotRawObject(b
);
744 PyrObject
*stack
= g
->gc
->Stack();
745 int stackDepth
= g
->sp
- stack
->slots
+ 1;
746 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
747 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
748 if (stackNeeded
> stackSize
) {
749 reallocStack(g
, stackNeeded
, stackDepth
);
753 pslot
= array
->slots
- 1;
755 //pend = (double*)(pslot + size);
756 //while (pslot<pend) slotCopy(++qslot, ++pslot);
757 for (m
=0; m
<size
; ++m
) slotCopy(++qslot
, ++pslot
);
760 return blockValue(g
, size
+numArgsPushed
-1);
762 } else if (slotRawObject(b
)->classptr
== class_list
) {
763 list
= slotRawList(b
);
764 if (NotObj(&list
->array
)) return errWrongType
;
765 array
= slotRawObject(&list
->array
);
766 if (array
->classptr
!= class_array
) return errWrongType
;
768 } else { // last arg is not a list or array, so pass as normal
769 return blockValue(g
, numArgsPushed
);
772 return blockValue(g
, numArgsPushed
);
776 int blockValueEnvir(struct VMGlobals
*g
, int numArgsPushed
);
778 int blockValueArrayEnvir(struct VMGlobals
*g
, int numArgsPushed
);
779 int blockValueArrayEnvir(struct VMGlobals
*g
, int numArgsPushed
)
784 PyrSlot
*pslot
, *qslot
;
787 //a = g->sp - numArgsPushed + 1;
791 if (slotRawObject(b
)->classptr
== class_array
) {
792 array
= (PyrObject
*)slotRawObject(b
);
796 PyrObject
*stack
= g
->gc
->Stack();
797 int stackDepth
= g
->sp
- stack
->slots
+ 1;
798 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
799 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
800 if (stackNeeded
> stackSize
) {
801 reallocStack(g
, stackNeeded
, stackDepth
);
805 pslot
= array
->slots
- 1;
807 //pend = (double*)(pslot + size);
808 //while (pslot<pend) slotCopy(++qslot, ++pslot);
809 for (m
=0; m
<size
; ++m
) slotCopy(++qslot
, ++pslot
);
812 return blockValueEnvir(g
, size
+numArgsPushed
-1);
814 } else if (slotRawObject(b
)->classptr
== class_list
) {
815 list
= slotRawList(b
);
816 if (NotObj(&list
->array
)) return errWrongType
;
817 array
= slotRawObject(&list
->array
);
818 if (array
->classptr
!= class_array
) return errWrongType
;
820 } else { // last arg is not a list or array, so pass as normal
821 return blockValueEnvir(g
, numArgsPushed
);
824 return blockValueEnvir(g
, numArgsPushed
);
828 int blockValue(struct VMGlobals
*g
, int numArgsPushed
)
833 PyrSlot
*pslot
, *qslot
;
836 int i
, m
, mmax
, numtemps
;
840 PyrFrame
*homeContext
;
842 PyrMethodRaw
*methraw
;
845 int tailCall
= g
->tailCall
;
857 args
= g
->sp
- numArgsPushed
+ 1;
862 closure
= (PyrClosure
*)slotRawObject(args
);
863 block
= slotRawBlock(&closure
->block
);
864 context
= slotRawFrame(&closure
->context
);
866 proto
= IsObj(&block
->prototypeFrame
) ? slotRawObject(&block
->prototypeFrame
) : 0;
867 methraw
= METHRAW(block
);
868 numtemps
= methraw
->numtemps
;
871 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
872 vars
= frame
->vars
- 1;
873 frame
->classptr
= class_frame
;
874 frame
->size
= FRAMESIZE
+ numtemps
;
875 SetObject(&frame
->method
, block
);
876 slotCopy(&frame
->homeContext
,&context
->homeContext
);
877 slotCopy(&frame
->context
,&closure
->context
);
880 SetPtr(&caller
->ip
, g
->ip
);
881 SetObject(&frame
->caller
, g
->frame
);
883 SetInt(&frame
->caller
, 0);
885 SetPtr(&frame
->ip
, 0);
889 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
893 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
894 /* push all args to frame */
898 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
900 /* push default arg values */
901 pslot
= vars
+ numArgsPushed
;
902 qslot
= proto
->slots
+ numArgsPushed
- 1;
903 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
904 } else if (methraw
->varargs
) {
908 /* push all normal args to frame */
911 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
914 i
= numArgsPushed
- methraw
->numargs
;
915 list
= newPyrArray(g
->gc
, i
, 0, false);
919 SetObject(rslot
, list
);
920 //SetObject(vars + methraw->numargs + 1, list);
922 /* put extra args into list */
923 lslot
= list
->slots
- 1;
924 // fixed and raw sizes are zero
925 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
927 if (methraw
->numvars
) {
928 /* push default keyword and var values */
929 pslot
= vars
+ methraw
->numargs
+ 1;
930 qslot
= proto
->slots
+ methraw
->numargs
;
931 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
934 if (methraw
->numargs
) {
935 /* push all args to frame */
938 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
940 if (methraw
->numvars
) {
941 /* push default keyword and var values */
942 pslot
= vars
+ methraw
->numargs
;
943 qslot
= proto
->slots
+ methraw
->numargs
- 1;
944 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
948 homeContext
= slotRawFrame(&frame
->homeContext
);
950 PyrMethodRaw
*methraw
;
951 g
->method
= slotRawMethod(&homeContext
->method
);
952 methraw
= METHRAW(g
->method
);
953 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
955 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
961 int blockValueWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
);
962 int blockValueWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
)
967 PyrSlot
*pslot
, *qslot
;
970 int i
, j
, m
, mmax
, numtemps
, numArgsPushed
;
974 PyrFrame
*homeContext
;
976 PyrMethodRaw
*methraw
;
979 int tailCall
= g
->tailCall
;
991 args
= g
->sp
- allArgsPushed
+ 1;
996 closure
= (PyrClosure
*)slotRawObject(args
);
997 block
= slotRawBlock(&closure
->block
);
998 context
= slotRawFrame(&closure
->context
);
1000 proto
= slotRawObject(&block
->prototypeFrame
);
1001 methraw
= METHRAW(block
);
1002 numtemps
= methraw
->numtemps
;
1004 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1006 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1007 vars
= frame
->vars
- 1;
1008 frame
->classptr
= class_frame
;
1009 frame
->size
= FRAMESIZE
+ numtemps
;
1010 SetObject(&frame
->method
, block
);
1011 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1012 slotCopy(&frame
->context
,&closure
->context
);
1015 SetPtr(&caller
->ip
, g
->ip
);
1016 SetObject(&frame
->caller
, g
->frame
);
1018 SetInt(&frame
->caller
, 0);
1020 SetPtr(&frame
->ip
, 0);
1023 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1027 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1028 /* push all args to frame */
1032 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1034 /* push default arg values */
1035 pslot
= vars
+ numArgsPushed
;
1036 qslot
= proto
->slots
+ numArgsPushed
- 1;
1037 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1038 } else if (methraw
->varargs
) {
1042 /* push all normal args to frame */
1045 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1048 i
= numArgsPushed
- methraw
->numargs
;
1049 list
= newPyrArray(g
->gc
, i
, 0, false);
1053 SetObject(rslot
, list
);
1054 //SetObject(vars + methraw->numargs + 1, list);
1056 /* put extra args into list */
1057 lslot
= list
->slots
- 1;
1058 // fixed and raw sizes are zero
1060 //while (lslot < lend) slotCopy(++lslot, ++qslot);
1061 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1063 if (methraw
->numvars
) {
1064 /* push default keyword and var values */
1065 pslot
= vars
+ methraw
->numargs
+ 1;
1066 qslot
= proto
->slots
+ methraw
->numargs
;
1067 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1070 if (methraw
->numargs
) {
1071 /* push all args to frame */
1074 //pend = pslot + methraw->numargs;
1075 //while (pslot < pend) slotCopy(++pslot, ++qslot);
1076 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1078 if (methraw
->numvars
) {
1079 /* push default keyword and var values */
1080 pslot
= vars
+ methraw
->numargs
;
1081 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1082 //pend = pslot + methraw->numvars;
1083 //while (pslot<pend) slotCopy(++pslot, ++qslot);
1084 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1087 // do keyword lookup:
1088 if (numKeyArgsPushed
&& methraw
->posargs
) {
1090 PyrSymbol
**name0
, **name
;
1091 name0
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1092 key
= args
+ numArgsPushed
+ 1;
1093 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1095 for (j
=0; j
<methraw
->posargs
; ++j
, ++name
) {
1096 if (*name
== slotRawSymbol(key
)) {
1097 slotCopy(&vars
[j
+1],&key
[1]);
1101 if (gKeywordError
) {
1102 post("WARNING: keyword arg '%s' not found in call to function.\n",
1103 slotRawSymbol(key
)->name
);
1109 homeContext
= slotRawFrame(&frame
->homeContext
);
1111 PyrMethodRaw
*methraw
;
1112 g
->method
= slotRawMethod(&homeContext
->method
);
1113 methraw
= METHRAW(g
->method
);
1114 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1116 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1121 bool identDict_lookupNonNil(PyrObject
*dict
, PyrSlot
*key
, int hash
, PyrSlot
*result
);
1123 int blockValueEnvir(struct VMGlobals
*g
, int numArgsPushed
)
1128 PyrSlot
*pslot
, *qslot
;
1131 int i
, m
, mmax
, numtemps
;
1135 PyrFrame
*homeContext
;
1136 PyrClosure
*closure
;
1137 PyrMethodRaw
*methraw
;
1138 PyrSlot
*curEnvirSlot
;
1140 #if TAILCALLOPTIMIZE
1141 int tailCall
= g
->tailCall
;
1143 if (tailCall
== 1) {
1144 returnFromMethod(g
);
1153 args
= g
->sp
- numArgsPushed
+ 1;
1158 closure
= (PyrClosure
*)slotRawObject(args
);
1159 block
= slotRawBlock(&closure
->block
);
1160 context
= slotRawFrame(&closure
->context
);
1162 proto
= slotRawObject(&block
->prototypeFrame
);
1163 methraw
= METHRAW(block
);
1164 numtemps
= methraw
->numtemps
;
1167 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1168 vars
= frame
->vars
- 1;
1169 frame
->classptr
= class_frame
;
1170 frame
->size
= FRAMESIZE
+ numtemps
;
1171 SetObject(&frame
->method
, block
);
1172 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1173 slotCopy(&frame
->context
,&closure
->context
);
1176 SetPtr(&caller
->ip
, g
->ip
);
1177 SetObject(&frame
->caller
, g
->frame
);
1179 SetInt(&frame
->caller
, 0);
1181 SetPtr(&frame
->ip
, 0);
1185 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1189 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1190 /* push all args to frame */
1194 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1196 /* push default arg values */
1197 pslot
= vars
+ numArgsPushed
;
1198 qslot
= proto
->slots
+ numArgsPushed
- 1;
1199 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1201 // replace defaults with environment variables
1202 curEnvirSlot
= &g
->classvars
->slots
[1]; // currentEnvironment is the second class var.
1204 if (isKindOfSlot(curEnvirSlot
, s_identitydictionary
->u
.classobj
)) {
1205 PyrSymbol
**argNames
;
1206 argNames
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1207 for (m
=numArgsPushed
; m
<methraw
->numargs
; ++m
) {
1208 // replace the args with values from the environment if they exist
1210 SetSymbol(&keyslot
, argNames
[m
]);
1211 identDict_lookupNonNil(slotRawObject(curEnvirSlot
), &keyslot
, calcHash(&keyslot
), vars
+m
+1);
1214 } else if (methraw
->varargs
) {
1218 /* push all normal args to frame */
1221 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1224 i
= numArgsPushed
- methraw
->numargs
;
1225 list
= newPyrArray(g
->gc
, i
, 0, false);
1229 SetObject(rslot
, list
);
1230 //SetObject(vars + methraw->numargs + 1, list);
1232 /* put extra args into list */
1233 lslot
= list
->slots
- 1;
1234 // fixed and raw sizes are zero
1235 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1237 if (methraw
->numvars
) {
1238 /* push default keyword and var values */
1239 pslot
= vars
+ methraw
->numargs
+ 1;
1240 qslot
= proto
->slots
+ methraw
->numargs
;
1241 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1244 if (methraw
->numargs
) {
1245 /* push all args to frame */
1248 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1250 if (methraw
->numvars
) {
1251 /* push default keyword and var values */
1252 pslot
= vars
+ methraw
->numargs
;
1253 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1254 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1258 homeContext
= slotRawFrame(&frame
->homeContext
);
1260 PyrMethodRaw
*methraw
;
1261 g
->method
= slotRawMethod(&homeContext
->method
);
1262 methraw
= METHRAW(g
->method
);
1263 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1265 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1270 int blockValueEnvirWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
);
1271 int blockValueEnvirWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
)
1276 PyrSlot
*pslot
, *qslot
;
1279 int i
, j
, m
, mmax
, numtemps
, numArgsPushed
;
1283 PyrFrame
*homeContext
;
1284 PyrClosure
*closure
;
1285 PyrMethodRaw
*methraw
;
1286 PyrSlot
*curEnvirSlot
;
1288 #if TAILCALLOPTIMIZE
1289 int tailCall
= g
->tailCall
;
1291 if (tailCall
== 1) {
1292 returnFromMethod(g
);
1301 args
= g
->sp
- allArgsPushed
+ 1;
1306 closure
= (PyrClosure
*)slotRawObject(args
);
1307 block
= slotRawBlock(&closure
->block
);
1308 context
= slotRawFrame(&closure
->context
);
1310 proto
= slotRawObject(&block
->prototypeFrame
);
1311 methraw
= METHRAW(block
);
1312 numtemps
= methraw
->numtemps
;
1314 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1316 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1317 vars
= frame
->vars
- 1;
1318 frame
->classptr
= class_frame
;
1319 frame
->size
= FRAMESIZE
+ numtemps
;
1320 SetObject(&frame
->method
, block
);
1321 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1322 slotCopy(&frame
->context
,&closure
->context
);
1325 SetPtr(&caller
->ip
, g
->ip
);
1326 SetObject(&frame
->caller
, g
->frame
);
1328 SetInt(&frame
->caller
, 0);
1330 SetPtr(&frame
->ip
, 0);
1334 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1338 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1339 /* push all args to frame */
1343 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1345 /* push default arg values */
1346 pslot
= vars
+ numArgsPushed
;
1347 qslot
= proto
->slots
+ numArgsPushed
- 1;
1348 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1350 // replace defaults with environment variables
1351 curEnvirSlot
= &g
->classvars
->slots
[1]; // currentEnvironment is the second class var.
1353 if (isKindOfSlot(curEnvirSlot
, s_identitydictionary
->u
.classobj
)) {
1354 PyrSymbol
**argNames
;
1355 argNames
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1356 for (m
=numArgsPushed
; m
<methraw
->numargs
; ++m
) {
1357 // replace the args with values from the environment if they exist
1359 SetSymbol(&keyslot
, argNames
[m
]);
1360 identDict_lookupNonNil(slotRawObject(curEnvirSlot
), &keyslot
, calcHash(&keyslot
), vars
+m
+1);
1365 } else if (methraw
->varargs
) {
1369 /* push all normal args to frame */
1372 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1375 i
= numArgsPushed
- methraw
->numargs
;
1376 list
= newPyrArray(g
->gc
, i
, 0, false);
1380 SetObject(rslot
, list
);
1381 //SetObject(vars + methraw->numargs + 1, list);
1383 /* put extra args into list */
1384 lslot
= list
->slots
- 1;
1385 // fixed and raw sizes are zero
1387 //while (lslot < lend) slotCopy(++lslot, ++qslot);
1388 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1390 if (methraw
->numvars
) {
1391 /* push default keyword and var values */
1392 pslot
= vars
+ methraw
->numargs
+ 1;
1393 qslot
= proto
->slots
+ methraw
->numargs
;
1394 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1397 if (methraw
->numargs
) {
1398 /* push all args to frame */
1401 //pend = pslot + methraw->numargs;
1402 //while (pslot < pend) slotCopy(++pslot, ++qslot);
1403 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1405 if (methraw
->numvars
) {
1406 /* push default keyword and var values */
1407 pslot
= vars
+ methraw
->numargs
;
1408 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1409 //pend = pslot + methraw->numvars;
1410 //while (pslot<pend) slotCopy(++pslot, ++qslot);
1411 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1414 // do keyword lookup:
1415 if (numKeyArgsPushed
&& methraw
->posargs
) {
1416 PyrSymbol
**name0
, **name
;
1418 name0
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1419 key
= args
+ numArgsPushed
+ 1;
1420 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1422 for (j
=0; j
<methraw
->posargs
; ++j
, ++name
) {
1423 if (*name
== slotRawSymbol(key
)) {
1424 slotCopy(&vars
[j
+1],&key
[1]);
1428 if (gKeywordError
) {
1429 post("WARNING: keyword arg '%s' not found in call to function.\n",
1430 slotRawSymbol(key
)->name
);
1436 homeContext
= slotRawFrame(&frame
->homeContext
);
1438 PyrMethodRaw
*methraw
;
1439 g
->method
= slotRawMethod(&homeContext
->method
);
1440 methraw
= METHRAW(g
->method
);
1441 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1443 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1449 int objectPerform(struct VMGlobals
*g
, int numArgsPushed
)
1451 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1452 PyrSlot
*pslot
, *qslot
;
1453 PyrSymbol
*selector
;
1456 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1457 selSlot
= recvrSlot
+ 1;
1458 if (IsSym(selSlot
)) {
1459 selector
= slotRawSymbol(selSlot
);
1460 // move args down one to fill selector's position
1461 pslot
= selSlot
- 1;
1463 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1466 // now the stack looks just like it would for a normal message send
1467 } else if (IsObj(selSlot
)) {
1469 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1470 listSlot
= slotRawObject(listSlot
)->slots
;
1472 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1475 PyrObject
*array
= slotRawObject(listSlot
);
1476 if (array
->size
< 1) {
1477 error("Array must have a selector.\n");
1480 selSlot
= array
->slots
;
1481 selector
= slotRawSymbol(selSlot
);
1483 if (numArgsPushed
>2) {
1484 qslot
= recvrSlot
+ numArgsPushed
;
1485 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1486 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(--pslot
, --qslot
);
1491 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1493 g
->sp
+= array
->size
- 2;
1494 numArgsPushed
+= array
->size
- 2;
1495 // now the stack looks just like it would for a normal message send
1499 error("perform selector not a Symbol or Array.\n");
1500 dumpObjectSlot(selSlot
);
1501 return errWrongType
;
1504 sendMessage(g
, selector
, numArgsPushed
);
1509 int objectPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
);
1510 int objectPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
)
1512 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1513 PyrSlot
*pslot
, *qslot
;
1514 PyrSymbol
*selector
;
1517 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1518 selSlot
= recvrSlot
+ 1;
1519 if (IsSym(selSlot
)) {
1520 selector
= slotRawSymbol(selSlot
);
1521 // move args down one to fill selector's position
1522 pslot
= selSlot
- 1;
1524 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1527 // now the stack looks just like it would for a normal message send
1528 } else if (IsObj(selSlot
)) {
1530 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1531 listSlot
= slotRawObject(listSlot
)->slots
;
1533 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1536 PyrObject
*array
= slotRawObject(listSlot
);
1537 if (array
->size
< 1) {
1538 error("Array must have a selector.\n");
1541 selSlot
= array
->slots
;
1542 selector
= slotRawSymbol(selSlot
);
1544 if (numArgsPushed
>2) {
1545 qslot
= recvrSlot
+ numArgsPushed
;
1546 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1547 for (m
=0; m
<numArgsPushed
- 2; ++m
) *--pslot
= *--qslot
;
1552 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1554 g
->sp
+= array
->size
- 2;
1555 numArgsPushed
+= array
->size
- 2;
1556 // now the stack looks just like it would for a normal message send
1560 error("perform selector not a Symbol or Array.\n");
1561 dumpObjectSlot(selSlot
);
1562 return errWrongType
;
1565 sendMessageWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
1571 int objectPerformList(struct VMGlobals
*g
, int numArgsPushed
)
1573 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1574 PyrSlot
*pslot
, *qslot
;
1575 PyrSymbol
*selector
;
1576 int m
, mmax
, numargslots
;
1580 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1581 selSlot
= recvrSlot
+ 1;
1583 numargslots
= numArgsPushed
- 3;
1584 if (NotSym(selSlot
)) {
1585 error("Selector not a Symbol :\n");
1586 return errWrongType
;
1588 selector
= slotRawSymbol(selSlot
);
1590 if (NotObj(listSlot
)) {
1591 return objectPerform(g
, numArgsPushed
);
1593 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1595 array
= slotRawObject(listSlot
);
1597 PyrObject
*stack
= g
->gc
->Stack();
1598 int stackDepth
= g
->sp
- stack
->slots
+ 1;
1599 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
1600 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
1601 if (stackNeeded
> stackSize
) {
1602 reallocStack(g
, stackNeeded
, stackDepth
);
1603 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1604 selSlot
= recvrSlot
+ 1;
1608 if (numargslots
>0) {
1610 for (m
=0; m
<numargslots
; ++m
) slotCopy(++pslot
, ++qslot
);
1611 } else numargslots
= 0;
1612 qslot
= array
->slots
- 1;
1613 for (m
=0,mmax
=array
->size
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1614 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1615 listSlot
= slotRawObject(listSlot
)->slots
;
1616 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1617 error("List array not an Array.\n");
1618 dumpObjectSlot(listSlot
);
1619 return errWrongType
;
1623 return objectPerform(g
, numArgsPushed
);
1625 g
->sp
+= array
->size
- 2;
1626 numArgsPushed
= numargslots
+ array
->size
+ 1;
1627 // now the stack looks just like it would for a normal message send
1629 sendMessage(g
, selector
, numArgsPushed
);
1636 int objectSuperPerform(struct VMGlobals
*g
, int numArgsPushed
)
1638 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1639 PyrSlot
*pslot
, *qslot
;
1640 PyrSymbol
*selector
;
1643 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1645 PyrClass
* classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
1646 if (!isKindOfSlot(recvrSlot
, classobj
)) {
1647 error("superPerform must be called with 'this' as the receiver.\n");
1651 selSlot
= recvrSlot
+ 1;
1652 if (IsSym(selSlot
)) {
1653 selector
= slotRawSymbol(selSlot
);
1654 // move args down one to fill selector's position
1655 pslot
= selSlot
- 1;
1657 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1660 // now the stack looks just like it would for a normal message send
1661 } else if (IsObj(selSlot
)) {
1663 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1664 listSlot
= slotRawObject(listSlot
)->slots
;
1666 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1669 PyrObject
*array
= slotRawObject(listSlot
);
1670 if (array
->size
< 1) {
1671 error("Array must have a selector.\n");
1674 selSlot
= array
->slots
;
1675 selector
= slotRawSymbol(selSlot
);
1677 if (numArgsPushed
>2) {
1678 qslot
= recvrSlot
+ numArgsPushed
;
1679 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1680 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(--pslot
, --qslot
);
1685 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1687 g
->sp
+= array
->size
- 2;
1688 numArgsPushed
+= array
->size
- 2;
1689 // now the stack looks just like it would for a normal message send
1693 error("perform selector not a Symbol or Array.\n");
1694 dumpObjectSlot(selSlot
);
1695 return errWrongType
;
1698 sendSuperMessage(g
, selector
, numArgsPushed
);
1703 int objectSuperPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
);
1704 int objectSuperPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
)
1706 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1707 PyrSlot
*pslot
, *qslot
;
1708 PyrSymbol
*selector
;
1711 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1713 PyrClass
* classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
1714 if (!isKindOfSlot(recvrSlot
, classobj
)) {
1715 error("superPerform must be called with 'this' as the receiver.\n");
1719 selSlot
= recvrSlot
+ 1;
1720 if (IsSym(selSlot
)) {
1721 selector
= slotRawSymbol(selSlot
);
1722 // move args down one to fill selector's position
1723 pslot
= selSlot
- 1;
1725 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1728 // now the stack looks just like it would for a normal message send
1729 } else if (IsObj(selSlot
)) {
1731 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1732 listSlot
= slotRawObject(listSlot
)->slots
;
1734 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1737 PyrObject
*array
= slotRawObject(listSlot
);
1738 if (array
->size
< 1) {
1739 error("Array must have a selector.\n");
1742 selSlot
= array
->slots
;
1743 selector
= slotRawSymbol(selSlot
);
1745 if (numArgsPushed
>2) {
1746 qslot
= recvrSlot
+ numArgsPushed
;
1747 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1748 for (m
=0; m
<numArgsPushed
- 2; ++m
) *--pslot
= *--qslot
;
1753 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1755 g
->sp
+= array
->size
- 2;
1756 numArgsPushed
+= array
->size
- 2;
1757 // now the stack looks just like it would for a normal message send
1761 error("perform selector not a Symbol or Array.\n");
1762 dumpObjectSlot(selSlot
);
1763 return errWrongType
;
1766 sendSuperMessageWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
1772 int objectSuperPerformList(struct VMGlobals
*g
, int numArgsPushed
)
1774 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1775 PyrSlot
*pslot
, *qslot
;
1776 PyrSymbol
*selector
;
1777 int m
, mmax
, numargslots
;
1780 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1781 selSlot
= recvrSlot
+ 1;
1783 numargslots
= numArgsPushed
- 3;
1784 if (NotSym(selSlot
)) {
1785 error("Selector not a Symbol :\n");
1786 return errWrongType
;
1788 selector
= slotRawSymbol(selSlot
);
1789 if (NotObj(listSlot
)) {
1790 return objectPerform(g
, numArgsPushed
);
1792 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1795 if (numargslots
>0) {
1797 for (m
=0; m
<numargslots
; ++m
) slotCopy(++pslot
, ++qslot
);
1798 } else numargslots
= 0;
1799 array
= slotRawObject(listSlot
);
1800 qslot
= array
->slots
- 1;
1801 for (m
=0,mmax
=array
->size
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1802 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1803 listSlot
= slotRawObject(listSlot
)->slots
;
1804 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1805 error("List array not an Array.\n");
1806 dumpObjectSlot(listSlot
);
1807 return errWrongType
;
1811 return objectSuperPerform(g
, numArgsPushed
);
1813 g
->sp
+= array
->size
- 2;
1814 numArgsPushed
= numargslots
+ array
->size
+ 1;
1815 // now the stack looks just like it would for a normal message send
1817 sendSuperMessage(g
, selector
, numArgsPushed
);
1825 int objectPerformSelList(struct VMGlobals
*g
, int numArgsPushed
)
1827 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1828 PyrSlot
*pslot
, *qslot
;
1829 PyrSymbol
*selector
;
1833 recvrSlot
= g
->sp
- 1;
1836 if (NotObj(listSlot
)) {
1837 error("Expected Array or List.. Got :\n");
1838 dumpObjectSlot(listSlot
);
1839 return errWrongType
;
1841 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1843 array
= slotRawObject(listSlot
);
1845 selSlot
= array
->slots
;
1846 if (NotSym(selSlot
)) {
1847 error("Selector not a Symbol :\n");
1848 return errWrongType
;
1850 selector
= slotRawSymbol(selSlot
);
1854 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1855 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1856 listSlot
= slotRawObject(listSlot
)->slots
;
1857 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1858 error("List array not an Array.\n");
1859 dumpObjectSlot(listSlot
);
1860 return errWrongType
;
1864 error("Expected Array or List.. Got :\n");
1865 dumpObjectSlot(listSlot
);
1866 return errWrongType
;
1868 g
->sp
+= array
->size
- 2;
1869 numArgsPushed
= array
->size
;
1870 // now the stack looks just like it would for a normal message send
1872 sendMessage(g
, selector
, numArgsPushed
);
1878 int arrayPerformMsg(struct VMGlobals
*g
, int numArgsPushed
);
1879 int arrayPerformMsg(struct VMGlobals
*g
, int numArgsPushed
)
1881 PyrSlot
*recvrSlot
, *selSlot
, *arraySlot
;
1882 PyrSlot
*pslot
, *qslot
;
1883 PyrSymbol
*selector
;
1884 int m
, mmax
, numargslots
;
1887 arraySlot
= g
->sp
- numArgsPushed
+ 1;
1888 array
= slotRawObject(arraySlot
);
1889 if (array
->size
< 2) {
1890 error("Array must contain a receiver and a selector.\n");
1893 recvrSlot
= array
->slots
;
1894 selSlot
= recvrSlot
+ 1;
1895 numargslots
= numArgsPushed
- 1;
1896 if (NotSym(selSlot
)) {
1897 error("Selector not a Symbol :\n");
1898 return errWrongType
;
1901 selector
= slotRawSymbol(selSlot
);
1903 slotCopy(arraySlot
,recvrSlot
);
1905 if (numargslots
>0) {
1906 qslot
= arraySlot
+ numargslots
+ 1;
1907 pslot
= arraySlot
+ numargslots
+ array
->size
- 1;
1908 for (m
=0; m
<numargslots
; ++m
) slotCopy(--pslot
, --qslot
);
1909 } else numargslots
= 0;
1913 for (m
=0,mmax
=array
->size
-2; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1915 g
->sp
+= array
->size
- 2;
1916 numArgsPushed
= numargslots
+ array
->size
- 1;
1918 // now the stack looks just like it would for a normal message send
1920 sendMessage(g
, selector
, numArgsPushed
);
1925 int objectDump(struct VMGlobals
*g
, int numArgsPushed
)
1935 int prTotalFree(struct VMGlobals
*g
, int numArgsPushed
);
1936 int prTotalFree(struct VMGlobals
*g
, int numArgsPushed
)
1939 SetInt(a
, g
->allocPool
->TotalFree());
1943 int prLargestFreeBlock(struct VMGlobals
*g
, int numArgsPushed
);
1944 int prLargestFreeBlock(struct VMGlobals
*g
, int numArgsPushed
)
1947 SetInt(a
, g
->allocPool
->LargestFreeChunk());
1951 int dumpGCinfo(struct VMGlobals
*g
, int numArgsPushed
);
1952 int dumpGCinfo(struct VMGlobals
*g
, int numArgsPushed
)
1958 int dumpGCdumpGrey(struct VMGlobals
*g
, int numArgsPushed
);
1959 int dumpGCdumpGrey(struct VMGlobals
*g
, int numArgsPushed
)
1965 int dumpGCdumpSet(struct VMGlobals
*g
, int numArgsPushed
);
1966 int dumpGCdumpSet(struct VMGlobals
*g
, int numArgsPushed
)
1970 int err
= slotIntVal(b
, &set
);
1971 if (err
) return err
;
1973 g
->gc
->DumpSet(set
);
1977 int prGCSanity(struct VMGlobals
*g
, int numArgsPushed
);
1978 int prGCSanity(struct VMGlobals
*g
, int numArgsPushed
)
1980 g
->gc
->SanityCheck();
1985 int prTraceAllPathsTo(struct VMGlobals
*g
, int numArgsPushed
);
1986 int prTraceAllPathsTo(struct VMGlobals
*g
, int numArgsPushed
)
1989 g
->gc
->TracePathsTo(slotRawObject(a
), false);
1993 int prTraceAnyPathsTo(struct VMGlobals
*g
, int numArgsPushed
);
1994 int prTraceAnyPathsTo(struct VMGlobals
*g
, int numArgsPushed
)
1997 g
->gc
->TracePathsTo(slotRawObject(a
), true);
2001 int prTraceAnyPathToAllInstancesOf(struct VMGlobals
*g
, int numArgsPushed
);
2002 int prTraceAnyPathToAllInstancesOf(struct VMGlobals
*g
, int numArgsPushed
)
2005 g
->gc
->TraceAnyPathToAllInstancesOf(slotRawClass(a
)->name
.us
);
2010 extern PyrClass
*gClassList
;
2012 int prAllClasses(struct VMGlobals
*g
, int numArgsPushed
)
2021 array
= newPyrArray(g
->gc
, gNumClasses
, 0, true);
2022 classobj
= gClassList
;
2023 for (i
=0; classobj
; ++i
) {
2024 SetObject(array
->slots
+ i
, classobj
);
2025 classobj
= slotRawClass(&classobj
->nextclass
);
2027 array
->size
= gNumClasses
;
2028 SetObject(a
, array
);
2032 int prPostClassTree(struct VMGlobals
*g
, int numArgsPushed
)
2037 postClassTree(slotRawClass(a
), 0);
2041 int prDumpBackTrace(struct VMGlobals
*g
, int numArgsPushed
)
2050 /* the DebugFrameConstructor uses a work queue in order to avoid recursions, which could lead to stack overflows */
2051 struct DebugFrameConstructor
2053 void makeDebugFrame (VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2055 workQueue
.push_back(std::make_pair(frame
, outSlot
));
2060 void run_queue(VMGlobals
*g
)
2062 while (!workQueue
.empty()) {
2063 WorkQueueItem work
= workQueue
.back();
2064 workQueue
.pop_back();
2065 fillDebugFrame(g
, work
.first
, work
.second
);
2069 void fillDebugFrame(VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2071 PyrMethod
*meth
= slotRawMethod(&frame
->method
);
2072 PyrMethodRaw
* methraw
= METHRAW(meth
);
2074 PyrObject
* debugFrameObj
= instantiateObject(g
->gc
, getsym("DebugFrame")->u
.classobj
, 0, false, true);
2075 SetObject(outSlot
, debugFrameObj
);
2077 SetObject(debugFrameObj
->slots
+ 0, meth
);
2078 SetPtr(debugFrameObj
->slots
+ 5, meth
);
2080 int numargs
= methraw
->numargs
;
2081 int numvars
= methraw
->numvars
;
2083 PyrObject
* argArray
= (PyrObject
*)newPyrArray(g
->gc
, numargs
, 0, false);
2084 SetObject(debugFrameObj
->slots
+ 1, argArray
);
2085 for (int i
=0; i
<numargs
; ++i
)
2086 slotCopy(&argArray
->slots
[i
], &frame
->vars
[i
]);
2088 argArray
->size
= numargs
;
2090 SetNil(debugFrameObj
->slots
+ 1);
2093 PyrObject
* varArray
= (PyrObject
*)newPyrArray(g
->gc
, numvars
, 0, false);
2094 SetObject(debugFrameObj
->slots
+ 2, varArray
);
2095 for (int i
=0, j
=numargs
; i
<numvars
; ++i
,++j
)
2096 slotCopy(&varArray
->slots
[i
], &frame
->vars
[j
]);
2098 varArray
->size
= numvars
;
2100 SetNil(debugFrameObj
->slots
+ 2);
2102 if (slotRawFrame(&frame
->caller
)) {
2103 WorkQueueItem newWork
= std::make_pair(slotRawFrame(&frame
->caller
), debugFrameObj
->slots
+ 3);
2104 workQueue
.push_back(newWork
);
2106 SetNil(debugFrameObj
->slots
+ 3);
2108 if (IsObj(&frame
->context
) && slotRawFrame(&frame
->context
) == frame
)
2109 SetObject(debugFrameObj
->slots
+ 4, debugFrameObj
);
2110 else if (NotNil(&frame
->context
)) {
2111 WorkQueueItem newWork
= std::make_pair(slotRawFrame(&frame
->context
), debugFrameObj
->slots
+ 4);
2112 workQueue
.push_back(newWork
);
2114 SetNil(debugFrameObj
->slots
+ 4);
2117 typedef std::pair
<PyrFrame
*, PyrSlot
*> WorkQueueItem
;
2118 typedef std::vector
<WorkQueueItem
> WorkQueueType
;
2119 WorkQueueType workQueue
;
2122 static void MakeDebugFrame(VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2124 DebugFrameConstructor constructor
;
2125 constructor
.makeDebugFrame(g
, frame
, outSlot
);
2128 int prGetBackTrace(VMGlobals
*g
, int numArgsPushed
);
2129 int prGetBackTrace(VMGlobals
*g
, int numArgsPushed
)
2134 MakeDebugFrame(g
, g
->frame
, a
);
2139 int prObjectShallowCopy(struct VMGlobals
*g
, int numArgsPushed
)
2144 switch (GetTag(a
)) {
2146 SetRaw(a
, copyObject(g
->gc
, slotRawObject(a
), true));
2148 // the default case is to leave the argument unchanged on the stack
2153 int prObjectCopyImmutable(struct VMGlobals
*g
, int numArgsPushed
);
2154 int prObjectCopyImmutable(struct VMGlobals
*g
, int numArgsPushed
)
2159 switch (GetTag(a
)) {
2161 if (slotRawObject(a
)->obj_flags
& obj_immutable
) {
2162 SetRaw(a
, copyObject(g
->gc
, slotRawObject(a
), true));
2169 int prObjectIsMutable(struct VMGlobals
*g
, int numArgsPushed
);
2170 int prObjectIsMutable(struct VMGlobals
*g
, int numArgsPushed
)
2176 if (slotRawObject(a
)->obj_flags
& obj_immutable
) {
2187 int prObjectIsPermanent(struct VMGlobals
*g
, int numArgsPushed
);
2188 int prObjectIsPermanent(struct VMGlobals
*g
, int numArgsPushed
)
2194 if (slotRawObject(a
)->gc_color
== obj_permanent
) {
2207 int prDeepFreeze(struct VMGlobals
*g
, int numArgsPushed
);
2208 int prDeepFreeze(struct VMGlobals
*g
, int numArgsPushed
)
2213 PyrDeepFreezer
freezer(g
);
2214 int err
= freezer
.doDeepFreeze(a
);
2219 int prDeepCopy(struct VMGlobals
*g
, int numArgsPushed
);
2220 int prDeepCopy(struct VMGlobals
*g
, int numArgsPushed
)
2225 PyrDeepCopier
copier(g
);
2226 int err
= copier
.doDeepCopy(a
);
2233 bool IsSimpleLiteralSlot(PyrSlot
* slot
);
2234 bool IsSimpleLiteralSlot(PyrSlot
* slot
)
2236 switch (GetTag(slot
)) {
2237 case tagObj
: return slotRawObject(slot
)->IsPermanent();
2238 case tagInt
: return true;
2239 case tagSym
: return true;
2240 case tagChar
: return true;
2241 case tagNil
: return true;
2242 case tagFalse
: return true;
2243 case tagTrue
: return true;
2244 case tagPtr
: return false;
2245 default : return true;
2251 int prObjectCopyRange(struct VMGlobals
*g
, int numArgsPushed
)
2259 if (NotObj(a
)) return errWrongType
;
2260 if (NotInt(b
)) return errWrongType
;
2261 if (NotInt(c
)) return errWrongType
;
2262 SetRaw(a
, copyObjectRange(g
->gc
, slotRawObject(a
), slotRawInt(b
), slotRawInt(c
), true));
2268 int prObjectCopySeries(struct VMGlobals
*g
, int numArgsPushed
)
2270 PyrSlot
*a
, *b
, *c
, *d
;
2277 PyrObject
*inobj
= slotRawObject(a
);
2280 int size
= inobj
->size
;
2281 int flags
= ~(obj_immutable
) & inobj
->obj_flags
;
2283 int first
, second
, last
;
2285 if (IsInt(b
)) first
= slotRawInt(b
);
2286 else if (IsNil(b
)) first
= 0;
2287 else return errWrongType
;
2290 last
= slotRawInt(d
);
2291 if (last
< 0 && IsNil(b
)) {
2293 newobj
= g
->gc
->New(0, flags
, inobj
->obj_format
, true);
2295 newobj
->classptr
= inobj
->classptr
;
2299 } else if (IsNil(d
)) {
2300 if (first
>= size
) goto zerolength
;
2302 } else return errWrongType
;
2304 if (IsInt(c
)) second
= slotRawInt(c
);
2305 else if (IsNil(c
)) second
= first
< last
? first
+ 1 : first
- 1;
2306 else return errWrongType
;
2308 int step
= second
- first
;
2310 int elemsize
= gFormatElemSize
[inobj
->obj_format
];
2314 length
= (last
- first
) / step
+ 1;
2315 } else if (step
< 0) {
2316 length
= (first
- last
) / -step
+ 1;
2317 } else return errFailed
;
2319 int numbytes
= length
* elemsize
;
2321 newobj
= g
->gc
->New(numbytes
, flags
, inobj
->obj_format
, true);
2323 newobj
->classptr
= inobj
->classptr
;
2325 for (int i
=first
, j
=0; j
<length
; i
+=step
, ++j
) {
2327 if (i
>= 0 && i
< inobj
->size
) {
2328 getIndexedSlot(inobj
, &slot
, i
);
2329 int err
= putIndexedSlot(g
, newobj
, &slot
, newobj
->size
++);
2330 if (err
) return err
;
2338 void switchToThread(struct VMGlobals
*g
, struct PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
2340 int haltInterpreter(struct VMGlobals
*g
, int numArgsPushed
)
2342 switchToThread(g
, slotRawThread(&g
->process
->mainThread
), tDone
, &numArgsPushed
);
2343 // return all the way out.
2344 //PyrSlot *bottom = g->gc->Stack()->slots;
2345 //slotCopy(bottom,g->sp);
2346 //g->sp = bottom; // ??!! pop everybody
2351 longjmp(g
->escapeInterpreter
, 3);
2352 //hmm need to fix this to work only on main thread. //!!!
2353 //g->sp = g->gc->Stack()->slots - 1;
2359 int prCanCallOS(struct VMGlobals
*g
, int numArgsPushed
);
2360 int prCanCallOS(struct VMGlobals
*g
, int numArgsPushed
)
2364 SetBool(a
, g
->canCallOS
);
2369 extern bool gGenerateTailCallByteCodes
;
2371 int prGetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
);
2372 int prGetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
)
2376 SetBool(a
, gGenerateTailCallByteCodes
);
2381 int prSetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
);
2382 int prSetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
)
2384 //PyrSlot *a = g->sp - 1;
2386 #if TAILCALLOPTIMIZE
2389 gGenerateTailCallByteCodes
= true;
2390 } else if (IsFalse(b
)) {
2391 gGenerateTailCallByteCodes
= false;
2392 } else return errWrongType
;
2399 int prTraceOn(struct VMGlobals
*g
, int numArgsPushed
);
2400 int prTraceOn(struct VMGlobals
*g
, int numArgsPushed
)
2405 gTraceInterpreter
= IsTrue(a
);
2409 int prKeywordError(struct VMGlobals
*g
, int numArgsPushed
);
2410 int prKeywordError(struct VMGlobals
*g
, int numArgsPushed
)
2415 gKeywordError
= IsTrue(a
);
2419 int prFunDef_NumArgs(struct VMGlobals
*g
, int numArgsPushed
);
2420 int prFunDef_NumArgs(struct VMGlobals
*g
, int numArgsPushed
)
2423 PyrMethodRaw
*methraw
;
2426 methraw
= METHRAW(slotRawBlock(a
));
2427 SetInt(a
, methraw
->numargs
);
2431 int prFunDef_NumVars(struct VMGlobals
*g
, int numArgsPushed
);
2432 int prFunDef_NumVars(struct VMGlobals
*g
, int numArgsPushed
)
2435 PyrMethodRaw
*methraw
;
2438 methraw
= METHRAW(slotRawBlock(a
));
2439 SetInt(a
, methraw
->numvars
);
2443 int prFunDef_VarArgs(struct VMGlobals
*g
, int numArgsPushed
);
2444 int prFunDef_VarArgs(struct VMGlobals
*g
, int numArgsPushed
)
2447 PyrMethodRaw
*methraw
;
2450 methraw
= METHRAW(slotRawBlock(a
));
2451 if (methraw
->varargs
) { SetTrue(a
); } else { SetFalse(a
); }
2456 int undefinedPrimitive(struct VMGlobals
*g
, int numArgsPushed
)
2458 error("A primitive was not bound. %d %d\n", g
->primitiveIndex
, gPrimitiveTable
.size
);
2459 dumpObject((PyrObject
*)g
->primitiveMethod
);
2463 void dumpByteCodes(PyrBlock
*theBlock
);
2465 int prDumpByteCodes(struct VMGlobals
*g
, int numArgsPushed
)
2470 dumpByteCodes(slotRawBlock(a
));
2474 int prObjectPointsTo(struct VMGlobals
*g
, int numArgsPushed
)
2476 PyrSlot
*a
, *b
, temp
;
2483 if (NotObj(a
)) slotCopy(a
,&o_false
);
2485 obj
= slotRawObject(a
);
2486 for (i
=0; i
<obj
->size
; ++i
) {
2487 getIndexedSlot(obj
, &temp
, i
);
2488 if (SlotEq(&temp
, b
)) {
2489 slotCopy(a
,&o_true
);
2493 slotCopy(a
,&o_false
);
2499 int prObjectRespondsTo(struct VMGlobals
*g
, int numArgsPushed
)
2504 PyrSymbol
*selector
;
2510 classobj
= classOfSlot(a
);
2514 selector
= slotRawSymbol(b
);
2515 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2516 meth
= gRowTable
[index
];
2517 if (slotRawSymbol(&meth
->name
) != selector
) {
2518 slotCopy(a
,&o_false
);
2520 slotCopy(a
,&o_true
);
2522 } else if (isKindOfSlot(b
, class_array
)) {
2523 int size
= slotRawObject(b
)->size
;
2524 PyrSlot
*slot
= slotRawObject(b
)->slots
;
2525 for (int i
=0; i
<size
; ++i
, ++slot
) {
2527 if (NotSym(slot
)) return errWrongType
;
2529 selector
= slotRawSymbol(slot
);
2530 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2531 meth
= gRowTable
[index
];
2532 if (slotRawSymbol(&meth
->name
) != selector
) {
2533 slotCopy(a
,&o_false
);
2537 slotCopy(a
,&o_true
);
2538 } else return errWrongType
;
2542 PyrMethod
* GetFunctionCompileContext(VMGlobals
* g
);
2543 PyrMethod
* GetFunctionCompileContext(VMGlobals
* g
)
2546 PyrSymbol
*classsym
, *contextsym
;
2548 // lookup interpreter class
2549 classsym
= getsym("Interpreter");
2550 classobj
= classsym
->u
.classobj
;
2552 error("There is no Interpreter class.\n");
2555 // lookup functionCompileContext method
2556 contextsym
= getsym("functionCompileContext");
2557 int index
= slotRawInt(&classobj
->classIndex
) + contextsym
->u
.index
;
2558 meth
= gRowTable
[index
];
2559 if (!meth
|| slotRawSymbol(&meth
->name
) != contextsym
) {
2560 error("compile context method 'functionCompileContext' not found.\n");
2563 gCompilingClass
= classobj
;
2564 gCompilingMethod
= meth
;
2565 gCompilingBlock
= (PyrBlock
*)meth
;
2570 int prCompileString(struct VMGlobals
*g
, int numArgsPushed
)
2579 // check b is a string
2580 if (NotObj(b
)) return errWrongType
;
2581 if (!isKindOf(slotRawObject(b
), class_string
)) return errWrongType
;
2582 string
= slotRawString(b
);
2584 gRootParseNode
= NULL
;
2586 //assert(g->gc->SanityCheck());
2587 startLexerCmdLine(string
->s
, string
->size
);
2589 compilingCmdLine
= true;
2590 gCompilingVMGlobals
= g
;
2591 compilingCmdLineErrorWindow
= false;
2592 //assert(g->gc->SanityCheck());
2593 parseFailed
= yyparse();
2594 //assert(g->gc->SanityCheck());
2595 if (!parseFailed
&& gRootParseNode
) {
2598 meth
= GetFunctionCompileContext(g
);
2599 if (!meth
) return errFailed
;
2601 ((PyrBlockNode
*)gRootParseNode
)->mIsTopLevel
= true;
2603 SetNil(&slotResult
);
2604 COMPILENODE(gRootParseNode
, &slotResult
, true);
2606 if (NotObj(&slotResult
)
2607 || slotRawObject(&slotResult
)->classptr
!= class_fundef
) {
2609 error("Compile did not return a FunctionDef..\n");
2611 if (compileErrors
) {
2615 PyrClosure
*closure
;
2617 block
= slotRawBlock(&slotResult
);
2619 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, false);
2620 closure
->classptr
= class_func
;
2622 SetObject(&closure
->block
, block
);
2623 slotCopy(&closure
->context
,&slotRawInterpreter(&g
->process
->interpreter
)->context
);
2624 SetObject(a
, closure
);
2629 error("Command line parse failed\n");
2631 postfl("<nothing to do>\n");
2638 pyr_pool_compile
->FreeAll();
2640 compilingCmdLine
= false;
2642 return !(parseFailed
|| compileErrors
) ? errNone
: errFailed
;
2646 char sCodeStringIn
[8192];
2647 char sCodeStringOut
[8192];
2649 int prUGenCodeString(struct VMGlobals
*g
, int numArgsPushed
);
2650 int prUGenCodeString(struct VMGlobals
*g
, int numArgsPushed
)
2652 PyrSlot
*aa
, *bb
, *cc
, *dd
, *ee
;
2653 char *out
= sCodeStringOut
;
2654 char ugenPrefix
[16];
2657 aa
= g
->sp
- 4; // code string
2658 bb
= g
->sp
- 3; // ugen prefix
2659 ee
= g
->sp
- 2; // isDecl
2660 cc
= g
->sp
- 1; // input names
2661 dd
= g
->sp
; // input value strings
2664 err
= slotIntVal(bb
, &ugenIndex
);
2665 if (err
) return err
;
2666 if (!isKindOfSlot(cc
, class_array
) && !isKindOfSlot(cc
, class_symbolarray
)) return errWrongType
;
2667 if (!isKindOfSlot(dd
, class_array
)) return errWrongType
;
2668 bool isDecl
= IsTrue(ee
);
2670 PyrObject
*inputNamesObj
= slotRawObject(cc
);
2671 PyrObject
*inputStringsObj
= slotRawObject(dd
);
2673 sprintf(ugenPrefix
, "u%d", ugenIndex
);
2674 int ugenPrefixSize
= strlen(ugenPrefix
);
2675 PyrString
* codeStringObj
= slotRawString(aa
);
2676 int codeStringSize
= codeStringObj
->size
;
2677 if (codeStringSize
> 8000) {
2678 error("input string too int.\n");
2681 memcpy(sCodeStringIn
, codeStringObj
->s
, codeStringSize
);
2682 sCodeStringIn
[codeStringSize
] = 0;
2684 char* in
= sCodeStringIn
;
2686 while ((c
= *in
++) != 0) {
2695 for (int j
=0; j
<ugenPrefixSize
; ++j
) {
2696 *out
++ = ugenPrefix
[j
];
2698 } else if (c
== '$') {
2704 if (!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9'))) {
2714 for (int j
=0; j
<inputNamesObj
->size
; ++j
) {
2715 PyrSlot inputNameSlot
;
2716 getIndexedSlot(inputNamesObj
, &inputNameSlot
, j
);
2717 if (!IsSym(&inputNameSlot
)) return errWrongType
;
2718 PyrSymbol
* inputSym
= slotRawSymbol(&inputNameSlot
);
2719 char *inputName
= inputSym
->name
;
2720 int inputNameSize
= inputSym
->length
;
2721 if (inputNameSize
== nameSize
&& strncmp(inputName
, name
, nameSize
)==0) {
2727 if (slotIndex
>= 0) {
2728 PyrSlot
*inputStringSlot
= inputStringsObj
->slots
+ slotIndex
;
2729 if (!isKindOfSlot(inputStringSlot
, class_string
)) return errWrongType
;
2730 PyrString
*inputStringObj
= slotRawString(inputStringSlot
);
2731 char *input
= inputStringObj
->s
;
2732 int inputStringSize
= inputStringObj
->size
;
2733 for (int j
=0; j
<inputStringSize
; ++j
) {
2737 *out
++ = '?'; *out
++ = '?';
2738 for (int j
=0; j
<nameSize
; ++j
) {
2741 *out
++ = '?'; *out
++ = '?';
2746 if (out
- sCodeStringOut
> 8000) {
2756 PyrString
* outString
= newPyrString(g
->gc
, sCodeStringOut
, 0, true);
2757 SetObject(aa
, outString
);
2764 /*void threadSanity(VMGlobals *g, PyrThread *thread);
2765 void threadSanity(VMGlobals *g, PyrThread *thread)
2768 g->gc->numToScan = 1000000;
2770 assert(g->gc->SanityCheck());
2772 state = slotRawInt(&thread->state);
2773 if (state == tYield) {
2774 if (!IsObj(&thread->method)) { error("thread method not an Object\n"); }
2775 else if (!isKindOf(slotRawObject(&thread->method), class_method)) { error("thread method not a Method\n"); }
2776 else if (slotRawObject(&thread->method)->gc_color == gcColor.gcFree) { error("thread method is FREE\n"); }
2778 if (!IsObj(&thread->block)) { error("thread block not an Object\n"); }
2779 else if (!isKindOf(slotRawObject(&thread->block), class_func)) { error("thread block not a Function\n"); }
2780 else if (slotRawObject(&thread->block)->gc_color == gcColor.gcFree) { error("thread block is FREE\n"); }
2782 if (IsObj(&thread->receiver) &slotRawObject(&& thread->receiver)->gc_color == gcColor.gcFree)
2783 { error("thread receiver is FREE\n"); }
2785 FrameSanity(thread->frame.uof);
2787 oldthread->method.uom = g->method;
2788 oldthread->block.uoblk = g->block;
2789 SetObject(&oldthread->frame, g->frame);
2790 slotRawInt(&oldthread->ip) = (int)g->ip;
2791 slotRawInt(&oldthread->sp) = (int)g->sp;
2794 } else if (state == tInit) {
2796 postfl("bad state\n");
2801 PyrSymbol
*s_prready
;
2802 PyrSymbol
*s_prrunnextthread
;
2804 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
2805 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
)
2807 PyrThread
*oldthread
;
2811 #if TAILCALLOPTIMIZE
2812 g
->tailCall
= 0; // ?? prevent a crash. is there a way to allow a TCO ?
2815 oldthread
= g
->thread
;
2816 if (newthread
== oldthread
) return;
2817 //postfl("->switchToThread %d %p -> %p\n", oldstate, oldthread, newthread);
2818 //post("->switchToThread from %s:%s\n", slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name);
2819 //post("->stack %p g->sp %p [%d] g->top %p [%d]\n",
2820 // g->gc->Stack()->slots, g->sp, g->sp - g->gc->Stack()->slots, g->top, g->top - g->gc->Stack()->slots);
2821 //assert(g->gc->SanityCheck());
2822 //CallStackSanity(g, "switchToThreadA");
2823 //gcDumpInfo(g->gc);
2826 // save environment in oldthread
2827 PyrSlot
* currentEnvironmentSlot
= &g
->classvars
->slots
[1];
2828 slotCopy(&oldthread
->environment
,currentEnvironmentSlot
);
2829 gc
->GCWrite(oldthread
, currentEnvironmentSlot
);
2831 SetRaw(&oldthread
->state
, oldstate
);
2833 if (oldstate
== tDone
) {
2834 SetObject(&oldthread
->stack
, gc
->Stack());
2835 gc
->ToWhite(gc
->Stack());
2836 gc
->Stack()->size
= 0;
2837 gc
->GCWrite(oldthread
, gc
->Stack());
2838 SetNil(&oldthread
->method
);
2839 SetNil(&oldthread
->block
);
2840 SetNil(&oldthread
->receiver
);
2841 SetNil(&oldthread
->frame
);
2842 SetRaw(&oldthread
->ip
, (void*)0);
2843 SetRaw(&oldthread
->sp
, (void*)0);
2844 SetRaw(&oldthread
->numArgsPushed
, 0);
2845 SetRaw(&oldthread
->numpop
, 0);
2846 SetNil(&oldthread
->parent
);
2847 } else if (oldstate
== tInit
) {
2848 SetObject(&oldthread
->stack
, gc
->Stack());
2849 gc
->ToWhite(gc
->Stack());
2850 gc
->Stack()->size
= 0;
2851 gc
->GCWrite(oldthread
, gc
->Stack());
2852 SetNil(&oldthread
->method
);
2853 SetNil(&oldthread
->block
);
2854 SetNil(&oldthread
->receiver
);
2855 SetNil(&oldthread
->frame
);
2856 SetRaw(&oldthread
->ip
, (void*)0);
2857 SetRaw(&oldthread
->sp
, (void*)0);
2858 SetRaw(&oldthread
->numArgsPushed
, 0);
2859 SetRaw(&oldthread
->numpop
, 0);
2860 SetNil(&oldthread
->parent
);
2862 // save old thread's state
2863 SetObject(&oldthread
->stack
, gc
->Stack());
2864 gc
->ToWhite(gc
->Stack());
2865 gc
->Stack()->size
= g
->sp
- gc
->Stack()->slots
+ 1;
2866 //post("else %p %p\n", slotRawObject(&oldthread->stack), gc->Stack());
2868 SetObject(&oldthread
->method
, g
->method
);
2869 SetObject(&oldthread
->block
, g
->block
);
2870 SetObject(&oldthread
->frame
, g
->frame
);
2871 SetPtr(&oldthread
->ip
, g
->ip
);
2872 SetPtr(&oldthread
->sp
, g
->sp
);
2873 slotCopy(&oldthread
->receiver
,&g
->receiver
);
2874 SetRaw(&oldthread
->numArgsPushed
, *numArgsPushed
);
2875 SetRaw(&oldthread
->numpop
, g
->numpop
);
2877 //gc->ToGrey(oldthread);
2878 if (gc
->ObjIsBlack(oldthread
)) {
2879 gc
->GCWriteBlack(gc
->Stack());
2880 gc
->GCWriteBlack(g
->method
);
2881 gc
->GCWriteBlack(g
->block
);
2883 frame
= slotRawFrame(&oldthread
->frame
);
2884 gc
->GCWriteBlack(frame
);
2886 gc
->GCWriteBlack(&g
->receiver
);
2890 // restore new thread's state
2891 g
->thread
= newthread
;
2892 SetObject(&g
->process
->curThread
, newthread
);
2893 gc
->GCWrite(g
->process
, newthread
);
2895 gc
->SetStack(slotRawObject(&newthread
->stack
));
2896 gc
->ToBlack(gc
->Stack());
2897 SetNil(&newthread
->stack
);
2899 g
->method
= slotRawMethod(&newthread
->method
);
2900 g
->block
= slotRawBlock(&newthread
->block
);
2901 g
->frame
= slotRawFrame(&newthread
->frame
);
2902 g
->ip
= (unsigned char *)slotRawPtr(&newthread
->ip
);
2903 g
->sp
= (PyrSlot
*)slotRawPtr(&newthread
->sp
);
2904 slotCopy(&g
->receiver
,&newthread
->receiver
);
2906 g
->rgen
= (RGen
*)(slotRawObject(&newthread
->randData
)->slots
);
2908 *numArgsPushed
= slotRawInt(&newthread
->numArgsPushed
);
2910 // these are perhaps unecessary because a thread may not
2911 // legally block within a C primitive
2912 g
->numpop
= slotRawInt(&newthread
->numpop
);
2916 //post("switchToThread ip %p\n", g->ip);
2917 //post(slotRawInt(&"switchToThread newthread->ip) %d\n", slotRawInt(&newthread->ip));
2918 //post(slotRawInt(&"switchToThread oldthread->ip) %d\n", slotRawInt(&oldthread->ip));
2920 // wipe out values which will become stale as new thread executes:
2921 SetNil(&newthread
->method
);
2922 SetNil(&newthread
->block
);
2923 SetNil(&newthread
->frame
);
2924 SetRaw(&newthread
->ip
, (void*)0);
2925 SetRaw(&newthread
->sp
, (void*)0);
2926 SetNil(&newthread
->receiver
);
2928 SetRaw(&newthread
->state
, tRunning
);
2931 // set new environment
2932 slotCopy(currentEnvironmentSlot
,&g
->thread
->environment
);
2933 g
->gc
->GCWrite(g
->classvars
, currentEnvironmentSlot
);
2935 //post("old thread %p stack %p\n", oldthread, slotRawObject(&oldthread->stack));
2936 //post("new thread %p stack %p\n", g->thread, slotRawObject(&g->thread->stack));
2937 //post("main thread %p stack %p\n", slotRawThread(&g->process->mainThread), slotRawObject(&slotRawThread(&g->process->mainThread)->stack));
2939 //postfl("<-switchToThread\n");
2940 //post("<-stack %p g->sp %p [%d] g->top %p [%d]\n",
2941 // g->gc->Stack()->slots, g->sp, g->sp - g->gc->Stack()->slots, g->top, g->top - g->gc->Stack()->slots);
2942 //assert(g->gc->SanityCheck());
2943 //CallStackSanity(g, "switchToThreadB");
2944 //post("switchToThread ip2 %p\n", g->ip);
2947 void initPyrThread(VMGlobals
*g
, PyrThread
*thread
, PyrSlot
*func
, int stacksize
, PyrInt32Array
* rgenArray
,
2948 double beats
, double seconds
, PyrSlot
* clock
, bool collect
);
2949 void initPyrThread(VMGlobals
*g
, PyrThread
*thread
, PyrSlot
*func
, int stacksize
, PyrInt32Array
* rgenArray
,
2950 double beats
, double seconds
, PyrSlot
* clock
, bool collect
)
2955 slotCopy(&thread
->func
, func
);
2956 gc
->GCWrite(thread
, func
);
2958 array
= newPyrArray(gc
, stacksize
, 0, collect
);
2959 SetObject(&thread
->stack
, array
);
2960 gc
->GCWrite(thread
, array
);
2962 SetInt(&thread
->state
, tInit
);
2964 SetPtr(&thread
->ip
, 0);
2965 SetPtr(&thread
->sp
, 0);
2967 SetObject(&thread
->randData
, rgenArray
);
2968 gc
->GCWrite(thread
, rgenArray
);
2970 SetFloat(&thread
->beats
, beats
);
2971 SetFloat(&thread
->seconds
, seconds
);
2972 SetInt(&thread
->numArgsPushed
, 0);
2973 SetInt(&thread
->numpop
, 0);
2976 SetObject(&thread
->clock
, s_systemclock
->u
.classobj
);
2978 slotCopy(&thread
->clock
,clock
);
2979 gc
->GCWrite(thread
, clock
);
2982 PyrSlot
* currentEnvironmentSlot
= &g
->classvars
->slots
[1];
2983 slotCopy(&thread
->environment
,currentEnvironmentSlot
);
2984 gc
->GCWrite(thread
, currentEnvironmentSlot
);
2986 if(g
->process
) { // check we're not just starting up
2987 PyrSlot
* executingPath
= &g
->process
->nowExecutingPath
;
2988 slotCopy(&thread
->executingPath
,&g
->process
->nowExecutingPath
);
2989 gc
->GCWrite(thread
, &g
->process
->nowExecutingPath
);
2992 SetInt(&thread
->stackSize
, stacksize
);
2995 extern PyrSymbol
*s_prstart
;
2997 int prThreadInit(struct VMGlobals
*g
, int numArgsPushed
);
2998 int prThreadInit(struct VMGlobals
*g
, int numArgsPushed
)
3000 PyrSlot
*a
, *b
, *c
, *d
;
3004 //postfl("->prThreadInit\n");
3005 //assert(g->gc->SanityCheck());
3006 //CallStackSanity(g, "prThreadInit");
3007 a
= g
->sp
- 2; // thread
3008 b
= g
->sp
- 1; // function
3009 c
= g
->sp
; // stacksize
3011 thread
= slotRawThread(a
);
3013 if (NotObj(b
) || !isKindOf(slotRawObject(b
), class_func
)) {
3014 error("Thread function arg not a Function.\n");
3015 return errWrongType
;
3018 err
= slotIntVal(c
, &stacksize
);
3019 if (err
) return err
;
3021 stacksize
= std::max(stacksize
, EVALSTACKDEPTH
);
3023 initPyrThread(g
, thread
, b
, stacksize
, (PyrInt32Array
*)(slotRawObject(&g
->thread
->randData
)),
3024 slotRawFloat(&g
->thread
->beats
), slotRawFloat(&g
->thread
->seconds
), &g
->thread
->clock
, true);
3026 //postfl("<-prThreadInit\n");
3027 //assert(g->gc->SanityCheck());
3028 //CallStackSanity(g, "<prThreadInit");
3032 int prThreadRandSeed(struct VMGlobals
*g
, int numArgsPushed
);
3033 int prThreadRandSeed(struct VMGlobals
*g
, int numArgsPushed
)
3035 PyrSlot
*a
= g
->sp
- 1; // thread
3036 PyrSlot
*b
= g
->sp
; // rand seed
3038 PyrThread
*thread
= slotRawThread(a
);
3041 int err
= slotIntVal(b
, &seed
);
3042 if (err
) return err
;
3044 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, true);
3045 rgenArray
->size
= 4;
3046 ((RGen
*)(rgenArray
->i
))->init(seed
);
3048 if (thread
== g
->thread
) {
3049 g
->rgen
= (RGen
*)(rgenArray
->i
);
3051 SetObject(&thread
->randData
, rgenArray
);
3052 g
->gc
->GCWrite(thread
, rgenArray
);
3057 int prThreadGetRandData(struct VMGlobals
*g
, int numArgsPushed
);
3058 int prThreadGetRandData(struct VMGlobals
*g
, int numArgsPushed
)
3060 PyrSlot
*a
= g
->sp
; // thread
3062 PyrThread
*thread
= slotRawThread(a
);
3064 RGen
* rgen
= (RGen
*)slotRawObject(&thread
->randData
)->slots
;
3066 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, false);
3067 rgenArray
->size
= 3;
3069 rgenArray
->i
[0] = rgen
->s1
;
3070 rgenArray
->i
[1] = rgen
->s2
;
3071 rgenArray
->i
[2] = rgen
->s3
;
3073 SetObject(a
, rgenArray
);
3077 int prThreadSetRandData(struct VMGlobals
*g
, int numArgsPushed
);
3078 int prThreadSetRandData(struct VMGlobals
*g
, int numArgsPushed
)
3080 PyrSlot
*a
= g
->sp
- 1; // thread
3081 PyrSlot
*b
= g
->sp
; // rand data array
3083 if (!isKindOfSlot(b
, class_int32array
)) return errWrongType
;
3084 if (slotRawObject(b
)->size
< 3) return errWrongType
;
3086 PyrThread
*thread
= slotRawThread(a
);
3088 RGen
* rgen
= (RGen
*)slotRawObject(&thread
->randData
)->slots
;
3090 PyrInt32Array
*rgenArray
= (PyrInt32Array
*)slotRawObject(b
);
3092 rgen
->s1
= rgenArray
->i
[0];
3093 rgen
->s2
= rgenArray
->i
[1];
3094 rgen
->s3
= rgenArray
->i
[2];
3102 int transformMainThreadToRoutine(VMGlobals
*g
)
3104 PyrProcess
* process
= g
->process
;
3105 if (g
->thread
!= process
->mainThread
.uot
) return errFailed
;
3106 //if (g->thread != process->curThread.uot) return errFailed;
3108 PyrThread
* curthread
= (PyrThread
*)slotRawObject(&process
->mainThread
);
3110 // create a new main thread
3111 PyrThread
* newthread
= (PyrThread
*)instantiateObject(g
->gc
, class_thread
, 0, true, false);
3113 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, false);
3114 rgenArray
->size
= 4;
3115 ((RGen
*)(rgenArray
->i
))->init(timeseed());
3118 SetObject(&clockSlot
, s_systemclock
->u
.classobj
);
3119 initPyrThread(g
, newthread
, &o_nil
, EVALSTACKDEPTH
, rgenArray
, 0., 0., &clockSlot
, false);
3120 slotRawInt(&newthread
->sp
) = (int)slotRawObject(&newthread
->stack
)->slots
- 1;
3121 SetObject(&process
->mainThread
, newthread
);
3122 g
->gc
->GCWrite(process
, newthread
);
3124 curthread
->classptr
= class_routine
;
3125 PyrSlot
*cmdFunc
= &process
->interpreter
.uoi
->cmdFunc
;
3126 slotCopy(&curthread
->func
,cmdFunc
);
3127 g
->gc
->GCWrite(curthread
, cmdFunc
);
3132 void schedAdd(VMGlobals
*g
, PyrObject
* inQueue
, double inSeconds
, PyrSlot
* inTask
);
3136 int prRoutineYield(struct VMGlobals
*g
, int numArgsPushed
);
3137 int prRoutineYield(struct VMGlobals
*g
, int numArgsPushed
)
3141 //postfl("->prRoutineYield %p\n", g->thread);
3142 //assert(g->gc->SanityCheck());
3143 //CallStackSanity(g, "prRoutineYield");
3144 //postfl("->numArgsPushed %d\n", numArgsPushed);
3146 slotCopy(&value
,g
->sp
);
3148 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3149 error ("yield was called outside of a Routine.\n");
3153 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3154 SetNil(&g
->thread
->parent
);
3155 slotCopy(&g
->process
->nowExecutingPath
, &g
->thread
->oldExecutingPath
);
3156 //debugf("yield from thread %p to parent %p\n", g->thread, slotRawThread(&g->thread->parent));
3157 switchToThread(g
, parent
, tSuspended
, &numArgsPushed
);
3159 // on the other side of the looking glass, put the yielded value on the stack as the result..
3160 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3162 //postfl("<-numArgsPushed %d\n", numArgsPushed);
3163 //postfl("<-prRoutineYield\n");
3164 //assert(g->gc->SanityCheck());
3165 //CallStackSanity(g, "<prRoutineYield");
3169 int prRoutineAlwaysYield(struct VMGlobals
*g
, int numArgsPushed
);
3170 int prRoutineAlwaysYield(struct VMGlobals
*g
, int numArgsPushed
)
3174 //postfl("->prRoutineAlwaysYield ip %p\n", g->ip);
3175 //assert(g->gc->SanityCheck());
3176 //CallStackSanity(g, "prRoutineAlwaysYield");
3177 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3178 error ("alwaysYield was called outside of a Routine.\n");
3182 slotCopy(&value
,g
->sp
);
3183 slotCopy(&g
->thread
->terminalValue
,&value
);
3184 g
->gc
->GCWrite(g
->thread
, g
->sp
);
3186 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3187 SetNil(&g
->thread
->parent
);
3188 slotCopy(&g
->process
->nowExecutingPath
, &g
->thread
->oldExecutingPath
);
3189 //post("alwaysYield from thread %p to parent %p\n", g->thread, parent);
3190 switchToThread(g
, parent
, tDone
, &numArgsPushed
);
3192 // on the other side of the looking glass, put the yielded value on the stack as the result..
3193 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3195 //postfl("<-prRoutineAlwaysYield ip %p\n", g->ip);
3196 //assert(g->gc->SanityCheck());
3197 //CallStackSanity(g, "<prRoutineAlwaysYield");
3201 int prRoutineResume(struct VMGlobals
*g
, int numArgsPushed
);
3202 int prRoutineResume(struct VMGlobals
*g
, int numArgsPushed
)
3204 PyrSlot
*a
, *b
, threadSlot
, value
;
3208 //assert(g->gc->SanityCheck());
3209 //CallStackSanity(g, "prRoutineResume");
3213 thread
= slotRawThread(a
);
3214 state
= slotRawInt(&thread
->state
);
3215 //postfl("->prRoutineResume %d\n", state);
3217 slotCopy(&thread
->oldExecutingPath
,&g
->process
->nowExecutingPath
);
3218 slotCopy(&g
->process
->nowExecutingPath
, &thread
->executingPath
);
3219 if (state
== tInit
) {
3220 slotCopy(&threadSlot
,a
);
3223 //post("g->thread %p\n", g->thread);
3224 //post("thread %p\n", thread);
3225 SetObject(&thread
->parent
, g
->thread
);
3226 g
->gc
->GCWrite(thread
, g
->thread
);
3228 SetRaw(&thread
->beats
, slotRawFloat(&g
->thread
->beats
));
3229 SetRaw(&thread
->seconds
, slotRawFloat(&g
->thread
->seconds
));
3230 slotCopy(&thread
->clock
, &g
->thread
->clock
);
3231 g
->gc
->GCWrite(thread
, &g
->thread
->clock
);
3233 //postfl("start into thread %p from parent %p\n", thread, g->thread);
3234 switchToThread(g
, thread
, tSuspended
, &numArgsPushed
);
3237 //post("set stack %p %p\n", g->sp, g->gc->Stack()->slots - 1);
3238 g
->sp
= g
->gc
->Stack()->slots
- 1;
3239 slotCopy((++g
->sp
), &threadSlot
);
3240 slotCopy(&g
->receiver
, &threadSlot
);
3241 slotCopy((++g
->sp
),&value
);
3243 sendMessage(g
, s_prstart
, 2);
3244 } else if (state
== tSuspended
) {
3246 if (IsNil(&thread
->parent
)) {
3247 SetObject(&thread
->parent
, g
->thread
);
3249 g
->gc
->GCWrite(thread
, g
->thread
);
3251 SetRaw(&thread
->beats
, slotRawFloat(&g
->thread
->beats
));
3252 SetRaw(&thread
->seconds
, slotRawFloat(&g
->thread
->seconds
));
3253 slotCopy(&thread
->clock
,&g
->thread
->clock
);
3254 g
->gc
->GCWrite(thread
, &g
->thread
->clock
);
3257 //debugf("resume into thread %p from parent %p\n", thread, g->thread);
3258 switchToThread(g
, thread
, tSuspended
, &numArgsPushed
);
3259 // on the other side of the looking glass, put the yielded value on the stack as the result..
3260 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3261 } else if (state
== tDone
) {
3262 slotCopy(a
,&thread
->terminalValue
);
3263 } else if (state
== tRunning
) {
3264 error("Tried to resume the running thread.\n");
3267 error("Thread in strange state: %d\n", state
);
3270 //postfl("<-prRoutineResume\n");
3271 //CallStackSanity(g);
3275 int prRoutineReset(struct VMGlobals
*g
, int numArgsPushed
);
3276 int prRoutineReset(struct VMGlobals
*g
, int numArgsPushed
)
3281 //assert(g->gc->SanityCheck());
3282 //CallStackSanity(g, "prRoutineReset");
3283 thread
= slotRawThread(g
->sp
);
3284 state
= slotRawInt(&thread
->state
);
3285 //post("->prRoutineReset %d\n", state);
3286 if (state
== tSuspended
) {
3287 SetRaw(&thread
->state
, tInit
);
3288 slotRawObject(&thread
->stack
)->size
= 0;
3289 SetNil(&thread
->method
);
3290 SetNil(&thread
->block
);
3291 SetNil(&thread
->receiver
);
3292 SetNil(&thread
->frame
);
3293 SetRaw(&thread
->ip
, (void*)0);
3294 SetRaw(&thread
->sp
, (void*)0);
3295 SetRaw(&thread
->numArgsPushed
, 0);
3296 SetRaw(&thread
->numpop
, 0);
3297 SetNil(&thread
->parent
);
3298 } else if (state
== tDone
) {
3299 SetRaw(&thread
->state
, tInit
);
3300 slotRawObject(&thread
->stack
)->size
= 0;
3301 SetNil(&thread
->method
);
3302 SetNil(&thread
->block
);
3303 SetNil(&thread
->receiver
);
3304 SetNil(&thread
->frame
);
3305 SetRaw(&thread
->ip
, (void*)0);
3306 SetRaw(&thread
->sp
, (void*)0);
3307 SetRaw(&thread
->numArgsPushed
, 0);
3308 SetRaw(&thread
->numpop
, 0);
3309 SetNil(&thread
->parent
);
3310 } else if (state
== tInit
) {
3312 } else if (state
== tRunning
) {
3313 error("A Routine cannot reset itself except by yieldAndReset.\n");
3316 error("Routine in unknown state. %d\n", state
);
3319 //assert(g->gc->SanityCheck());
3320 //CallStackSanity(g, "<prRoutineReset");
3324 int prRoutineStop(struct VMGlobals
*g
, int numArgsPushed
);
3325 int prRoutineStop(struct VMGlobals
*g
, int numArgsPushed
)
3329 //post("->prRoutineStop\n");
3330 //assert(g->gc->SanityCheck());
3331 //CallStackSanity(g, "prRoutineStop");
3333 thread
= slotRawThread(g
->sp
);
3334 state
= slotRawInt(&thread
->state
);
3337 if (state
== tSuspended
|| state
== tInit
) {
3338 slotCopy(&g
->process
->nowExecutingPath
, &thread
->oldExecutingPath
);
3339 SetNil(&g
->thread
->terminalValue
);
3340 SetRaw(&thread
->state
, tDone
);
3341 slotRawObject(&thread
->stack
)->size
= 0;
3342 } else if (state
== tDone
) {
3344 } else if (state
== tRunning
) {
3345 error("Do not call .stop from within the Routine.\n");
3346 post("A Routine should stop itself using nil.alwaysYield.\n");
3349 error("Routine in unknown state. %d\n", state
);
3352 //assert(g->gc->SanityCheck());
3353 //CallStackSanity(g, "<prRoutineStop");
3358 int prRoutineYieldAndReset(struct VMGlobals
*g
, int numArgsPushed
);
3359 int prRoutineYieldAndReset(struct VMGlobals
*g
, int numArgsPushed
)
3361 PyrSlot
*a
, *b
, value
;
3364 //post("->prRoutineYieldAndReset\n");
3365 //assert(g->gc->SanityCheck());
3366 //CallStackSanity(g, "prRoutineYieldAndReset");
3370 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3371 error ("yieldAndReset was called outside of a Routine.\n");
3374 /*if (!slotRawThread(&g->thread->parent)) {
3375 error ("yieldAndReset was called from a thread with no parent.\n");
3380 if (IsFalse(b
)) state
= tSuspended
;
3383 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3384 SetNil(&g
->thread
->parent
);
3385 switchToThread(g
, parent
, state
, &numArgsPushed
);
3386 // on the other side of the looking glass, put the yielded value on the stack as the result..
3387 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3389 //slotCopy(&g->process->nowExecutingPath, &g->thread->oldExecutingPath);
3391 //post("<-prRoutineYieldAndReset\n");
3392 //assert(g->gc->SanityCheck());
3393 //CallStackSanity(g, "prRoutineYieldAndReset");
3398 bool gBlork
= false;
3400 int prBlork(struct VMGlobals
*g
, int numArgsPushed
);
3401 int prBlork(struct VMGlobals
*g
, int numArgsPushed
)
3406 if (IsTrue(a
)) gBlork
= true;
3407 else gBlork
= false;
3412 int prOverwriteMsg(struct VMGlobals
*g
, int numArgsPushed
);
3413 int prOverwriteMsg(struct VMGlobals
*g
, int numArgsPushed
)
3416 PyrString
* string
= newPyrString(g
->gc
, overwriteMsg
.c_str(), 0, false);
3417 SetObject(a
, string
);
3421 int prAppClockSchedNotify(struct VMGlobals
*g
, int numArgsPushed
)
3423 //NOTE: the _AppClock_SchedNotify primitive shall be redefined by language clients
3424 // if they wish to respond to AppClock scheduling notifications
3428 enum {includePaths
, excludePaths
};
3430 static int prLanguageConfig_getLibraryPaths(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3432 PyrSlot
*result
= g
->sp
;
3434 typedef SC_LanguageConfig::DirVector DirVector
;
3436 DirVector
const & dirVector
= (pathType
== includePaths
) ? gLibraryConfig
->includedDirectories()
3437 : gLibraryConfig
->excludedDirectories();
3439 size_t numberOfPaths
= dirVector
.size();
3440 PyrObject
* resultArray
= newPyrArray(g
->gc
, numberOfPaths
, 0, true);
3441 SetObject(result
, resultArray
);
3442 resultArray
->size
= numberOfPaths
;
3444 for (size_t i
= 0; i
!= numberOfPaths
; ++i
)
3445 SetObject(resultArray
->slots
+ i
, newPyrString(g
->gc
, dirVector
[i
].c_str(), 0, true));
3449 static int prLanguageConfig_getIncludePaths(struct VMGlobals
* g
, int numArgsPushed
)
3451 return prLanguageConfig_getLibraryPaths(g
, numArgsPushed
, includePaths
);
3454 static int prLanguageConfig_getExcludePaths(struct VMGlobals
* g
, int numArgsPushed
)
3456 return prLanguageConfig_getLibraryPaths(g
, numArgsPushed
, excludePaths
);
3459 static int prLanguageConfig_addLibraryPath(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3461 PyrSlot
*result
= g
->sp
- 1;
3462 PyrSlot
*removeString
= g
->sp
;
3464 char path
[MAXPATHLEN
];
3465 bool error
= slotStrVal(removeString
, path
, MAXPATHLEN
);
3467 return errWrongType
;
3469 if (pathType
== includePaths
)
3470 gLibraryConfig
->addIncludedDirectory(path
);
3472 gLibraryConfig
->addExcludedDirectory(path
);
3476 static int prLanguageConfig_addIncludePath(struct VMGlobals
* g
, int numArgsPushed
)
3478 return prLanguageConfig_addLibraryPath(g
, numArgsPushed
, includePaths
);
3481 static int prLanguageConfig_addExcludePath(struct VMGlobals
* g
, int numArgsPushed
)
3483 return prLanguageConfig_addLibraryPath(g
, numArgsPushed
, excludePaths
);
3486 static int prLanguageConfig_removeLibraryPath(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3488 PyrSlot
*result
= g
->sp
- 1;
3489 PyrSlot
*dirString
= g
->sp
;
3491 char path
[MAXPATHLEN
];
3492 bool error
= slotStrVal(dirString
, path
, MAXPATHLEN
);
3494 return errWrongType
;
3496 if (pathType
== includePaths
)
3497 gLibraryConfig
->removeIncludedDirectory(path
);
3499 gLibraryConfig
->removeExcludedDirectory(path
);
3503 static int prLanguageConfig_removeIncludePath(struct VMGlobals
* g
, int numArgsPushed
)
3505 return prLanguageConfig_removeLibraryPath(g
, numArgsPushed
, includePaths
);
3508 static int prLanguageConfig_removeExcludePath(struct VMGlobals
* g
, int numArgsPushed
)
3510 return prLanguageConfig_removeLibraryPath(g
, numArgsPushed
, excludePaths
);
3513 static int prLanguageConfig_writeConfigFile(struct VMGlobals
* g
, int numArgsPushed
)
3515 PyrSlot
*result
= g
->sp
- 1;
3516 PyrSlot
*fileString
= g
->sp
;
3518 char path
[MAXPATHLEN
];
3519 if (NotNil(fileString
)) {
3520 bool error
= slotStrVal(fileString
, path
, MAXPATHLEN
);
3522 return errWrongType
;
3524 sc_GetUserConfigDirectory(path
, PATH_MAX
);
3525 sc_AppendToPath(path
, MAXPATHLEN
, "sclang_conf.yaml");
3528 gLibraryConfig
->writeLibraryConfigYAML(path
);
3532 extern bool gPostInlineWarnings
;
3533 static int prLanguageConfig_getPostInlineWarnings(struct VMGlobals
* g
, int numArgsPushed
)
3535 PyrSlot
*result
= g
->sp
;
3536 SetBool(result
, gPostInlineWarnings
);
3540 static int prLanguageConfig_setPostInlineWarnings(struct VMGlobals
* g
, int numArgsPushed
)
3542 PyrSlot
*result
= g
->sp
- 1;
3543 PyrSlot
*arg
= g
->sp
;
3546 gPostInlineWarnings
= true;
3547 else if (IsFalse(arg
))
3548 gPostInlineWarnings
= false;
3550 return errWrongType
;
3556 #define PRIMGROWSIZE 480
3557 PrimitiveTable gPrimitiveTable
;
3559 void initPrimitiveTable()
3562 gPrimitiveTable
.maxsize
= PRIMGROWSIZE
;
3563 gPrimitiveTable
.size
= 0;
3565 // lifetime: runtime. primitives are reloaded when library is compiled.
3566 gPrimitiveTable
.table
= (PrimitiveDef
*)pyr_pool_runtime
->Alloc(gPrimitiveTable
.maxsize
* sizeof(PrimitiveDef
));
3567 MEMFAIL(gPrimitiveTable
.table
);
3568 for (i
=0; i
<gPrimitiveTable
.maxsize
; ++i
) {
3569 gPrimitiveTable
.table
[i
].func
= undefinedPrimitive
;
3570 gPrimitiveTable
.table
[i
].name
= s_none
;
3571 gPrimitiveTable
.table
[i
].base
= 0;
3572 gPrimitiveTable
.table
[i
].numArgs
= 0;
3573 gPrimitiveTable
.table
[i
].varArgs
= 0;
3574 gPrimitiveTable
.table
[i
].keyArgs
= 0;
3578 void growPrimitiveTable(int newsize
)
3580 PrimitiveDef
*oldtable
;
3582 //postfl("growPrimitiveTable %d %d\n", oldsize, newsize);
3583 oldtable
= gPrimitiveTable
.table
;
3584 oldsize
= gPrimitiveTable
.maxsize
;
3585 gPrimitiveTable
.maxsize
= newsize
;
3587 // lifetime: runtime. primitives are reloaded when library is compiled.
3588 gPrimitiveTable
.table
= (PrimitiveDef
*)pyr_pool_runtime
->Alloc(gPrimitiveTable
.maxsize
* sizeof(PrimitiveDef
));
3589 MEMFAIL(gPrimitiveTable
.table
);
3590 memcpy(gPrimitiveTable
.table
, oldtable
, oldsize
* sizeof(PrimitiveDef
));
3591 for (i
=oldsize
; i
<gPrimitiveTable
.maxsize
; ++i
) {
3592 gPrimitiveTable
.table
[i
].func
= undefinedPrimitive
;
3593 gPrimitiveTable
.table
[i
].name
= s_none
;
3594 gPrimitiveTable
.table
[i
].base
= 0;
3595 gPrimitiveTable
.table
[i
].numArgs
= 0;
3596 gPrimitiveTable
.table
[i
].varArgs
= 0;
3597 gPrimitiveTable
.table
[i
].keyArgs
= 0;
3599 pyr_pool_runtime
->Free(oldtable
);
3602 int definePrimitive(int base
, int index
, const char *name
, PrimitiveHandler handler
,
3603 int numArgs
, int varArgs
)
3608 if (name
[0] != '_') {
3609 error("*** Primitive Name must begin with an underscore ***\n");
3610 postfl("name: '%s' index: %d\n", name
, index
);
3613 tableIndex
= base
+ index
;
3614 if (tableIndex
< 0) {
3615 error("*** Negative Primitive Index ***\n");
3616 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3619 if (tableIndex
>= gPrimitiveTable
.maxsize
) {
3620 growPrimitiveTable(tableIndex
+ PRIMGROWSIZE
);
3622 if (gPrimitiveTable
.table
[tableIndex
].func
!= undefinedPrimitive
) {
3623 error("*** Duplicate Primitive Index ***\n");
3624 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3628 gPrimitiveTable
.table
[tableIndex
].func
= handler
;
3629 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3630 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3631 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3632 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3633 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 0;
3634 if (tableIndex
> gPrimitiveTable
.size
) gPrimitiveTable
.size
= tableIndex
;
3635 sym
->u
.index
= tableIndex
;
3639 int definePrimitiveWithKeys(int base
, int index
, const char *name
,
3640 PrimitiveHandler handler
, PrimitiveWithKeysHandler keyhandler
,
3641 int numArgs
, int varArgs
)
3646 if (name
[0] != '_') {
3647 error("*** Primitive Name must begin with an underscore ***\n");
3648 postfl("name: '%s' index: %d\n", name
, index
);
3651 tableIndex
= base
+ index
;
3652 if (tableIndex
< 0) {
3653 error("*** Negative Primitive Index ***\n");
3654 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3657 if (tableIndex
+1 >= gPrimitiveTable
.maxsize
) {
3658 growPrimitiveTable(tableIndex
+ PRIMGROWSIZE
);
3660 if (gPrimitiveTable
.table
[tableIndex
].func
!= undefinedPrimitive
) {
3661 error("*** Duplicate Primitive Index ***\n");
3662 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3666 gPrimitiveTable
.table
[tableIndex
].func
= handler
;
3667 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3668 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3669 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3670 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3671 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 1;
3672 sym
->u
.index
= tableIndex
;
3675 gPrimitiveTable
.table
[tableIndex
].func
= (PrimitiveHandler
)keyhandler
;
3676 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3677 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3678 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3679 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3680 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 1;
3681 if (tableIndex
> gPrimitiveTable
.size
) gPrimitiveTable
.size
= tableIndex
;
3685 int nextPrimitiveIndex()
3687 return gPrimitiveTable
.size
+ 1;
3691 void doPrimitive(VMGlobals
* g
, PyrMethod
* meth
, int numArgsPushed
)
3695 #ifdef GC_SANITYCHECK
3696 g
->gc
->SanityCheck();
3699 //post("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3701 PyrMethodRaw
*methraw
= METHRAW(meth
);
3702 int primIndex
= methraw
->specialIndex
;
3704 PrimitiveDef
*def
= gPrimitiveTable
.table
+ primIndex
;
3705 int numArgsNeeded
= def
->numArgs
;
3706 int diff
= numArgsNeeded
- numArgsPushed
;
3708 if (diff
!= 0) { // incorrect num of args
3709 if (diff
> 0) { // not enough args
3710 PyrSlot
* pslot
= g
->sp
;
3711 PyrSlot
* qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
3712 for (int m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
3715 } else if (def
->varArgs
) { // has var args
3716 numArgsNeeded
= numArgsPushed
;
3718 g
->sp
+= diff
; // remove excess args
3721 g
->numpop
= numArgsNeeded
- 1;
3722 g
->primitiveIndex
= primIndex
- def
->base
;
3723 g
->primitiveMethod
= meth
;
3724 g
->args
= g
->sp
- numArgsNeeded
;
3727 #ifdef GC_SANITYCHECK
3728 g
->gc
->SanityCheck();
3730 err
= (*def
->func
)(g
, numArgsNeeded
);
3731 #ifdef GC_SANITYCHECK
3732 g
->gc
->SanityCheck();
3734 } catch (std::exception
& ex
) {
3735 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3739 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3742 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3744 //post("primitive failed %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3745 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3746 SetInt(&g
->thread
->primitiveError
, err
);
3747 executeMethod(g
, meth
, numArgsNeeded
);
3749 #ifdef GC_SANITYCHECK
3750 g
->gc
->SanityCheck();
3754 void doPrimitiveWithKeys(VMGlobals
* g
, PyrMethod
* meth
, int allArgsPushed
, int numKeyArgsPushed
)
3756 int i
, j
, m
, diff
, err
;
3757 PyrSlot
*pslot
, *qslot
;
3758 int numArgsNeeded
, numArgsPushed
;
3760 #ifdef GC_SANITYCHECK
3761 g
->gc
->SanityCheck();
3763 //post("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3764 //printf("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3766 PyrMethodRaw
*methraw
= METHRAW(meth
);
3767 int primIndex
= methraw
->specialIndex
;
3768 PrimitiveDef
*def
= gPrimitiveTable
.table
+ primIndex
;
3769 g
->primitiveIndex
= primIndex
- def
->base
;
3770 g
->primitiveMethod
= meth
;
3772 if (def
->keyArgs
&& numKeyArgsPushed
) {
3773 g
->numpop
= allArgsPushed
- 1;
3775 err
= ((PrimitiveWithKeysHandler
)def
[1].func
)(g
, allArgsPushed
, numKeyArgsPushed
);
3776 } catch (std::exception
& ex
) {
3777 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3781 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3784 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3786 //post("primerr %d\n", err);
3787 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3788 SetInt(&g
->thread
->primitiveError
, err
);
3789 executeMethodWithKeys(g
, meth
, allArgsPushed
, numKeyArgsPushed
);
3792 numArgsNeeded
= def
->numArgs
;
3793 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<< 1);
3795 if (numKeyArgsPushed
) {
3796 // evacuate keyword args to separate area
3797 pslot
= keywordstack
+ (numKeyArgsPushed
<<1);
3799 for (m
=0; m
<numKeyArgsPushed
; ++m
) {
3800 slotCopy(--pslot
, --qslot
);
3801 slotCopy(--pslot
, --qslot
);
3805 diff
= numArgsNeeded
- numArgsPushed
;
3806 if (diff
!= 0) { // incorrect num of args
3807 if (diff
> 0) { // not enough args
3808 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3809 pslot
= g
->sp
- diff
;
3810 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
3811 for (m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
3812 } else if (def
->varArgs
) { // has var args
3813 numArgsNeeded
= numArgsPushed
;
3814 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3816 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3820 // do keyword lookup:
3821 if (numKeyArgsPushed
&& methraw
->posargs
) {
3822 PyrSymbol
**name0
, **name
;
3823 PyrSlot
*key
, *vars
;
3824 name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
3826 vars
= g
->sp
- numArgsNeeded
+ 1;
3827 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
3829 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
3830 if (*name
== slotRawSymbol(key
)) {
3831 slotCopy(&vars
[j
],&key
[1]);
3835 if (gKeywordError
) {
3836 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
3837 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3842 g
->numpop
= numArgsNeeded
- 1;
3844 err
= (*def
->func
)(g
, numArgsNeeded
);
3845 } catch (std::exception
& ex
) {
3846 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3850 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3853 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3855 //post("primerr %d\n", err);
3856 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3857 SetInt(&g
->thread
->primitiveError
, err
);
3858 executeMethod(g
, meth
, numArgsNeeded
);
3861 #ifdef GC_SANITYCHECK
3862 g
->gc
->SanityCheck();
3866 void initPrimitives()
3870 initPrimitiveTable();
3873 base
= nextPrimitiveIndex();
3874 definePrimitive(base
, opNeg
, "_Neg", doSpecialUnaryArithMsg
, 1, 0);
3875 definePrimitive(base
, opBitNot
, "_BitNot", doSpecialUnaryArithMsg
, 1, 0);
3876 definePrimitive(base
, opAbs
, "_Abs", doSpecialUnaryArithMsg
, 1, 0);
3877 definePrimitive(base
, opAsFloat
, "_AsFloat", doSpecialUnaryArithMsg
, 1, 0);
3878 definePrimitive(base
, opAsInt
, "_AsInt", doSpecialUnaryArithMsg
, 1, 0);
3879 definePrimitive(base
, opCeil
, "_Ceil", doSpecialUnaryArithMsg
, 1, 0); // 5
3880 definePrimitive(base
, opFloor
, "_Floor", doSpecialUnaryArithMsg
, 1, 0);
3881 definePrimitive(base
, opFrac
, "_Frac", doSpecialUnaryArithMsg
, 1, 0);
3882 definePrimitive(base
, opSign
, "_Sign", doSpecialUnaryArithMsg
, 1, 0);
3883 definePrimitive(base
, opSquared
, "_Squared", doSpecialUnaryArithMsg
, 1, 0);
3884 definePrimitive(base
, opCubed
, "_Cubed", doSpecialUnaryArithMsg
, 1, 0); //10
3885 definePrimitive(base
, opSqrt
, "_Sqrt", doSpecialUnaryArithMsg
, 1, 0);
3886 definePrimitive(base
, opExp
, "_Exp", doSpecialUnaryArithMsg
, 1, 0);
3887 definePrimitive(base
, opRecip
, "_Recip", doSpecialUnaryArithMsg
, 1, 0);
3888 definePrimitive(base
, opMIDICPS
, "_MIDICPS", doSpecialUnaryArithMsg
, 1, 0);
3889 definePrimitive(base
, opCPSMIDI
, "_CPSMIDI", doSpecialUnaryArithMsg
, 1, 0); //15
3891 definePrimitive(base
, opMIDIRatio
, "_MIDIRatio", doSpecialUnaryArithMsg
, 1, 0);
3892 definePrimitive(base
, opRatioMIDI
, "_RatioMIDI", doSpecialUnaryArithMsg
, 1, 0);
3893 definePrimitive(base
, opDbAmp
, "_DbAmp", doSpecialUnaryArithMsg
, 1, 0);
3894 definePrimitive(base
, opAmpDb
, "_AmpDb", doSpecialUnaryArithMsg
, 1, 0);
3895 definePrimitive(base
, opOctCPS
, "_OctCPS", doSpecialUnaryArithMsg
, 1, 0);
3896 definePrimitive(base
, opCPSOct
, "_CPSOct", doSpecialUnaryArithMsg
, 1, 0);
3897 definePrimitive(base
, opLog
, "_Log", doSpecialUnaryArithMsg
, 1, 0);
3898 definePrimitive(base
, opLog2
, "_Log2", doSpecialUnaryArithMsg
, 1, 0);
3899 definePrimitive(base
, opLog10
, "_Log10", doSpecialUnaryArithMsg
, 1, 0);
3900 definePrimitive(base
, opSin
, "_Sin", doSpecialUnaryArithMsg
, 1, 0);
3901 definePrimitive(base
, opCos
, "_Cos", doSpecialUnaryArithMsg
, 1, 0);
3902 definePrimitive(base
, opTan
, "_Tan", doSpecialUnaryArithMsg
, 1, 0);
3903 definePrimitive(base
, opArcSin
, "_ArcSin", doSpecialUnaryArithMsg
, 1, 0);
3904 definePrimitive(base
, opArcCos
, "_ArcCos", doSpecialUnaryArithMsg
, 1, 0);
3905 definePrimitive(base
, opArcTan
, "_ArcTan", doSpecialUnaryArithMsg
, 1, 0);
3906 definePrimitive(base
, opSinH
, "_SinH", doSpecialUnaryArithMsg
, 1, 0);
3907 definePrimitive(base
, opCosH
, "_CosH", doSpecialUnaryArithMsg
, 1, 0);
3908 definePrimitive(base
, opTanH
, "_TanH", doSpecialUnaryArithMsg
, 1, 0);
3909 definePrimitive(base
, opRand
, "_Rand", doSpecialUnaryArithMsg
, 1, 0);
3910 definePrimitive(base
, opRand2
, "_Rand2", doSpecialUnaryArithMsg
, 1, 0);
3911 definePrimitive(base
, opLinRand
, "_LinRand", doSpecialUnaryArithMsg
, 1, 0);
3912 definePrimitive(base
, opBiLinRand
, "_BiLinRand", doSpecialUnaryArithMsg
, 1, 0);
3914 definePrimitive(base
, opSum3Rand
, "_Sum3Rand", doSpecialUnaryArithMsg
, 1, 0);
3915 // definePrimitive(base, opExpRand, "_ExpRand", doSpecialUnaryArithMsg, 1, 0);
3916 // definePrimitive(base, opBiExpRand, "_BiExpRand", doSpecialUnaryArithMsg, 1, 0);
3917 // definePrimitive(base, opGammaRand, "_GammaRand", doSpecialUnaryArithMsg, 1, 0);
3918 // definePrimitive(base, opGaussRand, "_GaussRand", doSpecialUnaryArithMsg, 1, 0);
3919 // definePrimitive(base, opPoiRand, "_PoiRand", doSpecialUnaryArithMsg, 1, 0);
3921 definePrimitive(base
, opDistort
, "_Distort", doSpecialUnaryArithMsg
, 1, 0);
3922 definePrimitive(base
, opSoftClip
, "_SoftClip", doSpecialUnaryArithMsg
, 1, 0);
3923 definePrimitive(base
, opCoin
, "_Coin", doSpecialUnaryArithMsg
, 1, 0);
3925 definePrimitive(base
, opRectWindow
, "_RectWindow", doSpecialUnaryArithMsg
, 1, 0);
3926 definePrimitive(base
, opHanWindow
, "_HanWindow", doSpecialUnaryArithMsg
, 1, 0);
3927 definePrimitive(base
, opWelchWindow
, "_WelchWindow", doSpecialUnaryArithMsg
, 1, 0);
3928 definePrimitive(base
, opTriWindow
, "_TriWindow", doSpecialUnaryArithMsg
, 1, 0);
3930 definePrimitive(base
, opSCurve
, "_SCurve", doSpecialUnaryArithMsg
, 1, 0);
3931 definePrimitive(base
, opRamp
, "_Ramp", doSpecialUnaryArithMsg
, 1, 0);
3933 definePrimitive(base
, opDigitValue
, "_DigitValue", doSpecialUnaryArithMsg
, 1, 0);
3937 base
= nextPrimitiveIndex();
3938 definePrimitive(base
, opAdd
, "_Add", prAddNum
, 2, 0);
3939 definePrimitive(base
, opSub
, "_Sub", prSubNum
, 2, 0);
3940 definePrimitive(base
, opMul
, "_Mul", prMulNum
, 2, 0);
3942 definePrimitive(base
, opIDiv
, "_IDiv", prSpecialBinaryArithMsg
, 3, 0);
3943 definePrimitive(base
, opFDiv
, "_FDiv", prSpecialBinaryArithMsg
, 3, 0);
3944 definePrimitive(base
, opMod
, "_Mod", prSpecialBinaryArithMsg
, 3, 0);
3945 definePrimitive(base
, opEQ
, "_EQ", prSpecialBinaryArithMsg
, 3, 0);
3946 definePrimitive(base
, opNE
, "_NE", prSpecialBinaryArithMsg
, 3, 0);
3947 definePrimitive(base
, opLT
, "_LT", prSpecialBinaryArithMsg
, 3, 0);
3948 definePrimitive(base
, opGT
, "_GT", prSpecialBinaryArithMsg
, 3, 0);
3949 definePrimitive(base
, opLE
, "_LE", prSpecialBinaryArithMsg
, 3, 0);
3950 definePrimitive(base
, opGE
, "_GE", prSpecialBinaryArithMsg
, 3, 0);
3951 //definePrimitive(base, opIdentical, "_Identical", prSpecialBinaryArithMsg, 3, 0);
3952 //definePrimitive(base, opNotIdentical, "_NotIdentical", prSpecialBinaryArithMsg, 3, 0);
3954 definePrimitive(base
, opMin
, "_Min", prSpecialBinaryArithMsg
, 3, 0);
3955 definePrimitive(base
, opMax
, "_Max", prSpecialBinaryArithMsg
, 3, 0);
3956 definePrimitive(base
, opBitAnd
, "_BitAnd", prSpecialBinaryArithMsg
, 3, 0);
3957 definePrimitive(base
, opBitOr
, "_BitOr", prSpecialBinaryArithMsg
, 3, 0);
3958 definePrimitive(base
, opBitXor
, "_BitXor", prSpecialBinaryArithMsg
, 3, 0);
3959 definePrimitive(base
, opLCM
, "_LCM", prSpecialBinaryArithMsg
, 3, 0);
3960 definePrimitive(base
, opGCD
, "_GCD", prSpecialBinaryArithMsg
, 3, 0);
3961 definePrimitive(base
, opRound
, "_Round", prSpecialBinaryArithMsg
, 3, 0);
3962 definePrimitive(base
, opRoundUp
, "_RoundUp", prSpecialBinaryArithMsg
, 3, 0);
3963 definePrimitive(base
, opTrunc
, "_Trunc", prSpecialBinaryArithMsg
, 3, 0);
3964 definePrimitive(base
, opAtan2
, "_Atan2", prSpecialBinaryArithMsg
, 3, 0);
3965 definePrimitive(base
, opHypot
, "_Hypot", prSpecialBinaryArithMsg
, 3, 0);
3966 definePrimitive(base
, opHypotx
, "_HypotApx", prSpecialBinaryArithMsg
, 3, 0);
3967 definePrimitive(base
, opPow
, "_Pow", prSpecialBinaryArithMsg
, 3, 0);
3968 definePrimitive(base
, opShiftLeft
, "_ShiftLeft", prSpecialBinaryArithMsg
, 3, 0);
3969 definePrimitive(base
, opShiftRight
, "_ShiftRight", prSpecialBinaryArithMsg
, 3, 0);
3970 definePrimitive(base
, opUnsignedShift
, "_UnsignedShift", prSpecialBinaryArithMsg
, 3, 0);
3971 definePrimitive(base
, opFill
, "_Fill", prSpecialBinaryArithMsg
, 3, 0);
3972 definePrimitive(base
, opRing1
, "_Ring1", prSpecialBinaryArithMsg
, 3, 0); // a * (b + 1) == a * b + a
3973 definePrimitive(base
, opRing2
, "_Ring2", prSpecialBinaryArithMsg
, 3, 0); // a * b + a + b
3974 definePrimitive(base
, opRing3
, "_Ring3", prSpecialBinaryArithMsg
, 3, 0); // a*a*b
3975 definePrimitive(base
, opRing4
, "_Ring4", prSpecialBinaryArithMsg
, 3, 0); // a*a*b - a*b*b
3976 definePrimitive(base
, opDifSqr
, "_DifSqr", prSpecialBinaryArithMsg
, 3, 0); // a*a - b*b
3977 definePrimitive(base
, opSumSqr
, "_SumSqr", prSpecialBinaryArithMsg
, 3, 0); // a*a + b*b
3978 definePrimitive(base
, opSqrSum
, "_SqrSum", prSpecialBinaryArithMsg
, 3, 0); // (a + b)^2
3979 definePrimitive(base
, opSqrDif
, "_SqrDif", prSpecialBinaryArithMsg
, 3, 0); // (a - b)^2
3980 definePrimitive(base
, opAbsDif
, "_AbsDif", prSpecialBinaryArithMsg
, 3, 0); // abs(a - b)
3981 definePrimitive(base
, opThresh
, "_Thresh", prSpecialBinaryArithMsg
, 3, 0); // a * max(0,b)
3982 definePrimitive(base
, opAMClip
, "_AMClip", prSpecialBinaryArithMsg
, 3, 0); // a * max(0,b)
3983 definePrimitive(base
, opScaleNeg
, "_ScaleNeg", prSpecialBinaryArithMsg
, 3, 0); // a < 0 ? a*b : a
3984 definePrimitive(base
, opClip2
, "_Clip2", prSpecialBinaryArithMsg
, 3, 0);
3985 definePrimitive(base
, opFold2
, "_Fold2", prSpecialBinaryArithMsg
, 3, 0);
3986 definePrimitive(base
, opWrap2
, "_Wrap2", prSpecialBinaryArithMsg
, 3, 0);
3987 definePrimitive(base
, opExcess
, "_Excess", prSpecialBinaryArithMsg
, 3, 0);
3988 definePrimitive(base
, opFirstArg
, "_FirstArg", prSpecialBinaryArithMsg
, 3, 0);
3989 definePrimitive(base
, opRandRange
, "_RandRange", prSpecialBinaryArithMsg
, 3, 0);
3990 definePrimitive(base
, opExpRandRange
, "_ExpRandRange", prSpecialBinaryArithMsg
, 3, 0);
3992 // general primitives
3993 base
= nextPrimitiveIndex();
3995 definePrimitive(base
, index
++, "_Halt", haltInterpreter
, 1, 0);
3996 definePrimitive(base
, index
++, "_InstVarAt", instVarAt
, 2, 0);
3997 definePrimitive(base
, index
++, "_InstVarPut", instVarPut
, 3, 0);
3998 definePrimitive(base
, index
++, "_InstVarSize", instVarSize
, 1, 0);
3999 definePrimitive(base
, index
++, "_ObjectHash", objectHash
, 1, 0);
4000 definePrimitive(base
, index
++, "_ObjectClass", objectClass
, 1, 0);
4001 definePrimitive(base
, index
++, "_BasicNew", basicNew
, 2, 0);
4002 definePrimitive(base
, index
++, "_BasicNewClear", basicNewClear
, 2, 0);
4003 definePrimitive(base
, index
++, "_BasicNewCopyArgsToInstVars", basicNewCopyArgsToInstanceVars
, 1, 1);
4004 //definePrimitive(base, index++, "_BasicNewCopyArgsByName", basicNewCopyArgsByName, 1, 1);
4006 definePrimitiveWithKeys(base
, index
, "_FunctionValue", blockValue
, blockValueWithKeys
, 1, 1);
4008 definePrimitiveWithKeys(base
, index
, "_FunctionValueEnvir", blockValueEnvir
, blockValueEnvirWithKeys
, 1, 1);
4011 definePrimitive(base
, index
++, "_FunctionValueArray", blockValueArray
, 1, 1);
4012 definePrimitive(base
, index
++, "_FunctionValueArrayEnvir", blockValueArrayEnvir
, 1, 1);
4013 definePrimitive(base
, index
++, "_FunctionDefAsFunction", prFunctionDefAsFunction
, 1, 0);
4014 definePrimitive(base
, index
++, "_FunctionDefDumpContexts", prFunctionDefDumpContexts
, 1, 0);
4015 definePrimitive(base
, index
++, "_FunctionDefIsClosed", prFunctionDefIsClosed
, 1, 0);
4016 definePrimitive(base
, index
++, "_FunctionDefIsWithinClosed", prFunctionDefIsWithinClosed
, 1, 0);
4018 definePrimitive(base
, index
++, "_ObjectIsKindOf", objectIsKindOf
, 2, 0);
4019 definePrimitive(base
, index
++, "_ObjectIsMemberOf", objectIsMemberOf
, 2, 0);
4020 definePrimitive(base
, index
++, "_ObjectDump", objectDump
, 1, 0);
4021 definePrimitive(base
, index
++, "_TotalFree", prTotalFree
, 1, 0);
4022 definePrimitive(base
, index
++, "_LargestFreeBlock", prLargestFreeBlock
, 1, 0);
4024 definePrimitive(base
, index
++, "_GCInfo", dumpGCinfo
, 1, 0);
4025 definePrimitive(base
, index
++, "_GCDumpGrey", dumpGCdumpGrey
, 1, 0);
4026 definePrimitive(base
, index
++, "_GCDumpSet", dumpGCdumpSet
, 2, 0);
4027 definePrimitive(base
, index
++, "_GCSanity", prGCSanity
, 1, 0);
4029 definePrimitive(base
, index
++, "_TraceAllPathsTo", prTraceAllPathsTo
, 1, 0);
4030 definePrimitive(base
, index
++, "_TraceAnyPathsTo", prTraceAnyPathsTo
, 1, 0);
4031 definePrimitive(base
, index
++, "_TraceAnyPathToAllInstancesOf", prTraceAnyPathToAllInstancesOf
, 1, 0);
4034 definePrimitive(base
, index
++, "_Identical", objectIdentical
, 2, 0);
4035 definePrimitive(base
, index
++, "_NotIdentical", objectNotIdentical
, 2, 0);
4036 definePrimitiveWithKeys(base
, index
, "_ObjectPerform", objectPerform
, objectPerformWithKeys
, 2, 1);
4038 definePrimitive(base
, index
++, "_ObjectPerformList", objectPerformList
, 2, 1);
4039 definePrimitiveWithKeys(base
, index
, "_SuperPerform", objectSuperPerform
, objectSuperPerformWithKeys
, 2, 1);
4041 definePrimitive(base
, index
++, "_SuperPerformList", objectSuperPerformList
, 2, 1);
4042 definePrimitive(base
, index
++, "_ObjectPerformMsg", objectPerformSelList
, 2, 0);
4043 //definePrimitive(base, index++, "_ArrayPerformMsg", arrayPerformMsg, 1, 1);
4044 definePrimitive(base
, index
++, "_ObjectString", prObjectString
, 1, 0);
4045 definePrimitive(base
, index
++, "_Float_AsStringPrec", prFloat_AsStringPrec
, 2, 0);
4046 definePrimitive(base
, index
++, "_ObjectCompileString", prAsCompileString
, 1, 0);
4047 definePrimitive(base
, index
++, "_ClassString", prClassString
, 1, 0);
4048 definePrimitive(base
, index
++, "_PostString", prPostString
, 1, 0);
4049 definePrimitive(base
, index
++, "_PostLine", prPostLine
, 1, 0);
4050 definePrimitive(base
, index
++, "_HostDebugger", prDebugger
, 1, 0);
4051 definePrimitive(base
, index
++, "_Trace", prTraceOn
, 1, 0);
4052 definePrimitive(base
, index
++, "_CanCallOS", prCanCallOS
, 1, 0);
4053 definePrimitive(base
, index
++, "_KeywordError", prKeywordError
, 1, 0);
4054 definePrimitive(base
, index
++, "_GetTailCallOptimize", prGetTailCallOptimize
, 1, 0);
4055 definePrimitive(base
, index
++, "_SetTailCallOptimize", prSetTailCallOptimize
, 2, 0);
4058 definePrimitive(base
, index
++, "_PrimitiveError", prPrimitiveError
, 1, 0);
4059 definePrimitive(base
, index
++, "_PrimitiveErrorString", prPrimitiveErrorString
, 1, 0);
4060 definePrimitive(base
, index
++, "_DumpStack", prDumpStack
, 1, 0);
4061 definePrimitive(base
, index
++, "_DumpDetailedBackTrace", prDumpDetailedBackTrace
, 1, 0);
4062 definePrimitive(base
, index
++, "_StackDepth", prStackDepth
, 1, 0);
4063 definePrimitive(base
, index
++, "_PrimName", prPrimName
, 1, 0);
4064 definePrimitive(base
, index
++, "_ObjectShallowCopy", prObjectShallowCopy
, 1, 0);
4065 definePrimitive(base
, index
++, "_ObjectCopyImmutable", prObjectCopyImmutable
, 1, 0);
4066 definePrimitive(base
, index
++, "_ObjectCopyRange", prObjectCopyRange
, 3, 0);
4067 definePrimitive(base
, index
++, "_ObjectCopySeries", prObjectCopySeries
, 4, 0);
4068 definePrimitive(base
, index
++, "_ObjectPointsTo", prObjectPointsTo
, 2, 0);
4069 definePrimitive(base
, index
++, "_ObjectRespondsTo", prObjectRespondsTo
, 2, 0);
4070 definePrimitive(base
, index
++, "_ObjectIsMutable", prObjectIsMutable
, 1, 0);
4071 definePrimitive(base
, index
++, "_ObjectIsPermanent", prObjectIsPermanent
, 1, 0);
4072 definePrimitive(base
, index
++, "_ObjectDeepFreeze", prDeepFreeze
, 1, 0);
4073 definePrimitive(base
, index
++, "_ObjectDeepCopy", prDeepCopy
, 1, 0);
4076 definePrimitive(base
, index
++, "_CompileExpression", prCompileString
, 2, 0);
4078 definePrimitive(base
, index
++, "_GetBackTrace", prGetBackTrace
, 1, 0);
4079 definePrimitive(base
, index
++, "_DumpBackTrace", prDumpBackTrace
, 1, 0);
4080 definePrimitive(base
, index
++, "_DumpByteCodes", prDumpByteCodes
, 1, 0);
4082 definePrimitive(base
, index
++, "_AllClasses", prAllClasses
, 1, 0);
4083 definePrimitive(base
, index
++, "_DumpClassSubtree", prPostClassTree
, 1, 0);
4085 // definePrimitive(base, index++, "_TabletTracking", prTabletTracking, 1, 0);
4087 definePrimitive(base
, index
++, "_FunDef_NumArgs", prFunDef_NumArgs
, 1, 0);
4088 definePrimitive(base
, index
++, "_FunDef_NumVars", prFunDef_NumVars
, 1, 0);
4089 definePrimitive(base
, index
++, "_FunDef_VarArgs", prFunDef_VarArgs
, 1, 0);
4091 definePrimitive(base
, index
++, "_Thread_Init", prThreadInit
, 3, 0);
4092 definePrimitive(base
, index
++, "_Thread_RandSeed", prThreadRandSeed
, 2, 0);
4093 definePrimitive(base
, index
++, "_Thread_GetRandData", prThreadGetRandData
, 1, 0);
4094 definePrimitive(base
, index
++, "_Thread_SetRandData", prThreadSetRandData
, 2, 0);
4095 // definePrimitive(base, index++, "_ThreadRun", prThreadRun, 2, 0);
4096 // definePrimitive(base, index++, "_RunNextThread", prRunNextThread, 1, 0);
4097 definePrimitive(base
, index
++, "_RoutineYield", prRoutineYield
, 1, 0);
4098 definePrimitive(base
, index
++, "_RoutineAlwaysYield", prRoutineAlwaysYield
, 1, 0);
4099 definePrimitive(base
, index
++, "_RoutineResume", prRoutineResume
, 2, 0);
4100 definePrimitive(base
, index
++, "_RoutineReset", prRoutineReset
, 1, 0);
4101 definePrimitive(base
, index
++, "_RoutineYieldAndReset", prRoutineYieldAndReset
, 2, 0);
4102 definePrimitive(base
, index
++, "_RoutineStop", prRoutineStop
, 1, 0);
4104 // definePrimitive(base, index++, "_IsDemo", prIsDemo, 1, 0);
4105 definePrimitive(base
, index
++, "_Blork", prBlork
, 1, 0);
4106 definePrimitive(base
, index
++, "_UGenCodeString", prUGenCodeString
, 5, 0);
4107 definePrimitive(base
, index
++, "_MainOverwriteMsg", prOverwriteMsg
, 1, 0);
4109 definePrimitive(base
, index
++, "_AppClock_SchedNotify", prAppClockSchedNotify
, 1, 0);
4110 definePrimitive(base
, index
++, "_LanguageConfig_getIncludePaths", prLanguageConfig_getIncludePaths
, 1, 0);
4111 definePrimitive(base
, index
++, "_LanguageConfig_getExcludePaths", prLanguageConfig_getExcludePaths
, 1, 0);
4112 definePrimitive(base
, index
++, "_LanguageConfig_addIncludePath", prLanguageConfig_addIncludePath
, 2, 0);
4113 definePrimitive(base
, index
++, "_LanguageConfig_addExcludePath", prLanguageConfig_addExcludePath
, 2, 0);
4114 definePrimitive(base
, index
++, "_LanguageConfig_removeIncludePath", prLanguageConfig_removeIncludePath
, 2, 0);
4115 definePrimitive(base
, index
++, "_LanguageConfig_removeExcludePath", prLanguageConfig_removeExcludePath
, 2, 0);
4116 definePrimitive(base
, index
++, "_LanguageConfig_writeConfigFile", prLanguageConfig_writeConfigFile
, 2, 0);
4117 definePrimitive(base
, index
++, "_LanguageConfig_getPostInlineWarnings", prLanguageConfig_getPostInlineWarnings
, 1, 0);
4118 definePrimitive(base
, index
++, "_LanguageConfig_setPostInlineWarnings", prLanguageConfig_setPostInlineWarnings
, 2, 0);
4120 //void initOscilPrimitives();
4121 //void initControllerPrimitives();
4123 //initOscilPrimitives();
4124 //initControllerPrimitives();
4125 initMathPrimitives();
4126 initSignalPrimitives();
4127 initArrayPrimitives();
4129 void initSymbolPrimitives();
4130 initSymbolPrimitives();
4132 void initArchiverPrimitives();
4133 initArchiverPrimitives();
4135 void initArrayPrimitives();
4136 initArrayPrimitives();
4138 void initBitPrimitives();
4139 initBitPrimitives();
4141 void initCharPrimitives();
4142 initCharPrimitives();
4144 void initFilePrimitives();
4145 initFilePrimitives();
4147 void initPlatformPrimitives();
4148 initPlatformPrimitives();
4150 void initStringPrimitives();
4151 initStringPrimitives();
4153 void initListPrimitives();
4154 initListPrimitives();
4157 void initUnixPrimitives();
4158 initUnixPrimitives();
4160 void init_OSC_primitives();
4161 init_OSC_primitives();
4163 /* these probably should be moved out of the Lang code
4164 into an App init primitives section */
4165 void initGUIPrimitives();
4166 initGUIPrimitives();
4168 void initSCViewPrimitives();
4169 initSCViewPrimitives();
4171 void initSchedPrimitives();
4172 initSchedPrimitives();
4174 #if (defined(__APPLE__) && !defined(SC_IPHONE)) || defined(HAVE_ALSA)
4175 void initMIDIPrimitives();
4176 initMIDIPrimitives();
4179 #if !defined(SC_WIN32) && !defined(SC_IPHONE)
4180 void initHIDPrimitives();
4181 initHIDPrimitives();
4183 void initSpeechPrimitives();
4184 initSpeechPrimitives();
4186 void initCocoaFilePrimitives();
4187 initCocoaFilePrimitives();
4189 void initCocoaBridgePrimitives();
4190 initCocoaBridgePrimitives();
4192 void initSerialPrimitives();
4193 initSerialPrimitives();
4195 void initWiiPrimitives();
4196 initWiiPrimitives();
4200 void initCoreAudioPrimitives();
4201 initCoreAudioPrimitives();
4205 void initRendezvousPrimitives();
4206 initRendezvousPrimitives();
4208 #ifdef SCOGL_COMPILE
4209 void initOpenGLPrimitives();
4210 initOpenGLPrimitives();
4214 QtCollider::initPrimitives();
4217 s_recvmsg
= getsym("receiveMsg");
4218 post("\tNumPrimitives = %d\n", nextPrimitiveIndex());
4226 s_prrunnextthread
= getsym("prRunNextThread");
4227 s_prready
= getsym("prReady");