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
21 #include "PyrMessage.h"
22 #include "PyrPrimitiveProto.h"
23 #include "PyrInterpreter.h"
24 #include "PyrPrimitive.h"
25 #include "PyrListPrim.h"
26 #include "PyrSymbol.h"
31 #include "PredefinedSymbols.h"
32 #include "PyrObjectProto.h"
35 #define DEBUGMETHODS 0
38 PyrMethod
**gRowTable
;
40 PyrSlot keywordstack
[MAXKEYSLOTS
];
41 bool gKeywordError
= true;
42 extern bool gTraceInterpreter
;
44 long cvxUniqueMethods
;
45 extern int ivxIdentDict_array
;
47 void StoreToImmutableB(VMGlobals
*g
, PyrSlot
*& sp
, unsigned char *& ip
);
49 void initUniqueMethods()
52 cvxUniqueMethods
= classVarOffset("Object", "uniqueMethods", &dummyclass
);
55 void sendMessageWithKeys(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
, long numKeyArgsPushed
)
57 PyrMethod
*meth
= NULL
;
58 PyrMethodRaw
*methraw
;
59 PyrSlot
*recvrSlot
, *sp
;
64 //postfl("->sendMessage\n");
67 CallStackSanity(g
, "sendMessageWithKeys");
69 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
71 classobj
= classOfSlot(recvrSlot
);
74 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
75 meth
= gRowTable
[index
];
77 if (slotRawSymbol(&meth
->name
) != selector
) {
78 doesNotUnderstandWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
80 methraw
= METHRAW(meth
);
81 //postfl("methraw->methType %d\n", methraw->methType);
82 switch (methraw
->methType
) {
83 case methNormal
: /* normal msg send */
84 executeMethodWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
86 case methReturnSelf
: /* return self */
87 g
->sp
-= numArgsPushed
- 1;
89 case methReturnLiteral
: /* return literal */
90 sp
= g
->sp
-= numArgsPushed
- 1;
91 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
93 case methReturnArg
: /* return an argument */
94 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
96 g
->sp
-= numArgsPushed
- 1;
98 index
= methraw
->specialIndex
; // zero is index of the first argument
99 if (index
< numArgsPushed
) {
100 slotCopy(sp
, sp
+ index
);
102 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
105 case methReturnInstVar
: /* return inst var */
106 sp
= g
->sp
-= numArgsPushed
- 1;
107 index
= methraw
->specialIndex
;
108 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
110 case methAssignInstVar
: /* assign inst var */
111 sp
= g
->sp
-= numArgsPushed
- 1;
112 index
= methraw
->specialIndex
;
113 obj
= slotRawObject(recvrSlot
);
114 if (obj
->obj_flags
& obj_immutable
) { StoreToImmutableB(g
, sp
, g
->ip
); }
116 if (numArgsPushed
>= 2) {
117 slotCopy(&obj
->slots
[index
], sp
+ 1);
118 g
->gc
->GCWrite(obj
, sp
+ 1);
120 SetNil(&obj
->slots
[index
]);
122 slotCopy(sp
, recvrSlot
);
125 case methReturnClassVar
: /* return class var */
126 sp
= g
->sp
-= numArgsPushed
- 1;
127 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
129 case methAssignClassVar
: /* assign class var */
130 sp
= g
->sp
-= numArgsPushed
- 1;
131 if (numArgsPushed
>= 2) {
132 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
133 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
135 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
137 slotCopy(sp
, recvrSlot
);
139 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
140 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
141 numKeyArgsPushed
= 0;
142 selector
= slotRawSymbol(&meth
->selectors
);
144 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
145 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
146 numKeyArgsPushed
= 0;
147 selector
= slotRawSymbol(&meth
->selectors
);
148 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
150 case methForwardInstVar
: /* forward to an instance variable */
151 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
152 numKeyArgsPushed
= 0;
153 selector
= slotRawSymbol(&meth
->selectors
);
154 index
= methraw
->specialIndex
;
155 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
157 classobj
= classOfSlot(recvrSlot
);
160 case methForwardClassVar
: /* forward to a class variable */
161 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
162 numKeyArgsPushed
= 0;
163 selector
= slotRawSymbol(&meth
->selectors
);
164 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
166 classobj
= classOfSlot(recvrSlot
);
169 case methPrimitive
: /* primitive */
170 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
171 #ifdef GC_SANITYCHECK
172 g
->gc
->SanityCheck();
180 #ifdef GC_SANITYCHECK
181 g
->gc
->SanityCheck();
182 CallStackSanity(g
, "<sendMessageWithKeys");
184 //postfl("<-sendMessage\n");
188 void sendMessage(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
)
190 PyrMethod
*meth
= NULL
;
191 PyrMethodRaw
*methraw
;
192 PyrSlot
*recvrSlot
, *sp
;
197 //postfl("->sendMessage\n");
198 #ifdef GC_SANITYCHECK
199 g
->gc
->SanityCheck();
200 CallStackSanity(g
, "sendMessage");
202 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
204 classobj
= classOfSlot(recvrSlot
);
207 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
208 meth
= gRowTable
[index
];
210 if (slotRawSymbol(&meth
->name
) != selector
) {
211 doesNotUnderstand(g
, selector
, numArgsPushed
);
213 methraw
= METHRAW(meth
);
214 //postfl("methraw->methType %d\n", methraw->methType);
215 switch (methraw
->methType
) {
216 case methNormal
: /* normal msg send */
217 executeMethod(g
, meth
, numArgsPushed
);
219 case methReturnSelf
: /* return self */
220 g
->sp
-= numArgsPushed
- 1;
222 case methReturnLiteral
: /* return literal */
223 sp
= g
->sp
-= numArgsPushed
- 1;
224 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
226 case methReturnArg
: /* return an argument */
227 sp
= g
->sp
-= numArgsPushed
- 1;
228 index
= methraw
->specialIndex
; // zero is index of the first argument
229 if (index
< numArgsPushed
) {
230 slotCopy(sp
, sp
+ index
);
232 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
235 case methReturnInstVar
: /* return inst var */
236 sp
= g
->sp
-= numArgsPushed
- 1;
237 index
= methraw
->specialIndex
;
238 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
240 case methAssignInstVar
: /* assign inst var */
241 sp
= g
->sp
-= numArgsPushed
- 1;
242 index
= methraw
->specialIndex
;
243 obj
= slotRawObject(recvrSlot
);
244 if (obj
->obj_flags
& obj_immutable
) { StoreToImmutableB(g
, sp
, g
->ip
); }
246 if (numArgsPushed
>= 2) {
247 slotCopy(&obj
->slots
[index
], sp
+ 1);
248 g
->gc
->GCWrite(obj
, sp
+ 1);
250 SetNil(&obj
->slots
[index
]);
252 slotCopy(sp
, recvrSlot
);
255 case methReturnClassVar
: /* return class var */
256 sp
= g
->sp
-= numArgsPushed
- 1;
257 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
259 case methAssignClassVar
: /* assign class var */
260 sp
= g
->sp
-= numArgsPushed
- 1;
261 if (numArgsPushed
>= 2) {
262 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
263 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
265 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
267 slotCopy(sp
, recvrSlot
);
269 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
270 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
271 /* push default arg values */
272 PyrSlot
*pslot
, *qslot
;
275 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
276 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
277 numArgsPushed
= methraw
->numargs
;
280 selector
= slotRawSymbol(&meth
->selectors
);
282 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
283 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
284 /* push default arg values */
285 PyrSlot
*pslot
, *qslot
;
288 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
289 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
290 numArgsPushed
= methraw
->numargs
;
293 selector
= slotRawSymbol(&meth
->selectors
);
294 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
296 case methForwardInstVar
: /* forward to an instance variable */
297 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
298 /* push default arg values */
299 PyrSlot
*pslot
, *qslot
;
302 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
303 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
304 numArgsPushed
= methraw
->numargs
;
307 selector
= slotRawSymbol(&meth
->selectors
);
308 index
= methraw
->specialIndex
;
309 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
311 classobj
= classOfSlot(recvrSlot
);
314 case methForwardClassVar
: /* forward to a class variable */
315 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
316 /* push default arg values */
317 PyrSlot
*pslot
, *qslot
;
320 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
321 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
322 numArgsPushed
= methraw
->numargs
;
325 selector
= slotRawSymbol(&meth
->selectors
);
326 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
328 classobj
= classOfSlot(recvrSlot
);
331 case methPrimitive
: /* primitive */
332 doPrimitive(g
, meth
, numArgsPushed
);
333 #ifdef GC_SANITYCHECK
334 g
->gc
->SanityCheck();
338 case methMultDispatchByClass : {
339 index = methraw->specialIndex;
340 if (index < numArgsPushed) {
341 classobj = slotRawObject(sp + index)->classptr;
342 selector = slotRawSymbol(&meth->selectors);
345 doesNotUnderstand(g, selector, numArgsPushed);
348 case methMultDispatchByValue : {
349 index = methraw->specialIndex;
350 if (index < numArgsPushed) {
351 index = arrayAtIdentityHashInPairs(array, b);
352 meth = slotRawObject(&meth->selectors)->slots[index + 1].uom;
353 goto meth_select_again;
355 doesNotUnderstand(g, selector, numArgsPushed);
365 #ifdef GC_SANITYCHECK
366 g
->gc
->SanityCheck();
367 CallStackSanity(g
, "<sendMessage");
369 //postfl("<-sendMessage\n");
373 void sendSuperMessageWithKeys(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
, long numKeyArgsPushed
)
375 PyrMethod
*meth
= NULL
;
376 PyrMethodRaw
*methraw
;
377 PyrSlot
*recvrSlot
, *sp
;
382 //postfl("->sendMessage\n");
383 #ifdef GC_SANITYCHECK
384 g
->gc
->SanityCheck();
385 CallStackSanity(g
, "sendSuperMessageWithKeys");
387 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
389 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
390 //assert(isKindOfSlot(recvrSlot, classobj));
393 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
394 meth
= gRowTable
[index
];
396 if (slotRawSymbol(&meth
->name
) != selector
) {
397 doesNotUnderstandWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
399 methraw
= METHRAW(meth
);
400 //postfl("methraw->methType %d\n", methraw->methType);
401 switch (methraw
->methType
) {
402 case methNormal
: /* normal msg send */
403 executeMethodWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
405 case methReturnSelf
: /* return self */
406 g
->sp
-= numArgsPushed
- 1;
408 case methReturnLiteral
: /* return literal */
409 sp
= g
->sp
-= numArgsPushed
- 1;
410 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
412 case methReturnArg
: /* return an argument */
413 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
414 numKeyArgsPushed
= 0;
415 g
->sp
-= numArgsPushed
- 1;
417 index
= methraw
->specialIndex
; // zero is index of the first argument
418 if (index
< numArgsPushed
) {
419 slotCopy(sp
, sp
+ index
);
421 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
424 case methReturnInstVar
: /* return inst var */
425 sp
= g
->sp
-= numArgsPushed
- 1;
426 index
= methraw
->specialIndex
;
427 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
429 case methAssignInstVar
: /* assign inst var */
430 sp
= g
->sp
-= numArgsPushed
- 1;
431 index
= methraw
->specialIndex
;
432 obj
= slotRawObject(recvrSlot
);
433 if (obj
->obj_flags
& obj_immutable
) { StoreToImmutableB(g
, sp
, g
->ip
); }
435 if (numArgsPushed
>= 2) {
436 slotCopy(&obj
->slots
[index
], sp
+ 1);
437 g
->gc
->GCWrite(obj
, sp
+ 1);
439 SetNil(&obj
->slots
[index
]);
441 slotCopy(sp
, recvrSlot
);
444 case methReturnClassVar
: /* return class var */
445 sp
= g
->sp
-= numArgsPushed
- 1;
446 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
448 case methAssignClassVar
: /* assign class var */
449 sp
= g
->sp
-= numArgsPushed
- 1;
450 if (numArgsPushed
>= 2) {
451 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
452 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
454 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
456 slotCopy(sp
, recvrSlot
);
458 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
459 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
460 numKeyArgsPushed
= 0;
461 selector
= slotRawSymbol(&meth
->selectors
);
463 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
464 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
465 numKeyArgsPushed
= 0;
466 selector
= slotRawSymbol(&meth
->selectors
);
467 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
469 case methForwardInstVar
: /* forward to an instance variable */
470 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
471 numKeyArgsPushed
= 0;
472 selector
= slotRawSymbol(&meth
->selectors
);
473 index
= methraw
->specialIndex
;
474 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
476 classobj
= classOfSlot(recvrSlot
);
479 case methForwardClassVar
: /* forward to a class variable */
480 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
481 numKeyArgsPushed
= 0;
482 selector
= slotRawSymbol(&meth
->selectors
);
483 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
485 classobj
= classOfSlot(recvrSlot
);
488 case methPrimitive
: /* primitive */
489 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
490 #ifdef GC_SANITYCHECK
491 g
->gc
->SanityCheck();
499 #ifdef GC_SANITYCHECK
500 g
->gc
->SanityCheck();
501 CallStackSanity(g
, "<sendSuperMessageWithKeys");
503 //postfl("<-sendMessage\n");
507 void sendSuperMessage(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
)
509 PyrMethod
*meth
= NULL
;
510 PyrMethodRaw
*methraw
;
511 PyrSlot
*recvrSlot
, *sp
;
516 //postfl("->sendMessage\n");
517 #ifdef GC_SANITYCHECK
518 g
->gc
->SanityCheck();
519 CallStackSanity(g
, "sendSuperMessage");
521 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
523 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
524 //assert(isKindOfSlot(recvrSlot, classobj));
527 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
528 meth
= gRowTable
[index
];
530 if (slotRawSymbol(&meth
->name
) != selector
) {
531 doesNotUnderstand(g
, selector
, numArgsPushed
);
533 methraw
= METHRAW(meth
);
534 //postfl("methraw->methType %d\n", methraw->methType);
535 switch (methraw
->methType
) {
536 case methNormal
: /* normal msg send */
537 executeMethod(g
, meth
, numArgsPushed
);
539 case methReturnSelf
: /* return self */
540 g
->sp
-= numArgsPushed
- 1;
542 case methReturnLiteral
: /* return literal */
543 sp
= g
->sp
-= numArgsPushed
- 1;
544 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
546 case methReturnArg
: /* return an argument */
547 sp
= g
->sp
-= numArgsPushed
- 1;
548 index
= methraw
->specialIndex
; // zero is index of the first argument
549 if (index
< numArgsPushed
) {
550 slotCopy(sp
, sp
+ index
);
552 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
555 case methReturnInstVar
: /* return inst var */
556 sp
= g
->sp
-= numArgsPushed
- 1;
557 index
= methraw
->specialIndex
;
558 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
560 case methAssignInstVar
: /* assign inst var */
561 sp
= g
->sp
-= numArgsPushed
- 1;
562 index
= methraw
->specialIndex
;
563 obj
= slotRawObject(recvrSlot
);
564 if (obj
->obj_flags
& obj_immutable
) { StoreToImmutableB(g
, sp
, g
->ip
); }
566 if (numArgsPushed
>= 2) {
567 slotCopy(&obj
->slots
[index
], sp
+ 1);
568 g
->gc
->GCWrite(obj
, sp
+ 1);
570 SetNil(&obj
->slots
[index
]);
572 slotCopy(sp
, recvrSlot
);
575 case methReturnClassVar
: /* return class var */
576 sp
= g
->sp
-= numArgsPushed
- 1;
577 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
579 case methAssignClassVar
: /* assign class var */
580 sp
= g
->sp
-= numArgsPushed
- 1;
581 if (numArgsPushed
>= 2) {
582 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
583 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
585 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
587 slotCopy(sp
, recvrSlot
);
589 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
590 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
591 /* push default arg values */
592 PyrSlot
*pslot
, *qslot
;
595 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
596 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
597 numArgsPushed
= methraw
->numargs
;
600 selector
= slotRawSymbol(&meth
->selectors
);
602 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
603 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
604 /* push default arg values */
605 PyrSlot
*pslot
, *qslot
;
608 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
609 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
610 numArgsPushed
= methraw
->numargs
;
613 selector
= slotRawSymbol(&meth
->selectors
);
614 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
616 case methForwardInstVar
: /* forward to an instance variable */
617 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
618 /* push default arg values */
619 PyrSlot
*pslot
, *qslot
;
622 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
623 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
624 numArgsPushed
= methraw
->numargs
;
627 selector
= slotRawSymbol(&meth
->selectors
);
628 index
= methraw
->specialIndex
;
629 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
631 classobj
= classOfSlot(recvrSlot
);
634 case methForwardClassVar
: /* forward to a class variable */
635 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
636 /* push default arg values */
637 PyrSlot
*pslot
, *qslot
;
640 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
641 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
642 numArgsPushed
= methraw
->numargs
;
645 selector
= slotRawSymbol(&meth
->selectors
);
646 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
648 classobj
= classOfSlot(recvrSlot
);
651 case methPrimitive
: /* primitive */
652 doPrimitive(g
, meth
, numArgsPushed
);
653 #ifdef GC_SANITYCHECK
654 g
->gc
->SanityCheck();
658 case methMultDispatchByClass : {
659 index = methraw->specialIndex;
660 if (index < numArgsPushed) {
661 classobj = slotRawObject(sp + index)->classptr;
662 selector = slotRawSymbol(&meth->selectors);
665 doesNotUnderstand(g, selector, numArgsPushed);
668 case methMultDispatchByValue : {
669 index = methraw->specialIndex;
670 if (index < numArgsPushed) {
671 index = arrayAtIdentityHashInPairs(array, b);
672 meth = slotRawObject(&meth->selectors)->slots[index + 1].uom;
673 goto meth_select_again;
675 doesNotUnderstand(g, selector, numArgsPushed);
685 #ifdef GC_SANITYCHECK
686 g
->gc
->SanityCheck();
687 CallStackSanity(g
, "<sendSuperMessage");
689 //postfl("<-sendMessage\n");
693 extern PyrClass
*class_identdict
;
694 void doesNotUnderstandWithKeys(VMGlobals
*g
, PyrSymbol
*selector
,
695 long numArgsPushed
, long numKeyArgsPushed
)
697 PyrSlot
*qslot
, *pslot
, *pend
;
699 PyrSlot
*uniqueMethodSlot
, *arraySlot
, *recvrSlot
, *selSlot
, *slot
;
704 #ifdef GC_SANITYCHECK
705 g
->gc
->SanityCheck();
707 // move args up by one to make room for selector
710 pend
= pslot
- numArgsPushed
+ 1;
711 while (pslot
> pend
) *--pslot
= *--qslot
;
713 selSlot
= g
->sp
- numArgsPushed
+ 2;
714 SetSymbol(selSlot
, selector
);
717 recvrSlot
= selSlot
- 1;
719 classobj
= classOfSlot(recvrSlot
);
721 index
= slotRawInt(&classobj
->classIndex
) + s_nocomprendo
->u
.index
;
722 meth
= gRowTable
[index
];
725 if (slotRawClass(&meth
->ownerclass
) == class_object
) {
726 // lookup instance specific method
727 uniqueMethodSlot
= &g
->classvars
->slots
[cvxUniqueMethods
];
728 if (isKindOfSlot(uniqueMethodSlot
, class_identdict
)) {
729 arraySlot
= slotRawObject(uniqueMethodSlot
)->slots
+ ivxIdentDict_array
;
730 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
731 i
= arrayAtIdentityHashInPairs(array
, recvrSlot
);
733 slot
= array
->slots
+ i
;
736 if (isKindOfSlot(slot
, class_identdict
)) {
737 arraySlot
= slotRawObject(slot
)->slots
+ ivxIdentDict_array
;
738 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
739 i
= arrayAtIdentityHashInPairs(array
, selSlot
);
741 slot
= array
->slots
+ i
;
744 slotCopy(selSlot
, recvrSlot
);
745 slotCopy(recvrSlot
, slot
);
746 blockValueWithKeys(g
, numArgsPushed
+1, numKeyArgsPushed
);
758 executeMethodWithKeys(g
, meth
, numArgsPushed
+1, numKeyArgsPushed
);
760 #ifdef GC_SANITYCHECK
761 g
->gc
->SanityCheck();
765 int blockValue(struct VMGlobals
*g
, int numArgsPushed
);
767 void doesNotUnderstand(VMGlobals
*g
, PyrSymbol
*selector
,
770 PyrSlot
*qslot
, *pslot
, *pend
;
772 PyrSlot
*uniqueMethodSlot
, *arraySlot
, *recvrSlot
, *selSlot
, *slot
;
777 #ifdef GC_SANITYCHECK
778 g
->gc
->SanityCheck();
780 // move args up by one to make room for selector
783 pend
= pslot
- numArgsPushed
+ 1;
784 while (pslot
> pend
) *--pslot
= *--qslot
;
786 selSlot
= g
->sp
- numArgsPushed
+ 2;
787 SetSymbol(selSlot
, selector
);
790 recvrSlot
= selSlot
- 1;
792 classobj
= classOfSlot(recvrSlot
);
794 index
= slotRawInt(&classobj
->classIndex
) + s_nocomprendo
->u
.index
;
795 meth
= gRowTable
[index
];
798 if (slotRawClass(&meth
->ownerclass
) == class_object
) {
799 // lookup instance specific method
800 uniqueMethodSlot
= &g
->classvars
->slots
[cvxUniqueMethods
];
801 if (isKindOfSlot(uniqueMethodSlot
, class_identdict
)) {
802 arraySlot
= slotRawObject(uniqueMethodSlot
)->slots
+ ivxIdentDict_array
;
803 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
804 i
= arrayAtIdentityHashInPairs(array
, recvrSlot
);
806 slot
= array
->slots
+ i
;
809 if (isKindOfSlot(slot
, class_identdict
)) {
810 arraySlot
= slotRawObject(slot
)->slots
+ ivxIdentDict_array
;
811 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
812 i
= arrayAtIdentityHashInPairs(array
, selSlot
);
814 slot
= array
->slots
+ i
;
817 slotCopy(selSlot
, recvrSlot
);
818 slotCopy(recvrSlot
, slot
);
819 blockValue(g
, numArgsPushed
+1);
831 executeMethod(g
, meth
, numArgsPushed
+1);
833 #ifdef GC_SANITYCHECK
834 g
->gc
->SanityCheck();
838 void executeMethodWithKeys(VMGlobals
*g
, PyrMethod
*meth
, long allArgsPushed
, long numKeyArgsPushed
)
840 PyrMethodRaw
*methraw
;
843 PyrSlot
*pslot
, *qslot
;
847 long i
, j
, m
, mmax
, numtemps
, numargs
, numArgsPushed
;
849 #ifdef GC_SANITYCHECK
850 g
->gc
->SanityCheck();
851 CallStackSanity(g
, "executeMethodWithKeys");
854 if (gTraceInterpreter
) {
856 postfl(" %s:%s -> %s:%s\n",
857 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
,
858 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
860 postfl(" top -> %s:%s\n",
861 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
866 if (gTraceInterpreter
) {
867 slotRawInt(&meth
->callMeter
)++;
872 int tailCall
= g
->tailCall
;
884 proto
= slotRawObject(&meth
->prototypeFrame
);
885 methraw
= METHRAW(meth
);
886 numtemps
= methraw
->numtemps
;
887 numargs
= methraw
->numargs
;
889 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
890 //DumpStack(g, g->sp);
891 //postfl("executeMethod allArgsPushed %d numKeyArgsPushed %d\n", allArgsPushed, numKeyArgsPushed);
893 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
894 vars
= frame
->vars
- 1;
895 frame
->classptr
= class_frame
;
896 frame
->size
= FRAMESIZE
+ proto
->size
;
897 SetObject(&frame
->method
, meth
);
898 SetObject(&frame
->homeContext
, frame
);
899 SetObject(&frame
->context
, frame
);
902 SetPtr(&caller
->ip
, g
->ip
);
903 SetObject(&frame
->caller
, caller
);
905 SetInt(&frame
->caller
, 0);
907 SetPtr(&frame
->ip
, 0);
910 g
->ip
= slotRawInt8Array(&meth
->code
)->b
- 1;
912 g
->block
= (PyrBlock
*)meth
;
914 g
->sp
-= allArgsPushed
;
918 if (numArgsPushed
<= numargs
) { /* not enough args pushed */
919 /* push all args to frame */
920 for (m
=0,mmax
=numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
922 /* push default arg & var values */
923 pslot
= vars
+ numArgsPushed
;
924 qslot
= proto
->slots
+ numArgsPushed
- 1;
925 for (m
=0, mmax
=numtemps
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
926 } else if (methraw
->varargs
) {
930 /* push all normal args to frame */
931 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
934 i
= numArgsPushed
- numargs
;
935 list
= newPyrArray(g
->gc
, i
, 0, false);
939 SetObject(rslot
, list
);
940 //SetObject(vars + numargs + 1, list);
942 /* put extra args into list */
943 lslot
= (list
->slots
- 1);
944 // fixed and raw sizes are zero
945 for (m
=0,mmax
=i
; m
<mmax
; ++m
) slotCopy(++lslot
, ++qslot
);
947 if (methraw
->numvars
) {
948 /* push default keyword and var values */
949 pslot
= vars
+ numargs
+ 1;
950 qslot
= proto
->slots
+ numargs
;
951 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
954 /* push all args to frame */
955 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
957 if (methraw
->numvars
) {
958 /* push default keyword and var values */
959 pslot
= vars
+ numargs
;
960 qslot
= proto
->slots
+ numargs
- 1;
961 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
964 // do keyword lookup:
965 if (numKeyArgsPushed
&& methraw
->posargs
) {
966 PyrSymbol
**name0
, **name
;
968 name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
969 key
= g
->sp
+ numArgsPushed
+ 1;
970 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
972 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
973 if (*name
== slotRawSymbol(key
)) {
974 slotCopy(&vars
[j
+1], &key
[1]);
979 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
980 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
986 slotCopy(&g
->receiver
, &vars
[1]);
987 #ifdef GC_SANITYCHECK
988 g
->gc
->SanityCheck();
989 CallStackSanity(g
, "<executeMethodWithKeys");
994 void executeMethod(VMGlobals
*g
, PyrMethod
*meth
, long numArgsPushed
)
996 PyrMethodRaw
*methraw
;
999 PyrSlot
*pslot
, *qslot
;
1003 long i
, m
, mmax
, numtemps
, numargs
;
1005 #ifdef GC_SANITYCHECK
1006 g
->gc
->SanityCheck();
1007 CallStackSanity(g
, "executeMethod");
1010 if (gTraceInterpreter
) {
1012 postfl(" %s:%s -> %s:%s\n",
1013 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
,
1014 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1016 postfl(" top -> %s:%s\n",
1017 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1022 if (gTraceInterpreter
) {
1023 slotRawInt(&meth
->callMeter
)++;
1027 #if TAILCALLOPTIMIZE
1028 int tailCall
= g
->tailCall
;
1030 if (tailCall
== 1) {
1031 returnFromMethod(g
);
1040 proto
= slotRawObject(&meth
->prototypeFrame
);
1041 methraw
= METHRAW(meth
);
1042 numtemps
= methraw
->numtemps
;
1043 numargs
= methraw
->numargs
;
1046 //postfl("executeMethod allArgsPushed %d numKeyArgsPushed %d\n", allArgsPushed, numKeyArgsPushed);
1048 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1049 vars
= frame
->vars
- 1;
1050 frame
->classptr
= class_frame
;
1051 frame
->size
= FRAMESIZE
+ proto
->size
;
1052 SetObject(&frame
->method
, meth
);
1053 SetObject(&frame
->homeContext
, frame
);
1054 SetObject(&frame
->context
, frame
);
1057 SetPtr(&caller
->ip
, g
->ip
);
1058 SetObject(&frame
->caller
, caller
);
1060 SetInt(&frame
->caller
, 0);
1062 SetPtr(&frame
->ip
, 0);
1065 g
->ip
= slotRawInt8Array(&meth
->code
)->b
- 1;
1067 g
->block
= (PyrBlock
*)meth
;
1069 g
->sp
-= numArgsPushed
;
1073 if (numArgsPushed
<= numargs
) { /* not enough args pushed */
1074 /* push all args to frame */
1075 for (m
=0,mmax
=numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1077 /* push default arg & var values */
1078 pslot
= vars
+ numArgsPushed
;
1079 qslot
= proto
->slots
+ numArgsPushed
- 1;
1080 for (m
=0, mmax
=numtemps
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1081 } else if (methraw
->varargs
) {
1085 /* push all normal args to frame */
1086 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1089 i
= numArgsPushed
- numargs
;
1090 list
= newPyrArray(g
->gc
, i
, 0, false);
1094 SetObject(rslot
, list
);
1095 //SetObject(vars + numargs + 1, list);
1097 /* put extra args into list */
1098 lslot
= (list
->slots
- 1);
1099 // fixed and raw sizes are zero
1100 for (m
=0,mmax
=i
; m
<mmax
; ++m
) slotCopy(++lslot
, ++qslot
);
1102 if (methraw
->numvars
) {
1103 /* push default keyword and var values */
1104 pslot
= vars
+ numargs
+ 1;
1105 qslot
= proto
->slots
+ numargs
;
1106 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1109 /* push all args to frame */
1110 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1112 if (methraw
->numvars
) {
1113 /* push default keyword and var values */
1114 pslot
= vars
+ numargs
;
1115 qslot
= proto
->slots
+ numargs
- 1;
1116 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1119 slotCopy(&g
->receiver
, &vars
[1]);
1121 #ifdef GC_SANITYCHECK
1122 g
->gc
->SanityCheck();
1123 CallStackSanity(g
, "<executeMethod");
1127 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
1129 void returnFromBlock(VMGlobals
*g
)
1132 PyrFrame
*returnFrame
;
1133 PyrFrame
*homeContext
;
1136 PyrMethodRaw
*methraw
;
1137 PyrMethodRaw
*blockraw
;
1139 //if (gTraceInterpreter) postfl("->returnFromBlock\n");
1140 //printf("->returnFromBlock\n");
1141 #ifdef GC_SANITYCHECK
1142 g
->gc
->SanityCheck();
1143 CallStackSanity(g
, "returnFromBlock");
1145 curframe
= g
->frame
;
1148 returnFrame
= slotRawFrame(&curframe
->caller
);
1150 block
= slotRawBlock(&curframe
->method
);
1151 blockraw
= METHRAW(block
);
1153 g
->frame
= returnFrame
;
1154 g
->ip
= (unsigned char *)slotRawPtr(&returnFrame
->ip
);
1155 g
->block
= slotRawBlock(&returnFrame
->method
);
1156 homeContext
= slotRawFrame(&returnFrame
->homeContext
);
1157 meth
= slotRawMethod(&homeContext
->method
);
1158 methraw
= METHRAW(meth
);
1159 slotCopy(&g
->receiver
, &homeContext
->vars
[0]); //??
1162 meth
= slotRawMethod(&curframe
->method
);
1163 methraw
= METHRAW(meth
);
1164 if (!methraw
->needsHeapContext
) {
1165 g
->gc
->Free(curframe
);
1167 SetInt(&curframe
->caller
, 0);
1171 ////// this should never happen .
1172 error("return from Function at top of call stack.\n");
1176 g
->sp
= g
->gc
->Stack()->slots
- 1;
1177 longjmp(g
->escapeInterpreter
, 1);
1179 //if (gTraceInterpreter) postfl("<-returnFromBlock\n");
1180 #ifdef GC_SANITYCHECK
1181 g
->gc
->SanityCheck();
1182 CallStackSanity(g
, "returnFromBlock");
1187 void returnFromMethod(VMGlobals
*g
)
1189 PyrFrame
*returnFrame
, *curframe
, *homeContext
;
1191 PyrMethodRaw
*methraw
;
1192 curframe
= g
->frame
;
1194 //assert(slotRawFrame(&curframe->context) == NULL);
1196 /*if (gTraceInterpreter) {
1197 post("returnFromMethod %s:%s\n", slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name);
1198 post("tailcall %d\n", g->tailCall);
1200 #ifdef GC_SANITYCHECK
1201 g
->gc
->SanityCheck();
1203 homeContext
= slotRawFrame(&slotRawFrame(&curframe
->context
)->homeContext
);
1204 if (homeContext
== NULL
) {
1206 #if TAILCALLOPTIMIZE
1207 if (g
->tailCall
) return; // do nothing.
1211 static bool once = true;
1212 if (once || gTraceInterpreter)
1215 post("return all the way out. sd %d\n", g->sp - g->gc->Stack()->slots);
1217 slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name
1219 post("tailcall %d\n", g->tailCall);
1220 post("homeContext %p\n", homeContext);
1221 post("returnFrame %p\n", returnFrame);
1222 dumpObjectSlot(&homeContext->caller);
1223 DumpStack(g, g->sp);
1226 gTraceInterpreter = false;
1228 //if (IsNil(&homeContext->caller)) return; // do nothing.
1230 // return all the way out.
1231 PyrSlot
*bottom
= g
->gc
->Stack()->slots
;
1232 slotCopy(bottom
, g
->sp
);
1233 g
->sp
= bottom
; // ??!! pop everybody
1237 longjmp(g
->escapeInterpreter
, 2);
1239 returnFrame
= slotRawFrame(&homeContext
->caller
);
1241 if (returnFrame
== NULL
) goto null_return
;
1242 // make sure returnFrame is a caller and find earliest stack frame
1244 PyrFrame
*tempFrame
= curframe
;
1245 while (tempFrame
!= returnFrame
) {
1246 tempFrame
= slotRawFrame(&tempFrame
->caller
);
1248 if (isKindOf((PyrObject
*)g
->thread
, class_routine
) && NotNil(&g
->thread
->parent
)) {
1249 // not found, so yield to parent thread and continue searching.
1251 slotCopy(&value
, g
->sp
);
1253 int numArgsPushed
= 1;
1254 switchToThread(g
, slotRawThread(&g
->thread
->parent
), tSuspended
, &numArgsPushed
);
1256 // on the other side of the looking glass, put the yielded value on the stack as the result..
1257 g
->sp
-= numArgsPushed
- 1;
1258 slotCopy(g
->sp
, &value
);
1260 curframe
= tempFrame
= g
->frame
;
1262 slotCopy(&g
->sp
[2], &g
->sp
[0]);
1263 slotCopy(g
->sp
, &g
->receiver
);
1264 g
->sp
++; SetObject(g
->sp
, g
->method
);
1266 sendMessage(g
, getsym("outOfContextReturn"), 3);
1274 PyrFrame
*tempFrame
= curframe
;
1275 while (tempFrame
!= returnFrame
) {
1276 meth
= slotRawMethod(&tempFrame
->method
);
1277 methraw
= METHRAW(meth
);
1278 PyrFrame
*nextFrame
= slotRawFrame(&tempFrame
->caller
);
1279 if (!methraw
->needsHeapContext
) {
1280 SetInt(&tempFrame
->caller
, 0);
1282 if (tempFrame
!= homeContext
)
1283 SetInt(&tempFrame
->caller
, 0);
1285 tempFrame
= nextFrame
;
1290 g
->ip
= (unsigned char *)slotRawPtr(&returnFrame
->ip
);
1291 g
->frame
= returnFrame
;
1292 g
->block
= slotRawBlock(&returnFrame
->method
);
1294 homeContext
= slotRawFrame(&returnFrame
->homeContext
);
1295 meth
= slotRawMethod(&homeContext
->method
);
1296 methraw
= METHRAW(meth
);
1299 if (gTraceInterpreter
) {
1300 postfl("%s:%s <- %s:%s\n",
1301 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
,
1302 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
1308 slotCopy(&g
->receiver
, &homeContext
->vars
[0]);
1311 #ifdef GC_SANITYCHECK
1312 g
->gc
->SanityCheck();
1317 int keywordFixStack(VMGlobals
*g
, PyrMethod
*meth
, PyrMethodRaw
*methraw
, long allArgsPushed
,
1318 long numKeyArgsPushed
)
1320 PyrSlot
*pslot
, *qslot
;
1321 long i
, j
, m
, diff
, numArgsPushed
, numArgsNeeded
;
1323 if (numKeyArgsPushed
) {
1324 // evacuate keyword args to separate area
1325 pslot
= keywordstack
+ (numKeyArgsPushed
<<1);
1327 for (m
=0; m
<numKeyArgsPushed
; ++m
) {
1328 *--pslot
= *--qslot
;
1329 *--pslot
= *--qslot
;
1333 PyrSlot
*vars
= g
->sp
- allArgsPushed
+ 1;
1335 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1336 numArgsNeeded
= methraw
->numargs
;
1337 diff
= numArgsNeeded
- numArgsPushed
;
1338 if (diff
> 0) { // not enough args
1339 pslot
= vars
+ numArgsPushed
- 1;
1340 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
1341 for (m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
1342 numArgsPushed
= numArgsNeeded
;
1345 // do keyword lookup:
1346 if (numKeyArgsPushed
&& methraw
->posargs
) {
1347 PyrSymbol
**name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
1348 PyrSlot
*key
= keywordstack
;
1349 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1350 PyrSymbol
**name
= name0
;
1351 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
1352 if (*name
== slotRawSymbol(key
)) {
1353 slotCopy(&vars
[j
], &key
[1]);
1357 if (gKeywordError
) {
1358 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
1359 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1365 g
->sp
+= numArgsPushed
- allArgsPushed
;
1366 return numArgsPushed
;