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"
30 #include "PredefinedSymbols.h"
31 #include "PyrObjectProto.h"
34 #define DEBUGMETHODS 0
37 PyrMethod
**gRowTable
;
39 PyrSlot keywordstack
[MAXKEYSLOTS
];
40 bool gKeywordError
= true;
41 extern bool gTraceInterpreter
;
43 long cvxUniqueMethods
;
44 extern int ivxIdentDict_array
;
46 void StoreToImmutableB(VMGlobals
*g
, PyrSlot
*& sp
, unsigned char *& ip
);
48 void initUniqueMethods()
51 cvxUniqueMethods
= classVarOffset("Object", "uniqueMethods", &dummyclass
);
54 HOT
void sendMessageWithKeys(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
, long numKeyArgsPushed
)
56 PyrMethod
*meth
= NULL
;
57 PyrMethodRaw
*methraw
;
58 PyrSlot
*recvrSlot
, *sp
;
63 //postfl("->sendMessage\n");
66 CallStackSanity(g
, "sendMessageWithKeys");
68 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
70 classobj
= classOfSlot(recvrSlot
);
73 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
74 meth
= gRowTable
[index
];
76 if (slotRawSymbol(&meth
->name
) != selector
) {
77 doesNotUnderstandWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
79 methraw
= METHRAW(meth
);
80 //postfl("methraw->methType %d\n", methraw->methType);
81 switch (methraw
->methType
) {
82 case methNormal
: /* normal msg send */
83 executeMethodWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
85 case methReturnSelf
: /* return self */
86 g
->sp
-= numArgsPushed
- 1;
88 case methReturnLiteral
: /* return literal */
89 sp
= g
->sp
-= numArgsPushed
- 1;
90 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
92 case methReturnArg
: /* return an argument */
93 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
95 g
->sp
-= numArgsPushed
- 1;
97 index
= methraw
->specialIndex
; // zero is index of the first argument
98 if (index
< numArgsPushed
) {
99 slotCopy(sp
, sp
+ index
);
101 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
104 case methReturnInstVar
: /* return inst var */
105 sp
= g
->sp
-= numArgsPushed
- 1;
106 index
= methraw
->specialIndex
;
107 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
109 case methAssignInstVar
: /* assign inst var */
110 sp
= g
->sp
-= numArgsPushed
- 1;
111 index
= methraw
->specialIndex
;
112 obj
= slotRawObject(recvrSlot
);
113 if (obj
->IsImmutable()) { StoreToImmutableB(g
, sp
, g
->ip
); }
115 if (numArgsPushed
>= 2) {
116 slotCopy(&obj
->slots
[index
], sp
+ 1);
117 g
->gc
->GCWrite(obj
, sp
+ 1);
119 SetNil(&obj
->slots
[index
]);
121 slotCopy(sp
, recvrSlot
);
124 case methReturnClassVar
: /* return class var */
125 sp
= g
->sp
-= numArgsPushed
- 1;
126 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
128 case methAssignClassVar
: /* assign class var */
129 sp
= g
->sp
-= numArgsPushed
- 1;
130 if (numArgsPushed
>= 2) {
131 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
132 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
134 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
136 slotCopy(sp
, recvrSlot
);
138 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
139 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
140 numKeyArgsPushed
= 0;
141 selector
= slotRawSymbol(&meth
->selectors
);
143 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
144 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
145 numKeyArgsPushed
= 0;
146 selector
= slotRawSymbol(&meth
->selectors
);
147 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
149 case methForwardInstVar
: /* forward to an instance variable */
150 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
151 numKeyArgsPushed
= 0;
152 selector
= slotRawSymbol(&meth
->selectors
);
153 index
= methraw
->specialIndex
;
154 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
156 classobj
= classOfSlot(recvrSlot
);
159 case methForwardClassVar
: /* forward to a class variable */
160 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
161 numKeyArgsPushed
= 0;
162 selector
= slotRawSymbol(&meth
->selectors
);
163 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
165 classobj
= classOfSlot(recvrSlot
);
168 case methPrimitive
: /* primitive */
169 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
170 #ifdef GC_SANITYCHECK
171 g
->gc
->SanityCheck();
179 #ifdef GC_SANITYCHECK
180 g
->gc
->SanityCheck();
181 CallStackSanity(g
, "<sendMessageWithKeys");
183 //postfl("<-sendMessage\n");
187 HOT
void sendMessage(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
)
189 PyrMethod
*meth
= NULL
;
190 PyrMethodRaw
*methraw
;
191 PyrSlot
*recvrSlot
, *sp
;
196 //postfl("->sendMessage\n");
197 #ifdef GC_SANITYCHECK
198 g
->gc
->SanityCheck();
199 CallStackSanity(g
, "sendMessage");
201 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
203 classobj
= classOfSlot(recvrSlot
);
206 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
207 meth
= gRowTable
[index
];
209 if (slotRawSymbol(&meth
->name
) != selector
) {
210 doesNotUnderstand(g
, selector
, numArgsPushed
);
212 methraw
= METHRAW(meth
);
213 //postfl("methraw->methType %d\n", methraw->methType);
214 switch (methraw
->methType
) {
215 case methNormal
: /* normal msg send */
216 executeMethod(g
, meth
, numArgsPushed
);
218 case methReturnSelf
: /* return self */
219 g
->sp
-= numArgsPushed
- 1;
221 case methReturnLiteral
: /* return literal */
222 sp
= g
->sp
-= numArgsPushed
- 1;
223 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
225 case methReturnArg
: /* return an argument */
226 sp
= g
->sp
-= numArgsPushed
- 1;
227 index
= methraw
->specialIndex
; // zero is index of the first argument
228 if (index
< numArgsPushed
) {
229 slotCopy(sp
, sp
+ index
);
231 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
234 case methReturnInstVar
: /* return inst var */
235 sp
= g
->sp
-= numArgsPushed
- 1;
236 index
= methraw
->specialIndex
;
237 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
239 case methAssignInstVar
: /* assign inst var */
240 sp
= g
->sp
-= numArgsPushed
- 1;
241 index
= methraw
->specialIndex
;
242 obj
= slotRawObject(recvrSlot
);
243 if (obj
->IsImmutable()) { StoreToImmutableB(g
, sp
, g
->ip
); }
245 if (numArgsPushed
>= 2) {
246 slotCopy(&obj
->slots
[index
], sp
+ 1);
247 g
->gc
->GCWrite(obj
, sp
+ 1);
249 SetNil(&obj
->slots
[index
]);
251 slotCopy(sp
, recvrSlot
);
254 case methReturnClassVar
: /* return class var */
255 sp
= g
->sp
-= numArgsPushed
- 1;
256 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
258 case methAssignClassVar
: /* assign class var */
259 sp
= g
->sp
-= numArgsPushed
- 1;
260 if (numArgsPushed
>= 2) {
261 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
262 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
264 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
266 slotCopy(sp
, recvrSlot
);
268 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
269 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
270 /* push default arg values */
271 PyrSlot
*pslot
, *qslot
;
274 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
275 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
276 numArgsPushed
= methraw
->numargs
;
279 selector
= slotRawSymbol(&meth
->selectors
);
281 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
282 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
283 /* push default arg values */
284 PyrSlot
*pslot
, *qslot
;
287 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
288 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
289 numArgsPushed
= methraw
->numargs
;
292 selector
= slotRawSymbol(&meth
->selectors
);
293 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
295 case methForwardInstVar
: /* forward to an instance variable */
296 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
297 /* push default arg values */
298 PyrSlot
*pslot
, *qslot
;
301 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
302 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
303 numArgsPushed
= methraw
->numargs
;
306 selector
= slotRawSymbol(&meth
->selectors
);
307 index
= methraw
->specialIndex
;
308 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
310 classobj
= classOfSlot(recvrSlot
);
313 case methForwardClassVar
: /* forward to a class variable */
314 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
315 /* push default arg values */
316 PyrSlot
*pslot
, *qslot
;
319 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
320 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
321 numArgsPushed
= methraw
->numargs
;
324 selector
= slotRawSymbol(&meth
->selectors
);
325 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
327 classobj
= classOfSlot(recvrSlot
);
330 case methPrimitive
: /* primitive */
331 doPrimitive(g
, meth
, numArgsPushed
);
332 #ifdef GC_SANITYCHECK
333 g
->gc
->SanityCheck();
337 case methMultDispatchByClass : {
338 index = methraw->specialIndex;
339 if (index < numArgsPushed) {
340 classobj = slotRawObject(sp + index)->classptr;
341 selector = slotRawSymbol(&meth->selectors);
344 doesNotUnderstand(g, selector, numArgsPushed);
347 case methMultDispatchByValue : {
348 index = methraw->specialIndex;
349 if (index < numArgsPushed) {
350 index = arrayAtIdentityHashInPairs(array, b);
351 meth = slotRawObject(&meth->selectors)->slots[index + 1].uom;
352 goto meth_select_again;
354 doesNotUnderstand(g, selector, numArgsPushed);
364 #ifdef GC_SANITYCHECK
365 g
->gc
->SanityCheck();
366 CallStackSanity(g
, "<sendMessage");
368 //postfl("<-sendMessage\n");
372 HOT
void sendSuperMessageWithKeys(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
, long numKeyArgsPushed
)
374 PyrMethod
*meth
= NULL
;
375 PyrMethodRaw
*methraw
;
376 PyrSlot
*recvrSlot
, *sp
;
381 //postfl("->sendMessage\n");
382 #ifdef GC_SANITYCHECK
383 g
->gc
->SanityCheck();
384 CallStackSanity(g
, "sendSuperMessageWithKeys");
386 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
388 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
389 //assert(isKindOfSlot(recvrSlot, classobj));
392 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
393 meth
= gRowTable
[index
];
395 if (slotRawSymbol(&meth
->name
) != selector
) {
396 doesNotUnderstandWithKeys(g
, selector
, numArgsPushed
, numKeyArgsPushed
);
398 methraw
= METHRAW(meth
);
399 //postfl("methraw->methType %d\n", methraw->methType);
400 switch (methraw
->methType
) {
401 case methNormal
: /* normal msg send */
402 executeMethodWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
404 case methReturnSelf
: /* return self */
405 g
->sp
-= numArgsPushed
- 1;
407 case methReturnLiteral
: /* return literal */
408 sp
= g
->sp
-= numArgsPushed
- 1;
409 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
411 case methReturnArg
: /* return an argument */
412 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
413 numKeyArgsPushed
= 0;
414 g
->sp
-= numArgsPushed
- 1;
416 index
= methraw
->specialIndex
; // zero is index of the first argument
417 if (index
< numArgsPushed
) {
418 slotCopy(sp
, sp
+ index
);
420 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
423 case methReturnInstVar
: /* return inst var */
424 sp
= g
->sp
-= numArgsPushed
- 1;
425 index
= methraw
->specialIndex
;
426 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
428 case methAssignInstVar
: /* assign inst var */
429 sp
= g
->sp
-= numArgsPushed
- 1;
430 index
= methraw
->specialIndex
;
431 obj
= slotRawObject(recvrSlot
);
432 if (obj
->IsImmutable()) { StoreToImmutableB(g
, sp
, g
->ip
); }
434 if (numArgsPushed
>= 2) {
435 slotCopy(&obj
->slots
[index
], sp
+ 1);
436 g
->gc
->GCWrite(obj
, sp
+ 1);
438 SetNil(&obj
->slots
[index
]);
440 slotCopy(sp
, recvrSlot
);
443 case methReturnClassVar
: /* return class var */
444 sp
= g
->sp
-= numArgsPushed
- 1;
445 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
447 case methAssignClassVar
: /* assign class var */
448 sp
= g
->sp
-= numArgsPushed
- 1;
449 if (numArgsPushed
>= 2) {
450 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
451 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
453 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
455 slotCopy(sp
, recvrSlot
);
457 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
458 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
459 numKeyArgsPushed
= 0;
460 selector
= slotRawSymbol(&meth
->selectors
);
462 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
463 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
464 numKeyArgsPushed
= 0;
465 selector
= slotRawSymbol(&meth
->selectors
);
466 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
468 case methForwardInstVar
: /* forward to an instance variable */
469 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
470 numKeyArgsPushed
= 0;
471 selector
= slotRawSymbol(&meth
->selectors
);
472 index
= methraw
->specialIndex
;
473 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
475 classobj
= classOfSlot(recvrSlot
);
478 case methForwardClassVar
: /* forward to a class variable */
479 numArgsPushed
= keywordFixStack(g
, meth
, methraw
, numArgsPushed
, numKeyArgsPushed
);
480 numKeyArgsPushed
= 0;
481 selector
= slotRawSymbol(&meth
->selectors
);
482 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
484 classobj
= classOfSlot(recvrSlot
);
487 case methPrimitive
: /* primitive */
488 doPrimitiveWithKeys(g
, meth
, numArgsPushed
, numKeyArgsPushed
);
489 #ifdef GC_SANITYCHECK
490 g
->gc
->SanityCheck();
498 #ifdef GC_SANITYCHECK
499 g
->gc
->SanityCheck();
500 CallStackSanity(g
, "<sendSuperMessageWithKeys");
502 //postfl("<-sendMessage\n");
506 HOT
void sendSuperMessage(VMGlobals
*g
, PyrSymbol
*selector
, long numArgsPushed
)
508 PyrMethod
*meth
= NULL
;
509 PyrMethodRaw
*methraw
;
510 PyrSlot
*recvrSlot
, *sp
;
515 //postfl("->sendMessage\n");
516 #ifdef GC_SANITYCHECK
517 g
->gc
->SanityCheck();
518 CallStackSanity(g
, "sendSuperMessage");
520 recvrSlot
= g
->sp
- numArgsPushed
+ 1;
522 classobj
= slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->superclass
)->u
.classobj
;
523 //assert(isKindOfSlot(recvrSlot, classobj));
526 index
= slotRawInt(&classobj
->classIndex
) + selector
->u
.index
;
527 meth
= gRowTable
[index
];
529 if (slotRawSymbol(&meth
->name
) != selector
) {
530 doesNotUnderstand(g
, selector
, numArgsPushed
);
532 methraw
= METHRAW(meth
);
533 //postfl("methraw->methType %d\n", methraw->methType);
534 switch (methraw
->methType
) {
535 case methNormal
: /* normal msg send */
536 executeMethod(g
, meth
, numArgsPushed
);
538 case methReturnSelf
: /* return self */
539 g
->sp
-= numArgsPushed
- 1;
541 case methReturnLiteral
: /* return literal */
542 sp
= g
->sp
-= numArgsPushed
- 1;
543 slotCopy(sp
, &meth
->selectors
); /* in this case selectors is just a single value */
545 case methReturnArg
: /* return an argument */
546 sp
= g
->sp
-= numArgsPushed
- 1;
547 index
= methraw
->specialIndex
; // zero is index of the first argument
548 if (index
< numArgsPushed
) {
549 slotCopy(sp
, sp
+ index
);
551 slotCopy(sp
, &slotRawObject(&meth
->prototypeFrame
)->slots
[index
]);
554 case methReturnInstVar
: /* return inst var */
555 sp
= g
->sp
-= numArgsPushed
- 1;
556 index
= methraw
->specialIndex
;
557 slotCopy(sp
, &slotRawObject(recvrSlot
)->slots
[index
]);
559 case methAssignInstVar
: /* assign inst var */
560 sp
= g
->sp
-= numArgsPushed
- 1;
561 index
= methraw
->specialIndex
;
562 obj
= slotRawObject(recvrSlot
);
563 if (obj
->IsImmutable()) { StoreToImmutableB(g
, sp
, g
->ip
); }
565 if (numArgsPushed
>= 2) {
566 slotCopy(&obj
->slots
[index
], sp
+ 1);
567 g
->gc
->GCWrite(obj
, sp
+ 1);
569 SetNil(&obj
->slots
[index
]);
571 slotCopy(sp
, recvrSlot
);
574 case methReturnClassVar
: /* return class var */
575 sp
= g
->sp
-= numArgsPushed
- 1;
576 slotCopy(sp
, &g
->classvars
->slots
[methraw
->specialIndex
]);
578 case methAssignClassVar
: /* assign class var */
579 sp
= g
->sp
-= numArgsPushed
- 1;
580 if (numArgsPushed
>= 2) {
581 slotCopy(&g
->classvars
->slots
[methraw
->specialIndex
], sp
+ 1);
582 g
->gc
->GCWrite(g
->classvars
, sp
+ 1);
584 SetNil(&g
->classvars
->slots
[methraw
->specialIndex
]);
586 slotCopy(sp
, recvrSlot
);
588 case methRedirect
: /* send a different selector to self, e.g. this.subclassResponsibility */
589 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
590 /* push default arg values */
591 PyrSlot
*pslot
, *qslot
;
594 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
595 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
596 numArgsPushed
= methraw
->numargs
;
599 selector
= slotRawSymbol(&meth
->selectors
);
601 case methRedirectSuper
: /* send a different selector to self, e.g. this.subclassResponsibility */
602 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
603 /* push default arg values */
604 PyrSlot
*pslot
, *qslot
;
607 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
608 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
609 numArgsPushed
= methraw
->numargs
;
612 selector
= slotRawSymbol(&meth
->selectors
);
613 classobj
= slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->superclass
)->u
.classobj
;
615 case methForwardInstVar
: /* forward to an instance variable */
616 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
617 /* push default arg values */
618 PyrSlot
*pslot
, *qslot
;
621 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
622 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
623 numArgsPushed
= methraw
->numargs
;
626 selector
= slotRawSymbol(&meth
->selectors
);
627 index
= methraw
->specialIndex
;
628 slotCopy(recvrSlot
, &slotRawObject(recvrSlot
)->slots
[index
]);
630 classobj
= classOfSlot(recvrSlot
);
633 case methForwardClassVar
: /* forward to a class variable */
634 if (numArgsPushed
< methraw
->numargs
) { // not enough args pushed
635 /* push default arg values */
636 PyrSlot
*pslot
, *qslot
;
639 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
640 for (m
=0, mmax
=methraw
->numargs
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
641 numArgsPushed
= methraw
->numargs
;
644 selector
= slotRawSymbol(&meth
->selectors
);
645 slotCopy(recvrSlot
, &g
->classvars
->slots
[methraw
->specialIndex
]);
647 classobj
= classOfSlot(recvrSlot
);
650 case methPrimitive
: /* primitive */
651 doPrimitive(g
, meth
, numArgsPushed
);
652 #ifdef GC_SANITYCHECK
653 g
->gc
->SanityCheck();
657 case methMultDispatchByClass : {
658 index = methraw->specialIndex;
659 if (index < numArgsPushed) {
660 classobj = slotRawObject(sp + index)->classptr;
661 selector = slotRawSymbol(&meth->selectors);
664 doesNotUnderstand(g, selector, numArgsPushed);
667 case methMultDispatchByValue : {
668 index = methraw->specialIndex;
669 if (index < numArgsPushed) {
670 index = arrayAtIdentityHashInPairs(array, b);
671 meth = slotRawObject(&meth->selectors)->slots[index + 1].uom;
672 goto meth_select_again;
674 doesNotUnderstand(g, selector, numArgsPushed);
684 #ifdef GC_SANITYCHECK
685 g
->gc
->SanityCheck();
686 CallStackSanity(g
, "<sendSuperMessage");
688 //postfl("<-sendMessage\n");
692 extern PyrClass
*class_identdict
;
693 void doesNotUnderstandWithKeys(VMGlobals
*g
, PyrSymbol
*selector
,
694 long numArgsPushed
, long numKeyArgsPushed
)
696 PyrSlot
*qslot
, *pslot
, *pend
;
698 PyrSlot
*uniqueMethodSlot
, *arraySlot
, *recvrSlot
, *selSlot
, *slot
;
703 #ifdef GC_SANITYCHECK
704 g
->gc
->SanityCheck();
706 // move args up by one to make room for selector
709 pend
= pslot
- numArgsPushed
+ 1;
710 while (pslot
> pend
) *--pslot
= *--qslot
;
712 selSlot
= g
->sp
- numArgsPushed
+ 2;
713 SetSymbol(selSlot
, selector
);
716 recvrSlot
= selSlot
- 1;
718 classobj
= classOfSlot(recvrSlot
);
720 index
= slotRawInt(&classobj
->classIndex
) + s_nocomprendo
->u
.index
;
721 meth
= gRowTable
[index
];
724 if (slotRawClass(&meth
->ownerclass
) == class_object
) {
725 // lookup instance specific method
726 uniqueMethodSlot
= &g
->classvars
->slots
[cvxUniqueMethods
];
727 if (isKindOfSlot(uniqueMethodSlot
, class_identdict
)) {
728 arraySlot
= slotRawObject(uniqueMethodSlot
)->slots
+ ivxIdentDict_array
;
729 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
730 i
= arrayAtIdentityHashInPairs(array
, recvrSlot
);
732 slot
= array
->slots
+ i
;
735 if (isKindOfSlot(slot
, class_identdict
)) {
736 arraySlot
= slotRawObject(slot
)->slots
+ ivxIdentDict_array
;
737 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
738 i
= arrayAtIdentityHashInPairs(array
, selSlot
);
740 slot
= array
->slots
+ i
;
743 slotCopy(selSlot
, recvrSlot
);
744 slotCopy(recvrSlot
, slot
);
745 blockValueWithKeys(g
, numArgsPushed
+1, numKeyArgsPushed
);
757 executeMethodWithKeys(g
, meth
, numArgsPushed
+1, numKeyArgsPushed
);
759 #ifdef GC_SANITYCHECK
760 g
->gc
->SanityCheck();
764 int blockValue(struct VMGlobals
*g
, int numArgsPushed
);
766 void doesNotUnderstand(VMGlobals
*g
, PyrSymbol
*selector
,
769 PyrSlot
*qslot
, *pslot
, *pend
;
771 PyrSlot
*uniqueMethodSlot
, *arraySlot
, *recvrSlot
, *selSlot
, *slot
;
776 #ifdef GC_SANITYCHECK
777 g
->gc
->SanityCheck();
779 // move args up by one to make room for selector
782 pend
= pslot
- numArgsPushed
+ 1;
783 while (pslot
> pend
) *--pslot
= *--qslot
;
785 selSlot
= g
->sp
- numArgsPushed
+ 2;
786 SetSymbol(selSlot
, selector
);
789 recvrSlot
= selSlot
- 1;
791 classobj
= classOfSlot(recvrSlot
);
793 index
= slotRawInt(&classobj
->classIndex
) + s_nocomprendo
->u
.index
;
794 meth
= gRowTable
[index
];
797 if (slotRawClass(&meth
->ownerclass
) == class_object
) {
798 // lookup instance specific method
799 uniqueMethodSlot
= &g
->classvars
->slots
[cvxUniqueMethods
];
800 if (isKindOfSlot(uniqueMethodSlot
, class_identdict
)) {
801 arraySlot
= slotRawObject(uniqueMethodSlot
)->slots
+ ivxIdentDict_array
;
802 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
803 i
= arrayAtIdentityHashInPairs(array
, recvrSlot
);
805 slot
= array
->slots
+ i
;
808 if (isKindOfSlot(slot
, class_identdict
)) {
809 arraySlot
= slotRawObject(slot
)->slots
+ ivxIdentDict_array
;
810 if ((IsObj(arraySlot
) && (array
= slotRawObject(arraySlot
))->classptr
== class_array
)) {
811 i
= arrayAtIdentityHashInPairs(array
, selSlot
);
813 slot
= array
->slots
+ i
;
816 slotCopy(selSlot
, recvrSlot
);
817 slotCopy(recvrSlot
, slot
);
818 blockValue(g
, numArgsPushed
+1);
830 executeMethod(g
, meth
, numArgsPushed
+1);
832 #ifdef GC_SANITYCHECK
833 g
->gc
->SanityCheck();
837 HOT
void executeMethodWithKeys(VMGlobals
*g
, PyrMethod
*meth
, long allArgsPushed
, long numKeyArgsPushed
)
839 PyrMethodRaw
*methraw
;
842 PyrSlot
*pslot
, *qslot
;
846 long i
, j
, m
, mmax
, numtemps
, numargs
, numArgsPushed
;
848 #ifdef GC_SANITYCHECK
849 g
->gc
->SanityCheck();
850 CallStackSanity(g
, "executeMethodWithKeys");
853 if (gTraceInterpreter
) {
855 postfl(" %s:%s -> %s:%s\n",
856 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
,
857 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
859 postfl(" top -> %s:%s\n",
860 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
865 if (gTraceInterpreter
) {
866 slotRawInt(&meth
->callMeter
)++;
871 int tailCall
= g
->tailCall
;
883 proto
= slotRawObject(&meth
->prototypeFrame
);
884 methraw
= METHRAW(meth
);
885 numtemps
= methraw
->numtemps
;
886 numargs
= methraw
->numargs
;
888 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
889 //DumpStack(g, g->sp);
890 //postfl("executeMethod allArgsPushed %d numKeyArgsPushed %d\n", allArgsPushed, numKeyArgsPushed);
892 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
893 vars
= frame
->vars
- 1;
894 frame
->classptr
= class_frame
;
895 frame
->size
= FRAMESIZE
+ proto
->size
;
896 SetObject(&frame
->method
, meth
);
897 SetObject(&frame
->homeContext
, frame
);
898 SetObject(&frame
->context
, frame
);
901 SetPtr(&caller
->ip
, g
->ip
);
902 SetObject(&frame
->caller
, caller
);
904 SetInt(&frame
->caller
, 0);
906 SetPtr(&frame
->ip
, 0);
909 g
->ip
= slotRawInt8Array(&meth
->code
)->b
- 1;
911 g
->block
= (PyrBlock
*)meth
;
913 g
->sp
-= allArgsPushed
;
917 if (numArgsPushed
<= numargs
) { /* not enough args pushed */
918 /* push all args to frame */
919 for (m
=0,mmax
=numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
921 /* push default arg & var values */
922 pslot
= vars
+ numArgsPushed
;
923 qslot
= proto
->slots
+ numArgsPushed
- 1;
924 for (m
=0, mmax
=numtemps
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
925 } else if (methraw
->varargs
) {
929 /* push all normal args to frame */
930 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
933 i
= numArgsPushed
- numargs
;
934 list
= newPyrArray(g
->gc
, i
, 0, false);
938 SetObject(rslot
, list
);
939 //SetObject(vars + numargs + 1, list);
941 /* put extra args into list */
942 lslot
= (list
->slots
- 1);
943 // fixed and raw sizes are zero
944 for (m
=0,mmax
=i
; m
<mmax
; ++m
) slotCopy(++lslot
, ++qslot
);
946 if (methraw
->numvars
) {
947 /* push default keyword and var values */
948 pslot
= vars
+ numargs
+ 1;
949 qslot
= proto
->slots
+ numargs
;
950 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
953 /* push all args to frame */
954 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
956 if (methraw
->numvars
) {
957 /* push default keyword and var values */
958 pslot
= vars
+ numargs
;
959 qslot
= proto
->slots
+ numargs
- 1;
960 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
963 // do keyword lookup:
964 if (numKeyArgsPushed
&& methraw
->posargs
) {
965 PyrSymbol
**name0
, **name
;
967 name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
968 key
= g
->sp
+ numArgsPushed
+ 1;
969 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
971 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
972 if (*name
== slotRawSymbol(key
)) {
973 slotCopy(&vars
[j
+1], &key
[1]);
978 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
979 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
985 slotCopy(&g
->receiver
, &vars
[1]);
986 #ifdef GC_SANITYCHECK
987 g
->gc
->SanityCheck();
988 CallStackSanity(g
, "<executeMethodWithKeys");
993 HOT
void executeMethod(VMGlobals
*g
, PyrMethod
*meth
, long numArgsPushed
)
995 PyrMethodRaw
*methraw
;
998 PyrSlot
*pslot
, *qslot
;
1002 long i
, m
, mmax
, numtemps
, numargs
;
1004 #ifdef GC_SANITYCHECK
1005 g
->gc
->SanityCheck();
1006 CallStackSanity(g
, "executeMethod");
1009 if (gTraceInterpreter
) {
1011 postfl(" %s:%s -> %s:%s\n",
1012 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
,
1013 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1015 postfl(" top -> %s:%s\n",
1016 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1021 if (gTraceInterpreter
) {
1022 slotRawInt(&meth
->callMeter
)++;
1026 #if TAILCALLOPTIMIZE
1027 int tailCall
= g
->tailCall
;
1029 if (tailCall
== 1) {
1030 returnFromMethod(g
);
1039 proto
= slotRawObject(&meth
->prototypeFrame
);
1040 methraw
= METHRAW(meth
);
1041 numtemps
= methraw
->numtemps
;
1042 numargs
= methraw
->numargs
;
1045 //postfl("executeMethod allArgsPushed %d numKeyArgsPushed %d\n", allArgsPushed, numKeyArgsPushed);
1047 frame
= (PyrFrame
*)g
->gc
->NewFrame(methraw
->frameSize
, 0, obj_slot
, methraw
->needsHeapContext
);
1048 vars
= frame
->vars
- 1;
1049 frame
->classptr
= class_frame
;
1050 frame
->size
= FRAMESIZE
+ proto
->size
;
1051 SetObject(&frame
->method
, meth
);
1052 SetObject(&frame
->homeContext
, frame
);
1053 SetObject(&frame
->context
, frame
);
1056 SetPtr(&caller
->ip
, g
->ip
);
1057 SetObject(&frame
->caller
, caller
);
1059 SetInt(&frame
->caller
, 0);
1061 SetPtr(&frame
->ip
, 0);
1064 g
->ip
= slotRawInt8Array(&meth
->code
)->b
- 1;
1066 g
->block
= (PyrBlock
*)meth
;
1068 g
->sp
-= numArgsPushed
;
1072 if (numArgsPushed
<= numargs
) { /* not enough args pushed */
1073 /* push all args to frame */
1074 for (m
=0,mmax
=numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1076 /* push default arg & var values */
1077 pslot
= vars
+ numArgsPushed
;
1078 qslot
= proto
->slots
+ numArgsPushed
- 1;
1079 for (m
=0, mmax
=numtemps
- numArgsPushed
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1080 } else if (methraw
->varargs
) {
1084 /* push all normal args to frame */
1085 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1088 i
= numArgsPushed
- numargs
;
1089 list
= newPyrArray(g
->gc
, i
, 0, false);
1093 SetObject(rslot
, list
);
1094 //SetObject(vars + numargs + 1, list);
1096 /* put extra args into list */
1097 lslot
= (list
->slots
- 1);
1098 // fixed and raw sizes are zero
1099 for (m
=0,mmax
=i
; m
<mmax
; ++m
) slotCopy(++lslot
, ++qslot
);
1101 if (methraw
->numvars
) {
1102 /* push default keyword and var values */
1103 pslot
= vars
+ numargs
+ 1;
1104 qslot
= proto
->slots
+ numargs
;
1105 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1108 /* push all args to frame */
1109 for (m
=0,mmax
=numargs
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1111 if (methraw
->numvars
) {
1112 /* push default keyword and var values */
1113 pslot
= vars
+ numargs
;
1114 qslot
= proto
->slots
+ numargs
- 1;
1115 for (m
=0,mmax
=methraw
->numvars
; m
<mmax
; ++m
) slotCopy(++pslot
, ++qslot
);
1118 slotCopy(&g
->receiver
, &vars
[1]);
1120 #ifdef GC_SANITYCHECK
1121 g
->gc
->SanityCheck();
1122 CallStackSanity(g
, "<executeMethod");
1126 void switchToThread(VMGlobals
*g
, PyrThread
*newthread
, int oldstate
, int *numArgsPushed
);
1128 HOT
void returnFromBlock(VMGlobals
*g
)
1131 PyrFrame
*returnFrame
;
1132 PyrFrame
*homeContext
;
1135 PyrMethodRaw
*methraw
;
1136 PyrMethodRaw
*blockraw
;
1138 //if (gTraceInterpreter) postfl("->returnFromBlock\n");
1139 //printf("->returnFromBlock\n");
1140 #ifdef GC_SANITYCHECK
1141 g
->gc
->SanityCheck();
1142 CallStackSanity(g
, "returnFromBlock");
1144 curframe
= g
->frame
;
1147 returnFrame
= slotRawFrame(&curframe
->caller
);
1149 block
= slotRawBlock(&curframe
->method
);
1150 blockraw
= METHRAW(block
);
1152 g
->frame
= returnFrame
;
1153 g
->ip
= (unsigned char *)slotRawPtr(&returnFrame
->ip
);
1154 g
->block
= slotRawBlock(&returnFrame
->method
);
1155 homeContext
= slotRawFrame(&returnFrame
->homeContext
);
1156 meth
= slotRawMethod(&homeContext
->method
);
1157 methraw
= METHRAW(meth
);
1158 slotCopy(&g
->receiver
, &homeContext
->vars
[0]); //??
1161 meth
= slotRawMethod(&curframe
->method
);
1162 methraw
= METHRAW(meth
);
1163 if (!methraw
->needsHeapContext
) {
1164 g
->gc
->Free(curframe
);
1166 SetInt(&curframe
->caller
, 0);
1170 ////// this should never happen .
1171 error("return from Function at top of call stack.\n");
1175 g
->sp
= g
->gc
->Stack()->slots
- 1;
1176 longjmp(g
->escapeInterpreter
, 1);
1178 //if (gTraceInterpreter) postfl("<-returnFromBlock\n");
1179 #ifdef GC_SANITYCHECK
1180 g
->gc
->SanityCheck();
1181 CallStackSanity(g
, "returnFromBlock");
1186 HOT
void returnFromMethod(VMGlobals
*g
)
1188 PyrFrame
*returnFrame
, *curframe
, *homeContext
;
1190 PyrMethodRaw
*methraw
;
1191 curframe
= g
->frame
;
1193 //assert(slotRawFrame(&curframe->context) == NULL);
1195 /*if (gTraceInterpreter) {
1196 post("returnFromMethod %s:%s\n", slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name);
1197 post("tailcall %d\n", g->tailCall);
1199 #ifdef GC_SANITYCHECK
1200 g
->gc
->SanityCheck();
1202 homeContext
= slotRawFrame(&slotRawFrame(&curframe
->context
)->homeContext
);
1203 if (homeContext
== NULL
) {
1205 #if TAILCALLOPTIMIZE
1206 if (g
->tailCall
) return; // do nothing.
1210 static bool once = true;
1211 if (once || gTraceInterpreter)
1214 post("return all the way out. sd %d\n", g->sp - g->gc->Stack()->slots);
1216 slotRawClass(&g->method->ownerclass)->name.us->name, g->slotRawSymbol(&method->name)->name
1218 post("tailcall %d\n", g->tailCall);
1219 post("homeContext %p\n", homeContext);
1220 post("returnFrame %p\n", returnFrame);
1221 dumpObjectSlot(&homeContext->caller);
1222 DumpStack(g, g->sp);
1225 gTraceInterpreter = false;
1227 //if (IsNil(&homeContext->caller)) return; // do nothing.
1229 // return all the way out.
1230 PyrSlot
*bottom
= g
->gc
->Stack()->slots
;
1231 slotCopy(bottom
, g
->sp
);
1232 g
->sp
= bottom
; // ??!! pop everybody
1236 longjmp(g
->escapeInterpreter
, 2);
1238 returnFrame
= slotRawFrame(&homeContext
->caller
);
1240 if (returnFrame
== NULL
) goto null_return
;
1241 // make sure returnFrame is a caller and find earliest stack frame
1243 PyrFrame
*tempFrame
= curframe
;
1244 while (tempFrame
!= returnFrame
) {
1245 tempFrame
= slotRawFrame(&tempFrame
->caller
);
1247 if (isKindOf((PyrObject
*)g
->thread
, class_routine
) && NotNil(&g
->thread
->parent
)) {
1248 // not found, so yield to parent thread and continue searching.
1250 slotCopy(&value
, g
->sp
);
1252 int numArgsPushed
= 1;
1253 switchToThread(g
, slotRawThread(&g
->thread
->parent
), tSuspended
, &numArgsPushed
);
1255 // on the other side of the looking glass, put the yielded value on the stack as the result..
1256 g
->sp
-= numArgsPushed
- 1;
1257 slotCopy(g
->sp
, &value
);
1259 curframe
= tempFrame
= g
->frame
;
1261 slotCopy(&g
->sp
[2], &g
->sp
[0]);
1262 slotCopy(g
->sp
, &g
->receiver
);
1263 g
->sp
++; SetObject(g
->sp
, g
->method
);
1265 sendMessage(g
, getsym("outOfContextReturn"), 3);
1273 PyrFrame
*tempFrame
= curframe
;
1274 while (tempFrame
!= returnFrame
) {
1275 meth
= slotRawMethod(&tempFrame
->method
);
1276 methraw
= METHRAW(meth
);
1277 PyrFrame
*nextFrame
= slotRawFrame(&tempFrame
->caller
);
1278 if (!methraw
->needsHeapContext
) {
1279 SetInt(&tempFrame
->caller
, 0);
1281 if (tempFrame
!= homeContext
)
1282 SetInt(&tempFrame
->caller
, 0);
1284 tempFrame
= nextFrame
;
1289 g
->ip
= (unsigned char *)slotRawPtr(&returnFrame
->ip
);
1290 g
->frame
= returnFrame
;
1291 g
->block
= slotRawBlock(&returnFrame
->method
);
1293 homeContext
= slotRawFrame(&returnFrame
->homeContext
);
1294 meth
= slotRawMethod(&homeContext
->method
);
1295 methraw
= METHRAW(meth
);
1298 if (gTraceInterpreter
) {
1299 postfl("%s:%s <- %s:%s\n",
1300 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
,
1301 slotRawSymbol(&slotRawClass(&g
->method
->ownerclass
)->name
)->name
, slotRawSymbol(&g
->method
->name
)->name
1307 slotCopy(&g
->receiver
, &homeContext
->vars
[0]);
1310 #ifdef GC_SANITYCHECK
1311 g
->gc
->SanityCheck();
1316 int keywordFixStack(VMGlobals
*g
, PyrMethod
*meth
, PyrMethodRaw
*methraw
, long allArgsPushed
,
1317 long numKeyArgsPushed
)
1319 PyrSlot
*pslot
, *qslot
;
1320 long i
, j
, m
, diff
, numArgsPushed
, numArgsNeeded
;
1322 if (numKeyArgsPushed
) {
1323 // evacuate keyword args to separate area
1324 pslot
= keywordstack
+ (numKeyArgsPushed
<<1);
1326 for (m
=0; m
<numKeyArgsPushed
; ++m
) {
1327 *--pslot
= *--qslot
;
1328 *--pslot
= *--qslot
;
1332 PyrSlot
*vars
= g
->sp
- allArgsPushed
+ 1;
1334 numArgsPushed
= allArgsPushed
- (numKeyArgsPushed
<<1);
1335 numArgsNeeded
= methraw
->numargs
;
1336 diff
= numArgsNeeded
- numArgsPushed
;
1337 if (diff
> 0) { // not enough args
1338 pslot
= vars
+ numArgsPushed
- 1;
1339 qslot
= slotRawObject(&meth
->prototypeFrame
)->slots
+ numArgsPushed
- 1;
1340 for (m
=0; m
<diff
; ++m
) slotCopy(++pslot
, ++qslot
);
1341 numArgsPushed
= numArgsNeeded
;
1344 // do keyword lookup:
1345 if (numKeyArgsPushed
&& methraw
->posargs
) {
1346 PyrSymbol
**name0
= slotRawSymbolArray(&meth
->argNames
)->symbols
+ 1;
1347 PyrSlot
*key
= keywordstack
;
1348 for (i
=0; i
<numKeyArgsPushed
; ++i
, key
+=2) {
1349 PyrSymbol
**name
= name0
;
1350 for (j
=1; j
<methraw
->posargs
; ++j
, ++name
) {
1351 if (*name
== slotRawSymbol(key
)) {
1352 slotCopy(&vars
[j
], &key
[1]);
1356 if (gKeywordError
) {
1357 post("WARNING: keyword arg '%s' not found in call to %s:%s\n",
1358 slotRawSymbol(key
)->name
, slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
);
1364 g
->sp
+= numArgsPushed
- allArgsPushed
;
1365 return numArgsPushed
;