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"
62 #include "SCDocPrim.h"
66 extern bool gTraceInterpreter
;
69 void initPatternPrimitives();
72 PrimitiveHandler func
;
75 unsigned char numArgs
;
76 unsigned char varArgs
;
77 unsigned char keyArgs
;
85 extern PrimitiveTable gPrimitiveTable
;
87 extern PyrSlot o_nullframe
;
90 int getPrimitiveNumArgs(int index
)
92 return gPrimitiveTable
.table
[index
].numArgs
;
95 PyrSymbol
* getPrimitiveName(int index
)
97 return gPrimitiveTable
.table
[index
].name
;
100 int slotStrLen(PyrSlot
*slot
)
103 return slotRawSymbol(slot
)->length
;
104 if (isKindOfSlot(slot
, class_string
))
105 return slotRawObject(slot
)->size
;
110 int slotStrVal(PyrSlot
*slot
, char *str
, int maxlen
)
113 strncpy(str
, slotRawSymbol(slot
)->name
, maxlen
);
115 } else if (isKindOfSlot(slot
, class_string
)) {
117 len
= sc_min(maxlen
-1, slotRawObject(slot
)->size
);
118 memcpy(str
, slotRawString(slot
)->s
, len
);
125 int slotPStrVal(PyrSlot
*slot
, unsigned char *str
)
128 strncpy((char*)str
+1, slotRawSymbol(slot
)->name
, 255);
129 str
[0] = slotRawSymbol(slot
)->length
;
131 } else if (isKindOfSlot(slot
, class_string
)) {
133 len
= sc_min(255, slotRawObject(slot
)->size
);
134 memcpy(str
+1, slotRawString(slot
)->s
, len
);
141 int instVarAt(struct VMGlobals
*g
, int numArgsPushed
)
149 if (NotObj(a
)) return errWrongType
;
151 PyrObject
*obj
= slotRawObject(a
);
154 index
= slotRawInt(b
);
155 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
156 slotCopy(a
,&obj
->slots
[index
]);
157 } else if (IsSym(b
)) {
158 PyrSlot
*instVarNamesSlot
= &obj
->classptr
->instVarNames
;
159 if (!isKindOfSlot(instVarNamesSlot
, class_symbolarray
)) return errFailed
;
160 PyrSymbolArray
*instVarNames
= slotRawSymbolArray(instVarNamesSlot
);
161 PyrSymbol
**names
= instVarNames
->symbols
;
162 PyrSymbol
*name
= slotRawSymbol(b
);
163 for (int i
=0; i
<instVarNames
->size
; ++i
) {
164 if (names
[i
] == name
) {
165 slotCopy(a
,&obj
->slots
[i
]);
170 } else return errWrongType
;
174 int instVarPut(struct VMGlobals
*g
, int numArgsPushed
)
176 PyrSlot
*a
, *b
, *c
, *slot
;
184 if (NotObj(a
)) return errWrongType
;
185 obj
= slotRawObject(a
);
186 if (obj
->IsImmutable()) return errImmutableObject
;
189 index
= slotRawInt(b
);
190 if (index
< 0 || index
>= obj
->size
) return errIndexOutOfRange
;
191 slot
= obj
->slots
+ index
;
193 g
->gc
->GCWrite(obj
, slot
);
194 } else if (IsSym(b
)) {
195 PyrSlot
*instVarNamesSlot
= &obj
->classptr
->instVarNames
;
196 if (!IsObj(instVarNamesSlot
)) return errFailed
;
197 PyrSymbolArray
*instVarNames
= slotRawSymbolArray(instVarNamesSlot
);
198 PyrSymbol
**names
= instVarNames
->symbols
;
199 PyrSymbol
*name
= slotRawSymbol(b
);
200 for (int i
=0; i
<instVarNames
->size
; ++i
) {
201 if (names
[i
] == name
) {
202 slot
= obj
->slots
+ i
;
204 g
->gc
->GCWrite(obj
, slot
);
208 post("WARNING: %s instVarPut '%s' failed.\n", slotRawSymbol(&obj
->classptr
->name
)->name
, name
->name
);
210 } else return errWrongType
;
214 int instVarSize(struct VMGlobals
*g
, int numArgsPushed
)
224 obj
= slotRawObject(a
);
225 if (obj
->obj_format
== obj_notindexed
) {
226 SetInt(a
, obj
->size
);
234 int objectHash(struct VMGlobals
*g
, int numArgsPushed
)
246 int objectClass(struct VMGlobals
*g
, int numArgsPushed
)
252 classobj
= classOfSlot(a
);
253 SetObject(a
, classobj
);
257 int prPrimitiveError(struct VMGlobals
*g
, int numArgsPushed
)
262 slotCopy(a
,&g
->thread
->primitiveError
);
266 int prStackDepth(struct VMGlobals
*g
, int numArgsPushed
);
267 int prStackDepth(struct VMGlobals
*g
, int numArgsPushed
)
272 SetInt(a
, g
->gc
->StackDepth());
276 extern void DumpStack(VMGlobals
*g
, PyrSlot
*sp
);
278 int prDumpStack(struct VMGlobals
*g
, int numArgsPushed
)
284 void DumpDetailedBackTrace(VMGlobals
*g
);
285 int prDumpDetailedBackTrace(struct VMGlobals
*g
, int numArgsPushed
);
286 int prDumpDetailedBackTrace(struct VMGlobals
*g
, int numArgsPushed
)
288 DumpDetailedBackTrace(g
);
292 int prPrimitiveErrorString(struct VMGlobals
*g
, int numArgsPushed
)
299 switch (slotRawInt(&g
->thread
->primitiveError
)) {
300 case errReturn
: str
= "Return (not an error)."; break;
301 case errNone
: str
= "No Error"; break;
302 case errFailed
: str
= "Failed."; break;
303 case errBadPrimitive
: str
= "Bad Primitive."; break;
304 case errWrongType
: str
= "Wrong type."; break;
305 case errIndexNotAnInteger
: str
= "Index not an Integer"; break;
306 case errIndexOutOfRange
: str
= "Index out of range."; break;
307 case errImmutableObject
: str
= "Attempted write to immutable object."; break;
308 case errNotAnIndexableObject
: str
= "Not an indexable object."; break;
309 case errStackOverflow
: str
= "Stack overflow."; break;
310 case errOutOfMemory
: str
= "Out of memory."; break;
311 case errCantCallOS
: str
= "Operation cannot be called from this Process. Try using AppClock instead of SystemClock."; break;
313 default : str
= "Failed.";
315 string
= newPyrString(g
->gc
, str
, 0, true);
316 SetObject(a
, string
);
322 int prPostString(struct VMGlobals
*g
, int numArgsPushed
)
327 //if (NotObj(a)) return errWrongType;
328 // assume it is a string!
329 postText(slotRawString(a
)->s
, slotRawString(a
)->size
);
333 int prPostLine(struct VMGlobals
*g
, int numArgsPushed
)
338 //if (NotObj(a)) return errWrongType;
339 // assume it is a string!
340 postText(slotRawString(a
)->s
, slotRawString(a
)->size
);
345 int prDebugger(struct VMGlobals
*g
, int numArgsPushed
)
357 int prObjectString(struct VMGlobals
*g
, int numArgsPushed
)
365 string
= newPyrString(g
->gc
, slotRawSymbol(a
)->name
, 0, true);
366 SetObject(a
, string
);
368 } else if (postString(a
, str
)) {
369 string
= newPyrString(g
->gc
, str
, 0, true);
370 SetObject(a
, string
);
377 int prFloat_AsStringPrec(struct VMGlobals
*g
, int numArgsPushed
);
378 int prFloat_AsStringPrec(struct VMGlobals
*g
, int numArgsPushed
)
380 PyrSlot
*a
= g
->sp
- 1;
384 int err
= slotIntVal(b
, &precision
);
387 char fmt
[8], str
[256];
388 sprintf(fmt
, "%%.%dg", precision
);
389 sprintf(str
, fmt
, slotRawFloat(a
));
391 PyrString
*string
= newPyrString(g
->gc
, str
, 0, true);
392 SetObject(a
, string
);
397 int prAsCompileString(struct VMGlobals
*g
, int numArgsPushed
);
398 int prAsCompileString(struct VMGlobals
*g
, int numArgsPushed
)
406 int len
= strlen(slotRawSymbol(a
)->name
) + 1;
409 sprintf(str
, "'%s'", slotRawSymbol(a
)->name
);
410 string
= newPyrString(g
->gc
, str
, 0, true);
412 char *str
= (char*)malloc(len
+2);
413 sprintf(str
, "'%s'", slotRawSymbol(a
)->name
);
414 string
= newPyrString(g
->gc
, str
, 0, true);
419 err
= asCompileString(a
, str
);
421 string
= newPyrString(g
->gc
, str
, 0, true);
423 SetObject(a
, string
);
428 int prClassString(struct VMGlobals
*g
, int numArgsPushed
)
435 classobj
= classOfSlot(a
);
436 string
= newPyrString(g
->gc
, slotRawSymbol(&classobj
->name
)->name
, 0, true);
437 SetObject(a
, string
);
442 int prPrimName(struct VMGlobals
*g
, int numArgsPushed
)
448 thread
= slotRawThread(a
);
449 if (slotRawInt(&thread
->primitiveIndex
) <= gPrimitiveTable
.size
) {
450 SetSymbol(a
, gPrimitiveTable
.table
[slotRawInt(&thread
->primitiveIndex
)].name
);
452 SetSymbol(a
, s_none
);
457 int objectIsKindOf(struct VMGlobals
*g
, int numArgsPushed
)
460 PyrClass
*classobj
, *testclass
;
461 int objClassIndex
, testClassIndex
, maxSubclassIndex
;
466 if (NotObj(b
)) return errWrongType
;
467 testclass
= (PyrClass
*)slotRawObject(b
);
468 classobj
= classOfSlot(a
);
471 if (classobj
== testclass
) {
475 classobj
= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
479 // constant time lookup method:
481 objClassIndex
= slotRawInt(&classobj
->classIndex
);
482 testClassIndex
= slotRawInt(&testclass
->classIndex
);
483 maxSubclassIndex
= slotRawInt(&testclass
->maxSubclassIndex
);
485 /*post("%s %s\n", slotRawSymbol(&classobj->name)->name, testclass->name.us->name);
486 post("objClassIndex %d\n", objClassIndex);
487 post("testClassIndex %d\n", testClassIndex);
488 post("maxSubclassIndex %d\n", maxSubclassIndex);*/
490 if (objClassIndex
>= testClassIndex
&& objClassIndex
<= maxSubclassIndex
) {
503 int objectIsMemberOf(struct VMGlobals
*g
, int numArgsPushed
)
506 PyrClass
*classobj
, *testclass
;
511 if (NotObj(b
)) return errWrongType
;
512 testclass
= (PyrClass
*)slotRawObject(b
);
513 classobj
= classOfSlot(a
);
514 if (classobj
== testclass
) {
522 int objectIdentical(struct VMGlobals
*g
, int numArgsPushed
)
536 int objectNotIdentical(struct VMGlobals
*g
, int numArgsPushed
)
551 int basicNewClear(struct VMGlobals
*g
, int numArgsPushed
)
561 if (NotObj(a
)) return errWrongType
;
562 classobj
= (PyrClass
*)slotRawObject(a
);
563 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
564 // create an indexable object
567 size
= (int)slotRawFloat(b
);
568 } else if (NotNil(b
)) return errIndexNotAnInteger
;
571 size
= slotRawInt(b
);
573 if (size
< 0) size
= 0;
577 newobj
= instantiateObject(g
->gc
, classobj
, size
, true, true);
578 SetObject(a
, newobj
);
582 int basicNewCopyArgsToInstanceVars(struct VMGlobals
*g
, int numArgsPushed
);
583 int basicNewCopyArgsToInstanceVars(struct VMGlobals
*g
, int numArgsPushed
)
589 a
= g
->sp
- numArgsPushed
+ 1;
592 if (NotObj(a
)) return errWrongType
;
593 classobj
= (PyrClass
*)slotRawObject(a
);
594 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
595 error("CopyArgs : object has no instance variables.\n");
598 newobj
= instantiateObject(g
->gc
, classobj
, 0, true, true);
599 SetObject(a
, newobj
);
601 int length
= sc_min(numArgsPushed
-1, newobj
->size
);
602 for (int i
=0; i
<length
; ++i
) {
603 slotCopy(&newobj
->slots
[i
],&b
[i
]);
611 int basicNew(struct VMGlobals
*g
, int numArgsPushed
)
621 if (NotObj(a
)) return errWrongType
;
622 classobj
= (PyrClass
*)slotRawObject(a
);
623 if (slotRawInt(&classobj
->classFlags
) & classHasIndexableInstances
) {
624 // create an indexable object
627 size
= (int)slotRawFloat(b
);
628 } else if (NotNil(b
)) return errIndexNotAnInteger
;
631 size
= slotRawInt(b
);
633 if (size
< 0) size
= 0;
637 newobj
= instantiateObject(g
->gc
, classobj
, size
, false, true);
638 SetObject(a
, newobj
);
643 bool isClosed(PyrBlock
* fundef
);
644 bool isClosed(PyrBlock
* fundef
)
646 return IsNil(&fundef
->contextDef
) && fundef
->classptr
== class_fundef
;
649 bool isWithinClosed(PyrBlock
* fundef
);
650 bool isWithinClosed(PyrBlock
* fundef
)
653 if (isClosed(fundef
)) return true;
654 fundef
= slotRawBlock(&fundef
->contextDef
);
659 int prFunctionDefAsFunction(struct VMGlobals
*g
, int numArgsPushed
);
660 int prFunctionDefAsFunction(struct VMGlobals
*g
, int numArgsPushed
)
664 if (!isClosed(slotRawBlock(a
))) {
666 error("Only closed FunctionDef may be converted to a Function using asFunction.\n");
670 PyrClosure
* closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, true);
672 closure
->classptr
= gSpecialClasses
[op_class_func
]->u
.classobj
;
674 slotCopy(&closure
->block
,a
);
675 slotCopy(&closure
->context
,&slotRawInterpreter(&g
->process
->interpreter
)->context
);
676 SetObject(a
, closure
);
680 int prFunctionDefDumpContexts(struct VMGlobals
*g
, int numArgsPushed
);
681 int prFunctionDefDumpContexts(struct VMGlobals
*g
, int numArgsPushed
)
686 while (slotRawBlock(a
)) {
687 post("%2d context %s %p\n", i
++, slotRawSymbol(&slotRawObject(a
)->classptr
->name
)->name
, slotRawInt(&slotRawBlock(a
)->contextDef
));
688 a
= &slotRawBlock(a
)->contextDef
;
695 int prFunctionDefIsClosed(struct VMGlobals
*g
, int numArgsPushed
);
696 int prFunctionDefIsClosed(struct VMGlobals
*g
, int numArgsPushed
)
699 PyrBlock
*block
= slotRawBlock(a
);
701 SetBool(a
, isClosed(block
));
705 int prFunctionDefIsWithinClosed(struct VMGlobals
*g
, int numArgsPushed
);
706 int prFunctionDefIsWithinClosed(struct VMGlobals
*g
, int numArgsPushed
)
709 PyrBlock
*block
= slotRawBlock(a
);
711 SetBool(a
, isWithinClosed(block
));
716 void reallocStack(struct VMGlobals
*g
, int stackNeeded
, int stackDepth
)
718 //PyrThread *thread = g->thread;
720 int newStackSize
= NEXTPOWEROFTWO(stackNeeded
);
722 PyrObject
* array
= newPyrArray(gc
, newStackSize
, 0, false);
723 memcpy(array
->slots
, gc
->Stack()->slots
, stackDepth
* sizeof(PyrSlot
));
725 gc
->ToBlack(gc
->Stack());
726 g
->sp
= array
->slots
+ stackDepth
- 1;
730 int blockValueArray(struct VMGlobals
*g
, int numArgsPushed
)
735 PyrSlot
*pslot
, *qslot
;
738 //a = g->sp - numArgsPushed + 1;
742 if (slotRawObject(b
)->classptr
== class_array
) {
743 array
= (PyrObject
*)slotRawObject(b
);
747 PyrObject
*stack
= g
->gc
->Stack();
748 int stackDepth
= g
->sp
- stack
->slots
+ 1;
749 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
750 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
751 if (stackNeeded
> stackSize
) {
752 reallocStack(g
, stackNeeded
, stackDepth
);
756 pslot
= array
->slots
- 1;
758 //pend = (double*)(pslot + size);
759 //while (pslot<pend) slotCopy(++qslot, ++pslot);
760 for (m
=0; m
<size
; ++m
) slotCopy(++qslot
, ++pslot
);
763 return blockValue(g
, size
+numArgsPushed
-1);
765 } else if (slotRawObject(b
)->classptr
== class_list
) {
766 list
= slotRawList(b
);
767 if (NotObj(&list
->array
)) return errWrongType
;
768 array
= slotRawObject(&list
->array
);
769 if (array
->classptr
!= class_array
) return errWrongType
;
771 } else { // last arg is not a list or array, so pass as normal
772 return blockValue(g
, numArgsPushed
);
775 return blockValue(g
, numArgsPushed
);
779 int blockValueEnvir(struct VMGlobals
*g
, int numArgsPushed
);
781 int blockValueArrayEnvir(struct VMGlobals
*g
, int numArgsPushed
);
782 int blockValueArrayEnvir(struct VMGlobals
*g
, int numArgsPushed
)
787 PyrSlot
*pslot
, *qslot
;
790 //a = g->sp - numArgsPushed + 1;
794 if (slotRawObject(b
)->classptr
== class_array
) {
795 array
= (PyrObject
*)slotRawObject(b
);
799 PyrObject
*stack
= g
->gc
->Stack();
800 int stackDepth
= g
->sp
- stack
->slots
+ 1;
801 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
802 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
803 if (stackNeeded
> stackSize
) {
804 reallocStack(g
, stackNeeded
, stackDepth
);
808 pslot
= array
->slots
- 1;
810 //pend = (double*)(pslot + size);
811 //while (pslot<pend) slotCopy(++qslot, ++pslot);
812 for (m
=0; m
<size
; ++m
) slotCopy(++qslot
, ++pslot
);
815 return blockValueEnvir(g
, size
+numArgsPushed
-1);
817 } else if (slotRawObject(b
)->classptr
== class_list
) {
818 list
= slotRawList(b
);
819 if (NotObj(&list
->array
)) return errWrongType
;
820 array
= slotRawObject(&list
->array
);
821 if (array
->classptr
!= class_array
) return errWrongType
;
823 } else { // last arg is not a list or array, so pass as normal
824 return blockValueEnvir(g
, numArgsPushed
);
827 return blockValueEnvir(g
, numArgsPushed
);
831 HOT
int blockValue(struct VMGlobals
*g
, int numArgsPushed
)
836 PyrSlot
*pslot
, *qslot
;
839 int i
, m
, mmax
, numtemps
;
843 PyrFrame
*homeContext
;
845 PyrMethodRaw
*methraw
;
848 int tailCall
= g
->tailCall
;
860 args
= g
->sp
- numArgsPushed
+ 1;
865 closure
= (PyrClosure
*)slotRawObject(args
);
866 block
= slotRawBlock(&closure
->block
);
867 context
= slotRawFrame(&closure
->context
);
869 proto
= IsObj(&block
->prototypeFrame
) ? slotRawObject(&block
->prototypeFrame
) : NULL
;
870 methraw
= METHRAW(block
);
871 numtemps
= methraw
->numtemps
;
874 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
875 vars
= frame
->vars
- 1;
876 frame
->classptr
= class_frame
;
877 frame
->size
= FRAMESIZE
+ numtemps
;
878 SetObject(&frame
->method
, block
);
879 slotCopy(&frame
->homeContext
,&context
->homeContext
);
880 slotCopy(&frame
->context
,&closure
->context
);
883 SetPtr(&caller
->ip
, g
->ip
);
884 SetObject(&frame
->caller
, g
->frame
);
886 SetInt(&frame
->caller
, 0);
888 SetPtr(&frame
->ip
, 0);
892 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
896 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
897 /* push all args to frame */
901 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
903 /* push default arg values */
904 pslot
= vars
+ numArgsPushed
;
905 qslot
= proto
->slots
+ numArgsPushed
- 1;
906 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
907 } else if (methraw
->varargs
) {
911 /* push all normal args to frame */
914 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
917 i
= numArgsPushed
- methraw
->numargs
;
918 list
= newPyrArray(g
->gc
, i
, 0, false);
922 SetObject(rslot
, list
);
923 //SetObject(vars + methraw->numargs + 1, list);
925 /* put extra args into list */
926 lslot
= list
->slots
- 1;
927 // fixed and raw sizes are zero
928 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
930 if (methraw
->numvars
) {
931 /* push default keyword and var values */
932 pslot
= vars
+ methraw
->numargs
+ 1;
933 qslot
= proto
->slots
+ methraw
->numargs
;
934 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
937 if (methraw
->numargs
) {
938 /* push all args to frame */
941 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
943 if (methraw
->numvars
) {
944 /* push default keyword and var values */
945 pslot
= vars
+ methraw
->numargs
;
946 qslot
= proto
->slots
+ methraw
->numargs
- 1;
947 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
951 homeContext
= slotRawFrame(&frame
->homeContext
);
953 PyrMethodRaw
*methraw
;
954 g
->method
= slotRawMethod(&homeContext
->method
);
955 methraw
= METHRAW(g
->method
);
956 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
958 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
964 int blockValueWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
);
965 int blockValueWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
)
970 PyrSlot
*pslot
, *qslot
;
973 int i
, j
, m
, mmax
, numtemps
, numArgsPushed
;
977 PyrFrame
*homeContext
;
979 PyrMethodRaw
*methraw
;
982 int tailCall
= g
->tailCall
;
994 args
= g
->sp
- allArgsPushed
+ 1;
999 closure
= (PyrClosure
*)slotRawObject(args
);
1000 block
= slotRawBlock(&closure
->block
);
1001 context
= slotRawFrame(&closure
->context
);
1003 proto
= IsObj(&block
->prototypeFrame
) ? slotRawObject(&block
->prototypeFrame
) : NULL
;
1005 methraw
= METHRAW(block
);
1006 numtemps
= methraw
->numtemps
;
1008 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1010 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1011 vars
= frame
->vars
- 1;
1012 frame
->classptr
= class_frame
;
1013 frame
->size
= FRAMESIZE
+ numtemps
;
1014 SetObject(&frame
->method
, block
);
1015 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1016 slotCopy(&frame
->context
,&closure
->context
);
1019 SetPtr(&caller
->ip
, g
->ip
);
1020 SetObject(&frame
->caller
, g
->frame
);
1022 SetInt(&frame
->caller
, 0);
1024 SetPtr(&frame
->ip
, 0);
1027 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1031 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1032 /* push all args to frame */
1036 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1038 /* push default arg values */
1039 pslot
= vars
+ numArgsPushed
;
1040 qslot
= proto
->slots
+ numArgsPushed
- 1;
1041 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1042 } else if (methraw
->varargs
) {
1046 /* push all normal args to frame */
1049 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1052 i
= numArgsPushed
- methraw
->numargs
;
1053 list
= newPyrArray(g
->gc
, i
, 0, false);
1057 SetObject(rslot
, list
);
1058 //SetObject(vars + methraw->numargs + 1, list);
1060 /* put extra args into list */
1061 lslot
= list
->slots
- 1;
1062 // fixed and raw sizes are zero
1064 //while (lslot < lend) slotCopy(++lslot, ++qslot);
1065 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1067 if (methraw
->numvars
) {
1068 /* push default keyword and var values */
1069 pslot
= vars
+ methraw
->numargs
+ 1;
1070 qslot
= proto
->slots
+ methraw
->numargs
;
1071 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1074 if (methraw
->numargs
) {
1075 /* push all args to frame */
1078 //pend = pslot + methraw->numargs;
1079 //while (pslot < pend) slotCopy(++pslot, ++qslot);
1080 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1082 if (methraw
->numvars
) {
1083 /* push default keyword and var values */
1084 pslot
= vars
+ methraw
->numargs
;
1085 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1086 //pend = pslot + methraw->numvars;
1087 //while (pslot<pend) slotCopy(++pslot, ++qslot);
1088 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1091 // do keyword lookup:
1092 if (numKeyArgsPushed
&& methraw
->posargs
) {
1094 PyrSymbol
**name0
, **name
;
1095 name0
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1096 key
= args
+ numArgsPushed
+ 1;
1097 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1099 for (j
=0; j
<methraw
->posargs
; ++j
, ++name
) {
1100 if (*name
== slotRawSymbol(key
)) {
1101 slotCopy(&vars
[j
+1],&key
[1]);
1105 if (gKeywordError
) {
1106 post("WARNING: keyword arg '%s' not found in call to function.\n",
1107 slotRawSymbol(key
)->name
);
1113 homeContext
= slotRawFrame(&frame
->homeContext
);
1115 PyrMethodRaw
*methraw
;
1116 g
->method
= slotRawMethod(&homeContext
->method
);
1117 methraw
= METHRAW(g
->method
);
1118 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1120 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1125 bool identDict_lookupNonNil(PyrObject
*dict
, PyrSlot
*key
, int hash
, PyrSlot
*result
);
1127 int blockValueEnvir(struct VMGlobals
*g
, int numArgsPushed
)
1132 PyrSlot
*pslot
, *qslot
;
1135 int i
, m
, mmax
, numtemps
;
1139 PyrFrame
*homeContext
;
1140 PyrClosure
*closure
;
1141 PyrMethodRaw
*methraw
;
1142 PyrSlot
*curEnvirSlot
;
1144 #if TAILCALLOPTIMIZE
1145 int tailCall
= g
->tailCall
;
1147 if (tailCall
== 1) {
1148 returnFromMethod(g
);
1157 args
= g
->sp
- numArgsPushed
+ 1;
1162 closure
= (PyrClosure
*)slotRawObject(args
);
1163 block
= slotRawBlock(&closure
->block
);
1164 context
= slotRawFrame(&closure
->context
);
1166 proto
= IsObj(&block
->prototypeFrame
) ? slotRawObject(&block
->prototypeFrame
) : NULL
;
1168 methraw
= METHRAW(block
);
1169 numtemps
= methraw
->numtemps
;
1172 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1173 vars
= frame
->vars
- 1;
1174 frame
->classptr
= class_frame
;
1175 frame
->size
= FRAMESIZE
+ numtemps
;
1176 SetObject(&frame
->method
, block
);
1177 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1178 slotCopy(&frame
->context
,&closure
->context
);
1181 SetPtr(&caller
->ip
, g
->ip
);
1182 SetObject(&frame
->caller
, g
->frame
);
1184 SetInt(&frame
->caller
, 0);
1186 SetPtr(&frame
->ip
, 0);
1190 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1194 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1195 /* push all args to frame */
1199 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1201 /* push default arg values */
1202 pslot
= vars
+ numArgsPushed
;
1203 qslot
= proto
->slots
+ numArgsPushed
- 1;
1204 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1206 // replace defaults with environment variables
1207 curEnvirSlot
= &g
->classvars
->slots
[1]; // currentEnvironment is the second class var.
1209 if (isKindOfSlot(curEnvirSlot
, s_identitydictionary
->u
.classobj
)) {
1210 PyrSymbol
**argNames
;
1211 argNames
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1212 for (m
=numArgsPushed
; m
<methraw
->numargs
; ++m
) {
1213 // replace the args with values from the environment if they exist
1215 SetSymbol(&keyslot
, argNames
[m
]);
1216 identDict_lookupNonNil(slotRawObject(curEnvirSlot
), &keyslot
, calcHash(&keyslot
), vars
+m
+1);
1219 } else if (methraw
->varargs
) {
1223 /* push all normal args to frame */
1226 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1229 i
= numArgsPushed
- methraw
->numargs
;
1230 list
= newPyrArray(g
->gc
, i
, 0, false);
1234 SetObject(rslot
, list
);
1235 //SetObject(vars + methraw->numargs + 1, list);
1237 /* put extra args into list */
1238 lslot
= list
->slots
- 1;
1239 // fixed and raw sizes are zero
1240 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1242 if (methraw
->numvars
) {
1243 /* push default keyword and var values */
1244 pslot
= vars
+ methraw
->numargs
+ 1;
1245 qslot
= proto
->slots
+ methraw
->numargs
;
1246 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1249 if (methraw
->numargs
) {
1250 /* push all args to frame */
1253 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1255 if (methraw
->numvars
) {
1256 /* push default keyword and var values */
1257 pslot
= vars
+ methraw
->numargs
;
1258 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1259 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1263 homeContext
= slotRawFrame(&frame
->homeContext
);
1265 PyrMethodRaw
*methraw
;
1266 g
->method
= slotRawMethod(&homeContext
->method
);
1267 methraw
= METHRAW(g
->method
);
1268 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1270 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1275 int blockValueEnvirWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
);
1276 int blockValueEnvirWithKeys(VMGlobals
*g
, int allArgsPushed
, int numKeyArgsPushed
)
1281 PyrSlot
*pslot
, *qslot
;
1284 int i
, j
, m
, mmax
, numtemps
, numArgsPushed
;
1288 PyrFrame
*homeContext
;
1289 PyrClosure
*closure
;
1290 PyrMethodRaw
*methraw
;
1291 PyrSlot
*curEnvirSlot
;
1293 #if TAILCALLOPTIMIZE
1294 int tailCall
= g
->tailCall
;
1296 if (tailCall
== 1) {
1297 returnFromMethod(g
);
1306 args
= g
->sp
- allArgsPushed
+ 1;
1311 closure
= (PyrClosure
*)slotRawObject(args
);
1312 block
= slotRawBlock(&closure
->block
);
1313 context
= slotRawFrame(&closure
->context
);
1315 proto
= IsObj(&block
->prototypeFrame
) ? slotRawObject(&block
->prototypeFrame
) : NULL
;
1317 methraw
= METHRAW(block
);
1318 numtemps
= methraw
->numtemps
;
1320 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1322 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1323 vars
= frame
->vars
- 1;
1324 frame
->classptr
= class_frame
;
1325 frame
->size
= FRAMESIZE
+ numtemps
;
1326 SetObject(&frame
->method
, block
);
1327 slotCopy(&frame
->homeContext
,&context
->homeContext
);
1328 slotCopy(&frame
->context
,&closure
->context
);
1331 SetPtr(&caller
->ip
, g
->ip
);
1332 SetObject(&frame
->caller
, g
->frame
);
1334 SetInt(&frame
->caller
, 0);
1336 SetPtr(&frame
->ip
, 0);
1340 g
->ip
= slotRawInt8Array(&block
->code
)->b
- 1;
1344 if (numArgsPushed
<= methraw
->numargs
) { /* not enough args pushed */
1345 /* push all args to frame */
1349 for (m
=0; m
<numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1351 /* push default arg values */
1352 pslot
= vars
+ numArgsPushed
;
1353 qslot
= proto
->slots
+ numArgsPushed
- 1;
1354 for (m
=0; m
<numtemps
- numArgsPushed
; ++m
) slotCopy(++pslot
, ++qslot
);
1356 // replace defaults with environment variables
1357 curEnvirSlot
= &g
->classvars
->slots
[1]; // currentEnvironment is the second class var.
1359 if (isKindOfSlot(curEnvirSlot
, s_identitydictionary
->u
.classobj
)) {
1360 PyrSymbol
**argNames
;
1361 argNames
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1362 for (m
=numArgsPushed
; m
<methraw
->numargs
; ++m
) {
1363 // replace the args with values from the environment if they exist
1365 SetSymbol(&keyslot
, argNames
[m
]);
1366 identDict_lookupNonNil(slotRawObject(curEnvirSlot
), &keyslot
, calcHash(&keyslot
), vars
+m
+1);
1371 } else if (methraw
->varargs
) {
1375 /* push all normal args to frame */
1378 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1381 i
= numArgsPushed
- methraw
->numargs
;
1382 list
= newPyrArray(g
->gc
, i
, 0, false);
1386 SetObject(rslot
, list
);
1387 //SetObject(vars + methraw->numargs + 1, list);
1389 /* put extra args into list */
1390 lslot
= list
->slots
- 1;
1391 // fixed and raw sizes are zero
1393 //while (lslot < lend) slotCopy(++lslot, ++qslot);
1394 for (m
=0; m
<i
; ++m
) slotCopy(++lslot
, ++qslot
);
1396 if (methraw
->numvars
) {
1397 /* push default keyword and var values */
1398 pslot
= vars
+ methraw
->numargs
+ 1;
1399 qslot
= proto
->slots
+ methraw
->numargs
;
1400 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1403 if (methraw
->numargs
) {
1404 /* push all args to frame */
1407 //pend = pslot + methraw->numargs;
1408 //while (pslot < pend) slotCopy(++pslot, ++qslot);
1409 for (m
=0,mmax
=methraw
->numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1411 if (methraw
->numvars
) {
1412 /* push default keyword and var values */
1413 pslot
= vars
+ methraw
->numargs
;
1414 qslot
= proto
->slots
+ methraw
->numargs
- 1;
1415 //pend = pslot + methraw->numvars;
1416 //while (pslot<pend) slotCopy(++pslot, ++qslot);
1417 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1420 // do keyword lookup:
1421 if (numKeyArgsPushed
&& methraw
->posargs
) {
1422 PyrSymbol
**name0
, **name
;
1424 name0
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1425 key
= args
+ numArgsPushed
+ 1;
1426 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1428 for (j
=0; j
<methraw
->posargs
; ++j
, ++name
) {
1429 if (*name
== slotRawSymbol(key
)) {
1430 slotCopy(&vars
[j
+1],&key
[1]);
1434 if (gKeywordError
) {
1435 post("WARNING: keyword arg '%s' not found in call to function.\n",
1436 slotRawSymbol(key
)->name
);
1442 homeContext
= slotRawFrame(&frame
->homeContext
);
1444 PyrMethodRaw
*methraw
;
1445 g
->method
= slotRawMethod(&homeContext
->method
);
1446 methraw
= METHRAW(g
->method
);
1447 slotCopy(&g
->receiver
,&homeContext
->vars
[0]);
1449 slotCopy(&g
->receiver
,&g
->process
->interpreter
);
1455 int objectPerform(struct VMGlobals
*g
, int numArgsPushed
)
1457 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1458 PyrSlot
*pslot
, *qslot
;
1459 PyrSymbol
*selector
;
1462 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1463 selSlot
= recvrSlot
+ 1;
1464 if (IsSym(selSlot
)) {
1465 selector
= slotRawSymbol(selSlot
);
1466 // move args down one to fill selector's position
1467 pslot
= selSlot
- 1;
1469 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1472 // now the stack looks just like it would for a normal message send
1473 } else if (IsObj(selSlot
)) {
1475 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1476 listSlot
= slotRawObject(listSlot
)->slots
;
1478 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1481 PyrObject
*array
= slotRawObject(listSlot
);
1482 if (array
->size
< 1) {
1483 error("Array must have a selector.\n");
1486 selSlot
= array
->slots
;
1487 selector
= slotRawSymbol(selSlot
);
1489 if (numArgsPushed
>2) {
1490 qslot
= recvrSlot
+ numArgsPushed
;
1491 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1492 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(--pslot
, --qslot
);
1497 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1499 g
->sp
+= array
->size
- 2;
1500 numArgsPushed
+= array
->size
- 2;
1501 // now the stack looks just like it would for a normal message send
1505 error("perform selector not a Symbol or Array.\n");
1506 dumpObjectSlot(selSlot
);
1507 return errWrongType
;
1510 sendMessage(g
, selector
, numArgsPushed
);
1515 int objectPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
);
1516 int objectPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
)
1518 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1519 PyrSlot
*pslot
, *qslot
;
1520 PyrSymbol
*selector
;
1523 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1524 selSlot
= recvrSlot
+ 1;
1525 if (IsSym(selSlot
)) {
1526 selector
= slotRawSymbol(selSlot
);
1527 // move args down one to fill selector's position
1528 pslot
= selSlot
- 1;
1530 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1533 // now the stack looks just like it would for a normal message send
1534 } else if (IsObj(selSlot
)) {
1536 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1537 listSlot
= slotRawObject(listSlot
)->slots
;
1539 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1542 PyrObject
*array
= slotRawObject(listSlot
);
1543 if (array
->size
< 1) {
1544 error("Array must have a selector.\n");
1547 selSlot
= array
->slots
;
1548 selector
= slotRawSymbol(selSlot
);
1550 if (numArgsPushed
>2) {
1551 qslot
= recvrSlot
+ numArgsPushed
;
1552 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1553 for (m
=0; m
<numArgsPushed
- 2; ++m
) *--pslot
= *--qslot
;
1558 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1560 g
->sp
+= array
->size
- 2;
1561 numArgsPushed
+= array
->size
- 2;
1562 // now the stack looks just like it would for a normal message send
1566 error("perform selector not a Symbol or Array.\n");
1567 dumpObjectSlot(selSlot
);
1568 return errWrongType
;
1571 sendMessageWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
1577 int objectPerformList(struct VMGlobals
*g
, int numArgsPushed
)
1579 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1580 PyrSlot
*pslot
, *qslot
;
1581 PyrSymbol
*selector
;
1582 int m
, mmax
, numargslots
;
1586 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1587 selSlot
= recvrSlot
+ 1;
1589 numargslots
= numArgsPushed
- 3;
1590 if (NotSym(selSlot
)) {
1591 error("Selector not a Symbol :\n");
1592 return errWrongType
;
1594 selector
= slotRawSymbol(selSlot
);
1596 if (NotObj(listSlot
)) {
1597 return objectPerform(g
, numArgsPushed
);
1599 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1601 array
= slotRawObject(listSlot
);
1603 PyrObject
*stack
= g
->gc
->Stack();
1604 int stackDepth
= g
->sp
- stack
->slots
+ 1;
1605 int stackSize
= ARRAYMAXINDEXSIZE(stack
);
1606 int stackNeeded
= stackDepth
+ array
->size
+ 64; // 64 to allow extra for normal stack operations.
1607 if (stackNeeded
> stackSize
) {
1608 reallocStack(g
, stackNeeded
, stackDepth
);
1609 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1610 selSlot
= recvrSlot
+ 1;
1614 if (numargslots
>0) {
1616 for (m
=0; m
<numargslots
; ++m
) slotCopy(++pslot
, ++qslot
);
1617 } else numargslots
= 0;
1618 qslot
= array
->slots
- 1;
1619 for (m
=0,mmax
=array
->size
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1620 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1621 listSlot
= slotRawObject(listSlot
)->slots
;
1622 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1623 error("List array not an Array.\n");
1624 dumpObjectSlot(listSlot
);
1625 return errWrongType
;
1629 return objectPerform(g
, numArgsPushed
);
1631 g
->sp
+= array
->size
- 2;
1632 numArgsPushed
= numargslots
+ array
->size
+ 1;
1633 // now the stack looks just like it would for a normal message send
1635 sendMessage(g
, selector
, numArgsPushed
);
1642 int objectSuperPerform(struct VMGlobals
*g
, int numArgsPushed
)
1644 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1645 PyrSlot
*pslot
, *qslot
;
1646 PyrSymbol
*selector
;
1649 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1651 PyrClass
* classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
1652 if (!isKindOfSlot(recvrSlot
, classobj
)) {
1653 error("superPerform must be called with 'this' as the receiver.\n");
1657 selSlot
= recvrSlot
+ 1;
1658 if (IsSym(selSlot
)) {
1659 selector
= slotRawSymbol(selSlot
);
1660 // move args down one to fill selector's position
1661 pslot
= selSlot
- 1;
1663 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1666 // now the stack looks just like it would for a normal message send
1667 } else if (IsObj(selSlot
)) {
1669 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1670 listSlot
= slotRawObject(listSlot
)->slots
;
1672 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1675 PyrObject
*array
= slotRawObject(listSlot
);
1676 if (array
->size
< 1) {
1677 error("Array must have a selector.\n");
1680 selSlot
= array
->slots
;
1681 selector
= slotRawSymbol(selSlot
);
1683 if (numArgsPushed
>2) {
1684 qslot
= recvrSlot
+ numArgsPushed
;
1685 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1686 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(--pslot
, --qslot
);
1691 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1693 g
->sp
+= array
->size
- 2;
1694 numArgsPushed
+= array
->size
- 2;
1695 // now the stack looks just like it would for a normal message send
1699 error("perform selector not a Symbol or Array.\n");
1700 dumpObjectSlot(selSlot
);
1701 return errWrongType
;
1704 sendSuperMessage(g
, selector
, numArgsPushed
);
1709 int objectSuperPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
);
1710 int objectSuperPerformWithKeys(VMGlobals
*g
, int numArgsPushed
, int numKeyArgsPushed
)
1712 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1713 PyrSlot
*pslot
, *qslot
;
1714 PyrSymbol
*selector
;
1717 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1719 PyrClass
* classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
1720 if (!isKindOfSlot(recvrSlot
, classobj
)) {
1721 error("superPerform must be called with 'this' as the receiver.\n");
1725 selSlot
= recvrSlot
+ 1;
1726 if (IsSym(selSlot
)) {
1727 selector
= slotRawSymbol(selSlot
);
1728 // move args down one to fill selector's position
1729 pslot
= selSlot
- 1;
1731 for (m
=0; m
<numArgsPushed
- 2; ++m
) slotCopy(++pslot
, ++qslot
);
1734 // now the stack looks just like it would for a normal message send
1735 } else if (IsObj(selSlot
)) {
1737 if (slotRawObject(listSlot
)->classptr
== class_list
) {
1738 listSlot
= slotRawObject(listSlot
)->slots
;
1740 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1743 PyrObject
*array
= slotRawObject(listSlot
);
1744 if (array
->size
< 1) {
1745 error("Array must have a selector.\n");
1748 selSlot
= array
->slots
;
1749 selector
= slotRawSymbol(selSlot
);
1751 if (numArgsPushed
>2) {
1752 qslot
= recvrSlot
+ numArgsPushed
;
1753 pslot
= recvrSlot
+ numArgsPushed
+ array
->size
- 2;
1754 for (m
=0; m
<numArgsPushed
- 2; ++m
) *--pslot
= *--qslot
;
1759 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1761 g
->sp
+= array
->size
- 2;
1762 numArgsPushed
+= array
->size
- 2;
1763 // now the stack looks just like it would for a normal message send
1767 error("perform selector not a Symbol or Array.\n");
1768 dumpObjectSlot(selSlot
);
1769 return errWrongType
;
1772 sendSuperMessageWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
1778 int objectSuperPerformList(struct VMGlobals
*g
, int numArgsPushed
)
1780 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1781 PyrSlot
*pslot
, *qslot
;
1782 PyrSymbol
*selector
;
1783 int m
, mmax
, numargslots
;
1786 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
1787 selSlot
= recvrSlot
+ 1;
1789 numargslots
= numArgsPushed
- 3;
1790 if (NotSym(selSlot
)) {
1791 error("Selector not a Symbol :\n");
1792 return errWrongType
;
1794 selector
= slotRawSymbol(selSlot
);
1795 if (NotObj(listSlot
)) {
1796 return objectPerform(g
, numArgsPushed
);
1798 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1801 if (numargslots
>0) {
1803 for (m
=0; m
<numargslots
; ++m
) slotCopy(++pslot
, ++qslot
);
1804 } else numargslots
= 0;
1805 array
= slotRawObject(listSlot
);
1806 qslot
= array
->slots
- 1;
1807 for (m
=0,mmax
=array
->size
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1808 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1809 listSlot
= slotRawObject(listSlot
)->slots
;
1810 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1811 error("List array not an Array.\n");
1812 dumpObjectSlot(listSlot
);
1813 return errWrongType
;
1817 return objectSuperPerform(g
, numArgsPushed
);
1819 g
->sp
+= array
->size
- 2;
1820 numArgsPushed
= numargslots
+ array
->size
+ 1;
1821 // now the stack looks just like it would for a normal message send
1823 sendSuperMessage(g
, selector
, numArgsPushed
);
1831 int objectPerformSelList(struct VMGlobals
*g
, int numArgsPushed
)
1833 PyrSlot
*recvrSlot
, *selSlot
, *listSlot
;
1834 PyrSlot
*pslot
, *qslot
;
1835 PyrSymbol
*selector
;
1839 recvrSlot
= g
->sp
- 1;
1842 if (NotObj(listSlot
)) {
1843 error("Expected Array or List.. Got :\n");
1844 dumpObjectSlot(listSlot
);
1845 return errWrongType
;
1847 if (slotRawObject(listSlot
)->classptr
== class_array
) {
1849 array
= slotRawObject(listSlot
);
1851 selSlot
= array
->slots
;
1852 if (NotSym(selSlot
)) {
1853 error("Selector not a Symbol :\n");
1854 return errWrongType
;
1856 selector
= slotRawSymbol(selSlot
);
1860 for (m
=0,mmax
=array
->size
-1; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1861 } else if (slotRawObject(listSlot
)->classptr
== class_list
) {
1862 listSlot
= slotRawObject(listSlot
)->slots
;
1863 if (NotObj(listSlot
) || slotRawObject(listSlot
)->classptr
!= class_array
) {
1864 error("List array not an Array.\n");
1865 dumpObjectSlot(listSlot
);
1866 return errWrongType
;
1870 error("Expected Array or List.. Got :\n");
1871 dumpObjectSlot(listSlot
);
1872 return errWrongType
;
1874 g
->sp
+= array
->size
- 2;
1875 numArgsPushed
= array
->size
;
1876 // now the stack looks just like it would for a normal message send
1878 sendMessage(g
, selector
, numArgsPushed
);
1884 int arrayPerformMsg(struct VMGlobals
*g
, int numArgsPushed
);
1885 int arrayPerformMsg(struct VMGlobals
*g
, int numArgsPushed
)
1887 PyrSlot
*recvrSlot
, *selSlot
, *arraySlot
;
1888 PyrSlot
*pslot
, *qslot
;
1889 PyrSymbol
*selector
;
1890 int m
, mmax
, numargslots
;
1893 arraySlot
= g
->sp
- numArgsPushed
+ 1;
1894 array
= slotRawObject(arraySlot
);
1895 if (array
->size
< 2) {
1896 error("Array must contain a receiver and a selector.\n");
1899 recvrSlot
= array
->slots
;
1900 selSlot
= recvrSlot
+ 1;
1901 numargslots
= numArgsPushed
- 1;
1902 if (NotSym(selSlot
)) {
1903 error("Selector not a Symbol :\n");
1904 return errWrongType
;
1907 selector
= slotRawSymbol(selSlot
);
1909 slotCopy(arraySlot
,recvrSlot
);
1911 if (numargslots
>0) {
1912 qslot
= arraySlot
+ numargslots
+ 1;
1913 pslot
= arraySlot
+ numargslots
+ array
->size
- 1;
1914 for (m
=0; m
<numargslots
; ++m
) slotCopy(--pslot
, --qslot
);
1915 } else numargslots
= 0;
1919 for (m
=0,mmax
=array
->size
-2; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1921 g
->sp
+= array
->size
- 2;
1922 numArgsPushed
= numargslots
+ array
->size
- 1;
1924 // now the stack looks just like it would for a normal message send
1926 sendMessage(g
, selector
, numArgsPushed
);
1931 int objectDump(struct VMGlobals
*g
, int numArgsPushed
)
1941 int prTotalFree(struct VMGlobals
*g
, int numArgsPushed
);
1942 int prTotalFree(struct VMGlobals
*g
, int numArgsPushed
)
1945 SetInt(a
, g
->allocPool
->TotalFree());
1949 int prLargestFreeBlock(struct VMGlobals
*g
, int numArgsPushed
);
1950 int prLargestFreeBlock(struct VMGlobals
*g
, int numArgsPushed
)
1953 SetInt(a
, g
->allocPool
->LargestFreeChunk());
1957 int dumpGCinfo(struct VMGlobals
*g
, int numArgsPushed
);
1958 int dumpGCinfo(struct VMGlobals
*g
, int numArgsPushed
)
1964 int dumpGCdumpGrey(struct VMGlobals
*g
, int numArgsPushed
);
1965 int dumpGCdumpGrey(struct VMGlobals
*g
, int numArgsPushed
)
1971 int dumpGCdumpSet(struct VMGlobals
*g
, int numArgsPushed
);
1972 int dumpGCdumpSet(struct VMGlobals
*g
, int numArgsPushed
)
1976 int err
= slotIntVal(b
, &set
);
1977 if (err
) return err
;
1979 g
->gc
->DumpSet(set
);
1983 int prGCSanity(struct VMGlobals
*g
, int numArgsPushed
);
1984 int prGCSanity(struct VMGlobals
*g
, int numArgsPushed
)
1986 g
->gc
->SanityCheck();
1991 int prTraceAllPathsTo(struct VMGlobals
*g
, int numArgsPushed
);
1992 int prTraceAllPathsTo(struct VMGlobals
*g
, int numArgsPushed
)
1995 g
->gc
->TracePathsTo(slotRawObject(a
), false);
1999 int prTraceAnyPathsTo(struct VMGlobals
*g
, int numArgsPushed
);
2000 int prTraceAnyPathsTo(struct VMGlobals
*g
, int numArgsPushed
)
2003 g
->gc
->TracePathsTo(slotRawObject(a
), true);
2007 int prTraceAnyPathToAllInstancesOf(struct VMGlobals
*g
, int numArgsPushed
);
2008 int prTraceAnyPathToAllInstancesOf(struct VMGlobals
*g
, int numArgsPushed
)
2011 g
->gc
->TraceAnyPathToAllInstancesOf(slotRawClass(a
)->name
.us
);
2016 extern PyrClass
*gClassList
;
2018 int prAllClasses(struct VMGlobals
*g
, int numArgsPushed
)
2027 array
= newPyrArray(g
->gc
, gNumClasses
, 0, true);
2028 classobj
= gClassList
;
2029 for (i
=0; classobj
; ++i
) {
2030 SetObject(array
->slots
+ i
, classobj
);
2031 classobj
= slotRawClass(&classobj
->nextclass
);
2033 array
->size
= gNumClasses
;
2034 SetObject(a
, array
);
2038 int prPostClassTree(struct VMGlobals
*g
, int numArgsPushed
)
2043 postClassTree(slotRawClass(a
), 0);
2047 int prDumpBackTrace(struct VMGlobals
*g
, int numArgsPushed
)
2056 /* the DebugFrameConstructor uses a work queue in order to avoid recursions, which could lead to stack overflows */
2057 struct DebugFrameConstructor
2059 void makeDebugFrame (VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2061 workQueue
.push_back(std::make_pair(frame
, outSlot
));
2066 void run_queue(VMGlobals
*g
)
2068 while (!workQueue
.empty()) {
2069 WorkQueueItem work
= workQueue
.back();
2070 workQueue
.pop_back();
2071 fillDebugFrame(g
, work
.first
, work
.second
);
2075 void fillDebugFrame(VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2077 PyrMethod
*meth
= slotRawMethod(&frame
->method
);
2078 PyrMethodRaw
* methraw
= METHRAW(meth
);
2080 PyrObject
* debugFrameObj
= instantiateObject(g
->gc
, getsym("DebugFrame")->u
.classobj
, 0, false, true);
2081 SetObject(outSlot
, debugFrameObj
);
2083 SetObject(debugFrameObj
->slots
+ 0, meth
);
2084 SetPtr(debugFrameObj
->slots
+ 5, meth
);
2086 int numargs
= methraw
->numargs
;
2087 int numvars
= methraw
->numvars
;
2089 PyrObject
* argArray
= (PyrObject
*)newPyrArray(g
->gc
, numargs
, 0, false);
2090 SetObject(debugFrameObj
->slots
+ 1, argArray
);
2091 for (int i
=0; i
<numargs
; ++i
)
2092 slotCopy(&argArray
->slots
[i
], &frame
->vars
[i
]);
2094 argArray
->size
= numargs
;
2096 SetNil(debugFrameObj
->slots
+ 1);
2099 PyrObject
* varArray
= (PyrObject
*)newPyrArray(g
->gc
, numvars
, 0, false);
2100 SetObject(debugFrameObj
->slots
+ 2, varArray
);
2101 for (int i
=0, j
=numargs
; i
<numvars
; ++i
,++j
)
2102 slotCopy(&varArray
->slots
[i
], &frame
->vars
[j
]);
2104 varArray
->size
= numvars
;
2106 SetNil(debugFrameObj
->slots
+ 2);
2108 if (slotRawFrame(&frame
->caller
)) {
2109 WorkQueueItem newWork
= std::make_pair(slotRawFrame(&frame
->caller
), debugFrameObj
->slots
+ 3);
2110 workQueue
.push_back(newWork
);
2112 SetNil(debugFrameObj
->slots
+ 3);
2114 if (IsObj(&frame
->context
) && slotRawFrame(&frame
->context
) == frame
)
2115 SetObject(debugFrameObj
->slots
+ 4, debugFrameObj
);
2116 else if (NotNil(&frame
->context
)) {
2117 WorkQueueItem newWork
= std::make_pair(slotRawFrame(&frame
->context
), debugFrameObj
->slots
+ 4);
2118 workQueue
.push_back(newWork
);
2120 SetNil(debugFrameObj
->slots
+ 4);
2123 typedef std::pair
<PyrFrame
*, PyrSlot
*> WorkQueueItem
;
2124 typedef std::vector
<WorkQueueItem
> WorkQueueType
;
2125 WorkQueueType workQueue
;
2128 static void MakeDebugFrame(VMGlobals
*g
, PyrFrame
*frame
, PyrSlot
*outSlot
)
2130 DebugFrameConstructor constructor
;
2131 constructor
.makeDebugFrame(g
, frame
, outSlot
);
2134 int prGetBackTrace(VMGlobals
*g
, int numArgsPushed
);
2135 int prGetBackTrace(VMGlobals
*g
, int numArgsPushed
)
2140 MakeDebugFrame(g
, g
->frame
, a
);
2145 int prObjectShallowCopy(struct VMGlobals
*g
, int numArgsPushed
)
2150 switch (GetTag(a
)) {
2152 SetRaw(a
, copyObject(g
->gc
, slotRawObject(a
), true));
2154 // the default case is to leave the argument unchanged on the stack
2159 int prObjectCopyImmutable(struct VMGlobals
*g
, int numArgsPushed
);
2160 int prObjectCopyImmutable(struct VMGlobals
*g
, int numArgsPushed
)
2165 switch (GetTag(a
)) {
2167 if (slotRawObject(a
)->obj_flags
& obj_immutable
) {
2168 SetRaw(a
, copyObject(g
->gc
, slotRawObject(a
), true));
2175 int prObjectIsMutable(struct VMGlobals
*g
, int numArgsPushed
);
2176 int prObjectIsMutable(struct VMGlobals
*g
, int numArgsPushed
)
2182 if (slotRawObject(a
)->obj_flags
& obj_immutable
) {
2193 int prObjectIsPermanent(struct VMGlobals
*g
, int numArgsPushed
);
2194 int prObjectIsPermanent(struct VMGlobals
*g
, int numArgsPushed
)
2200 if (slotRawObject(a
)->gc_color
== obj_permanent
) {
2213 int prDeepFreeze(struct VMGlobals
*g
, int numArgsPushed
);
2214 int prDeepFreeze(struct VMGlobals
*g
, int numArgsPushed
)
2219 PyrDeepFreezer
freezer(g
);
2220 int err
= freezer
.doDeepFreeze(a
);
2225 int prDeepCopy(struct VMGlobals
*g
, int numArgsPushed
);
2226 int prDeepCopy(struct VMGlobals
*g
, int numArgsPushed
)
2231 PyrDeepCopier
copier(g
);
2232 int err
= copier
.doDeepCopy(a
);
2239 bool IsSimpleLiteralSlot(PyrSlot
* slot
);
2240 bool IsSimpleLiteralSlot(PyrSlot
* slot
)
2242 switch (GetTag(slot
)) {
2243 case tagObj
: return slotRawObject(slot
)->IsPermanent();
2244 case tagInt
: return true;
2245 case tagSym
: return true;
2246 case tagChar
: return true;
2247 case tagNil
: return true;
2248 case tagFalse
: return true;
2249 case tagTrue
: return true;
2250 case tagPtr
: return false;
2251 default : return true;
2257 int prObjectCopyRange(struct VMGlobals
*g
, int numArgsPushed
)
2265 if (NotObj(a
)) return errWrongType
;
2266 if (NotInt(b
)) return errWrongType
;
2267 if (NotInt(c
)) return errWrongType
;
2268 SetRaw(a
, copyObjectRange(g
->gc
, slotRawObject(a
), slotRawInt(b
), slotRawInt(c
), true));
2274 int prObjectCopySeries(struct VMGlobals
*g
, int numArgsPushed
)
2276 PyrSlot
*a
, *b
, *c
, *d
;
2283 PyrObject
*inobj
= slotRawObject(a
);
2286 int size
= inobj
->size
;
2287 int flags
= ~(obj_immutable
) & inobj
->obj_flags
;
2289 int first
, second
, last
;
2291 if (IsInt(b
)) first
= slotRawInt(b
);
2292 else if (IsNil(b
)) first
= 0;
2293 else return errWrongType
;
2296 last
= slotRawInt(d
);
2297 if (last
< 0 && IsNil(b
)) {
2299 newobj
= g
->gc
->New(0, flags
, inobj
->obj_format
, true);
2301 newobj
->classptr
= inobj
->classptr
;
2305 } else if (IsNil(d
)) {
2306 if (first
>= size
) goto zerolength
;
2308 } else return errWrongType
;
2310 if (IsInt(c
)) second
= slotRawInt(c
);
2311 else if (IsNil(c
)) second
= first
< last
? first
+ 1 : first
- 1;
2312 else return errWrongType
;
2314 int step
= second
- first
;
2316 int elemsize
= gFormatElemSize
[inobj
->obj_format
];
2320 length
= (last
- first
) / step
+ 1;
2321 } else if (step
< 0) {
2322 length
= (first
- last
) / -step
+ 1;
2323 } else return errFailed
;
2325 int numbytes
= length
* elemsize
;
2327 newobj
= g
->gc
->New(numbytes
, flags
, inobj
->obj_format
, true);
2329 newobj
->classptr
= inobj
->classptr
;
2331 for (int i
=first
, j
=0; j
<length
; i
+=step
, ++j
) {
2333 if (i
>= 0 && i
< inobj
->size
) {
2334 getIndexedSlot(inobj
, &slot
, i
);
2335 int err
= putIndexedSlot(g
, newobj
, &slot
, newobj
->size
++);
2336 if (err
) return err
;
2344 void switchToThread(struct VMGlobals
*g
, struct PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
2346 int haltInterpreter(struct VMGlobals
*g
, int numArgsPushed
)
2348 switchToThread(g
, slotRawThread(&g
->process
->mainThread
), tDone
, &numArgsPushed
);
2349 // return all the way out.
2350 //PyrSlot *bottom = g->gc->Stack()->slots;
2351 //slotCopy(bottom,g->sp);
2352 //g->sp = bottom; // ??!! pop everybody
2357 longjmp(g
->escapeInterpreter
, 3);
2358 //hmm need to fix this to work only on main thread. //!!!
2359 //g->sp = g->gc->Stack()->slots - 1;
2365 int prCanCallOS(struct VMGlobals
*g
, int numArgsPushed
);
2366 int prCanCallOS(struct VMGlobals
*g
, int numArgsPushed
)
2370 SetBool(a
, g
->canCallOS
);
2375 extern bool gGenerateTailCallByteCodes
;
2377 int prGetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
);
2378 int prGetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
)
2382 SetBool(a
, gGenerateTailCallByteCodes
);
2387 int prSetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
);
2388 int prSetTailCallOptimize(struct VMGlobals
*g
, int numArgsPushed
)
2390 //PyrSlot *a = g->sp - 1;
2392 #if TAILCALLOPTIMIZE
2395 gGenerateTailCallByteCodes
= true;
2396 } else if (IsFalse(b
)) {
2397 gGenerateTailCallByteCodes
= false;
2398 } else return errWrongType
;
2405 int prTraceOn(struct VMGlobals
*g
, int numArgsPushed
);
2406 int prTraceOn(struct VMGlobals
*g
, int numArgsPushed
)
2411 gTraceInterpreter
= IsTrue(a
);
2415 int prKeywordError(struct VMGlobals
*g
, int numArgsPushed
);
2416 int prKeywordError(struct VMGlobals
*g
, int numArgsPushed
)
2421 gKeywordError
= IsTrue(a
);
2425 int prFunDef_NumArgs(struct VMGlobals
*g
, int numArgsPushed
);
2426 int prFunDef_NumArgs(struct VMGlobals
*g
, int numArgsPushed
)
2429 PyrMethodRaw
*methraw
;
2432 methraw
= METHRAW(slotRawBlock(a
));
2433 SetInt(a
, methraw
->numargs
);
2437 int prFunDef_NumVars(struct VMGlobals
*g
, int numArgsPushed
);
2438 int prFunDef_NumVars(struct VMGlobals
*g
, int numArgsPushed
)
2441 PyrMethodRaw
*methraw
;
2444 methraw
= METHRAW(slotRawBlock(a
));
2445 SetInt(a
, methraw
->numvars
);
2449 int prFunDef_VarArgs(struct VMGlobals
*g
, int numArgsPushed
);
2450 int prFunDef_VarArgs(struct VMGlobals
*g
, int numArgsPushed
)
2453 PyrMethodRaw
*methraw
;
2456 methraw
= METHRAW(slotRawBlock(a
));
2457 if (methraw
->varargs
) { SetTrue(a
); } else { SetFalse(a
); }
2462 int undefinedPrimitive(struct VMGlobals
*g
, int numArgsPushed
)
2464 error("A primitive was not bound. %d %d\n", g
->primitiveIndex
, gPrimitiveTable
.size
);
2465 dumpObject((PyrObject
*)g
->primitiveMethod
);
2469 void dumpByteCodes(PyrBlock
*theBlock
);
2471 int prDumpByteCodes(struct VMGlobals
*g
, int numArgsPushed
)
2476 dumpByteCodes(slotRawBlock(a
));
2480 int prObjectPointsTo(struct VMGlobals
*g
, int numArgsPushed
)
2482 PyrSlot
*a
, *b
, temp
;
2489 if (NotObj(a
)) slotCopy(a
,&o_false
);
2491 obj
= slotRawObject(a
);
2492 for (i
=0; i
<obj
->size
; ++i
) {
2493 getIndexedSlot(obj
, &temp
, i
);
2494 if (SlotEq(&temp
, b
)) {
2495 slotCopy(a
,&o_true
);
2499 slotCopy(a
,&o_false
);
2505 int prObjectRespondsTo(struct VMGlobals
*g
, int numArgsPushed
)
2510 PyrSymbol
*selector
;
2516 classobj
= classOfSlot(a
);
2520 selector
= slotRawSymbol(b
);
2521 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2522 meth
= gRowTable
[index
];
2523 if (slotRawSymbol(&meth
->name
) != selector
) {
2524 slotCopy(a
,&o_false
);
2526 slotCopy(a
,&o_true
);
2528 } else if (isKindOfSlot(b
, class_array
)) {
2529 int size
= slotRawObject(b
)->size
;
2530 PyrSlot
*slot
= slotRawObject(b
)->slots
;
2531 for (int i
=0; i
<size
; ++i
, ++slot
) {
2533 if (NotSym(slot
)) return errWrongType
;
2535 selector
= slotRawSymbol(slot
);
2536 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
2537 meth
= gRowTable
[index
];
2538 if (slotRawSymbol(&meth
->name
) != selector
) {
2539 slotCopy(a
,&o_false
);
2543 slotCopy(a
,&o_true
);
2544 } else return errWrongType
;
2548 PyrMethod
* GetFunctionCompileContext(VMGlobals
* g
);
2549 PyrMethod
* GetFunctionCompileContext(VMGlobals
* g
)
2552 PyrSymbol
*classsym
, *contextsym
;
2554 // lookup interpreter class
2555 classsym
= getsym("Interpreter");
2556 classobj
= classsym
->u
.classobj
;
2558 error("There is no Interpreter class.\n");
2561 // lookup functionCompileContext method
2562 contextsym
= getsym("functionCompileContext");
2563 int index
= slotRawInt(&classobj
->classIndex
) + contextsym
->u
.index
;
2564 meth
= gRowTable
[index
];
2565 if (!meth
|| slotRawSymbol(&meth
->name
) != contextsym
) {
2566 error("compile context method 'functionCompileContext' not found.\n");
2569 gCompilingClass
= classobj
;
2570 gCompilingMethod
= meth
;
2571 gCompilingBlock
= (PyrBlock
*)meth
;
2576 int prCompileString(struct VMGlobals
*g
, int numArgsPushed
)
2585 // check b is a string
2586 if (NotObj(b
)) return errWrongType
;
2587 if (!isKindOf(slotRawObject(b
), class_string
)) return errWrongType
;
2588 string
= slotRawString(b
);
2590 gRootParseNode
= NULL
;
2592 //assert(g->gc->SanityCheck());
2593 startLexerCmdLine(string
->s
, string
->size
);
2595 compilingCmdLine
= true;
2596 gCompilingVMGlobals
= g
;
2597 compilingCmdLineErrorWindow
= false;
2598 //assert(g->gc->SanityCheck());
2599 parseFailed
= yyparse();
2600 //assert(g->gc->SanityCheck());
2601 if (!parseFailed
&& gRootParseNode
) {
2604 meth
= GetFunctionCompileContext(g
);
2605 if (!meth
) return errFailed
;
2607 ((PyrBlockNode
*)gRootParseNode
)->mIsTopLevel
= true;
2609 SetNil(&slotResult
);
2610 COMPILENODE(gRootParseNode
, &slotResult
, true);
2612 if (NotObj(&slotResult
)
2613 || slotRawObject(&slotResult
)->classptr
!= class_fundef
) {
2615 error("Compile did not return a FunctionDef..\n");
2617 if (compileErrors
) {
2621 PyrClosure
*closure
;
2623 block
= slotRawBlock(&slotResult
);
2625 closure
= (PyrClosure
*)g
->gc
->New(2*sizeof(PyrSlot
), 0, obj_notindexed
, false);
2626 closure
->classptr
= class_func
;
2628 SetObject(&closure
->block
, block
);
2629 slotCopy(&closure
->context
,&slotRawInterpreter(&g
->process
->interpreter
)->context
);
2630 SetObject(a
, closure
);
2635 error("Command line parse failed\n");
2637 postfl("<nothing to do>\n");
2644 pyr_pool_compile
->FreeAll();
2646 compilingCmdLine
= false;
2648 return !(parseFailed
|| compileErrors
) ? errNone
: errFailed
;
2652 char sCodeStringIn
[8192];
2653 char sCodeStringOut
[8192];
2655 int prUGenCodeString(struct VMGlobals
*g
, int numArgsPushed
);
2656 int prUGenCodeString(struct VMGlobals
*g
, int numArgsPushed
)
2658 PyrSlot
*aa
, *bb
, *cc
, *dd
, *ee
;
2659 char *out
= sCodeStringOut
;
2660 char ugenPrefix
[16];
2663 aa
= g
->sp
- 4; // code string
2664 bb
= g
->sp
- 3; // ugen prefix
2665 ee
= g
->sp
- 2; // isDecl
2666 cc
= g
->sp
- 1; // input names
2667 dd
= g
->sp
; // input value strings
2670 err
= slotIntVal(bb
, &ugenIndex
);
2671 if (err
) return err
;
2672 if (!isKindOfSlot(cc
, class_array
) && !isKindOfSlot(cc
, class_symbolarray
)) return errWrongType
;
2673 if (!isKindOfSlot(dd
, class_array
)) return errWrongType
;
2674 bool isDecl
= IsTrue(ee
);
2676 PyrObject
*inputNamesObj
= slotRawObject(cc
);
2677 PyrObject
*inputStringsObj
= slotRawObject(dd
);
2679 sprintf(ugenPrefix
, "u%d", ugenIndex
);
2680 int ugenPrefixSize
= strlen(ugenPrefix
);
2681 PyrString
* codeStringObj
= slotRawString(aa
);
2682 int codeStringSize
= codeStringObj
->size
;
2683 if (codeStringSize
> 8000) {
2684 error("input string too int.\n");
2687 memcpy(sCodeStringIn
, codeStringObj
->s
, codeStringSize
);
2688 sCodeStringIn
[codeStringSize
] = 0;
2690 char* in
= sCodeStringIn
;
2692 while ((c
= *in
++) != 0) {
2701 for (int j
=0; j
<ugenPrefixSize
; ++j
) {
2702 *out
++ = ugenPrefix
[j
];
2704 } else if (c
== '$') {
2710 if (!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9'))) {
2720 for (int j
=0; j
<inputNamesObj
->size
; ++j
) {
2721 PyrSlot inputNameSlot
;
2722 getIndexedSlot(inputNamesObj
, &inputNameSlot
, j
);
2723 if (!IsSym(&inputNameSlot
)) return errWrongType
;
2724 PyrSymbol
* inputSym
= slotRawSymbol(&inputNameSlot
);
2725 char *inputName
= inputSym
->name
;
2726 int inputNameSize
= inputSym
->length
;
2727 if (inputNameSize
== nameSize
&& strncmp(inputName
, name
, nameSize
)==0) {
2733 if (slotIndex
>= 0) {
2734 PyrSlot
*inputStringSlot
= inputStringsObj
->slots
+ slotIndex
;
2735 if (!isKindOfSlot(inputStringSlot
, class_string
)) return errWrongType
;
2736 PyrString
*inputStringObj
= slotRawString(inputStringSlot
);
2737 char *input
= inputStringObj
->s
;
2738 int inputStringSize
= inputStringObj
->size
;
2739 for (int j
=0; j
<inputStringSize
; ++j
) {
2743 *out
++ = '?'; *out
++ = '?';
2744 for (int j
=0; j
<nameSize
; ++j
) {
2747 *out
++ = '?'; *out
++ = '?';
2752 if (out
- sCodeStringOut
> 8000) {
2762 PyrString
* outString
= newPyrString(g
->gc
, sCodeStringOut
, 0, true);
2763 SetObject(aa
, outString
);
2770 /*void threadSanity(VMGlobals *g, PyrThread *thread);
2771 void threadSanity(VMGlobals *g, PyrThread *thread)
2774 g->gc->numToScan = 1000000;
2776 assert(g->gc->SanityCheck());
2778 state = slotRawInt(&thread->state);
2779 if (state == tYield) {
2780 if (!IsObj(&thread->method)) { error("thread method not an Object\n"); }
2781 else if (!isKindOf(slotRawObject(&thread->method), class_method)) { error("thread method not a Method\n"); }
2782 else if (slotRawObject(&thread->method)->gc_color == gcColor.gcFree) { error("thread method is FREE\n"); }
2784 if (!IsObj(&thread->block)) { error("thread block not an Object\n"); }
2785 else if (!isKindOf(slotRawObject(&thread->block), class_func)) { error("thread block not a Function\n"); }
2786 else if (slotRawObject(&thread->block)->gc_color == gcColor.gcFree) { error("thread block is FREE\n"); }
2788 if (IsObj(&thread->receiver) &slotRawObject(&& thread->receiver)->gc_color == gcColor.gcFree)
2789 { error("thread receiver is FREE\n"); }
2791 FrameSanity(thread->frame.uof);
2793 oldthread->method.uom = g->method;
2794 oldthread->block.uoblk = g->block;
2795 SetObject(&oldthread->frame, g->frame);
2796 slotRawInt(&oldthread->ip) = (int)g->ip;
2797 slotRawInt(&oldthread->sp) = (int)g->sp;
2800 } else if (state == tInit) {
2802 postfl("bad state\n");
2807 PyrSymbol
*s_prready
;
2808 PyrSymbol
*s_prrunnextthread
;
2810 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
2811 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
)
2813 PyrThread
*oldthread
;
2817 #if TAILCALLOPTIMIZE
2818 g
->tailCall
= 0; // ?? prevent a crash. is there a way to allow a TCO ?
2821 oldthread
= g
->thread
;
2822 if (newthread
== oldthread
) return;
2823 //postfl("->switchToThread %d %p -> %p\n", oldstate, oldthread, newthread);
2824 //post("->switchToThread from %s:%s\n", slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name);
2825 //post("->stack %p g->sp %p [%d] g->top %p [%d]\n",
2826 // g->gc->Stack()->slots, g->sp, g->sp - g->gc->Stack()->slots, g->top, g->top - g->gc->Stack()->slots);
2827 //assert(g->gc->SanityCheck());
2828 //CallStackSanity(g, "switchToThreadA");
2829 //gcDumpInfo(g->gc);
2832 // save environment in oldthread
2833 PyrSlot
* currentEnvironmentSlot
= &g
->classvars
->slots
[1];
2834 slotCopy(&oldthread
->environment
,currentEnvironmentSlot
);
2835 gc
->GCWrite(oldthread
, currentEnvironmentSlot
);
2837 SetRaw(&oldthread
->state
, oldstate
);
2839 if (oldstate
== tDone
) {
2840 SetObject(&oldthread
->stack
, gc
->Stack());
2841 gc
->ToWhite(gc
->Stack());
2842 gc
->Stack()->size
= 0;
2843 gc
->GCWrite(oldthread
, gc
->Stack());
2844 SetNil(&oldthread
->method
);
2845 SetNil(&oldthread
->block
);
2846 SetNil(&oldthread
->receiver
);
2847 SetNil(&oldthread
->frame
);
2848 SetRaw(&oldthread
->ip
, (void*)0);
2849 SetRaw(&oldthread
->sp
, (void*)0);
2850 SetRaw(&oldthread
->numArgsPushed
, 0);
2851 SetRaw(&oldthread
->numpop
, 0);
2852 SetNil(&oldthread
->parent
);
2853 } else if (oldstate
== tInit
) {
2854 SetObject(&oldthread
->stack
, gc
->Stack());
2855 gc
->ToWhite(gc
->Stack());
2856 gc
->Stack()->size
= 0;
2857 gc
->GCWrite(oldthread
, gc
->Stack());
2858 SetNil(&oldthread
->method
);
2859 SetNil(&oldthread
->block
);
2860 SetNil(&oldthread
->receiver
);
2861 SetNil(&oldthread
->frame
);
2862 SetRaw(&oldthread
->ip
, (void*)0);
2863 SetRaw(&oldthread
->sp
, (void*)0);
2864 SetRaw(&oldthread
->numArgsPushed
, 0);
2865 SetRaw(&oldthread
->numpop
, 0);
2866 SetNil(&oldthread
->parent
);
2868 // save old thread's state
2869 SetObject(&oldthread
->stack
, gc
->Stack());
2870 gc
->ToWhite(gc
->Stack());
2871 gc
->Stack()->size
= g
->sp
- gc
->Stack()->slots
+ 1;
2872 //post("else %p %p\n", slotRawObject(&oldthread->stack), gc->Stack());
2874 SetObject(&oldthread
->method
, g
->method
);
2875 SetObject(&oldthread
->block
, g
->block
);
2876 SetObject(&oldthread
->frame
, g
->frame
);
2877 SetPtr(&oldthread
->ip
, g
->ip
);
2878 SetPtr(&oldthread
->sp
, g
->sp
);
2879 slotCopy(&oldthread
->receiver
,&g
->receiver
);
2880 SetRaw(&oldthread
->numArgsPushed
, *numArgsPushed
);
2881 SetRaw(&oldthread
->numpop
, g
->numpop
);
2883 //gc->ToGrey(oldthread);
2884 if (gc
->ObjIsBlack(oldthread
)) {
2885 gc
->GCWriteBlack(gc
->Stack());
2886 gc
->GCWriteBlack(g
->method
);
2887 gc
->GCWriteBlack(g
->block
);
2889 frame
= slotRawFrame(&oldthread
->frame
);
2890 gc
->GCWriteBlack(frame
);
2892 gc
->GCWriteBlack(&g
->receiver
);
2896 // restore new thread's state
2897 g
->thread
= newthread
;
2898 SetObject(&g
->process
->curThread
, newthread
);
2899 gc
->GCWrite(g
->process
, newthread
);
2901 gc
->SetStack(slotRawObject(&newthread
->stack
));
2902 gc
->ToBlack(gc
->Stack());
2903 SetNil(&newthread
->stack
);
2905 g
->method
= slotRawMethod(&newthread
->method
);
2906 g
->block
= slotRawBlock(&newthread
->block
);
2907 g
->frame
= slotRawFrame(&newthread
->frame
);
2908 g
->ip
= (unsigned char *)slotRawPtr(&newthread
->ip
);
2909 g
->sp
= (PyrSlot
*)slotRawPtr(&newthread
->sp
);
2910 slotCopy(&g
->receiver
,&newthread
->receiver
);
2912 g
->rgen
= (RGen
*)(slotRawObject(&newthread
->randData
)->slots
);
2914 *numArgsPushed
= slotRawInt(&newthread
->numArgsPushed
);
2916 // these are perhaps unecessary because a thread may not
2917 // legally block within a C primitive
2918 g
->numpop
= slotRawInt(&newthread
->numpop
);
2922 //post("switchToThread ip %p\n", g->ip);
2923 //post(slotRawInt(&"switchToThread newthread->ip) %d\n", slotRawInt(&newthread->ip));
2924 //post(slotRawInt(&"switchToThread oldthread->ip) %d\n", slotRawInt(&oldthread->ip));
2926 // wipe out values which will become stale as new thread executes:
2927 SetNil(&newthread
->method
);
2928 SetNil(&newthread
->block
);
2929 SetNil(&newthread
->frame
);
2930 SetRaw(&newthread
->ip
, (void*)0);
2931 SetRaw(&newthread
->sp
, (void*)0);
2932 SetNil(&newthread
->receiver
);
2934 SetRaw(&newthread
->state
, tRunning
);
2937 // set new environment
2938 slotCopy(currentEnvironmentSlot
,&g
->thread
->environment
);
2939 g
->gc
->GCWrite(g
->classvars
, currentEnvironmentSlot
);
2941 //post("old thread %p stack %p\n", oldthread, slotRawObject(&oldthread->stack));
2942 //post("new thread %p stack %p\n", g->thread, slotRawObject(&g->thread->stack));
2943 //post("main thread %p stack %p\n", slotRawThread(&g->process->mainThread), slotRawObject(&slotRawThread(&g->process->mainThread)->stack));
2945 //postfl("<-switchToThread\n");
2946 //post("<-stack %p g->sp %p [%d] g->top %p [%d]\n",
2947 // g->gc->Stack()->slots, g->sp, g->sp - g->gc->Stack()->slots, g->top, g->top - g->gc->Stack()->slots);
2948 //assert(g->gc->SanityCheck());
2949 //CallStackSanity(g, "switchToThreadB");
2950 //post("switchToThread ip2 %p\n", g->ip);
2953 void initPyrThread(VMGlobals
*g
, PyrThread
*thread
, PyrSlot
*func
, int stacksize
, PyrInt32Array
* rgenArray
,
2954 double beats
, double seconds
, PyrSlot
* clock
, bool collect
);
2955 void initPyrThread(VMGlobals
*g
, PyrThread
*thread
, PyrSlot
*func
, int stacksize
, PyrInt32Array
* rgenArray
,
2956 double beats
, double seconds
, PyrSlot
* clock
, bool collect
)
2961 slotCopy(&thread
->func
, func
);
2962 gc
->GCWrite(thread
, func
);
2964 array
= newPyrArray(gc
, stacksize
, 0, collect
);
2965 SetObject(&thread
->stack
, array
);
2966 gc
->GCWrite(thread
, array
);
2968 SetInt(&thread
->state
, tInit
);
2970 SetPtr(&thread
->ip
, 0);
2971 SetPtr(&thread
->sp
, 0);
2973 SetObject(&thread
->randData
, rgenArray
);
2974 gc
->GCWrite(thread
, rgenArray
);
2976 SetFloat(&thread
->beats
, beats
);
2977 SetFloat(&thread
->seconds
, seconds
);
2978 SetInt(&thread
->numArgsPushed
, 0);
2979 SetInt(&thread
->numpop
, 0);
2982 SetObject(&thread
->clock
, s_systemclock
->u
.classobj
);
2984 slotCopy(&thread
->clock
,clock
);
2985 gc
->GCWrite(thread
, clock
);
2988 PyrSlot
* currentEnvironmentSlot
= &g
->classvars
->slots
[1];
2989 slotCopy(&thread
->environment
,currentEnvironmentSlot
);
2990 gc
->GCWrite(thread
, currentEnvironmentSlot
);
2992 if(g
->process
) { // check we're not just starting up
2993 slotCopy(&thread
->executingPath
,&g
->process
->nowExecutingPath
);
2994 gc
->GCWrite(thread
, &g
->process
->nowExecutingPath
);
2997 SetInt(&thread
->stackSize
, stacksize
);
3000 extern PyrSymbol
*s_prstart
;
3002 int prThreadInit(struct VMGlobals
*g
, int numArgsPushed
);
3003 int prThreadInit(struct VMGlobals
*g
, int numArgsPushed
)
3009 //postfl("->prThreadInit\n");
3010 //assert(g->gc->SanityCheck());
3011 //CallStackSanity(g, "prThreadInit");
3012 a
= g
->sp
- 2; // thread
3013 b
= g
->sp
- 1; // function
3014 c
= g
->sp
; // stacksize
3016 thread
= slotRawThread(a
);
3018 if (NotObj(b
) || !isKindOf(slotRawObject(b
), class_func
)) {
3019 error("Thread function arg not a Function.\n");
3020 return errWrongType
;
3023 err
= slotIntVal(c
, &stacksize
);
3024 if (err
) return err
;
3026 stacksize
= std::max(stacksize
, EVALSTACKDEPTH
);
3028 initPyrThread(g
, thread
, b
, stacksize
, (PyrInt32Array
*)(slotRawObject(&g
->thread
->randData
)),
3029 slotRawFloat(&g
->thread
->beats
), slotRawFloat(&g
->thread
->seconds
), &g
->thread
->clock
, true);
3031 //postfl("<-prThreadInit\n");
3032 //assert(g->gc->SanityCheck());
3033 //CallStackSanity(g, "<prThreadInit");
3037 int prThreadRandSeed(struct VMGlobals
*g
, int numArgsPushed
);
3038 int prThreadRandSeed(struct VMGlobals
*g
, int numArgsPushed
)
3040 PyrSlot
*a
= g
->sp
- 1; // thread
3041 PyrSlot
*b
= g
->sp
; // rand seed
3043 PyrThread
*thread
= slotRawThread(a
);
3046 int err
= slotIntVal(b
, &seed
);
3047 if (err
) return err
;
3049 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, true);
3050 rgenArray
->size
= 4;
3051 ((RGen
*)(rgenArray
->i
))->init(seed
);
3053 if (thread
== g
->thread
) {
3054 g
->rgen
= (RGen
*)(rgenArray
->i
);
3056 SetObject(&thread
->randData
, rgenArray
);
3057 g
->gc
->GCWrite(thread
, rgenArray
);
3062 int prThreadGetRandData(struct VMGlobals
*g
, int numArgsPushed
);
3063 int prThreadGetRandData(struct VMGlobals
*g
, int numArgsPushed
)
3065 PyrSlot
*a
= g
->sp
; // thread
3067 PyrThread
*thread
= slotRawThread(a
);
3069 RGen
* rgen
= (RGen
*)slotRawObject(&thread
->randData
)->slots
;
3071 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, false);
3072 rgenArray
->size
= 3;
3074 rgenArray
->i
[0] = rgen
->s1
;
3075 rgenArray
->i
[1] = rgen
->s2
;
3076 rgenArray
->i
[2] = rgen
->s3
;
3078 SetObject(a
, rgenArray
);
3082 int prThreadSetRandData(struct VMGlobals
*g
, int numArgsPushed
);
3083 int prThreadSetRandData(struct VMGlobals
*g
, int numArgsPushed
)
3085 PyrSlot
*a
= g
->sp
- 1; // thread
3086 PyrSlot
*b
= g
->sp
; // rand data array
3088 if (!isKindOfSlot(b
, class_int32array
)) return errWrongType
;
3089 if (slotRawObject(b
)->size
< 3) return errWrongType
;
3091 PyrThread
*thread
= slotRawThread(a
);
3093 RGen
* rgen
= (RGen
*)slotRawObject(&thread
->randData
)->slots
;
3095 PyrInt32Array
*rgenArray
= (PyrInt32Array
*)slotRawObject(b
);
3097 rgen
->s1
= rgenArray
->i
[0];
3098 rgen
->s2
= rgenArray
->i
[1];
3099 rgen
->s3
= rgenArray
->i
[2];
3107 int transformMainThreadToRoutine(VMGlobals
*g
)
3109 PyrProcess
* process
= g
->process
;
3110 if (g
->thread
!= process
->mainThread
.uot
) return errFailed
;
3111 //if (g->thread != process->curThread.uot) return errFailed;
3113 PyrThread
* curthread
= (PyrThread
*)slotRawObject(&process
->mainThread
);
3115 // create a new main thread
3116 PyrThread
* newthread
= (PyrThread
*)instantiateObject(g
->gc
, class_thread
, 0, true, false);
3118 PyrInt32Array
*rgenArray
= newPyrInt32Array(g
->gc
, 4, 0, false);
3119 rgenArray
->size
= 4;
3120 ((RGen
*)(rgenArray
->i
))->init(timeseed());
3123 SetObject(&clockSlot
, s_systemclock
->u
.classobj
);
3124 initPyrThread(g
, newthread
, &o_nil
, EVALSTACKDEPTH
, rgenArray
, 0., 0., &clockSlot
, false);
3125 slotRawInt(&newthread
->sp
) = (int)slotRawObject(&newthread
->stack
)->slots
- 1;
3126 SetObject(&process
->mainThread
, newthread
);
3127 g
->gc
->GCWrite(process
, newthread
);
3129 curthread
->classptr
= class_routine
;
3130 PyrSlot
*cmdFunc
= &process
->interpreter
.uoi
->cmdFunc
;
3131 slotCopy(&curthread
->func
,cmdFunc
);
3132 g
->gc
->GCWrite(curthread
, cmdFunc
);
3137 void schedAdd(VMGlobals
*g
, PyrObject
* inQueue
, double inSeconds
, PyrSlot
* inTask
);
3141 int prRoutineYield(struct VMGlobals
*g
, int numArgsPushed
);
3142 int prRoutineYield(struct VMGlobals
*g
, int numArgsPushed
)
3146 //postfl("->prRoutineYield %p\n", g->thread);
3147 //assert(g->gc->SanityCheck());
3148 //CallStackSanity(g, "prRoutineYield");
3149 //postfl("->numArgsPushed %d\n", numArgsPushed);
3151 slotCopy(&value
,g
->sp
);
3153 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3154 error ("yield was called outside of a Routine.\n");
3158 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3159 SetNil(&g
->thread
->parent
);
3160 slotCopy(&g
->process
->nowExecutingPath
, &g
->thread
->oldExecutingPath
);
3161 //debugf("yield from thread %p to parent %p\n", g->thread, slotRawThread(&g->thread->parent));
3162 switchToThread(g
, parent
, tSuspended
, &numArgsPushed
);
3164 // on the other side of the looking glass, put the yielded value on the stack as the result..
3165 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3167 //postfl("<-numArgsPushed %d\n", numArgsPushed);
3168 //postfl("<-prRoutineYield\n");
3169 //assert(g->gc->SanityCheck());
3170 //CallStackSanity(g, "<prRoutineYield");
3174 int prRoutineAlwaysYield(struct VMGlobals
*g
, int numArgsPushed
);
3175 int prRoutineAlwaysYield(struct VMGlobals
*g
, int numArgsPushed
)
3179 //postfl("->prRoutineAlwaysYield ip %p\n", g->ip);
3180 //assert(g->gc->SanityCheck());
3181 //CallStackSanity(g, "prRoutineAlwaysYield");
3182 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3183 error ("alwaysYield was called outside of a Routine.\n");
3187 slotCopy(&value
,g
->sp
);
3188 slotCopy(&g
->thread
->terminalValue
,&value
);
3189 g
->gc
->GCWrite(g
->thread
, g
->sp
);
3191 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3192 SetNil(&g
->thread
->parent
);
3193 slotCopy(&g
->process
->nowExecutingPath
, &g
->thread
->oldExecutingPath
);
3194 //post("alwaysYield from thread %p to parent %p\n", g->thread, parent);
3195 switchToThread(g
, parent
, tDone
, &numArgsPushed
);
3197 // on the other side of the looking glass, put the yielded value on the stack as the result..
3198 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3200 //postfl("<-prRoutineAlwaysYield ip %p\n", g->ip);
3201 //assert(g->gc->SanityCheck());
3202 //CallStackSanity(g, "<prRoutineAlwaysYield");
3206 int prRoutineResume(struct VMGlobals
*g
, int numArgsPushed
);
3207 int prRoutineResume(struct VMGlobals
*g
, int numArgsPushed
)
3209 PyrSlot
*a
, *b
, threadSlot
, value
;
3213 //assert(g->gc->SanityCheck());
3214 //CallStackSanity(g, "prRoutineResume");
3218 thread
= slotRawThread(a
);
3219 state
= slotRawInt(&thread
->state
);
3220 //postfl("->prRoutineResume %d\n", state);
3222 slotCopy(&thread
->oldExecutingPath
,&g
->process
->nowExecutingPath
);
3223 slotCopy(&g
->process
->nowExecutingPath
, &thread
->executingPath
);
3224 if (state
== tInit
) {
3225 slotCopy(&threadSlot
,a
);
3228 //post("g->thread %p\n", g->thread);
3229 //post("thread %p\n", thread);
3230 SetObject(&thread
->parent
, g
->thread
);
3231 g
->gc
->GCWrite(thread
, g
->thread
);
3233 SetRaw(&thread
->beats
, slotRawFloat(&g
->thread
->beats
));
3234 SetRaw(&thread
->seconds
, slotRawFloat(&g
->thread
->seconds
));
3235 slotCopy(&thread
->clock
, &g
->thread
->clock
);
3236 g
->gc
->GCWrite(thread
, &g
->thread
->clock
);
3238 //postfl("start into thread %p from parent %p\n", thread, g->thread);
3239 switchToThread(g
, thread
, tSuspended
, &numArgsPushed
);
3242 //post("set stack %p %p\n", g->sp, g->gc->Stack()->slots - 1);
3243 g
->sp
= g
->gc
->Stack()->slots
- 1;
3244 slotCopy((++g
->sp
), &threadSlot
);
3245 slotCopy(&g
->receiver
, &threadSlot
);
3246 slotCopy((++g
->sp
),&value
);
3248 sendMessage(g
, s_prstart
, 2);
3249 } else if (state
== tSuspended
) {
3251 if (IsNil(&thread
->parent
)) {
3252 SetObject(&thread
->parent
, g
->thread
);
3254 g
->gc
->GCWrite(thread
, g
->thread
);
3256 SetRaw(&thread
->beats
, slotRawFloat(&g
->thread
->beats
));
3257 SetRaw(&thread
->seconds
, slotRawFloat(&g
->thread
->seconds
));
3258 slotCopy(&thread
->clock
,&g
->thread
->clock
);
3259 g
->gc
->GCWrite(thread
, &g
->thread
->clock
);
3262 //debugf("resume into thread %p from parent %p\n", thread, g->thread);
3263 switchToThread(g
, thread
, tSuspended
, &numArgsPushed
);
3264 // on the other side of the looking glass, put the yielded value on the stack as the result..
3265 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3266 } else if (state
== tDone
) {
3267 slotCopy(a
,&thread
->terminalValue
);
3268 } else if (state
== tRunning
) {
3269 error("Tried to resume the running thread.\n");
3272 error("Thread in strange state: %d\n", state
);
3275 //postfl("<-prRoutineResume\n");
3276 //CallStackSanity(g);
3280 int prRoutineReset(struct VMGlobals
*g
, int numArgsPushed
);
3281 int prRoutineReset(struct VMGlobals
*g
, int numArgsPushed
)
3286 //assert(g->gc->SanityCheck());
3287 //CallStackSanity(g, "prRoutineReset");
3288 thread
= slotRawThread(g
->sp
);
3289 state
= slotRawInt(&thread
->state
);
3290 //post("->prRoutineReset %d\n", state);
3291 if (state
== tSuspended
) {
3292 SetRaw(&thread
->state
, tInit
);
3293 slotRawObject(&thread
->stack
)->size
= 0;
3294 SetNil(&thread
->method
);
3295 SetNil(&thread
->block
);
3296 SetNil(&thread
->receiver
);
3297 SetNil(&thread
->frame
);
3298 SetRaw(&thread
->ip
, (void*)0);
3299 SetRaw(&thread
->sp
, (void*)0);
3300 SetRaw(&thread
->numArgsPushed
, 0);
3301 SetRaw(&thread
->numpop
, 0);
3302 SetNil(&thread
->parent
);
3303 } else if (state
== tDone
) {
3304 SetRaw(&thread
->state
, tInit
);
3305 slotRawObject(&thread
->stack
)->size
= 0;
3306 SetNil(&thread
->method
);
3307 SetNil(&thread
->block
);
3308 SetNil(&thread
->receiver
);
3309 SetNil(&thread
->frame
);
3310 SetRaw(&thread
->ip
, (void*)0);
3311 SetRaw(&thread
->sp
, (void*)0);
3312 SetRaw(&thread
->numArgsPushed
, 0);
3313 SetRaw(&thread
->numpop
, 0);
3314 SetNil(&thread
->parent
);
3315 } else if (state
== tInit
) {
3317 } else if (state
== tRunning
) {
3318 error("A Routine cannot reset itself except by yieldAndReset.\n");
3321 error("Routine in unknown state. %d\n", state
);
3324 //assert(g->gc->SanityCheck());
3325 //CallStackSanity(g, "<prRoutineReset");
3329 int prRoutineStop(struct VMGlobals
*g
, int numArgsPushed
);
3330 int prRoutineStop(struct VMGlobals
*g
, int numArgsPushed
)
3334 //post("->prRoutineStop\n");
3335 //assert(g->gc->SanityCheck());
3336 //CallStackSanity(g, "prRoutineStop");
3338 thread
= slotRawThread(g
->sp
);
3339 state
= slotRawInt(&thread
->state
);
3342 if (state
== tSuspended
|| state
== tInit
) {
3343 slotCopy(&g
->process
->nowExecutingPath
, &thread
->oldExecutingPath
);
3344 SetNil(&g
->thread
->terminalValue
);
3345 SetRaw(&thread
->state
, tDone
);
3346 slotRawObject(&thread
->stack
)->size
= 0;
3347 } else if (state
== tDone
) {
3349 } else if (state
== tRunning
) {
3350 error("Do not call .stop from within the Routine.\n");
3351 post("A Routine should stop itself using nil.alwaysYield.\n");
3354 error("Routine in unknown state. %d\n", state
);
3357 //assert(g->gc->SanityCheck());
3358 //CallStackSanity(g, "<prRoutineStop");
3363 int prRoutineYieldAndReset(struct VMGlobals
*g
, int numArgsPushed
);
3364 int prRoutineYieldAndReset(struct VMGlobals
*g
, int numArgsPushed
)
3366 PyrSlot
*a
, *b
, value
;
3369 //post("->prRoutineYieldAndReset\n");
3370 //assert(g->gc->SanityCheck());
3371 //CallStackSanity(g, "prRoutineYieldAndReset");
3375 if (!isKindOf((PyrObject
*)g
->thread
, class_routine
)) {
3376 error ("yieldAndReset was called outside of a Routine.\n");
3379 /*if (!slotRawThread(&g->thread->parent)) {
3380 error ("yieldAndReset was called from a thread with no parent.\n");
3385 if (IsFalse(b
)) state
= tSuspended
;
3388 PyrThread
*parent
= slotRawThread(&g
->thread
->parent
);
3389 SetNil(&g
->thread
->parent
);
3390 switchToThread(g
, parent
, state
, &numArgsPushed
);
3391 // on the other side of the looking glass, put the yielded value on the stack as the result..
3392 slotCopy((g
->sp
- numArgsPushed
+ 1),&value
);
3394 //slotCopy(&g->process->nowExecutingPath, &g->thread->oldExecutingPath);
3396 //post("<-prRoutineYieldAndReset\n");
3397 //assert(g->gc->SanityCheck());
3398 //CallStackSanity(g, "prRoutineYieldAndReset");
3403 bool gBlork
= false;
3405 int prBlork(struct VMGlobals
*g
, int numArgsPushed
);
3406 int prBlork(struct VMGlobals
*g
, int numArgsPushed
)
3411 if (IsTrue(a
)) gBlork
= true;
3412 else gBlork
= false;
3417 int prOverwriteMsg(struct VMGlobals
*g
, int numArgsPushed
);
3418 int prOverwriteMsg(struct VMGlobals
*g
, int numArgsPushed
)
3421 PyrString
* string
= newPyrString(g
->gc
, overwriteMsg
.c_str(), 0, false);
3422 SetObject(a
, string
);
3426 int prAppClockSchedNotify(struct VMGlobals
*g
, int numArgsPushed
)
3428 //NOTE: the _AppClock_SchedNotify primitive shall be redefined by language clients
3429 // if they wish to respond to AppClock scheduling notifications
3433 enum {includePaths
, excludePaths
};
3435 static int prLanguageConfig_getLibraryPaths(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3437 PyrSlot
*result
= g
->sp
;
3439 typedef SC_LanguageConfig::DirVector DirVector
;
3441 DirVector
const & dirVector
= (pathType
== includePaths
) ? gLibraryConfig
->includedDirectories()
3442 : gLibraryConfig
->excludedDirectories();
3444 size_t numberOfPaths
= dirVector
.size();
3445 PyrObject
* resultArray
= newPyrArray(g
->gc
, numberOfPaths
, 0, true);
3446 SetObject(result
, resultArray
);
3447 resultArray
->size
= numberOfPaths
;
3449 for (size_t i
= 0; i
!= numberOfPaths
; ++i
)
3450 SetObject(resultArray
->slots
+ i
, newPyrString(g
->gc
, dirVector
[i
].c_str(), 0, true));
3454 static int prLanguageConfig_getIncludePaths(struct VMGlobals
* g
, int numArgsPushed
)
3456 return prLanguageConfig_getLibraryPaths(g
, numArgsPushed
, includePaths
);
3459 static int prLanguageConfig_getExcludePaths(struct VMGlobals
* g
, int numArgsPushed
)
3461 return prLanguageConfig_getLibraryPaths(g
, numArgsPushed
, excludePaths
);
3464 static int prLanguageConfig_addLibraryPath(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3466 PyrSlot
*removeString
= g
->sp
;
3468 char path
[MAXPATHLEN
];
3469 bool error
= slotStrVal(removeString
, path
, MAXPATHLEN
);
3471 return errWrongType
;
3473 if (pathType
== includePaths
)
3474 gLibraryConfig
->addIncludedDirectory(path
);
3476 gLibraryConfig
->addExcludedDirectory(path
);
3480 static int prLanguageConfig_addIncludePath(struct VMGlobals
* g
, int numArgsPushed
)
3482 return prLanguageConfig_addLibraryPath(g
, numArgsPushed
, includePaths
);
3485 static int prLanguageConfig_addExcludePath(struct VMGlobals
* g
, int numArgsPushed
)
3487 return prLanguageConfig_addLibraryPath(g
, numArgsPushed
, excludePaths
);
3490 static int prLanguageConfig_removeLibraryPath(struct VMGlobals
* g
, int numArgsPushed
, int pathType
)
3492 PyrSlot
*dirString
= g
->sp
;
3494 char path
[MAXPATHLEN
];
3495 bool error
= slotStrVal(dirString
, path
, MAXPATHLEN
);
3497 return errWrongType
;
3499 if (pathType
== includePaths
)
3500 gLibraryConfig
->removeIncludedDirectory(path
);
3502 gLibraryConfig
->removeExcludedDirectory(path
);
3506 static int prLanguageConfig_removeIncludePath(struct VMGlobals
* g
, int numArgsPushed
)
3508 return prLanguageConfig_removeLibraryPath(g
, numArgsPushed
, includePaths
);
3511 static int prLanguageConfig_removeExcludePath(struct VMGlobals
* g
, int numArgsPushed
)
3513 return prLanguageConfig_removeLibraryPath(g
, numArgsPushed
, excludePaths
);
3516 static int prLanguageConfig_writeConfigFile(struct VMGlobals
* g
, int numArgsPushed
)
3518 PyrSlot
*fileString
= g
->sp
;
3520 char path
[MAXPATHLEN
];
3521 if (NotNil(fileString
)) {
3522 bool error
= slotStrVal(fileString
, path
, MAXPATHLEN
);
3524 return errWrongType
;
3526 sc_GetUserConfigDirectory(path
, PATH_MAX
);
3527 sc_AppendToPath(path
, MAXPATHLEN
, "sclang_conf.yaml");
3530 gLibraryConfig
->writeLibraryConfigYAML(path
);
3534 extern bool gPostInlineWarnings
;
3535 static int prLanguageConfig_getPostInlineWarnings(struct VMGlobals
* g
, int numArgsPushed
)
3537 PyrSlot
*result
= g
->sp
;
3538 SetBool(result
, gPostInlineWarnings
);
3542 static int prLanguageConfig_setPostInlineWarnings(struct VMGlobals
* g
, int numArgsPushed
)
3544 PyrSlot
*arg
= g
->sp
;
3547 gPostInlineWarnings
= true;
3548 else if (IsFalse(arg
))
3549 gPostInlineWarnings
= false;
3551 return errWrongType
;
3557 #define PRIMGROWSIZE 480
3558 PrimitiveTable gPrimitiveTable
;
3560 void initPrimitiveTable()
3563 gPrimitiveTable
.maxsize
= PRIMGROWSIZE
;
3564 gPrimitiveTable
.size
= 0;
3566 // lifetime: runtime. primitives are reloaded when library is compiled.
3567 gPrimitiveTable
.table
= (PrimitiveDef
*)pyr_pool_runtime
->Alloc(gPrimitiveTable
.maxsize
* sizeof(PrimitiveDef
));
3568 MEMFAIL(gPrimitiveTable
.table
);
3569 for (i
=0; i
<gPrimitiveTable
.maxsize
; ++i
) {
3570 gPrimitiveTable
.table
[i
].func
= undefinedPrimitive
;
3571 gPrimitiveTable
.table
[i
].name
= s_none
;
3572 gPrimitiveTable
.table
[i
].base
= 0;
3573 gPrimitiveTable
.table
[i
].numArgs
= 0;
3574 gPrimitiveTable
.table
[i
].varArgs
= 0;
3575 gPrimitiveTable
.table
[i
].keyArgs
= 0;
3579 void growPrimitiveTable(int newsize
)
3581 PrimitiveDef
*oldtable
;
3583 //postfl("growPrimitiveTable %d %d\n", oldsize, newsize);
3584 oldtable
= gPrimitiveTable
.table
;
3585 oldsize
= gPrimitiveTable
.maxsize
;
3586 gPrimitiveTable
.maxsize
= newsize
;
3588 // lifetime: runtime. primitives are reloaded when library is compiled.
3589 gPrimitiveTable
.table
= (PrimitiveDef
*)pyr_pool_runtime
->Alloc(gPrimitiveTable
.maxsize
* sizeof(PrimitiveDef
));
3590 MEMFAIL(gPrimitiveTable
.table
);
3591 memcpy(gPrimitiveTable
.table
, oldtable
, oldsize
* sizeof(PrimitiveDef
));
3592 for (i
=oldsize
; i
<gPrimitiveTable
.maxsize
; ++i
) {
3593 gPrimitiveTable
.table
[i
].func
= undefinedPrimitive
;
3594 gPrimitiveTable
.table
[i
].name
= s_none
;
3595 gPrimitiveTable
.table
[i
].base
= 0;
3596 gPrimitiveTable
.table
[i
].numArgs
= 0;
3597 gPrimitiveTable
.table
[i
].varArgs
= 0;
3598 gPrimitiveTable
.table
[i
].keyArgs
= 0;
3600 pyr_pool_runtime
->Free(oldtable
);
3603 int definePrimitive(int base
, int index
, const char *name
, PrimitiveHandler handler
,
3604 int numArgs
, int varArgs
)
3609 if (name
[0] != '_') {
3610 error("*** Primitive Name must begin with an underscore ***\n");
3611 postfl("name: '%s' index: %d\n", name
, index
);
3614 tableIndex
= base
+ index
;
3615 if (tableIndex
< 0) {
3616 error("*** Negative Primitive Index ***\n");
3617 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3620 if (tableIndex
>= gPrimitiveTable
.maxsize
) {
3621 growPrimitiveTable(tableIndex
+ PRIMGROWSIZE
);
3623 if (gPrimitiveTable
.table
[tableIndex
].func
!= undefinedPrimitive
) {
3624 error("*** Duplicate Primitive Index ***\n");
3625 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3629 gPrimitiveTable
.table
[tableIndex
].func
= handler
;
3630 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3631 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3632 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3633 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3634 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 0;
3635 if (tableIndex
> gPrimitiveTable
.size
) gPrimitiveTable
.size
= tableIndex
;
3636 sym
->u
.index
= tableIndex
;
3640 int definePrimitiveWithKeys(int base
, int index
, const char *name
,
3641 PrimitiveHandler handler
, PrimitiveWithKeysHandler keyhandler
,
3642 int numArgs
, int varArgs
)
3647 if (name
[0] != '_') {
3648 error("*** Primitive Name must begin with an underscore ***\n");
3649 postfl("name: '%s' index: %d\n", name
, index
);
3652 tableIndex
= base
+ index
;
3653 if (tableIndex
< 0) {
3654 error("*** Negative Primitive Index ***\n");
3655 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3658 if (tableIndex
+1 >= gPrimitiveTable
.maxsize
) {
3659 growPrimitiveTable(tableIndex
+ PRIMGROWSIZE
);
3661 if (gPrimitiveTable
.table
[tableIndex
].func
!= undefinedPrimitive
) {
3662 error("*** Duplicate Primitive Index ***\n");
3663 postfl("name: '%s' index: %d\n", name
, tableIndex
);
3667 gPrimitiveTable
.table
[tableIndex
].func
= handler
;
3668 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3669 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3670 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3671 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3672 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 1;
3673 sym
->u
.index
= tableIndex
;
3676 gPrimitiveTable
.table
[tableIndex
].func
= (PrimitiveHandler
)keyhandler
;
3677 gPrimitiveTable
.table
[tableIndex
].name
= sym
;
3678 gPrimitiveTable
.table
[tableIndex
].base
= base
;
3679 gPrimitiveTable
.table
[tableIndex
].numArgs
= numArgs
;
3680 gPrimitiveTable
.table
[tableIndex
].varArgs
= varArgs
;
3681 gPrimitiveTable
.table
[tableIndex
].keyArgs
= 1;
3682 if (tableIndex
> gPrimitiveTable
.size
) gPrimitiveTable
.size
= tableIndex
;
3686 int nextPrimitiveIndex()
3688 return gPrimitiveTable
.size
+ 1;
3692 void doPrimitive(VMGlobals
* g
, PyrMethod
* meth
, int numArgsPushed
)
3696 #ifdef GC_SANITYCHECK
3697 g
->gc
->SanityCheck();
3700 //post("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3702 PyrMethodRaw
*methraw
= METHRAW(meth
);
3703 int primIndex
= methraw
->specialIndex
;
3705 PrimitiveDef
*def
= gPrimitiveTable
.table
+ primIndex
;
3706 int numArgsNeeded
= def
->numArgs
;
3707 int diff
= numArgsNeeded
- numArgsPushed
;
3709 if (diff
!= 0) { // incorrect num of args
3710 if (diff
> 0) { // not enough args
3711 PyrSlot
* pslot
= g
->sp
;
3712 PyrSlot
* qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
3713 for (int m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
3716 } else if (def
->varArgs
) { // has var args
3717 numArgsNeeded
= numArgsPushed
;
3719 g
->sp
+= diff
; // remove excess args
3722 g
->numpop
= numArgsNeeded
- 1;
3723 g
->primitiveIndex
= primIndex
- def
->base
;
3724 g
->primitiveMethod
= meth
;
3725 g
->args
= g
->sp
- numArgsNeeded
;
3728 #ifdef GC_SANITYCHECK
3729 g
->gc
->SanityCheck();
3731 err
= (*def
->func
)(g
, numArgsNeeded
);
3732 #ifdef GC_SANITYCHECK
3733 g
->gc
->SanityCheck();
3735 } catch (std::exception
& ex
) {
3736 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3740 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3743 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3745 //post("primitive failed %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3746 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3747 SetInt(&g
->thread
->primitiveError
, err
);
3748 executeMethod(g
, meth
, numArgsNeeded
);
3750 #ifdef GC_SANITYCHECK
3751 g
->gc
->SanityCheck();
3755 void doPrimitiveWithKeys(VMGlobals
* g
, PyrMethod
* meth
, int allArgsPushed
, int numKeyArgsPushed
)
3757 int i
, j
, m
, diff
, err
;
3758 PyrSlot
*pslot
, *qslot
;
3759 int numArgsNeeded
, numArgsPushed
;
3761 #ifdef GC_SANITYCHECK
3762 g
->gc
->SanityCheck();
3764 //post("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3765 //printf("doPrimitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name);
3767 PyrMethodRaw
*methraw
= METHRAW(meth
);
3768 int primIndex
= methraw
->specialIndex
;
3769 PrimitiveDef
*def
= gPrimitiveTable
.table
+ primIndex
;
3770 g
->primitiveIndex
= primIndex
- def
->base
;
3771 g
->primitiveMethod
= meth
;
3773 if (def
->keyArgs
&& numKeyArgsPushed
) {
3774 g
->numpop
= allArgsPushed
- 1;
3776 err
= ((PrimitiveWithKeysHandler
)def
[1].func
)(g
, allArgsPushed
, numKeyArgsPushed
);
3777 } catch (std::exception
& ex
) {
3778 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3782 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3785 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3787 //post("primerr %d\n", err);
3788 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3789 SetInt(&g
->thread
->primitiveError
, err
);
3790 executeMethodWithKeys(g
, meth
, allArgsPushed
, numKeyArgsPushed
);
3793 numArgsNeeded
= def
->numArgs
;
3794 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<< 1);
3796 if (numKeyArgsPushed
) {
3797 // evacuate keyword args to separate area
3798 pslot
= keywordstack
+ (numKeyArgsPushed
<<1);
3800 for (m
=0; m
<numKeyArgsPushed
; ++m
) {
3801 slotCopy(--pslot
, --qslot
);
3802 slotCopy(--pslot
, --qslot
);
3806 diff
= numArgsNeeded
- numArgsPushed
;
3807 if (diff
!= 0) { // incorrect num of args
3808 if (diff
> 0) { // not enough args
3809 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3810 pslot
= g
->sp
- diff
;
3811 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
3812 for (m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
3813 } else if (def
->varArgs
) { // has var args
3814 numArgsNeeded
= numArgsPushed
;
3815 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3817 g
->sp
+= numArgsNeeded
- allArgsPushed
; // remove excess args
3821 // do keyword lookup:
3822 if (numKeyArgsPushed
&& methraw
->posargs
) {
3823 PyrSymbol
**name0
, **name
;
3824 PyrSlot
*key
, *vars
;
3825 name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
3827 vars
= g
->sp
- numArgsNeeded
+ 1;
3828 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
3830 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
3831 if (*name
== slotRawSymbol(key
)) {
3832 slotCopy(&vars
[j
],&key
[1]);
3836 if (gKeywordError
) {
3837 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
3838 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3843 g
->numpop
= numArgsNeeded
- 1;
3845 err
= (*def
->func
)(g
, numArgsNeeded
);
3846 } catch (std::exception
& ex
) {
3847 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3851 post("caught exception in primitive %s:%s\n", slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
3854 if (err
<= errNone
) g
->sp
-= g
->numpop
;
3856 //post("primerr %d\n", err);
3857 SetInt(&g
->thread
->primitiveIndex
, methraw
->specialIndex
);
3858 SetInt(&g
->thread
->primitiveError
, err
);
3859 executeMethod(g
, meth
, numArgsNeeded
);
3862 #ifdef GC_SANITYCHECK
3863 g
->gc
->SanityCheck();
3867 void initPrimitives()
3871 initPrimitiveTable();
3874 base
= nextPrimitiveIndex();
3875 definePrimitive(base
, opNeg
, "_Neg", doSpecialUnaryArithMsg
, 1, 0);
3876 definePrimitive(base
, opBitNot
, "_BitNot", doSpecialUnaryArithMsg
, 1, 0);
3877 definePrimitive(base
, opAbs
, "_Abs", doSpecialUnaryArithMsg
, 1, 0);
3878 definePrimitive(base
, opAsFloat
, "_AsFloat", doSpecialUnaryArithMsg
, 1, 0);
3879 definePrimitive(base
, opAsInt
, "_AsInt", doSpecialUnaryArithMsg
, 1, 0);
3880 definePrimitive(base
, opCeil
, "_Ceil", doSpecialUnaryArithMsg
, 1, 0); // 5
3881 definePrimitive(base
, opFloor
, "_Floor", doSpecialUnaryArithMsg
, 1, 0);
3882 definePrimitive(base
, opFrac
, "_Frac", doSpecialUnaryArithMsg
, 1, 0);
3883 definePrimitive(base
, opSign
, "_Sign", doSpecialUnaryArithMsg
, 1, 0);
3884 definePrimitive(base
, opSquared
, "_Squared", doSpecialUnaryArithMsg
, 1, 0);
3885 definePrimitive(base
, opCubed
, "_Cubed", doSpecialUnaryArithMsg
, 1, 0); //10
3886 definePrimitive(base
, opSqrt
, "_Sqrt", doSpecialUnaryArithMsg
, 1, 0);
3887 definePrimitive(base
, opExp
, "_Exp", doSpecialUnaryArithMsg
, 1, 0);
3888 definePrimitive(base
, opRecip
, "_Recip", doSpecialUnaryArithMsg
, 1, 0);
3889 definePrimitive(base
, opMIDICPS
, "_MIDICPS", doSpecialUnaryArithMsg
, 1, 0);
3890 definePrimitive(base
, opCPSMIDI
, "_CPSMIDI", doSpecialUnaryArithMsg
, 1, 0); //15
3892 definePrimitive(base
, opMIDIRatio
, "_MIDIRatio", doSpecialUnaryArithMsg
, 1, 0);
3893 definePrimitive(base
, opRatioMIDI
, "_RatioMIDI", doSpecialUnaryArithMsg
, 1, 0);
3894 definePrimitive(base
, opDbAmp
, "_DbAmp", doSpecialUnaryArithMsg
, 1, 0);
3895 definePrimitive(base
, opAmpDb
, "_AmpDb", doSpecialUnaryArithMsg
, 1, 0);
3896 definePrimitive(base
, opOctCPS
, "_OctCPS", doSpecialUnaryArithMsg
, 1, 0);
3897 definePrimitive(base
, opCPSOct
, "_CPSOct", doSpecialUnaryArithMsg
, 1, 0);
3898 definePrimitive(base
, opLog
, "_Log", doSpecialUnaryArithMsg
, 1, 0);
3899 definePrimitive(base
, opLog2
, "_Log2", doSpecialUnaryArithMsg
, 1, 0);
3900 definePrimitive(base
, opLog10
, "_Log10", doSpecialUnaryArithMsg
, 1, 0);
3901 definePrimitive(base
, opSin
, "_Sin", doSpecialUnaryArithMsg
, 1, 0);
3902 definePrimitive(base
, opCos
, "_Cos", doSpecialUnaryArithMsg
, 1, 0);
3903 definePrimitive(base
, opTan
, "_Tan", doSpecialUnaryArithMsg
, 1, 0);
3904 definePrimitive(base
, opArcSin
, "_ArcSin", doSpecialUnaryArithMsg
, 1, 0);
3905 definePrimitive(base
, opArcCos
, "_ArcCos", doSpecialUnaryArithMsg
, 1, 0);
3906 definePrimitive(base
, opArcTan
, "_ArcTan", doSpecialUnaryArithMsg
, 1, 0);
3907 definePrimitive(base
, opSinH
, "_SinH", doSpecialUnaryArithMsg
, 1, 0);
3908 definePrimitive(base
, opCosH
, "_CosH", doSpecialUnaryArithMsg
, 1, 0);
3909 definePrimitive(base
, opTanH
, "_TanH", doSpecialUnaryArithMsg
, 1, 0);
3910 definePrimitive(base
, opRand
, "_Rand", doSpecialUnaryArithMsg
, 1, 0);
3911 definePrimitive(base
, opRand2
, "_Rand2", doSpecialUnaryArithMsg
, 1, 0);
3912 definePrimitive(base
, opLinRand
, "_LinRand", doSpecialUnaryArithMsg
, 1, 0);
3913 definePrimitive(base
, opBiLinRand
, "_BiLinRand", doSpecialUnaryArithMsg
, 1, 0);
3915 definePrimitive(base
, opSum3Rand
, "_Sum3Rand", doSpecialUnaryArithMsg
, 1, 0);
3916 // definePrimitive(base, opExpRand, "_ExpRand", doSpecialUnaryArithMsg, 1, 0);
3917 // definePrimitive(base, opBiExpRand, "_BiExpRand", doSpecialUnaryArithMsg, 1, 0);
3918 // definePrimitive(base, opGammaRand, "_GammaRand", doSpecialUnaryArithMsg, 1, 0);
3919 // definePrimitive(base, opGaussRand, "_GaussRand", doSpecialUnaryArithMsg, 1, 0);
3920 // definePrimitive(base, opPoiRand, "_PoiRand", doSpecialUnaryArithMsg, 1, 0);
3922 definePrimitive(base
, opDistort
, "_Distort", doSpecialUnaryArithMsg
, 1, 0);
3923 definePrimitive(base
, opSoftClip
, "_SoftClip", doSpecialUnaryArithMsg
, 1, 0);
3924 definePrimitive(base
, opCoin
, "_Coin", doSpecialUnaryArithMsg
, 1, 0);
3926 definePrimitive(base
, opRectWindow
, "_RectWindow", doSpecialUnaryArithMsg
, 1, 0);
3927 definePrimitive(base
, opHanWindow
, "_HanWindow", doSpecialUnaryArithMsg
, 1, 0);
3928 definePrimitive(base
, opWelchWindow
, "_WelchWindow", doSpecialUnaryArithMsg
, 1, 0);
3929 definePrimitive(base
, opTriWindow
, "_TriWindow", doSpecialUnaryArithMsg
, 1, 0);
3931 definePrimitive(base
, opSCurve
, "_SCurve", doSpecialUnaryArithMsg
, 1, 0);
3932 definePrimitive(base
, opRamp
, "_Ramp", doSpecialUnaryArithMsg
, 1, 0);
3934 definePrimitive(base
, opDigitValue
, "_DigitValue", doSpecialUnaryArithMsg
, 1, 0);
3938 base
= nextPrimitiveIndex();
3939 definePrimitive(base
, opAdd
, "_Add", prAddNum
, 2, 0);
3940 definePrimitive(base
, opSub
, "_Sub", prSubNum
, 2, 0);
3941 definePrimitive(base
, opMul
, "_Mul", prMulNum
, 2, 0);
3943 definePrimitive(base
, opIDiv
, "_IDiv", prSpecialBinaryArithMsg
, 3, 0);
3944 definePrimitive(base
, opFDiv
, "_FDiv", prSpecialBinaryArithMsg
, 3, 0);
3945 definePrimitive(base
, opMod
, "_Mod", prSpecialBinaryArithMsg
, 3, 0);
3946 definePrimitive(base
, opEQ
, "_EQ", prSpecialBinaryArithMsg
, 3, 0);
3947 definePrimitive(base
, opNE
, "_NE", prSpecialBinaryArithMsg
, 3, 0);
3948 definePrimitive(base
, opLT
, "_LT", prSpecialBinaryArithMsg
, 3, 0);
3949 definePrimitive(base
, opGT
, "_GT", prSpecialBinaryArithMsg
, 3, 0);
3950 definePrimitive(base
, opLE
, "_LE", prSpecialBinaryArithMsg
, 3, 0);
3951 definePrimitive(base
, opGE
, "_GE", prSpecialBinaryArithMsg
, 3, 0);
3952 //definePrimitive(base, opIdentical, "_Identical", prSpecialBinaryArithMsg, 3, 0);
3953 //definePrimitive(base, opNotIdentical, "_NotIdentical", prSpecialBinaryArithMsg, 3, 0);
3955 definePrimitive(base
, opMin
, "_Min", prSpecialBinaryArithMsg
, 3, 0);
3956 definePrimitive(base
, opMax
, "_Max", prSpecialBinaryArithMsg
, 3, 0);
3957 definePrimitive(base
, opBitAnd
, "_BitAnd", prSpecialBinaryArithMsg
, 3, 0);
3958 definePrimitive(base
, opBitOr
, "_BitOr", prSpecialBinaryArithMsg
, 3, 0);
3959 definePrimitive(base
, opBitXor
, "_BitXor", prSpecialBinaryArithMsg
, 3, 0);
3960 definePrimitive(base
, opLCM
, "_LCM", prSpecialBinaryArithMsg
, 3, 0);
3961 definePrimitive(base
, opGCD
, "_GCD", prSpecialBinaryArithMsg
, 3, 0);
3962 definePrimitive(base
, opRound
, "_Round", prSpecialBinaryArithMsg
, 3, 0);
3963 definePrimitive(base
, opRoundUp
, "_RoundUp", prSpecialBinaryArithMsg
, 3, 0);
3964 definePrimitive(base
, opTrunc
, "_Trunc", prSpecialBinaryArithMsg
, 3, 0);
3965 definePrimitive(base
, opAtan2
, "_Atan2", prSpecialBinaryArithMsg
, 3, 0);
3966 definePrimitive(base
, opHypot
, "_Hypot", prSpecialBinaryArithMsg
, 3, 0);
3967 definePrimitive(base
, opHypotx
, "_HypotApx", prSpecialBinaryArithMsg
, 3, 0);
3968 definePrimitive(base
, opPow
, "_Pow", prSpecialBinaryArithMsg
, 3, 0);
3969 definePrimitive(base
, opShiftLeft
, "_ShiftLeft", prSpecialBinaryArithMsg
, 3, 0);
3970 definePrimitive(base
, opShiftRight
, "_ShiftRight", prSpecialBinaryArithMsg
, 3, 0);
3971 definePrimitive(base
, opUnsignedShift
, "_UnsignedShift", prSpecialBinaryArithMsg
, 3, 0);
3972 definePrimitive(base
, opFill
, "_Fill", prSpecialBinaryArithMsg
, 3, 0);
3973 definePrimitive(base
, opRing1
, "_Ring1", prSpecialBinaryArithMsg
, 3, 0); // a * (b + 1) == a * b + a
3974 definePrimitive(base
, opRing2
, "_Ring2", prSpecialBinaryArithMsg
, 3, 0); // a * b + a + b
3975 definePrimitive(base
, opRing3
, "_Ring3", prSpecialBinaryArithMsg
, 3, 0); // a*a*b
3976 definePrimitive(base
, opRing4
, "_Ring4", prSpecialBinaryArithMsg
, 3, 0); // a*a*b - a*b*b
3977 definePrimitive(base
, opDifSqr
, "_DifSqr", prSpecialBinaryArithMsg
, 3, 0); // a*a - b*b
3978 definePrimitive(base
, opSumSqr
, "_SumSqr", prSpecialBinaryArithMsg
, 3, 0); // a*a + b*b
3979 definePrimitive(base
, opSqrSum
, "_SqrSum", prSpecialBinaryArithMsg
, 3, 0); // (a + b)^2
3980 definePrimitive(base
, opSqrDif
, "_SqrDif", prSpecialBinaryArithMsg
, 3, 0); // (a - b)^2
3981 definePrimitive(base
, opAbsDif
, "_AbsDif", prSpecialBinaryArithMsg
, 3, 0); // abs(a - b)
3982 definePrimitive(base
, opThresh
, "_Thresh", prSpecialBinaryArithMsg
, 3, 0); // a * max(0,b)
3983 definePrimitive(base
, opAMClip
, "_AMClip", prSpecialBinaryArithMsg
, 3, 0); // a * max(0,b)
3984 definePrimitive(base
, opScaleNeg
, "_ScaleNeg", prSpecialBinaryArithMsg
, 3, 0); // a < 0 ? a*b : a
3985 definePrimitive(base
, opClip2
, "_Clip2", prSpecialBinaryArithMsg
, 3, 0);
3986 definePrimitive(base
, opFold2
, "_Fold2", prSpecialBinaryArithMsg
, 3, 0);
3987 definePrimitive(base
, opWrap2
, "_Wrap2", prSpecialBinaryArithMsg
, 3, 0);
3988 definePrimitive(base
, opExcess
, "_Excess", prSpecialBinaryArithMsg
, 3, 0);
3989 definePrimitive(base
, opFirstArg
, "_FirstArg", prSpecialBinaryArithMsg
, 3, 0);
3990 definePrimitive(base
, opRandRange
, "_RandRange", prSpecialBinaryArithMsg
, 3, 0);
3991 definePrimitive(base
, opExpRandRange
, "_ExpRandRange", prSpecialBinaryArithMsg
, 3, 0);
3993 // general primitives
3994 base
= nextPrimitiveIndex();
3996 definePrimitive(base
, index
++, "_Halt", haltInterpreter
, 1, 0);
3997 definePrimitive(base
, index
++, "_InstVarAt", instVarAt
, 2, 0);
3998 definePrimitive(base
, index
++, "_InstVarPut", instVarPut
, 3, 0);
3999 definePrimitive(base
, index
++, "_InstVarSize", instVarSize
, 1, 0);
4000 definePrimitive(base
, index
++, "_ObjectHash", objectHash
, 1, 0);
4001 definePrimitive(base
, index
++, "_ObjectClass", objectClass
, 1, 0);
4002 definePrimitive(base
, index
++, "_BasicNew", basicNew
, 2, 0);
4003 definePrimitive(base
, index
++, "_BasicNewClear", basicNewClear
, 2, 0);
4004 definePrimitive(base
, index
++, "_BasicNewCopyArgsToInstVars", basicNewCopyArgsToInstanceVars
, 1, 1);
4005 //definePrimitive(base, index++, "_BasicNewCopyArgsByName", basicNewCopyArgsByName, 1, 1);
4007 definePrimitiveWithKeys(base
, index
, "_FunctionValue", blockValue
, blockValueWithKeys
, 1, 1);
4009 definePrimitiveWithKeys(base
, index
, "_FunctionValueEnvir", blockValueEnvir
, blockValueEnvirWithKeys
, 1, 1);
4012 definePrimitive(base
, index
++, "_FunctionValueArray", blockValueArray
, 1, 1);
4013 definePrimitive(base
, index
++, "_FunctionValueArrayEnvir", blockValueArrayEnvir
, 1, 1);
4014 definePrimitive(base
, index
++, "_FunctionDefAsFunction", prFunctionDefAsFunction
, 1, 0);
4015 definePrimitive(base
, index
++, "_FunctionDefDumpContexts", prFunctionDefDumpContexts
, 1, 0);
4016 definePrimitive(base
, index
++, "_FunctionDefIsClosed", prFunctionDefIsClosed
, 1, 0);
4017 definePrimitive(base
, index
++, "_FunctionDefIsWithinClosed", prFunctionDefIsWithinClosed
, 1, 0);
4019 definePrimitive(base
, index
++, "_ObjectIsKindOf", objectIsKindOf
, 2, 0);
4020 definePrimitive(base
, index
++, "_ObjectIsMemberOf", objectIsMemberOf
, 2, 0);
4021 definePrimitive(base
, index
++, "_ObjectDump", objectDump
, 1, 0);
4022 definePrimitive(base
, index
++, "_TotalFree", prTotalFree
, 1, 0);
4023 definePrimitive(base
, index
++, "_LargestFreeBlock", prLargestFreeBlock
, 1, 0);
4025 definePrimitive(base
, index
++, "_GCInfo", dumpGCinfo
, 1, 0);
4026 definePrimitive(base
, index
++, "_GCDumpGrey", dumpGCdumpGrey
, 1, 0);
4027 definePrimitive(base
, index
++, "_GCDumpSet", dumpGCdumpSet
, 2, 0);
4028 definePrimitive(base
, index
++, "_GCSanity", prGCSanity
, 1, 0);
4030 definePrimitive(base
, index
++, "_TraceAllPathsTo", prTraceAllPathsTo
, 1, 0);
4031 definePrimitive(base
, index
++, "_TraceAnyPathsTo", prTraceAnyPathsTo
, 1, 0);
4032 definePrimitive(base
, index
++, "_TraceAnyPathToAllInstancesOf", prTraceAnyPathToAllInstancesOf
, 1, 0);
4035 definePrimitive(base
, index
++, "_Identical", objectIdentical
, 2, 0);
4036 definePrimitive(base
, index
++, "_NotIdentical", objectNotIdentical
, 2, 0);
4037 definePrimitiveWithKeys(base
, index
, "_ObjectPerform", objectPerform
, objectPerformWithKeys
, 2, 1);
4039 definePrimitive(base
, index
++, "_ObjectPerformList", objectPerformList
, 2, 1);
4040 definePrimitiveWithKeys(base
, index
, "_SuperPerform", objectSuperPerform
, objectSuperPerformWithKeys
, 2, 1);
4042 definePrimitive(base
, index
++, "_SuperPerformList", objectSuperPerformList
, 2, 1);
4043 definePrimitive(base
, index
++, "_ObjectPerformMsg", objectPerformSelList
, 2, 0);
4044 //definePrimitive(base, index++, "_ArrayPerformMsg", arrayPerformMsg, 1, 1);
4045 definePrimitive(base
, index
++, "_ObjectString", prObjectString
, 1, 0);
4046 definePrimitive(base
, index
++, "_Float_AsStringPrec", prFloat_AsStringPrec
, 2, 0);
4047 definePrimitive(base
, index
++, "_ObjectCompileString", prAsCompileString
, 1, 0);
4048 definePrimitive(base
, index
++, "_ClassString", prClassString
, 1, 0);
4049 definePrimitive(base
, index
++, "_PostString", prPostString
, 1, 0);
4050 definePrimitive(base
, index
++, "_PostLine", prPostLine
, 1, 0);
4051 definePrimitive(base
, index
++, "_HostDebugger", prDebugger
, 1, 0);
4052 definePrimitive(base
, index
++, "_Trace", prTraceOn
, 1, 0);
4053 definePrimitive(base
, index
++, "_CanCallOS", prCanCallOS
, 1, 0);
4054 definePrimitive(base
, index
++, "_KeywordError", prKeywordError
, 1, 0);
4055 definePrimitive(base
, index
++, "_GetTailCallOptimize", prGetTailCallOptimize
, 1, 0);
4056 definePrimitive(base
, index
++, "_SetTailCallOptimize", prSetTailCallOptimize
, 2, 0);
4059 definePrimitive(base
, index
++, "_PrimitiveError", prPrimitiveError
, 1, 0);
4060 definePrimitive(base
, index
++, "_PrimitiveErrorString", prPrimitiveErrorString
, 1, 0);
4061 definePrimitive(base
, index
++, "_DumpStack", prDumpStack
, 1, 0);
4062 definePrimitive(base
, index
++, "_DumpDetailedBackTrace", prDumpDetailedBackTrace
, 1, 0);
4063 definePrimitive(base
, index
++, "_StackDepth", prStackDepth
, 1, 0);
4064 definePrimitive(base
, index
++, "_PrimName", prPrimName
, 1, 0);
4065 definePrimitive(base
, index
++, "_ObjectShallowCopy", prObjectShallowCopy
, 1, 0);
4066 definePrimitive(base
, index
++, "_ObjectCopyImmutable", prObjectCopyImmutable
, 1, 0);
4067 definePrimitive(base
, index
++, "_ObjectCopyRange", prObjectCopyRange
, 3, 0);
4068 definePrimitive(base
, index
++, "_ObjectCopySeries", prObjectCopySeries
, 4, 0);
4069 definePrimitive(base
, index
++, "_ObjectPointsTo", prObjectPointsTo
, 2, 0);
4070 definePrimitive(base
, index
++, "_ObjectRespondsTo", prObjectRespondsTo
, 2, 0);
4071 definePrimitive(base
, index
++, "_ObjectIsMutable", prObjectIsMutable
, 1, 0);
4072 definePrimitive(base
, index
++, "_ObjectIsPermanent", prObjectIsPermanent
, 1, 0);
4073 definePrimitive(base
, index
++, "_ObjectDeepFreeze", prDeepFreeze
, 1, 0);
4074 definePrimitive(base
, index
++, "_ObjectDeepCopy", prDeepCopy
, 1, 0);
4077 definePrimitive(base
, index
++, "_CompileExpression", prCompileString
, 2, 0);
4079 definePrimitive(base
, index
++, "_GetBackTrace", prGetBackTrace
, 1, 0);
4080 definePrimitive(base
, index
++, "_DumpBackTrace", prDumpBackTrace
, 1, 0);
4081 definePrimitive(base
, index
++, "_DumpByteCodes", prDumpByteCodes
, 1, 0);
4083 definePrimitive(base
, index
++, "_AllClasses", prAllClasses
, 1, 0);
4084 definePrimitive(base
, index
++, "_DumpClassSubtree", prPostClassTree
, 1, 0);
4086 // definePrimitive(base, index++, "_TabletTracking", prTabletTracking, 1, 0);
4088 definePrimitive(base
, index
++, "_FunDef_NumArgs", prFunDef_NumArgs
, 1, 0);
4089 definePrimitive(base
, index
++, "_FunDef_NumVars", prFunDef_NumVars
, 1, 0);
4090 definePrimitive(base
, index
++, "_FunDef_VarArgs", prFunDef_VarArgs
, 1, 0);
4092 definePrimitive(base
, index
++, "_Thread_Init", prThreadInit
, 3, 0);
4093 definePrimitive(base
, index
++, "_Thread_RandSeed", prThreadRandSeed
, 2, 0);
4094 definePrimitive(base
, index
++, "_Thread_GetRandData", prThreadGetRandData
, 1, 0);
4095 definePrimitive(base
, index
++, "_Thread_SetRandData", prThreadSetRandData
, 2, 0);
4096 // definePrimitive(base, index++, "_ThreadRun", prThreadRun, 2, 0);
4097 // definePrimitive(base, index++, "_RunNextThread", prRunNextThread, 1, 0);
4098 definePrimitive(base
, index
++, "_RoutineYield", prRoutineYield
, 1, 0);
4099 definePrimitive(base
, index
++, "_RoutineAlwaysYield", prRoutineAlwaysYield
, 1, 0);
4100 definePrimitive(base
, index
++, "_RoutineResume", prRoutineResume
, 2, 0);
4101 definePrimitive(base
, index
++, "_RoutineReset", prRoutineReset
, 1, 0);
4102 definePrimitive(base
, index
++, "_RoutineYieldAndReset", prRoutineYieldAndReset
, 2, 0);
4103 definePrimitive(base
, index
++, "_RoutineStop", prRoutineStop
, 1, 0);
4105 // definePrimitive(base, index++, "_IsDemo", prIsDemo, 1, 0);
4106 definePrimitive(base
, index
++, "_Blork", prBlork
, 1, 0);
4107 definePrimitive(base
, index
++, "_UGenCodeString", prUGenCodeString
, 5, 0);
4108 definePrimitive(base
, index
++, "_MainOverwriteMsg", prOverwriteMsg
, 1, 0);
4110 definePrimitive(base
, index
++, "_AppClock_SchedNotify", prAppClockSchedNotify
, 1, 0);
4111 definePrimitive(base
, index
++, "_LanguageConfig_getIncludePaths", prLanguageConfig_getIncludePaths
, 1, 0);
4112 definePrimitive(base
, index
++, "_LanguageConfig_getExcludePaths", prLanguageConfig_getExcludePaths
, 1, 0);
4113 definePrimitive(base
, index
++, "_LanguageConfig_addIncludePath", prLanguageConfig_addIncludePath
, 2, 0);
4114 definePrimitive(base
, index
++, "_LanguageConfig_addExcludePath", prLanguageConfig_addExcludePath
, 2, 0);
4115 definePrimitive(base
, index
++, "_LanguageConfig_removeIncludePath", prLanguageConfig_removeIncludePath
, 2, 0);
4116 definePrimitive(base
, index
++, "_LanguageConfig_removeExcludePath", prLanguageConfig_removeExcludePath
, 2, 0);
4117 definePrimitive(base
, index
++, "_LanguageConfig_writeConfigFile", prLanguageConfig_writeConfigFile
, 2, 0);
4118 definePrimitive(base
, index
++, "_LanguageConfig_getPostInlineWarnings", prLanguageConfig_getPostInlineWarnings
, 1, 0);
4119 definePrimitive(base
, index
++, "_LanguageConfig_setPostInlineWarnings", prLanguageConfig_setPostInlineWarnings
, 2, 0);
4121 //void initOscilPrimitives();
4122 //void initControllerPrimitives();
4124 //initOscilPrimitives();
4125 //initControllerPrimitives();
4126 initMathPrimitives();
4127 initSignalPrimitives();
4128 initArrayPrimitives();
4130 void initSymbolPrimitives();
4131 initSymbolPrimitives();
4133 void initArchiverPrimitives();
4134 initArchiverPrimitives();
4136 void initArrayPrimitives();
4137 initArrayPrimitives();
4139 void initBitPrimitives();
4140 initBitPrimitives();
4142 void initCharPrimitives();
4143 initCharPrimitives();
4145 void initFilePrimitives();
4146 initFilePrimitives();
4148 void initPlatformPrimitives();
4149 initPlatformPrimitives();
4151 void initStringPrimitives();
4152 initStringPrimitives();
4154 void initListPrimitives();
4155 initListPrimitives();
4158 void initUnixPrimitives();
4159 initUnixPrimitives();
4161 void init_OSC_primitives();
4162 init_OSC_primitives();
4164 /* these probably should be moved out of the Lang code
4165 into an App init primitives section */
4166 void initGUIPrimitives();
4167 initGUIPrimitives();
4169 void initSCViewPrimitives();
4170 initSCViewPrimitives();
4172 void initSchedPrimitives();
4173 initSchedPrimitives();
4175 #if defined(__APPLE__) || defined(HAVE_ALSA) || defined(HAVE_PORTMIDI)
4176 void initMIDIPrimitives();
4177 initMIDIPrimitives();
4180 #if !defined(SC_WIN32) && !defined(SC_IPHONE)
4181 void initHIDPrimitives();
4182 initHIDPrimitives();
4184 void initSpeechPrimitives();
4185 initSpeechPrimitives();
4187 void initCocoaFilePrimitives();
4188 initCocoaFilePrimitives();
4190 void initCocoaBridgePrimitives();
4191 initCocoaBridgePrimitives();
4193 void initSerialPrimitives();
4194 initSerialPrimitives();
4196 void initWiiPrimitives();
4197 initWiiPrimitives();
4201 void initCoreAudioPrimitives();
4202 initCoreAudioPrimitives();
4206 void initRendezvousPrimitives();
4207 initRendezvousPrimitives();
4209 #ifdef SCOGL_COMPILE
4210 void initOpenGLPrimitives();
4211 initOpenGLPrimitives();
4215 QtCollider::initPrimitives();
4219 void initScIDEPrimitives();
4220 initScIDEPrimitives();
4223 initSCDocPrimitives();
4225 s_recvmsg
= getsym("receiveMsg");
4226 post("\tNumPrimitives = %d\n", nextPrimitiveIndex());
4234 s_prrunnextthread
= getsym("prRunNextThread");
4235 s_prready
= getsym("prReady");