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
22 #include "PyrParseNode.h"
24 #include "PyrKernel.h"
25 #include "PyrListPrim.h"
26 #include "PyrSymbolTable.h"
28 #include "PyrKernelProto.h"
29 #include "PyrObjectProto.h"
36 #include "InitAlloc.h"
37 #include "PredefinedSymbols.h"
38 #include "SimpleStack.h"
39 #include "PyrPrimitive.h"
40 #include "SC_Win32Utils.h"
42 AdvancingAllocPool gParseNodePool
;
44 PyrSymbol
*gSpecialUnarySelectors
[opNumUnarySelectors
];
45 PyrSymbol
*gSpecialBinarySelectors
[opNumBinarySelectors
];
46 PyrSymbol
*gSpecialSelectors
[opmNumSpecialSelectors
];
47 PyrSymbol
* gSpecialClasses
[op_NumSpecialClasses
];
48 PyrSlot gSpecialValues
[svNumSpecialValues
];
50 PyrParseNode
* gRootParseNode
;
53 int conjureConstantIndex(PyrParseNode
*node
, PyrBlock
* func
, PyrSlot
*slot
);
54 void compilePushConstant(PyrParseNode
* node
, PyrSlot
*slot
);
56 PyrClass
*gCurrentClass
= NULL
;
57 PyrClass
*gCurrentMetaClass
= NULL
;
58 PyrClass
*gCompilingClass
= NULL
;
59 PyrMethod
*gCompilingMethod
= NULL
;
60 PyrBlock
*gCompilingBlock
= NULL
;
61 PyrBlock
*gPartiallyAppliedFunction
= NULL
;
63 bool gIsTailCodeBranch
= false;
64 bool gTailIsMethodReturn
= false;
65 int gFunctionHighestExternalRef
= 1;
66 bool gFunctionCantBeClosed
= true;
68 bool gGenerateTailCallByteCodes
= true;
70 bool gGenerateTailCallByteCodes
= false;
75 int compileErrors
= 0;
76 int numOverwrites
= 0;
77 std::string overwriteMsg
;
79 extern bool compilingCmdLine
;
80 extern int errLineOffset
, errCharPosOffset
;
82 bool gPostInlineWarnings
= false;
84 const char* nodename
[] = {
91 /* variable declarations */
117 "MultiAssignVarListNode",
127 if (gGenerateTailCallByteCodes
&& gIsTailCodeBranch
)
129 //if (gCompilingClass && gCompilingMethod) post("tail call %s:%s ismethod %d\n",
130 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name, gTailIsMethodReturn);
131 if (gTailIsMethodReturn
)
143 return gCompilingVMGlobals
? gCompilingVMGlobals
->gc
: 0;
150 overwriteMsg
.clear();
157 void initParseNodes()
161 void initParserPool()
163 //postfl("initPool gParseNodePool pyr_pool_compile\n");
164 gParseNodePool
.Init(pyr_pool_compile
, 32000, 32000, 2000);
167 void freeParserPool()
169 //postfl("freePool gParseNodePool pyr_pool_compile\n");
170 gParseNodePool
.FreeAll();
173 PyrParseNode::PyrParseNode(int inClassNo
)
175 mClassno
= inClassNo
;
183 void compileNodeList(PyrParseNode
*node
, bool onTailBranch
)
186 //postfl("->compileNodeList\n");
187 for (; node
; node
= node
->mNext
) {
188 //postfl("-->compileNodeList %p\n", node);
189 COMPILENODE(node
, &dummy
, onTailBranch
);
190 //postfl("<--compileNodeList %p\n", node);
192 //postfl("<-compileNodeList\n");
195 void nodePostErrorLine(PyrParseNode
* node
)
197 postErrorLine(node
->mLineno
, linestarts
[node
->mLineno
], node
->mCharno
);
200 PyrPushNameNode
* newPyrPushNameNode(PyrSlotNode
*slotNode
)
202 slotNode
->mClassno
= pn_PushNameNode
;
203 return (PyrPushNameNode
*)slotNode
;
206 void compilePushVar(PyrParseNode
*node
, PyrSymbol
*varName
)
208 int level
, index
, vindex
, varType
;
212 //postfl("compilePushVar\n");
213 classobj
= gCompilingClass
;
214 if (varName
->name
[0] >= 'A' && varName
->name
[0] <= 'Z') {
215 if (compilingCmdLine
&& varName
->u
.classobj
== NULL
) {
216 error("Class not defined.\n");
217 nodePostErrorLine(node
);
220 if (findSpecialClassName(varName
, &index
)) {
221 compileOpcode(opExtended
, opPushSpecialValue
); // special op for pushing a class
225 SetSymbol(&slot
, varName
);
226 index
= conjureLiteralSlotIndex(node
, gCompilingBlock
, &slot
);
227 compileOpcode(opExtended
, opExtended
); // special op for pushing a class
231 } else if (varName
== s_this
|| varName
== s_super
) {
232 gFunctionCantBeClosed
= true;
233 compileOpcode(opPushSpecialValue
, opsvSelf
);
234 } else if (varName
== s_true
) {
235 compileOpcode(opPushSpecialValue
, opsvTrue
);
236 } else if (varName
== s_false
) {
237 compileOpcode(opPushSpecialValue
, opsvFalse
);
238 } else if (varName
== s_nil
) {
239 compileOpcode(opPushSpecialValue
, opsvNil
);
240 } else if (findVarName(gCompilingBlock
, &classobj
, varName
,
241 &varType
, &level
, &index
, &tempfunc
)) {
245 compileOpcode(opPushInstVar
, index
);
248 index
+= slotRawInt(&classobj
->classVarIndex
);
250 compileByte((opPushClassVar
<<4) | ((index
>> 8) & 15));
251 compileByte(index
& 255);
253 compileByte(opPushClassVar
);
254 compileByte((index
>> 8) & 255);
255 compileByte(index
& 255);
259 PyrSlot
*slot
= slotRawObject(&classobj
->constValues
)->slots
+ index
;
260 compilePushConstant(node
, slot
);
265 compileOpcode(opPushTempZeroVar
, vindex
);
266 } else if (level
< 8) {
267 compileOpcode(opPushTempVar
, level
);
270 compileByte(opPushTempVar
);
276 compileOpcode(opExtended
, opSpecialOpcode
);
281 error("Variable '%s' not defined.\n", varName
->name
);
282 nodePostErrorLine(node
);
288 PyrCurryArgNode
* newPyrCurryArgNode()
290 PyrCurryArgNode
* node
= ALLOCNODE(PyrCurryArgNode
);
294 void PyrCurryArgNode::compile(PyrSlot
*result
)
296 if (gPartiallyAppliedFunction
) {
297 compileOpcode(opPushTempZeroVar
, mArgNum
);
299 error("found _ argument outside of a call.\n");
300 nodePostErrorLine((PyrParseNode
*)this);
305 PyrSlotNode
* newPyrSlotNode(PyrSlot
*slot
)
307 PyrSlotNode
* node
= ALLOCNODE(PyrSlotNode
);
312 void PyrSlotNode::compile(PyrSlot
*result
)
314 if (mClassno
== pn_LiteralNode
)
315 compileLiteral(result
);
316 else if (mClassno
== pn_PushLitNode
)
317 compilePushLit(result
);
318 else if (mClassno
== pn_PushNameNode
)
319 compilePushVar((PyrParseNode
*)this, slotRawSymbol(&mSlot
));
321 error("compilePyrSlotNode: shouldn't get here.\n");
322 dumpObjectSlot(&mSlot
);
323 nodePostErrorLine((PyrParseNode
*)this);
330 PyrClassExtNode
* newPyrClassExtNode(PyrSlotNode
* className
, PyrMethodNode
* methods
)
332 PyrClassExtNode
* node
= ALLOCNODE(PyrClassExtNode
);
333 node
->mClassName
= className
;
335 node
->mMethods
= methods
;
339 void PyrClassExtNode::compile(PyrSlot
*result
)
341 PyrClass
*classobj
= slotRawSymbol(&mClassName
->mSlot
)->u
.classobj
;
344 asRelativePath(gCompilingFileSym
->name
, extPath
);
345 error("Class extension for nonexistent class '%s'\n In file:'%s'\n",
346 slotRawSymbol(&mClassName
->mSlot
)->name
,
351 gCurrentClass
= classobj
;
352 gCurrentMetaClass
= classobj
->classptr
;
353 compileExtNodeMethods(this);
356 void compileExtNodeMethods(PyrClassExtNode
* node
)
358 PyrMethodNode
*method
;
359 method
= node
->mMethods
;
360 for (; method
; method
= (PyrMethodNode
*)method
->mNext
) {
362 //post("compile ext %s:%s\n",
363 method
->mExtension
= true;
364 compilePyrMethodNode(method
, &dummy
);
366 gCompilingMethod
= NULL
;
367 gCompilingBlock
= NULL
;
368 gPartiallyAppliedFunction
= NULL
;
372 PyrClassNode
* newPyrClassNode(PyrSlotNode
* className
, PyrSlotNode
* superClassName
,
373 PyrVarListNode
* varlists
, PyrMethodNode
* methods
, PyrSlotNode
* indexType
)
375 PyrClassNode
* node
= ALLOCNODE(PyrClassNode
);
376 node
->mClassName
= className
;
377 node
->mIndexType
= indexType
;
379 node
->mSuperClassName
= superClassName
;
380 node
->mVarlists
= varlists
;
381 node
->mMethods
= methods
;
382 node
->mVarTally
[varInst
] = 0;
383 node
->mVarTally
[varClass
] = 0;
384 node
->mVarTally
[varTemp
] = 0;
385 node
->mVarTally
[varConst
] = 0;
386 //node->mVarTally[varPool] = 0;
390 bool compareVarDefs(PyrClassNode
* node
, PyrClass
* classobj
)
392 int numinstvars
, numclassvars
;
393 int i
, xinst
, xclass
;
394 PyrVarListNode
* varlist
;
395 PyrVarDefNode
*vardef
;
396 PyrParseNode
*errnode
;
397 PyrSymbol
**varNames
;
400 isIntrinsic
= slotRawInt(&classobj
->classFlags
) & classIsIntrinsic
;
402 numinstvars
= numInstVars(classobj
);
403 numclassvars
= numClassVars(classobj
);
404 if (numinstvars
== node
->mVarTally
[varInst
] + node
->mNumSuperInstVars
405 && numclassvars
== node
->mVarTally
[varClass
]) {
408 xinst
= node
->mNumSuperInstVars
;
409 varlist
= node
->mVarlists
;
410 for (; varlist
; varlist
= (PyrVarListNode
*)varlist
->mNext
) {
411 int type
= varlist
->mFlags
;
412 if (type
== varInst
) {
413 vardef
= varlist
->mVarDefs
;
414 varNames
= slotRawSymbolArray(&classobj
->instVarNames
)->symbols
;
415 for (i
=0; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
, xinst
++, ++i
) {
416 if (slotRawSymbol(&vardef
->mVarName
->mSlot
) != varNames
[xinst
]) {
417 errnode
= (PyrParseNode
*)vardef
;
418 //post("A %s %d %d %d\n", vardef->mVarName->slotRawSymbol(&mSlot)->name,
419 // vardef->mVarName->slotRawSymbol(&mSlot), varNames[xinst].us, xinst);
420 //post("A %s %s %d\n", vardef->mVarName->slotRawSymbol(&mSlot)->name,
421 // varNames[xinst].us->name, xinst);
425 } else if (type
== varClass
) {
426 vardef
= varlist
->mVarDefs
;
427 varNames
= slotRawSymbolArray(&classobj
->classVarNames
)->symbols
;
428 for (i
=0; vardef
&& xclass
< numclassvars
; vardef
= (PyrVarDefNode
*)vardef
->mNext
, xclass
++, ++i
) {
429 if (slotRawSymbol(&vardef
->mVarName
->mSlot
) != varNames
[xclass
]) {
430 errnode
= (PyrParseNode
*)vardef
;
431 //post("B %d %d %d\n", vardef->mVarName->slotRawSymbol(&mSlot), varNames[xclass].us, xclass);
438 //post("C %d %d %d %d %d\n", numinstvars, node->mVarTally[varInst], node->mNumSuperInstVars,
439 // numclassvars, node->mVarTally[varClass]);
440 errnode
= (node
->mVarlists
? (PyrParseNode
*)node
->mVarlists
: (PyrParseNode
*)node
->mClassName
);
447 error("You may not change variable definitions of intrinsic classes.\n");
448 nodePostErrorLine(errnode
);
454 void countClassVarDefs(PyrClassNode
* node
, int *numClassMethods
, int *numInstMethods
)
456 PyrVarListNode
* varlist
;
457 PyrVarDefNode
*vardef
;
459 //*numClassMethods = 0;
460 //*numInstMethods = 0;
462 node
->mVarTally
[varInst
] = 0;
463 node
->mVarTally
[varClass
] = 0;
464 node
->mVarTally
[varTemp
] = 0;
465 node
->mVarTally
[varConst
] = 0;
467 // count number of variables of each type
468 varlist
= node
->mVarlists
;
469 for (; varlist
; varlist
= (PyrVarListNode
*)varlist
->mNext
) {
470 int type
= varlist
->mFlags
;
471 vardef
= varlist
->mVarDefs
;
472 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
473 node
->mVarTally
[type
]++;
474 if (type
== varClass
) {
475 if (vardef
->mFlags
& rwReadOnly
) {
476 *numClassMethods
= *numClassMethods
+ 1;
478 if (vardef
->mFlags
& rwWriteOnly
) {
479 *numClassMethods
= *numClassMethods
+ 1;
481 } else if (type
== varInst
) {
482 if (vardef
->mFlags
& rwReadOnly
) {
483 *numInstMethods
= *numInstMethods
+ 1;
485 if (vardef
->mFlags
& rwWriteOnly
) {
486 *numInstMethods
= *numInstMethods
+ 1;
493 void countNodeMethods(PyrClassNode
* node
, int *numClassMethods
, int *numInstMethods
)
496 PyrMethodNode
*method
;
497 //*numClassMethods = 0;
498 //*numInstMethods = 0;
499 method
= node
->mMethods
;
500 for (; method
; method
= (PyrMethodNode
*)method
->mNext
) {
501 if (method
->mIsClassMethod
) *numClassMethods
= *numClassMethods
+ 1;
502 else *numInstMethods
= *numInstMethods
+ 1;
506 void compileNodeMethods(PyrClassNode
* node
)
508 PyrMethodNode
*method
;
509 method
= node
->mMethods
;
510 for (; method
; method
= (PyrMethodNode
*)method
->mNext
) {
512 method
->mExtension
= false;
513 compilePyrMethodNode(method
, &dummy
);
515 gCompilingMethod
= NULL
;
516 gCompilingBlock
= NULL
;
517 gPartiallyAppliedFunction
= NULL
;
521 PyrClass
* getNodeSuperclass(PyrClassNode
*node
)
523 PyrClass
*superclassobj
= NULL
;
524 // postfl("getNodeSuperclass node %d\n", node);
525 // postfl("getNodeSuperclass node->mSuperClassName %d\n", node->mSuperClassName);
526 // postfl("getNodeSuperclass node->mSuperClassName->mSlot.utag %d\n",
527 // node->mSuperClassName->mSlot.utag);
528 if (node
->mSuperClassName
&& IsSym(&node
->mSuperClassName
->mSlot
)) {
529 superclassobj
= slotRawSymbol(&node
->mSuperClassName
->mSlot
)->u
.classobj
;
530 if (superclassobj
== NULL
) {
531 error("Cannot find superclass '%s' for class '%s'\n",
532 slotSymString(&node
->mSuperClassName
->mSlot
),
533 slotSymString(&node
->mClassName
->mSlot
));
534 nodePostErrorLine((PyrParseNode
*)node
->mSuperClassName
);
535 superclassobj
= (PyrClass
*)-1;
539 if (slotRawSymbol(&node
->mClassName
->mSlot
) != s_object
) {
540 superclassobj
= class_object
;
541 } // else this is object and there is no superclass
543 return superclassobj
;
546 void fillClassPrototypes(PyrClassNode
*node
, PyrClass
*classobj
, PyrClass
*superclassobj
)
548 PyrVarListNode
* varlist
;
549 PyrVarDefNode
*vardef
;
550 PyrSlot
*islot
, *cslot
, *kslot
;
551 PyrSymbol
**inameslot
, **cnameslot
, **knameslot
;
552 PyrClass
*metaclassobj
;
554 PyrMethodRaw
*methraw
;
555 int instVarIndex
, classVarIndex
;
557 // copy superclass's prototype to here
558 if (superclassobj
&& NotNil(&superclassobj
->iprototype
)
559 && slotRawObject(&superclassobj
->iprototype
)->size
) {
561 memcpy(slotRawObject(&classobj
->iprototype
)->slots
, slotRawObject(&superclassobj
->iprototype
)->slots
,
562 sizeof(PyrSlot
)* slotRawObject(&superclassobj
->iprototype
)->size
);
563 //slotRawObject(&classobj->iprototype)->size = slotRawObject(&superclassobj->iprototype)->size;
564 slotRawObject(&classobj
->iprototype
)->size
= node
->mNumSuperInstVars
;
566 memcpy(slotRawSymbolArray(&classobj
->instVarNames
)->symbols
,
567 slotRawSymbolArray(&superclassobj
->instVarNames
)->symbols
,
568 sizeof(PyrSymbol
*)* slotRawObject(&superclassobj
->instVarNames
)->size
);
569 //slotRawObject(&classobj->instVarNames)->size = slotRawObject(&superclassobj->iprototype)->size;
570 slotRawObject(&classobj
->instVarNames
)->size
= node
->mNumSuperInstVars
;
572 // fill the class' own part of prototypes
573 metaclassobj
= classobj
->classptr
;
574 varlist
= node
->mVarlists
;
575 if (NotNil(&classobj
->iprototype
)) {
576 islot
= slotRawObject(&classobj
->iprototype
)->slots
+ node
->mNumSuperInstVars
;
578 if (NotNil(&classobj
->cprototype
)) {
579 cslot
= slotRawObject(&classobj
->cprototype
)->slots
;
581 if (NotNil(&classobj
->constValues
)) {
582 kslot
= slotRawObject(&classobj
->constValues
)->slots
;
584 if (NotNil(&classobj
->instVarNames
)) {
585 inameslot
= slotRawSymbolArray(&classobj
->instVarNames
)->symbols
+ node
->mNumSuperInstVars
;
587 if (NotNil(&classobj
->classVarNames
)) {
588 cnameslot
= slotRawSymbolArray(&classobj
->classVarNames
)->symbols
;
590 if (NotNil(&classobj
->constNames
)) {
591 knameslot
= slotRawSymbolArray(&classobj
->constNames
)->symbols
;
593 instVarIndex
= node
->mNumSuperInstVars
;
595 for (; varlist
; varlist
= (PyrVarListNode
*)varlist
->mNext
) {
596 int type
= varlist
->mFlags
;
599 vardef
= varlist
->mVarDefs
;
600 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
602 compilePyrLiteralNode((PyrLiteralNode
*)vardef
->mDefVal
, &litslot
);
604 slotRawObject(&classobj
->iprototype
)->size
++;
605 *inameslot
++ = slotRawSymbol(&vardef
->mVarName
->mSlot
);
606 slotRawSymbolArray(&classobj
->instVarNames
)->size
++;
607 if (vardef
->mFlags
& rwReadOnly
) {
608 // create getter method
609 method
= newPyrMethod();
610 methraw
= METHRAW(method
);
611 methraw
->unused1
= 0;
612 methraw
->unused2
= 0;
613 methraw
->numargs
= 1;
614 methraw
->numvars
= 0;
615 methraw
->posargs
= 1;
616 methraw
->varargs
= 0;
617 methraw
->numtemps
= 1;
618 methraw
->popSize
= 0;
619 SetNil(&method
->contextDef
);
620 SetNil(&method
->varNames
);
621 SetObject(&method
->ownerclass
, classobj
);
622 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
623 SetInt(&method
->charPos
, linestarts
[vardef
->mVarName
->mLineno
] + errCharPosOffset
);
624 slotCopy(&method
->name
, &vardef
->mVarName
->mSlot
);
625 methraw
->methType
= methReturnInstVar
;
626 methraw
->specialIndex
= instVarIndex
;
627 addMethod(classobj
, method
);
629 if (vardef
->mFlags
& rwWriteOnly
) {
630 char setterName
[256];
631 PyrSymbol
*setterSym
;
632 sprintf(setterName
, "%s_", slotRawSymbol(&vardef
->mVarName
->mSlot
)->name
);
633 //underscore = strcpy(setterName, slotRawSymbol(&vardef->mVarName->mSlot)->name);
634 //underscore[0] = '_';
636 setterSym
= getsym(setterName
);
637 // create setter method
638 method
= newPyrMethod();
639 methraw
= METHRAW(method
);
640 methraw
->unused1
= 0;
641 methraw
->unused2
= 0;
642 methraw
->numargs
= 2;
643 methraw
->numvars
= 0;
644 methraw
->posargs
= 2;
645 methraw
->varargs
= 0;
646 methraw
->numtemps
= 2;
647 methraw
->popSize
= 1;
648 SetNil(&method
->contextDef
);
649 SetNil(&method
->varNames
);
650 SetObject(&method
->ownerclass
, classobj
);
651 SetSymbol(&method
->name
, setterSym
);
652 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
653 SetInt(&method
->charPos
, linestarts
[vardef
->mVarName
->mLineno
] + errCharPosOffset
);
655 methraw
->methType
= methAssignInstVar
;
656 methraw
->specialIndex
= instVarIndex
;
657 addMethod(classobj
, method
);
663 vardef
= varlist
->mVarDefs
;
664 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
666 compilePyrLiteralNode((PyrLiteralNode
*)vardef
->mDefVal
, &litslot
);
668 slotRawObject(&classobj
->cprototype
)->size
++;
669 *cnameslot
++ = slotRawSymbol(&vardef
->mVarName
->mSlot
);
670 slotRawSymbolArray(&classobj
->classVarNames
)->size
++;
671 if (vardef
->mFlags
& rwReadOnly
) {
672 // create getter method
673 method
= newPyrMethod();
674 methraw
= METHRAW(method
);
675 methraw
->unused1
= 0;
676 methraw
->unused2
= 0;
677 methraw
->numargs
= 1;
678 methraw
->numvars
= 0;
679 methraw
->posargs
= 1;
680 methraw
->varargs
= 0;
681 methraw
->numtemps
= 1;
682 methraw
->popSize
= 0;
683 SetNil(&method
->contextDef
);
684 SetNil(&method
->varNames
);
685 SetObject(&method
->ownerclass
, metaclassobj
);
686 slotCopy(&method
->name
, &vardef
->mVarName
->mSlot
);
687 SetSymbol(&method
->selectors
, slotRawSymbol(&classobj
->name
));
688 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
689 SetInt(&method
->charPos
, linestarts
[vardef
->mVarName
->mLineno
] + errCharPosOffset
);
691 methraw
->methType
= methReturnClassVar
;
692 methraw
->specialIndex
= classVarIndex
+ slotRawInt(&classobj
->classVarIndex
);
693 addMethod(metaclassobj
, method
);
695 if (vardef
->mFlags
& rwWriteOnly
) {
696 char setterName
[256];
697 PyrSymbol
*setterSym
;
698 sprintf(setterName
, "%s_", slotRawSymbol(&vardef
->mVarName
->mSlot
)->name
);
699 //underscore = strcpy(setterName, slotRawSymbol(&vardef->mVarName->mSlot)->name);
700 //underscore[0] = '_';
702 setterSym
= getsym(setterName
);
703 // create setter method
704 method
= newPyrMethod();
705 methraw
= METHRAW(method
);
706 methraw
->numargs
= 2;
707 methraw
->numvars
= 0;
708 methraw
->posargs
= 2;
709 methraw
->varargs
= 0;
710 methraw
->numtemps
= 2;
711 methraw
->popSize
= 1;
712 SetNil(&method
->contextDef
);
713 SetNil(&method
->varNames
);
714 SetObject(&method
->ownerclass
, metaclassobj
);
715 SetSymbol(&method
->name
, setterSym
);
716 SetSymbol(&method
->selectors
, slotRawSymbol(&classobj
->name
));
717 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
718 SetInt(&method
->charPos
, linestarts
[vardef
->mVarName
->mLineno
] + errCharPosOffset
);
720 methraw
->methType
= methAssignClassVar
;
721 methraw
->specialIndex
= classVarIndex
+ slotRawInt(&classobj
->classVarIndex
);
722 addMethod(metaclassobj
, method
);
728 vardef
= varlist
->mVarDefs
;
729 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
731 compilePyrLiteralNode((PyrLiteralNode
*)vardef
->mDefVal
, &litslot
);
733 slotRawObject(&classobj
->constValues
)->size
++;
734 *knameslot
++ = slotRawSymbol(&vardef
->mVarName
->mSlot
);
735 slotRawSymbolArray(&classobj
->constNames
)->size
++;
736 if (vardef
->mFlags
& rwReadOnly
) {
737 // create getter method
738 method
= newPyrMethod();
739 methraw
= METHRAW(method
);
740 methraw
->unused1
= 0;
741 methraw
->unused2
= 0;
742 methraw
->numargs
= 1;
743 methraw
->numvars
= 0;
744 methraw
->posargs
= 1;
745 methraw
->varargs
= 0;
746 methraw
->numtemps
= 1;
747 methraw
->popSize
= 0;
748 SetNil(&method
->contextDef
);
749 SetNil(&method
->varNames
);
750 SetObject(&method
->ownerclass
, metaclassobj
);
751 slotCopy(&method
->name
, &vardef
->mVarName
->mSlot
);
752 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
753 SetInt(&method
->charPos
, linestarts
[vardef
->mVarName
->mLineno
] + errCharPosOffset
);
755 methraw
->methType
= methReturnLiteral
;
756 slotCopy(&method
->selectors
, &litslot
);
757 addMethod(metaclassobj
, method
);
765 int getIndexType(PyrClassNode
*classnode
)
770 node
= classnode
->mIndexType
;
771 if (node
== NULL
) res
= obj_notindexed
;
774 name
= slotRawSymbol(&node
->mSlot
)->name
;
775 if (strcmp(name
, "slot") == 0) res
= obj_slot
;
776 else if (strcmp(name
, "double") == 0) res
= obj_double
;
777 else if (strcmp(name
, "float") == 0) res
= obj_float
;
778 else if (strcmp(name
, "int32") == 0) res
= obj_int32
;
779 else if (strcmp(name
, "int16") == 0) res
= obj_int16
;
780 else if (strcmp(name
, "int8") == 0) res
= obj_int8
;
781 else if (strcmp(name
, "char") == 0) res
= obj_char
;
782 else if (strcmp(name
, "symbol") == 0) res
= obj_symbol
;
784 error("Illegal indexed type. Must be one of:\n"
785 " slot, double, float, int8, int16, int32, char\n");
794 void PyrClassNode::compile(PyrSlot
*result
)
796 PyrClass
*classobj
, *superclassobj
, *metaclassobj
;
797 int numClassMethods
, numInstMethods
;
799 bool varsDiffer
, superclassesDiffer
, indexTypesDiffer
;
800 bool shouldRecompileSubclasses
= false;
803 // find num instvars in superclass
804 //postfl("class '%s'\n", slotRawSymbol(&mClassName->mSlot)->name);
805 superclassobj
= getNodeSuperclass(this);
806 indexType
= getIndexType(this);
807 //postfl("%s %d\n", slotRawSymbol(&mClassName->mSlot)->name, indexType);
809 if ((size_t)superclassobj
== -1) {
810 // redundant error message removed:
811 //error("Can't find superclass of '%s'\n", slotRawSymbol(&mClassName->mSlot)->name);
812 //nodePostErrorLine(node);
813 return; // can't find superclass
815 mNumSuperInstVars
= numSuperInstVars(superclassobj
);
819 countClassVarDefs(this, &numClassMethods
, &numInstMethods
);
820 //postfl("accessor methods %d %d\n", numClassMethods, numInstMethods);
821 countNodeMethods(this, &numClassMethods
, &numInstMethods
);
822 //postfl("total methods %d %d\n", numClassMethods, numInstMethods);
824 // get or make a class object
825 // see if it already exists
826 classobj
= slotRawSymbol(&mClassName
->mSlot
)->u
.classobj
;
828 // deal with intrinsic classes or other classes being recompiled here.
829 // recompile of subclasses not necessary if inst and class vars are
831 metaclassobj
= (PyrClass
*)classobj
->classptr
;
832 isIntrinsic
= slotRawInt(&classobj
->classFlags
) & classIsIntrinsic
;
834 varsDiffer
= compareVarDefs(this, classobj
);
837 //error("Class '%s' declaration doesn't match intrinsic definition.\n",
838 // slotRawSymbol(&mClassName->mSlot)->name);
841 shouldRecompileSubclasses
= true;
844 superclassesDiffer
= superclassobj
!= slotRawSymbol(&classobj
->superclass
)->u
.classobj
;
845 indexTypesDiffer
= indexType
!= slotRawInt(&classobj
->instanceFormat
);
846 //postfl("%d %d %d\n", indexType, slotRawInt(&classobj->instanceFormat));
847 //if (varsDiffer || superclassesDiffer || indexTypesDiffer) {
848 if (varsDiffer
|| superclassesDiffer
|| indexTypesDiffer
) {
850 if (superclassesDiffer
) {
851 error("Superclass of '%s' does not match intrinsic definition.\n",
852 slotRawSymbol(&mClassName
->mSlot
)->name
);
853 nodePostErrorLine((PyrParseNode
*)(mSuperClassName
?
854 mSuperClassName
: mClassName
));
857 if (indexTypesDiffer
) {
858 error("Index type of '%s' does not match intrinsic definition.\n",
859 slotRawSymbol(&mClassName
->mSlot
)->name
);
860 nodePostErrorLine((indexType
? (PyrParseNode
*)mIndexType
: (PyrParseNode
*)mClassName
));
863 error("Class '%s' declaration doesn't match intrinsic definition.\n",
864 slotRawSymbol(&mClassName
->mSlot
)->name
);
867 shouldRecompileSubclasses
= true;
870 // reallocate fields in the class object
871 reallocClassObj(metaclassobj
,
872 classClassNumInstVars
, 0, 0,
873 numClassMethods
, indexType
, 0);
875 //postfl("^3 %d %d\n", metaclassobj, class_class);
876 //postfl("^4 %d %d\n", slotRawObject(&metaclassobj->iprototype), slotRawObject(&class_class->iprototype));
877 memcpy(slotRawObject(&metaclassobj
->iprototype
)->slots
, slotRawObject(&class_class
->iprototype
)->slots
,
878 sizeof(PyrSlot
) * classClassNumInstVars
);
879 memcpy(slotRawSymbolArray(&metaclassobj
->instVarNames
)->symbols
,
880 slotRawSymbolArray(&class_class
->instVarNames
)->symbols
,
881 sizeof(PyrSymbol
*) * classClassNumInstVars
);
882 slotRawObject(&metaclassobj
->iprototype
)->size
= classClassNumInstVars
;
883 slotRawSymbolArray(&metaclassobj
->instVarNames
)->size
= classClassNumInstVars
;
885 reallocClassObj(classobj
,
886 mVarTally
[varInst
] + mNumSuperInstVars
,
889 numInstMethods
, indexType
, 0);
892 PyrSymbol
*superClassName
, *metaClassName
, *metaSuperClassName
;
894 superClassName
= superclassobj
? slotRawSymbol(&superclassobj
->name
) : NULL
;
895 metaClassName
= getmetasym(slotRawSymbol(&mClassName
->mSlot
)->name
);
896 metaClassName
->flags
|= sym_MetaClass
;
897 metaSuperClassName
= superClassName
? getmetasym(superClassName
->name
) : NULL
;
899 metaclassobj
= newClassObj(class_class
,
900 metaClassName
, metaSuperClassName
,
901 classClassNumInstVars
, 0, 0, numClassMethods
, indexType
, 0);
903 //postfl("^1 %d %d\n", metaclassobj, class_class);
904 //postfl("^2 %d %d\n", slotRawObject(&metaclassobj->iprototype), slotRawObject(&class_class->iprototype));
906 memcpy(slotRawObject(&metaclassobj
->iprototype
)->slots
, slotRawObject(&class_class
->iprototype
)->slots
,
907 sizeof(PyrSlot
) * classClassNumInstVars
);
908 memcpy(slotRawSymbolArray(&metaclassobj
->instVarNames
)->symbols
,
909 slotRawSymbolArray(&class_class
->instVarNames
)->symbols
,
910 sizeof(PyrSymbol
*) * classClassNumInstVars
);
911 slotRawObject(&metaclassobj
->iprototype
)->size
= classClassNumInstVars
;
912 slotRawObject(&metaclassobj
->instVarNames
)->size
= classClassNumInstVars
;
914 classobj
= newClassObj(metaclassobj
,
915 slotRawSymbol(&mClassName
->mSlot
), superClassName
,
916 mVarTally
[varInst
] + mNumSuperInstVars
,
917 mVarTally
[varClass
], mVarTally
[varConst
], numInstMethods
, indexType
, 0);
919 gCurrentClass
= classobj
;
920 gCurrentMetaClass
= metaclassobj
;
921 if (gCompilingFileSym
) {
922 SetSymbol(&classobj
->filenameSym
, gCompilingFileSym
);
923 SetInt(&classobj
->charPos
, linestarts
[mClassName
->mLineno
] + errCharPosOffset
);
924 SetSymbol(&metaclassobj
->filenameSym
, gCompilingFileSym
);
925 SetInt(&metaclassobj
->charPos
, linestarts
[mClassName
->mLineno
] + errCharPosOffset
);
927 SetNil(&classobj
->filenameSym
);
928 SetNil(&metaclassobj
->filenameSym
);
931 // fill inst and class prototypes
932 fillClassPrototypes(this, classobj
, superclassobj
);
935 compileNodeMethods(this);
937 // recompileSubclasses
938 if (shouldRecompileSubclasses
) {
939 recompileSubclasses(classobj
);
943 void recompileSubclasses(PyrClass
* classobj
)
948 void catVarLists(PyrVarListNode
*varlist
);
949 void catVarLists(PyrVarListNode
*varlist
)
951 PyrVarListNode
*prevvarlist
;
952 PyrVarDefNode
*vardef
, *lastvardef
;
955 // find end of this list
956 vardef
= varlist
->mVarDefs
;
957 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
960 prevvarlist
= varlist
;
961 varlist
= (PyrVarListNode
*)varlist
->mNext
;
963 for (; varlist
; varlist
= (PyrVarListNode
*)varlist
->mNext
) {
964 vardef
= varlist
->mVarDefs
;
966 lastvardef
->mNext
= (PyrParseNode
*)vardef
;
968 prevvarlist
->mVarDefs
= vardef
;
970 // find end of this list
971 for (; vardef
; vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
980 void catVarLists(PyrVarListNode
*varlist
);
981 void catVarLists(PyrVarListNode
*varlist
)
983 PyrVarListNode
*prevvarlist
;
984 PyrVarDefNode
*vardef
, *lastvardef
;
987 // find end of this list
988 vardef
= varlist
->mVarDefs
;
989 lastvardef
= (PyrVarDefNode
*)vardef
->mTail
;
990 prevvarlist
= varlist
;
991 varlist
= (PyrVarListNode
*)varlist
->mNext
;
993 for (; varlist
; varlist
= (PyrVarListNode
*)varlist
->mNext
) {
994 vardef
= varlist
->mVarDefs
;
995 lastvardef
->mNext
= (PyrParseNode
*)vardef
;
997 // find end of this list
998 lastvardef
= (PyrVarDefNode
*)vardef
->mTail
;
1004 PyrMethodNode
* newPyrMethodNode(PyrSlotNode
* methodName
, PyrSlotNode
* primitiveName
,
1005 PyrArgListNode
* arglist
, PyrVarListNode
*varlist
, PyrParseNode
* body
, int isClassMethod
)
1007 PyrMethodNode
* node
= ALLOCNODE(PyrMethodNode
);
1008 node
->mMethodName
= methodName
;
1009 node
->mPrimitiveName
= primitiveName
;
1010 node
->mArglist
= arglist
;
1011 catVarLists(varlist
);
1012 node
->mVarlist
= varlist
;
1014 node
->mIsClassMethod
= isClassMethod
;
1018 enum { push_Normal
, push_AllArgs
, push_AllButFirstArg
, push_AllButFirstArg2
};
1020 int checkPushAllArgs(PyrParseNode
*actualArg
, int numArgs
);
1021 int checkPushAllArgs(PyrParseNode
*actualArg
, int numArgs
)
1024 PyrPushNameNode
*nameNode
;
1025 block
= gCompilingBlock
;
1028 //if (strcmp("ar", slotRawSymbol(&gCompilingMethod->name)->name)==0) Debugger();
1029 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1033 actualArg
= actualArg
->mNext
;
1034 for (i
=1; i
<numArgs
; ++i
) {
1035 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1038 nameNode
= (PyrPushNameNode
*)actualArg
;
1039 if (slotRawSymbol(&nameNode
->mSlot
) != slotRawSymbolArray(&block
->argNames
)->symbols
[i
]) {
1043 actualArg
= actualArg
->mNext
;
1045 return push_AllButFirstArg
;
1048 for (i
=0; i
<numArgs
; ++i
) {
1049 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1052 nameNode
= (PyrPushNameNode
*)actualArg
;
1053 if (slotRawSymbol(&nameNode
->mSlot
) != slotRawSymbolArray(&block
->argNames
)->symbols
[i
]) {
1056 actualArg
= actualArg
->mNext
;
1058 return push_AllArgs
;
1063 int checkPushAllButFirstTwoArgs(PyrParseNode
*actualArg
, int numArgs
);
1064 int checkPushAllButFirstTwoArgs(PyrParseNode
*actualArg
, int numArgs
)
1067 PyrPushNameNode
*nameNode
;
1068 block
= gCompilingBlock
;
1072 actualArg
= actualArg
->mNext
;
1073 actualArg
= actualArg
->mNext
;
1074 for (i
=1; i
<numArgs
; ++i
) {
1075 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1078 nameNode
= (PyrPushNameNode
*)actualArg
;
1079 /*if (slotRawSymbol(&gCompilingClass->name) == s_ugen) {
1080 post("check meth %s %d '%s' '%s'\n", slotRawSymbol(&gCompilingMethod->name)->name, i,
1081 slotRawSymbol(&nameNode->mSlot)->name,
1082 block->argNames.uosym->symbols[i]->name);
1084 if (slotRawSymbol(&nameNode
->mSlot
) != slotRawSymbolArray(&block
->argNames
)->symbols
[i
]) {
1088 actualArg
= actualArg
->mNext
;
1090 return push_AllButFirstArg2
;
1095 int compareCallArgs(PyrMethodNode
* node
, PyrCallNode
*cnode
, int *varIndex
, PyrClass
**specialClass
)
1097 int i
, numFormalArgs
, numActualArgs
;
1098 int special
, varType
, varLevel
;
1099 PyrParseNode
*actualArg
;
1100 PyrVarDefNode
*formalArg
;
1101 PyrPushNameNode
*nameNode
;
1103 // fail if has a rest arg .. too much trouble?
1104 if (node
->mArglist
&& node
->mArglist
->mRest
) {
1108 // check first actual arg is 'this'
1109 actualArg
= cnode
->mArglist
;
1110 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1113 nameNode
= (PyrPushNameNode
*)actualArg
;
1114 if (slotRawSymbol(&nameNode
->mSlot
) == s_this
) {
1115 special
= methRedirect
;
1116 } else if (slotRawSymbol(&nameNode
->mSlot
) == s_super
) {
1117 special
= methRedirectSuper
;
1122 classobj
= gCompilingClass
;
1123 varFound
= findVarName(gCompilingBlock
, &classobj
, slotRawSymbol(&nameNode
->mSlot
),
1124 &varType
, &varLevel
, varIndex
, NULL
);
1125 if (!varFound
) return methNormal
;
1127 if (varType
== varInst
) special
= methForwardInstVar
;
1128 else if (varType
== varClass
) {
1129 special
= methForwardClassVar
;
1130 *varIndex
+= slotRawInt(&classobj
->classVarIndex
);
1131 *specialClass
= classobj
;
1133 else return methNormal
;
1136 actualArg
= actualArg
->mNext
;
1137 numActualArgs
= nodeListLength((PyrParseNode
*)cnode
->mArglist
);
1139 if (!node
->mArglist
) {
1141 if (numActualArgs
!= numFormalArgs
) {
1145 numFormalArgs
= 1 + nodeListLength((PyrParseNode
*)node
->mArglist
->mVarDefs
);
1146 if (numActualArgs
!= numFormalArgs
) {
1150 formalArg
= node
->mArglist
->mVarDefs
;
1151 for (i
=0; i
<numActualArgs
-1; ++i
) {
1152 if (actualArg
->mClassno
!= pn_PushNameNode
) {
1156 nameNode
= (PyrPushNameNode
*)actualArg
;
1157 if (slotRawSymbol(&nameNode
->mSlot
) != slotRawSymbol(&formalArg
->mVarName
->mSlot
)) {
1161 formalArg
= (PyrVarDefNode
*)formalArg
->mNext
;
1162 actualArg
= actualArg
->mNext
;
1166 if (special == methForwardInstVar) {
1167 postfl("methForwardInstVar %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1168 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1170 if (special == methForwardClassVar) {
1171 postfl("methForwardClassVar %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1172 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1174 if (special == methRedirectSuper) {
1175 postfl("methRedirectSuper %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1176 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1180 // if (special == methTempDelegate) {
1181 // postfl("methTempDelegate %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
1182 // slotRawSymbol(&gCompilingMethod->name)->name);
1187 void installByteCodes(PyrBlock
*block
)
1189 PyrInt8Array
*byteArray
;
1191 ByteCodes byteCodes
;
1192 byteCodes
= getByteCodes();
1194 length
= byteCodeLength(byteCodes
);
1196 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
1197 byteArray
= newPyrInt8Array(compileGC(), length
, flags
, false);
1198 copyByteCodes(byteArray
->b
, byteCodes
);
1199 byteArray
->size
= length
;
1200 freeByteCodes(byteCodes
);
1201 SetObject(&block
->code
, byteArray
);
1203 error("installByteCodes: zero length byte codes\n");
1206 error("installByteCodes: NULL byte codes\n");
1210 PyrMethod
* initPyrMethod(PyrMethod
* method
);
1212 void compilePyrMethodNode(PyrMethodNode
*node
, PyrSlot
*result
)
1214 node
->compile(result
);
1217 void PyrMethodNode::compile(PyrSlot
*result
)
1219 PyrMethod
*method
, *oldmethod
;
1220 PyrMethodRaw
*methraw
;
1221 int i
, j
, numArgs
, numVars
, methType
, funcVarArgs
, firstKeyIndex
;
1222 int index
, numSlots
, numArgNames
;
1223 bool hasPrimitive
= false;
1224 bool hasVarExprs
= false;
1225 PyrVarDefNode
*vardef
;
1227 PyrSymbolArray
*argNames
, *varNames
;
1229 SetTailBranch
branch(false);
1231 //postfl("->method '%s'\n", slotRawSymbol(&mMethodName->mSlot)->name);
1232 gCompilingClass
= mIsClassMethod
? gCurrentMetaClass
: gCurrentClass
;
1233 oldmethod
= classFindDirectMethod(gCompilingClass
, slotRawSymbol(&mMethodName
->mSlot
));
1235 if (oldmethod
&& !mExtension
) {
1236 error("Method %s:%s already defined.\n",
1237 slotRawSymbol(&slotRawClass(&oldmethod
->ownerclass
)->name
)->name
, slotRawSymbol(&oldmethod
->name
)->name
);
1238 nodePostErrorLine((PyrParseNode
*)mMethodName
);
1246 // accumulate overwrite message onto the string buffer
1248 .append(slotRawSymbol(&slotRawClass(&oldmethod
->ownerclass
)->name
)->name
)
1250 .append(slotRawSymbol(&oldmethod
->name
)->name
)
1252 .append(gCompilingFileSym
->name
)
1254 .append(slotRawSymbol(&oldmethod
->filenameSym
)->name
)
1258 freePyrSlot(&method
->code
);
1259 freePyrSlot(&method
->selectors
);
1260 freePyrSlot(&method
->prototypeFrame
);
1261 freePyrSlot(&method
->argNames
);
1262 freePyrSlot(&method
->varNames
);
1263 initPyrMethod(method
);
1265 method
= newPyrMethod();
1267 SetObject(&method
->ownerclass
, gCompilingClass
);
1269 methraw
= METHRAW(method
);
1270 methraw
->unused1
= 0;
1271 methraw
->unused2
= 0;
1273 //postfl("method %p raw %p\n", method, methraw);
1274 method
->contextDef
= o_nil
;
1275 method
->name
= mMethodName
->mSlot
;
1276 if (gCompilingFileSym
) SetSymbol(&method
->filenameSym
, gCompilingFileSym
);
1277 SetInt(&method
->charPos
, linestarts
[mMethodName
->mLineno
] + errCharPosOffset
);
1278 if (mPrimitiveName
) {
1279 hasPrimitive
= true;
1280 method
->primitiveName
= mPrimitiveName
->mSlot
;
1281 methraw
->specialIndex
= slotRawSymbol(&mPrimitiveName
->mSlot
)->u
.index
;
1283 gCompilingBlock
= (PyrBlock
*)method
;
1284 gCompilingMethod
= (PyrMethod
*)method
;
1285 gPartiallyAppliedFunction
= NULL
;
1288 methraw
->needsHeapContext
= 0;
1290 methraw
->varargs
= funcVarArgs
= (mArglist
&& mArglist
->mRest
) ? 1 : 0;
1291 numArgs
= mArglist
? nodeListLength((PyrParseNode
*)mArglist
->mVarDefs
) + 1 : 1;
1292 numVars
= mVarlist
? nodeListLength((PyrParseNode
*)mVarlist
->mVarDefs
) : 0;
1294 numSlots
= numArgs
+ funcVarArgs
+ numVars
;
1295 methraw
->frameSize
= (numSlots
+ FRAMESIZE
) * sizeof(PyrSlot
);
1297 methraw
->numargs
= numArgs
;
1298 methraw
->numvars
= numVars
;
1299 methraw
->posargs
= numArgs
+ funcVarArgs
;
1300 methraw
->numtemps
= numSlots
;
1301 methraw
->popSize
= numSlots
- 1;
1302 firstKeyIndex
= numArgs
+ funcVarArgs
;
1304 numArgNames
= methraw
->posargs
;
1306 if (numSlots
== 1) {
1307 slotCopy(&method
->argNames
, &o_argnamethis
);
1308 slotCopy(&method
->prototypeFrame
, &o_onenilarray
);
1310 argNames
= newPyrSymbolArray(NULL
, numArgNames
, obj_permanent
| obj_immutable
, false);
1311 argNames
->size
= numArgNames
;
1312 SetObject(&method
->argNames
, argNames
);
1314 proto
= newPyrArray(NULL
, numSlots
, obj_permanent
| obj_immutable
, false);
1315 proto
->size
= numSlots
;
1316 SetObject(&method
->prototypeFrame
, proto
);
1319 slotRawSymbolArray(&method
->argNames
)->symbols
[0] = s_this
;
1321 PyrSymbol
**methargs
;
1322 methargs
= slotRawSymbolArray(&method
->argNames
)->symbols
;
1323 vardef
= mArglist
->mVarDefs
;
1324 for (i
=1; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1326 varslot
= &vardef
->mVarName
->mSlot
;
1327 // already declared as arg?
1328 for (j
=0; j
<i
; ++j
) {
1329 if (methargs
[j
] == slotRawSymbol(varslot
)) {
1330 error("Argument '%s' already declared in %s:%s\n",
1331 slotRawSymbol(varslot
)->name
,
1332 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
1333 nodePostErrorLine((PyrParseNode
*)vardef
);
1337 // put it in arglist
1338 methargs
[i
] = slotRawSymbol(varslot
);
1339 //postfl("defarg %d '%s'\n", i, slotRawSymbol(slot)->name);
1340 /*if (slotRawSymbol(varslot)->name[0] == 'a'
1341 && slotRawSymbol(varslot)->name[1] == 'r'
1342 && slotRawSymbol(varslot)->name[2] == 'g')
1344 post("%d %s:%s '%s'\n", i,
1345 slotRawSymbol(&gCompilingClass->name)->name,
1346 slotRawSymbol(&gCompilingMethod->name)->name,
1347 slotRawSymbol(varslot)->name);
1352 varslot
= &mArglist
->mRest
->mSlot
;
1353 // already declared as arg?
1354 for (j
=0; j
<numArgs
; ++j
) {
1355 if (methargs
[j
] == slotRawSymbol(varslot
)) {
1356 error("Argument '%s' already declared in %s:%s\n",
1357 slotRawSymbol(varslot
)->name
,
1358 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
1359 nodePostErrorLine((PyrParseNode
*)vardef
);
1363 // put it in arglist
1364 methargs
[i
] = slotRawSymbol(varslot
);
1365 //postfl("defrest '%s'\n", slotRawSymbol(slot)->name);
1368 // fill prototype args
1369 if (NotNil(&method
->prototypeFrame
)) {
1370 SetNil(&slotRawObject(&method
->prototypeFrame
)->slots
[0]);
1373 vardef
= mArglist
->mVarDefs
;
1374 for (i
=1; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1375 PyrSlot
*slot
, litval
;
1376 slot
= slotRawObject(&method
->prototypeFrame
)->slots
+ i
;
1377 //compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litval);
1378 if (vardef
->hasExpr(&litval
)) hasVarExprs
= true;
1382 slotCopy(&slotRawObject(&method
->prototypeFrame
)->slots
[numArgs
], &o_emptyarray
);
1388 varNames
= newPyrSymbolArray(NULL
, numVars
, obj_permanent
| obj_immutable
, false);
1389 varNames
->size
= numVars
;
1390 SetObject(&method
->varNames
, varNames
);
1392 SetNil(&method
->varNames
);
1397 PyrSymbol
**methargs
, **methvars
;
1398 methargs
= slotRawSymbolArray(&method
->argNames
)->symbols
;
1399 methvars
= slotRawSymbolArray(&method
->varNames
)->symbols
;
1400 vardef
= mVarlist
->mVarDefs
;
1401 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1403 varslot
= &vardef
->mVarName
->mSlot
;
1404 // already declared as arg?
1405 for (j
=0; j
<numArgNames
; ++j
) {
1406 if (methargs
[j
] == slotRawSymbol(varslot
)) {
1407 error("Variable '%s' already declared in %s:%s\n",
1408 slotRawSymbol(varslot
)->name
,
1409 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
1410 nodePostErrorLine((PyrParseNode
*)vardef
);
1414 // already declared as var?
1415 for (j
=0; j
<i
; ++j
) {
1416 if (methvars
[j
] == slotRawSymbol(varslot
)) {
1417 error("Variable '%s' already declared in %s:%s\n",
1418 slotRawSymbol(varslot
)->name
,
1419 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
1420 nodePostErrorLine((PyrParseNode
*)vardef
);
1424 // put it in mVarlist
1425 methvars
[i
] = slotRawSymbol(varslot
);
1426 //postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
1431 vardef
= mVarlist
->mVarDefs
;
1432 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1433 PyrSlot
*slot
, litval
;
1434 slot
= slotRawObject(&method
->prototypeFrame
)->slots
+ i
+ numArgs
+ funcVarArgs
;
1435 if (vardef
->hasExpr(&litval
)) hasVarExprs
= true;
1436 //compilePyrLiteralNode(vardef->mDefVal, &litval);
1441 methType
= methNormal
;
1443 methType
= methNormal
;
1444 } else if (hasPrimitive
) {
1445 methType
= methPrimitive
;
1447 if (getPrimitiveNumArgs(methraw->specialIndex) != numArgs) {
1448 post("warning: number of arguments for method %s:%s does not match primitive %s. %d vs %d\n",
1449 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name,
1450 getPrimitiveName(methraw->specialIndex)->name,
1451 numArgs, getPrimitiveNumArgs(methraw->specialIndex));
1454 } else if (slotRawSymbol(&gCompilingMethod
->name
) == s_nocomprendo
) {
1455 methType
= methNormal
;
1457 int bodyType
= mBody
->mClassno
;
1458 if (bodyType
== pn_ReturnNode
) {
1459 PyrReturnNode
*rnode
;
1460 PyrParseNode
*xnode
;
1464 rnode
= (PyrReturnNode
*)mBody
;
1465 xnode
= (PyrParseNode
*)rnode
->mExpr
;
1467 rtype
= xnode
->mClassno
;
1468 if (rtype
== pn_PushLitNode
) { // return literal ?
1469 compilePyrLiteralNode((PyrLiteralNode
*)xnode
, &rslot
);
1470 if (IsObj(&rslot
) && slotRawObject(&rslot
)->classptr
== class_fundef
) {
1471 methType
= methNormal
;
1473 methType
= methReturnLiteral
;
1474 method
->selectors
= rslot
;
1476 } else if (rtype
== pn_PushNameNode
) {
1478 rslot
= &((PyrPushNameNode
*)xnode
)->mSlot
;
1479 if (slotRawSymbol(rslot
) == s_this
) { // return this
1480 methType
= methReturnSelf
;
1482 if (funcFindArg((PyrBlock
*)method
, slotRawSymbol(rslot
), &index
)) { // return arg ?
1483 // eliminate the case where its an ellipsis or keyword argument
1484 if (index
< methraw
->numargs
) {
1485 methType
= methReturnArg
;
1486 methraw
->specialIndex
= index
; // when you change sp to sp - 1
1487 //methraw->specialIndex = index - 1;
1489 } else if (classFindInstVar(gCompilingClass
, slotRawSymbol(rslot
), &index
)) {
1491 methType
= methReturnInstVar
;
1492 methraw
->specialIndex
= index
;
1495 } else if (rtype
== pn_CallNode
) {
1496 // need to do this for binary opcodes too..
1499 PyrClass
*specialClass
= 0;
1500 cnode
= (PyrCallNode
*)xnode
;
1501 methType
= compareCallArgs(this, cnode
, &specialIndex
, &specialClass
);
1502 if (methType
!= methNormal
) {
1503 methraw
->specialIndex
= specialIndex
;
1504 method
->selectors
= cnode
->mSelector
->mSlot
;
1505 if (specialClass
) method
->constants
= specialClass
->name
;
1509 methType
= methReturnSelf
;
1511 } else if (bodyType
== pn_AssignNode
&& numArgs
== 2) { // assign inst var ?
1512 PyrAssignNode
*anode
;
1513 //post("methAssignInstVar 1 %s:%s\n",
1514 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1515 anode
= (PyrAssignNode
*)mBody
;
1516 if (anode
->mNext
&& anode
->mNext
->mClassno
== pn_ReturnNode
1517 && ((PyrReturnNode
*)anode
->mNext
)->mExpr
== NULL
) {
1518 //post("methAssignInstVar 2 %s:%s\n",
1519 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1520 if (classFindInstVar(gCompilingClass
, slotRawSymbol(&anode
->mVarName
->mSlot
), &index
)) {
1521 methType
= methAssignInstVar
;
1522 methraw
->specialIndex
= index
;
1523 //post("methAssignInstVar 3 %s:%s\n",
1524 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1530 methraw
->methType
= methType
;
1532 // optimize common cases
1534 if (methType
== methNormal
|| methType
== methPrimitive
) {
1541 if (gCompilingClass
== class_int
) {
1542 // handle some special cases
1543 name
= slotRawSymbol(&method
->name
);
1544 if (name
== gSpecialSelectors
[opmDo
]) {
1549 } else if (name
== gSpecialSelectors
[opmReverseDo
]) {
1556 } else if (name
== gSpecialSelectors
[opmFor
]) {
1563 } else if (name
== gSpecialSelectors
[opmForBy
]) {
1570 } else goto compile_body
;
1571 } else if (gCompilingClass
== class_arrayed_collection
) {
1572 name
= slotRawSymbol(&method
->name
);
1573 if (name
== gSpecialSelectors
[opmDo
]) {
1578 } else if (name
== gSpecialSelectors
[opmReverseDo
]) {
1585 } else goto compile_body
;
1586 } else if (slotRawSymbol(&gCompilingClass
->name
) == s_dictionary
) {
1587 name
= slotRawSymbol(&method
->name
);
1588 if (name
== getsym("keysValuesArrayDo")) {
1593 } else goto compile_body
;
1594 } else if (gCompilingClass
== class_number
) {
1595 name
= slotRawSymbol(&method
->name
);
1596 if (name
== gSpecialSelectors
[opmForSeries
]) {
1603 } else goto compile_body
;
1604 } else if (gCompilingClass
== class_float
) {
1605 // handle some special cases
1606 name
= slotRawSymbol(&method
->name
);
1607 if (name
== gSpecialSelectors
[opmDo
]) {
1612 } else if (name
== gSpecialSelectors
[opmReverseDo
]) {
1619 } else goto compile_body
;
1622 SetTailIsMethodReturn
mr(false);
1624 vardef
= mArglist
->mVarDefs
;
1625 for (i
=1; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1626 vardef
->compileArg(&dummy
);
1630 vardef
= mVarlist
->mVarDefs
;
1631 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
1632 vardef
->compile(&dummy
);
1635 COMPILENODE(mBody
, &dummy
, true);
1637 installByteCodes((PyrBlock
*)method
);
1641 addMethod(gCompilingClass
, method
);
1644 gCompilingMethod
= NULL
;
1645 gCompilingBlock
= NULL
;
1646 gPartiallyAppliedFunction
= NULL
;
1648 //postfl("<-method '%s'\n", slotRawSymbol(&mMethodName->mSlot)->name);
1651 PyrArgListNode
* newPyrArgListNode(PyrVarDefNode
* varDefs
, PyrSlotNode
* rest
)
1653 PyrArgListNode
* node
= ALLOCNODE(PyrArgListNode
);
1654 node
->mVarDefs
= varDefs
;
1659 void PyrArgListNode::compile(PyrSlot
*result
)
1661 error("compilePyrArgListNode: shouldn't get here.\n");
1666 PyrVarListNode
* newPyrVarListNode(PyrVarDefNode
* vardefs
, int flags
)
1668 PyrVarListNode
* node
= ALLOCNODE(PyrVarListNode
);
1669 node
->mVarDefs
= vardefs
;
1670 node
->mFlags
= flags
;
1674 void PyrVarListNode::compile(PyrSlot
*result
)
1676 error("compilePyrVarListNode: shouldn't get here.\n");
1680 PyrVarDefNode
* newPyrVarDefNode(PyrSlotNode
* varName
, PyrParseNode
* defVal
,
1683 PyrVarDefNode
* node
= ALLOCNODE(PyrVarDefNode
);
1684 node
->mVarName
= varName
;
1685 node
->mDefVal
= defVal
;
1686 node
->mFlags
= flags
;
1691 bool PyrVarDefNode::hasExpr(PyrSlot
*result
)
1693 if (result
) SetNil(result
);
1694 if (!mDefVal
) return false;
1695 if (mDefVal
->mClassno
!= pn_PushLitNode
&& mDefVal
->mClassno
!= pn_LiteralNode
) {
1696 //post("hasExpr A %s:%s %s %d\n", slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name, mVarName->slotRawSymbol(&mSlot)->name, mDefVal->mClassno);
1699 PyrPushLitNode
*node
= (PyrPushLitNode
*)mDefVal
;
1701 if (IsPtr(&node
->mSlot
)) {
1702 PyrParseNode
* litnode
= (PyrParseNode
*)slotRawPtr(&node
->mSlot
);
1704 if (litnode
->mClassno
== pn_BlockNode
) {
1705 //post("hasExpr B %s:%s %s %d\n", slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name, mVarName->slotRawSymbol(&mSlot)->name, node->mClassno);
1708 if (result
) node
->compileLiteral(result
);
1711 } else if (result
) *result
= node
->mSlot
;
1712 if (node
->mParens
) return true;
1716 void PyrVarDefNode::compile(PyrSlot
*result
)
1718 if (hasExpr(NULL
)) {
1719 COMPILENODE(mDefVal
, result
, false);
1720 compileAssignVar((PyrParseNode
*)this, slotRawSymbol(&mVarName
->mSlot
), mDrop
);
1723 //error("compilePyrVarDefNode: shouldn't get here.\n");
1727 void PyrVarDefNode::compileArg(PyrSlot
*result
)
1729 if (hasExpr(NULL
)) {
1730 ByteCodes trueByteCodes
;
1732 compilePushVar((PyrParseNode
*)this, slotRawSymbol(&mVarName
->mSlot
));
1735 trueByteCodes
= compileBodyWithGoto(this, 0, true);
1736 int jumplen
= byteCodeLength(trueByteCodes
);
1738 compileByte(143); // special opcodes
1740 compileByte((jumplen
>> 8) & 0xFF);
1741 compileByte(jumplen
& 0xFF);
1742 compileAndFreeByteCodes(trueByteCodes
);
1743 compileOpcode(opSpecialOpcode
, opcDrop
); // drop the boolean
1746 //error("compilePyrVarDefNode: shouldn't get here.\n");
1751 PyrCallNode
* newPyrCallNode(PyrSlotNode
* selector
, PyrParseNode
* arglist
,
1752 PyrParseNode
* keyarglist
, PyrParseNode
* blocklist
)
1754 PyrCallNode
* node
= ALLOCNODE(PyrCallNode
);
1755 node
->mSelector
= selector
;
1757 arglist
= linkNextNode(arglist
, blocklist
);
1759 node
->mArglist
= arglist
;
1760 node
->mKeyarglist
= keyarglist
;
1764 int PyrCallNode::isPartialApplication()
1767 PyrParseNode
* argnode
= mArglist
;
1768 for (; argnode
; argnode
= argnode
->mNext
) {
1769 if (argnode
->mClassno
== pn_CurryArgNode
) {
1770 ((PyrCurryArgNode
*)argnode
)->mArgNum
= sum
;
1775 PyrParseNode
* keynode
= mKeyarglist
;
1776 for (; keynode
; keynode
= keynode
->mNext
) {
1777 if (keynode
->mClassno
== pn_CurryArgNode
) {
1778 ((PyrCurryArgNode
*)keynode
)->mArgNum
= sum
;
1785 void PyrCallNodeBase::compilePartialApplication(int numCurryArgs
, PyrSlot
*result
)
1787 // create a function
1790 ByteCodes savedBytes
= saveByteCodeArray();
1792 int flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
1793 PyrBlock
* block
= newPyrBlock(flags
);
1796 SetObject(&blockSlot
, block
);
1798 int prevFunctionHighestExternalRef
= gFunctionHighestExternalRef
;
1799 bool prevFunctionCantBeClosed
= gFunctionCantBeClosed
;
1800 gFunctionHighestExternalRef
= 0;
1801 gFunctionCantBeClosed
= false;
1803 PyrClass
* prevClass
= gCompilingClass
;
1804 PyrBlock
* prevBlock
= gCompilingBlock
;
1805 gCompilingBlock
= block
;
1807 PyrBlock
* prevPartiallyAppliedFunction
= gPartiallyAppliedFunction
;
1808 gPartiallyAppliedFunction
= block
;
1810 PyrMethodRaw
* methraw
= METHRAW(block
);
1811 methraw
->unused1
= 0;
1812 methraw
->unused2
= 0;
1814 methraw
->needsHeapContext
= 0;
1816 SetObject(&block
->contextDef
, prevBlock
);
1818 methraw
->varargs
= 0;
1820 methraw
->frameSize
= (numCurryArgs
+ FRAMESIZE
) * sizeof(PyrSlot
);
1821 PyrObject
* proto
= newPyrArray(compileGC(), numCurryArgs
, flags
, false);
1822 proto
->size
= numCurryArgs
;
1823 SetObject(&block
->prototypeFrame
, proto
);
1825 PyrSymbolArray
* argNames
= newPyrSymbolArray(compileGC(), numCurryArgs
, flags
, false);
1826 argNames
->size
= numCurryArgs
;
1827 SetObject(&block
->argNames
, argNames
);
1829 SetNil(&block
->varNames
);
1831 methraw
->numargs
= numCurryArgs
;
1832 methraw
->numvars
= 0;
1833 methraw
->posargs
= numCurryArgs
;
1834 methraw
->numtemps
= numCurryArgs
;
1835 methraw
->popSize
= numCurryArgs
;
1836 methraw
->methType
= methBlock
;
1839 PyrSymbol
* s_empty
= getsym("_");
1840 PyrSymbol
**blockargs
= slotRawSymbolArray(&block
->argNames
)->symbols
;
1841 for (int i
=0; i
<numCurryArgs
; ++i
) {
1842 // put it in mArglist
1843 blockargs
[i
] = s_empty
;
1844 SetNil(proto
->slots
+ i
);
1850 SetTailBranch
branch(true);
1851 SetTailIsMethodReturn
mr(false);
1855 compileOpcode(opSpecialOpcode
, opcFunctionReturn
);
1856 installByteCodes(block
);
1858 gCompilingBlock
= prevBlock
;
1859 gPartiallyAppliedFunction
= prevPartiallyAppliedFunction
;
1861 restoreByteCodeArray(savedBytes
);
1862 int index
= conjureLiteralSlotIndex(this, gCompilingBlock
, &blockSlot
);
1863 compileOpcode(opExtended
, opPushLiteral
);
1866 if (!gFunctionCantBeClosed
&& gFunctionHighestExternalRef
== 0) {
1867 SetNil(&block
->contextDef
);
1869 METHRAW(prevBlock
)->needsHeapContext
= 1;
1872 gCompilingBlock
= prevBlock
;
1873 gCompilingClass
= prevClass
;
1874 gPartiallyAppliedFunction
= prevPartiallyAppliedFunction
;
1875 gFunctionCantBeClosed
= gFunctionCantBeClosed
|| prevFunctionCantBeClosed
;
1876 gFunctionHighestExternalRef
= sc_max(gFunctionHighestExternalRef
- 1, prevFunctionHighestExternalRef
);
1879 void PyrCallNodeBase::compile(PyrSlot
*result
)
1882 int numCurryArgs
= isPartialApplication();
1884 compilePartialApplication(numCurryArgs
, result
);
1886 compileCall(result
);
1890 bool isSeries(PyrParseNode
* node
, PyrParseNode
** args
)
1892 if (node
->mClassno
!= pn_CallNode
) return false;
1893 PyrCallNode
*callnode
= (PyrCallNode
*)node
;
1894 if (slotRawSymbol(&callnode
->mSelector
->mSlot
) != s_series
) return false;
1895 if (callnode
->mKeyarglist
) return false;
1896 *args
= callnode
->mArglist
;
1900 void PyrCallNode::compileCall(PyrSlot
*result
)
1905 PyrParseNode
*argnode2
;
1907 //postfl("compilePyrCallNode\n");
1908 PyrParseNode
* argnode
= mArglist
;
1909 PyrParseNode
* keynode
= mKeyarglist
;
1910 int numArgs
= nodeListLength(argnode
);
1911 int numKeyArgs
= nodeListLength(keynode
);
1912 int isSuper
= isSuperObjNode(argnode
);
1913 int numBlockArgs
= METHRAW(gCompilingBlock
)->numargs
;
1915 slotRawSymbol(&mSelector
->mSlot
)->flags
|= sym_Called
;
1916 index
= conjureSelectorIndex((PyrParseNode
*)mSelector
, gCompilingBlock
,
1917 isSuper
, slotRawSymbol(&mSelector
->mSlot
), &selType
);
1919 if (numKeyArgs
> 0 || (numArgs
> 15 && !(selType
== selSwitch
|| selType
== selCase
))) {
1920 for (; argnode
; argnode
= argnode
->mNext
) {
1921 COMPILENODE(argnode
, &dummy
, false);
1923 for (; keynode
; keynode
= keynode
->mNext
) {
1924 COMPILENODE(keynode
, &dummy
, false);
1928 compileByte(opSendSuper
);
1929 compileByte(numArgs
+ 2*numKeyArgs
);
1930 compileByte(numKeyArgs
);
1936 compileByte(opSendMsg
);
1937 compileByte(numArgs
+ 2*numKeyArgs
);
1938 compileByte(numKeyArgs
);
1943 compileByte(opSendSpecialMsg
);
1944 compileByte(numArgs
+ 2*numKeyArgs
);
1945 compileByte(numKeyArgs
);
1950 index
= conjureLiteralSlotIndex((PyrParseNode
*)mSelector
,
1951 gCompilingBlock
, &mSelector
->mSlot
);
1955 compileByte(opSendMsg
);
1956 compileByte(numArgs
+ 2*numKeyArgs
);
1957 compileByte(numKeyArgs
);
1962 } else if (isSuper
) {
1964 // pushes this as well, don't compile arg
1965 gFunctionCantBeClosed
= true;
1967 compileOpcode(opSendSuper
, numArgs
);
1970 for (; argnode
; argnode
= argnode
->mNext
) {
1971 COMPILENODE(argnode
, &dummy
, false);
1974 compileOpcode(opSendSuper
, numArgs
);
1979 if (argnode
->mClassno
== pn_PushNameNode
) {
1980 varname
= slotRawSymbol(&((PyrPushNameNode
*)argnode
)->mSlot
);
1984 if (varname
== s_this
) {
1985 gFunctionCantBeClosed
= true;
1989 if (numArgs
== 1 && varname
== s_this
) {
1991 compileOpcode(opSendMsg
, 0);
1993 //} else if (numArgs>1 && numArgs == numBlockArgs) {
1994 } else if (numArgs
>1 && numArgs
== numBlockArgs
) {
1995 // try for multiple push optimization
1997 code
= checkPushAllArgs(argnode
, numArgs
);
1998 if (code
== push_Normal
) goto normal
;
1999 else if (code
== push_AllArgs
) {
2001 compileByte(137); // push all args, send msg
2003 //post("137 pushAllArgs %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2004 // slotRawSymbol(&gCompilingMethod->name)->name);
2005 } else if (code
== push_AllButFirstArg
) {
2006 COMPILENODE(argnode
, &dummy
, false);
2008 compileByte(138); // push all but first arg, send msg
2010 //post("138 pushAllButFirstArg %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2011 // slotRawSymbol(&gCompilingMethod->name)->name);
2013 } else if (numArgs
>2 && numArgs
== numBlockArgs
+1) {
2015 code
= checkPushAllButFirstTwoArgs(argnode
, numBlockArgs
);
2016 if (code
== push_Normal
) goto normal
;
2017 else if (code
== push_AllButFirstArg2
) {
2018 COMPILENODE(argnode
, &dummy
, false);
2019 COMPILENODE(argnode
->mNext
, &dummy
, false);
2021 compileByte(141); // one arg pushed, push all but first arg, send msg
2023 //post("141 pushAllButFirstArg2 %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2024 // slotRawSymbol(&gCompilingMethod->name)->name);
2029 for (; argnode
; argnode
= argnode
->mNext
) {
2030 COMPILENODE(argnode
, &dummy
, false);
2033 compileOpcode(opSendMsg
, numArgs
);
2039 if (varname
== s_this
) {
2041 compileOpcode(opSendSpecialMsg
, 0);
2043 } else if (varname
) {
2046 int varType
, varLevel
, varIndex
;
2047 classobj
= gCompilingClass
;
2048 varFound
= findVarName(gCompilingBlock
, &classobj
, varname
,
2049 &varType
, &varLevel
, &varIndex
, &tempFunc
);
2050 if (varFound
&& varType
== varInst
) {
2051 //post("136 pushInstVar(sp) %s:%s '%s' %d %d\n", slotRawSymbol(&gCompilingClass->name)->name,
2052 // slotRawSymbol(&gCompilingMethod->name)->name, varname->name, varIndex, index);
2055 compileByte(varIndex
);
2057 } else goto special
;
2058 } else goto special
;
2059 } else if (index
== opmDo
&& isSeries(argnode
, &argnode
)) {
2060 index
= opmForSeries
;
2061 mArglist
= linkNextNode(argnode
, mArglist
->mNext
);
2062 numArgs
= nodeListLength(mArglist
);
2064 } else if (numArgs
>1 && numArgs
== numBlockArgs
) {
2065 //} else if (numArgs>1 && numArgs == numBlockArgs) {
2066 // try for multiple push optimization
2068 code
= checkPushAllArgs(argnode
, numArgs
);
2069 if (code
== push_Normal
) goto special
;
2070 else if (code
== push_AllArgs
) {
2072 compileByte(139); // push all args, send special msg
2074 //post("139 pushAllArgs(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2075 // slotRawSymbol(&gCompilingMethod->name)->name);
2076 } else if (code
== push_AllButFirstArg
) {
2077 COMPILENODE(argnode
, &dummy
, false);
2079 compileByte(140); // push all but first arg, send special msg
2081 //post("140 pushAllButFirstArg(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2082 // slotRawSymbol(&gCompilingMethod->name)->name);
2083 } else goto special
;
2084 } else if (numArgs
>2 && numArgs
== numBlockArgs
+1) {
2086 code
= checkPushAllButFirstTwoArgs(argnode
, numBlockArgs
);
2087 if (code
== push_Normal
) goto special
;
2088 else if (code
== push_AllButFirstArg2
) {
2089 COMPILENODE(argnode
, &dummy
, false);
2090 COMPILENODE(argnode
->mNext
, &dummy
, false);
2092 compileByte(142); // one arg pushed, push all but first arg, send msg
2094 //post("142 pushAllButFirstArg2(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2095 // slotRawSymbol(&gCompilingMethod->name)->name);
2096 } else goto special
;
2100 for (i
=0; argnode
; argnode
= argnode
->mNext
,i
++) {
2101 COMPILENODE(argnode
, &dummy
, false);
2104 compileOpcode(opSendSpecialMsg
, numArgs
);
2110 index
= conjureLiteralSlotIndex((PyrParseNode
*)mSelector
, gCompilingBlock
,
2114 for (; argnode
; argnode
= argnode
->mNext
) {
2115 COMPILENODE(argnode
, &dummy
, false);
2118 compileOpcode(opSendSpecialUnaryArithMsg
, index
);
2122 index
= conjureLiteralSlotIndex((PyrParseNode
*)mSelector
, gCompilingBlock
,
2126 //for (; argnode; argnode = argnode->mNext) {
2127 // COMPILENODE(argnode, &dummy, false);
2129 argnode2
= argnode
->mNext
;
2130 if (index
== opAdd
&& argnode2
->mClassno
== pn_PushLitNode
2131 && IsInt(&((PyrPushLitNode
*)argnode2
)->mSlot
)
2132 && slotRawInt(&((PyrPushLitNode
*)argnode2
)->mSlot
) == 1) {
2133 COMPILENODE(argnode
, &dummy
, false);
2134 compileOpcode(opPushSpecialValue
, opsvPlusOne
);
2135 } else if (index
== opSub
&& argnode2
->mClassno
== pn_PushLitNode
2136 && IsInt(&((PyrPushLitNode
*)argnode2
)->mSlot
)
2137 && slotRawInt(&((PyrPushLitNode
*)argnode2
)->mSlot
) == 1) {
2138 COMPILENODE(argnode
, &dummy
, false);
2139 compileOpcode(opPushSpecialValue
, opsvMinusOne
);
2141 COMPILENODE(argnode
, &dummy
, false);
2142 COMPILENODE(argnode
->mNext
, &dummy
, false);
2144 compileOpcode(opSendSpecialBinaryArithMsg
, index
);
2148 compileAnyIfMsg(this);
2151 compileCaseMsg(this);
2154 compileSwitchMsg(this);
2157 compileWhileMsg(this);
2160 compileLoopMsg(this);
2163 if (numArgs
== 2) compileAndMsg(argnode
, argnode
->mNext
);
2167 if (numArgs
== 2) compileOrMsg(argnode
, argnode
->mNext
);
2170 case selQuestionMark
:
2171 if (numArgs
== 2) compileQMsg(argnode
, argnode
->mNext
);
2173 case selDoubleQuestionMark
:
2174 if (numArgs
== 2) compileQQMsg(argnode
, argnode
->mNext
);
2176 case selExclamationQuestionMark
:
2177 if (numArgs
== 2) compileXQMsg(argnode
, argnode
->mNext
);
2181 if (numArgs
== 1 && varname
== s_this
) {
2183 compileOpcode(opSendMsg
, 0);
2186 for (; argnode
; argnode
= argnode
->mNext
) {
2187 COMPILENODE(argnode
, &dummy
, false);
2190 compileOpcode(opSendMsg
, numArgs
);
2198 ByteCodes
compileSubExpression(PyrPushLitNode
* litnode
, bool onTailBranch
)
2200 return compileSubExpressionWithGoto(litnode
, 0, onTailBranch
);
2203 ByteCodes
compileSubExpressionWithGoto(PyrPushLitNode
* litnode
, int branchLen
, bool onTailBranch
)
2205 PyrBlockNode
*bnode
= (PyrBlockNode
*)slotRawPtr(&litnode
->mSlot
);
2206 return compileBodyWithGoto(bnode
->mBody
, branchLen
, onTailBranch
);
2209 ByteCodes
compileBodyWithGoto(PyrParseNode
* body
, int branchLen
, bool onTailBranch
)
2211 ByteCodes currentByteCodes
, subExprByteCodes
;
2214 PyrBlock
* prevPartiallyAppliedFunction
= gPartiallyAppliedFunction
;
2215 gPartiallyAppliedFunction
= NULL
;
2217 currentByteCodes
= saveByteCodeArray();
2219 COMPILENODE(body
, &dummy
, onTailBranch
);
2221 if (!byteCodeLength(gCompilingByteCodes
)) {
2222 compileOpcode(opPushSpecialValue
, opsvNil
); // push nil
2224 compileJump(opcJumpFwd
, branchLen
);
2227 subExprByteCodes
= getByteCodes();
2228 restoreByteCodeArray(currentByteCodes
);
2230 gPartiallyAppliedFunction
= prevPartiallyAppliedFunction
;
2232 return subExprByteCodes
;
2236 ByteCodes
compileDefaultValue(int litIndex
, int realExprLen
)
2238 ByteCodes currentByteCodes
, defaultByteCodes
;
2240 currentByteCodes
= saveByteCodeArray();
2242 compileOpcode(opPushSpecialValue
, litIndex
);
2243 compileJump(realExprLen
, unconditionalJump
);
2245 defaultByteCodes
= getByteCodes();
2246 restoreByteCodeArray(currentByteCodes
);
2248 return (defaultByteCodes
);
2252 bool isAnInlineableBlock(PyrParseNode
*node
)
2255 if (node
->mClassno
== pn_PushLitNode
) {
2256 PyrPushLitNode
*anode
;
2257 PyrBlockNode
*bnode
;
2258 anode
= (PyrPushLitNode
*)node
;
2259 if (IsPtr(&anode
->mSlot
)
2260 && (bnode
= (PyrBlockNode
*)(slotRawPtr(&anode
->mSlot
)))->mClassno
== pn_BlockNode
) {
2261 if (bnode
->mArglist
|| bnode
->mVarlist
) {
2262 if (gPostInlineWarnings
) {
2263 post("WARNING: FunctionDef contains variable declarations and so"
2264 " will not be inlined.\n");
2265 if (bnode
->mArglist
)
2266 nodePostErrorLine((PyrParseNode
*)bnode
->mArglist
);
2268 nodePostErrorLine((PyrParseNode
*)bnode
->mVarlist
);
2277 bool isAnInlineableAtomicLiteralBlock(PyrParseNode
*node
)
2280 if (node
->mClassno
== pn_PushLitNode
) {
2281 PyrPushLitNode
*anode
;
2282 PyrBlockNode
*bnode
;
2283 anode
= (PyrPushLitNode
*)node
;
2284 if (IsPtr(&anode
->mSlot
)
2285 && (bnode
= (PyrBlockNode
*)(slotRawPtr(&anode
->mSlot
)))->mClassno
== pn_BlockNode
) {
2286 if (bnode
->mArglist
|| bnode
->mVarlist
) {
2287 if (gPostInlineWarnings
) {
2288 post("WARNING: FunctionDef contains variable declarations and so"
2289 " will not be inlined.\n");
2290 if (bnode
->mArglist
)
2291 nodePostErrorLine((PyrParseNode
*)bnode
->mArglist
);
2293 nodePostErrorLine((PyrParseNode
*)bnode
->mVarlist
);
2296 if (bnode
->mBody
->mClassno
== pn_DropNode
&& ((PyrDropNode
*)bnode
->mBody
)->mExpr2
->mClassno
== pn_BlockReturnNode
)
2297 res
= isAtomicLiteral(((PyrDropNode
*)bnode
->mBody
)->mExpr1
);
2306 bool isAtomicLiteral(PyrParseNode
*node
)
2309 if (node
->mClassno
== pn_PushLitNode
) {
2310 PyrPushLitNode
*anode
;
2311 anode
= (PyrPushLitNode
*)node
;
2312 if (NotObj(&anode
->mSlot
) && !IsPtr(&anode
->mSlot
)) res
= true;
2317 bool isWhileTrue(PyrParseNode
*node
)
2320 if (node
->mClassno
== pn_PushLitNode
) {
2321 PyrPushLitNode
*anode
;
2322 PyrBlockNode
*bnode
;
2323 anode
= (PyrPushLitNode
*)node
;
2324 if (IsPtr(&anode
->mSlot
)
2325 && (bnode
= (PyrBlockNode
*)(slotRawPtr(&anode
->mSlot
)))->mClassno
== pn_BlockNode
) {
2326 if (bnode
->mArglist
|| bnode
->mVarlist
) {
2328 post("WARNING: FunctionDef contains variable declarations and so"
2329 " will not be inlined.\n");
2330 if (bnode->mArglist) nodePostErrorLine((PyrParseNode*)bnode->mArglist);
2331 else nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2334 if (bnode
->mBody
->mClassno
== pn_PushLitNode
2335 && IsTrue(&((PyrPushLitNode
*)bnode
->mBody
)->mSlot
)) {
2339 } else if (IsTrue(&anode
->mSlot
)) {
2346 void compileAndMsg(PyrParseNode
* arg1
, PyrParseNode
* arg2
)
2349 ByteCodes trueByteCodes
;
2351 COMPILENODE(arg1
, &dummy
, false);
2352 if (isAnInlineableBlock(arg2
)) {
2353 trueByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2355 compileJump(opcJumpIfFalsePushFalse
, byteCodeLength(trueByteCodes
));
2356 compileAndFreeByteCodes(trueByteCodes
);
2358 COMPILENODE(arg2
, &dummy
, false);
2360 compileOpcode(opSendSpecialMsg
, 2);
2361 compileByte(opmAnd
);
2365 void compileOrMsg(PyrParseNode
* arg1
, PyrParseNode
* arg2
)
2368 ByteCodes falseByteCodes
;
2370 COMPILENODE(arg1
, &dummy
, false);
2371 if (isAnInlineableBlock(arg2
)) {
2372 falseByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2374 compileJump(opcJumpIfTruePushTrue
, byteCodeLength(falseByteCodes
));
2375 compileAndFreeByteCodes(falseByteCodes
);
2377 COMPILENODE(arg2
, &dummy
, false);
2379 compileOpcode(opSendSpecialMsg
, 2);
2384 void compileQMsg(PyrParseNode
* arg1
, PyrParseNode
* arg2
)
2389 COMPILENODE(arg1
, &dummy
, false);
2390 COMPILENODE(arg2
, &dummy
, false);
2391 compileByte(143); // special opcodes
2392 compileByte(22); // ??
2395 void compileQQMsg(PyrParseNode
* arg1
, PyrParseNode
* arg2
)
2397 // double question mark. ?? {|obj| ^if (this.notNil, this, func) }
2400 COMPILENODE(arg1
, &dummy
, false);
2401 if (isAnInlineableBlock(arg2
)) {
2402 ByteCodes nilByteCodes
;
2403 nilByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2405 int jumplen
= byteCodeLength(nilByteCodes
);
2406 compileByte(143); // special opcodes
2407 compileByte(23); // ??
2408 compileByte((jumplen
>> 8) & 0xFF);
2409 compileByte(jumplen
& 0xFF);
2410 compileAndFreeByteCodes(nilByteCodes
);
2412 COMPILENODE(arg2
, &dummy
, false);
2414 compileOpcode(opSendSpecialMsg
, 2);
2415 compileByte(opmDoubleQuestionMark
);
2419 void compileXQMsg(PyrParseNode
* arg1
, PyrParseNode
* arg2
)
2421 // double question mark. !? {|obj| ^if (this.isNil, this, func) }
2424 COMPILENODE(arg1
, &dummy
, false);
2425 if (isAnInlineableBlock(arg2
)) {
2426 ByteCodes nilByteCodes
;
2427 nilByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2429 int jumplen
= byteCodeLength(nilByteCodes
);
2430 compileByte(143); // special opcodes
2431 compileByte(27); // !?
2432 compileByte((jumplen
>> 8) & 0xFF);
2433 compileByte(jumplen
& 0xFF);
2434 compileAndFreeByteCodes(nilByteCodes
);
2436 COMPILENODE(arg2
, &dummy
, false);
2438 compileOpcode(opSendSpecialMsg
, 2);
2439 compileByte(opmExclamationQuestionMark
);
2443 void compileAnyIfMsg(PyrCallNodeBase2
* node
)
2445 PyrParseNode
* arg1
= node
->mArglist
;
2447 if (arg1
->mClassno
== pn_CallNode
) {
2448 PyrCallNode
* callNode
= (PyrCallNode
*)arg1
;
2449 int numCallArgs
= nodeListLength(callNode
->mArglist
);
2450 int numCallKeyArgs
= nodeListLength(callNode
->mKeyarglist
);
2451 if (numCallArgs
== 1 && numCallKeyArgs
== 0) {
2452 if (slotRawSymbol(&callNode
->mSelector
->mSlot
) == gSpecialUnarySelectors
[opIsNil
]) {
2453 compileIfNilMsg(node
, true);
2455 } else if (slotRawSymbol(&callNode
->mSelector
->mSlot
) == gSpecialUnarySelectors
[opNotNil
]) {
2456 compileIfNilMsg(node
, false);
2464 void compileIfMsg(PyrCallNodeBase2
* node
)
2467 ByteCodes trueByteCodes
, falseByteCodes
;
2469 int numArgs
= nodeListLength(node
->mArglist
);
2470 PyrParseNode
* arg1
= node
->mArglist
;
2471 PyrParseNode
*arg2
, *arg3
;
2476 if (isAnInlineableBlock(arg2
)) {
2477 COMPILENODE(arg1
, &dummy
, false);
2479 trueByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2480 if (byteCodeLength(trueByteCodes
)) {
2481 compileJump(opcJumpIfFalsePushNil
, byteCodeLength(trueByteCodes
));
2482 compileAndFreeByteCodes(trueByteCodes
);
2484 compileOpcode(opSpecialOpcode
, opcDrop
); // drop the boolean
2485 compileOpcode(opPushSpecialValue
, opsvNil
); // push nil
2487 } else goto unoptimized
;
2488 } else if (numArgs
== 3) {
2491 if (isAnInlineableBlock(arg2
) && isAnInlineableBlock(arg3
)) {
2492 COMPILENODE(arg1
, &dummy
, false);
2493 falseByteCodes
= compileSubExpression((PyrPushLitNode
*)arg3
, true);
2494 trueByteCodes
= compileSubExpressionWithGoto((PyrPushLitNode
*)arg2
, byteCodeLength(falseByteCodes
), true);
2495 if (byteCodeLength(falseByteCodes
)) {
2496 compileJump(opcJumpIfFalse
, byteCodeLength(trueByteCodes
));
2497 compileAndFreeByteCodes(trueByteCodes
);
2498 compileAndFreeByteCodes(falseByteCodes
);
2499 } else if (byteCodeLength(trueByteCodes
)) {
2500 compileJump(opcJumpIfFalsePushNil
, byteCodeLength(trueByteCodes
));
2501 compileAndFreeByteCodes(trueByteCodes
);
2503 compileOpcode(opSpecialOpcode
, opcDrop
); // drop the boolean
2504 compileOpcode(opPushSpecialValue
, opsvNil
); // push nil
2506 } else goto unoptimized
;
2509 for (; arg1
; arg1
= arg1
->mNext
) {
2510 COMPILENODE(arg1
, &dummy
, false);
2513 compileOpcode(opSendSpecialMsg
, numArgs
);
2518 void compileIfNilMsg(PyrCallNodeBase2
* node
, bool flag
)
2521 ByteCodes trueByteCodes
, falseByteCodes
;
2522 PyrParseNode
*arg2
, *arg3
;
2524 int numArgs
= nodeListLength(node
->mArglist
);
2525 PyrParseNode
* arg1
= node
->mArglist
;
2528 COMPILENODE(arg1
, &dummy
, false);
2530 compileOpcode(opSendSpecialMsg
, numArgs
);
2532 } else if (numArgs
== 2) {
2534 if (isAnInlineableBlock(arg2
)) {
2535 PyrCallNode
* callNode
= (PyrCallNode
*)arg1
;
2536 COMPILENODE(callNode
->mArglist
, &dummy
, false);
2538 trueByteCodes
= compileSubExpression((PyrPushLitNode
*)arg2
, true);
2539 int jumplen
= byteCodeLength(trueByteCodes
);
2541 compileByte(143); // special opcodes
2542 compileByte(flag
? 26 : 27);
2543 compileByte((jumplen
>> 8) & 0xFF);
2544 compileByte(jumplen
& 0xFF);
2545 compileAndFreeByteCodes(trueByteCodes
);
2547 compileOpcode(opSpecialOpcode
, opcDrop
); // drop the value
2548 compileOpcode(opPushSpecialValue
, opsvNil
); // push nil
2551 COMPILENODE(arg1
, &dummy
, false);
2552 COMPILENODE(arg2
, &dummy
, false);
2554 compileOpcode(opSendSpecialMsg
, numArgs
);
2557 } else if (numArgs
== 3) {
2560 if (isAnInlineableBlock(arg2
) && isAnInlineableBlock(arg3
)) {
2561 PyrCallNode
* callNode
= (PyrCallNode
*)arg1
;
2562 COMPILENODE(callNode
->mArglist
, &dummy
, false);
2564 falseByteCodes
= compileSubExpression((PyrPushLitNode
*)arg3
, true);
2565 int falseLen
= byteCodeLength(falseByteCodes
);
2566 trueByteCodes
= compileSubExpressionWithGoto((PyrPushLitNode
*)arg2
, falseLen
, true);
2567 int trueLen
= byteCodeLength(trueByteCodes
);
2569 compileByte(143); // special opcodes
2570 compileByte(flag
? 24 : 25);
2571 compileByte((trueLen
>> 8) & 0xFF);
2572 compileByte(trueLen
& 0xFF);
2573 compileAndFreeByteCodes(trueByteCodes
);
2574 compileAndFreeByteCodes(falseByteCodes
);
2575 } else if (trueLen
) {
2576 compileByte(143); // special opcodes
2577 compileByte(flag
? 26 : 27);
2578 compileByte((trueLen
>> 8) & 0xFF);
2579 compileByte(trueLen
& 0xFF);
2580 compileAndFreeByteCodes(trueByteCodes
);
2582 compileOpcode(opSpecialOpcode
, opcDrop
); // drop the boolean
2583 compileOpcode(opPushSpecialValue
, opsvNil
); // push nil
2586 COMPILENODE(arg1
, &dummy
, false);
2587 COMPILENODE(arg2
, &dummy
, false);
2588 COMPILENODE(arg3
, &dummy
, false);
2590 compileOpcode(opSendSpecialMsg
, numArgs
);
2594 for (; arg1
; arg1
= arg1
->mNext
) {
2595 COMPILENODE(arg1
, &dummy
, false);
2598 compileOpcode(opSendSpecialMsg
, numArgs
);
2603 PyrParseNode
* reverseNodeList(PyrParseNode
** list
)
2605 PyrParseNode
* temp1
= *list
;
2606 PyrParseNode
* temp2
= NULL
;
2607 PyrParseNode
* temp3
= NULL
;
2610 temp2
= temp1
->mNext
;
2611 temp1
->mNext
= temp3
;
2619 PyrCallNode
* buildCase(PyrParseNode
*arg1
)
2621 // transform case statement into nested if statements.
2622 //int numArgs = nodeListLength(arg1);
2624 //post("->buildCase %d\n", numArgs);
2626 PyrParseNode
*arg2
= arg1
->mNext
;
2628 PyrPushLitNode
*litnode
= (PyrPushLitNode
*)arg1
;
2629 PyrBlockNode
*bnode
= (PyrBlockNode
*)slotRawPtr(&litnode
->mSlot
);
2630 PyrParseNode
*bbody
= bnode
->mBody
;
2631 if (bbody
->mClassno
== pn_DropNode
) {
2632 PyrDropNode
* dropNode
= (PyrDropNode
*)bbody
;
2633 if (dropNode
->mExpr2
->mClassno
== pn_BlockReturnNode
) {
2634 arg1
= dropNode
->mExpr1
;
2643 PyrParseNode
*arg3
= 0;
2647 PyrParseNode
*arg4
= arg3
->mNext
;
2649 arg3
= buildCase(arg3
);
2650 PyrBlockNode
* bnode
= newPyrBlockNode(NULL
, NULL
, arg3
, false);
2651 arg3
= newPyrPushLitNode(NULL
, bnode
);
2665 post("arg1->mNext %p arg2 %p\n", arg1->mNext, arg2);
2667 post("arg2->mNext %p arg3 %p\n", arg2->mNext, arg3);
2668 post("isAnInlineableBlock arg2 %d\n", isAnInlineableBlock(arg2));
2671 post("isAnInlineableBlock arg3 %d\n", isAnInlineableBlock(arg3));
2672 post("arg3->mNext %p\n", arg3->mNext);
2678 SetSymbol(&selector
, gSpecialSelectors
[opmIf
]);
2679 PyrSlotNode
* selectorNode
= newPyrSlotNode(&selector
);
2680 PyrCallNode
*callNode
= newPyrCallNode(selectorNode
, arg1
, NULL
, NULL
);
2682 //post("<-buildCase %d\n", numArgs);
2687 void compileCaseMsg(PyrCallNodeBase2
* node
)
2689 PyrParseNode
*argnode
= node
->mArglist
;
2690 bool canInline
= true;
2691 for (; argnode
; argnode
= argnode
->mNext
) {
2692 if (!isAnInlineableBlock(argnode
)) {
2699 PyrCallNode
* callNode
= buildCase(node
->mArglist
);
2700 callNode
->compile(&dummy
);
2703 argnode
= node
->mArglist
;
2704 for (; argnode
; argnode
= argnode
->mNext
, ++numArgs
) {
2705 COMPILENODE(argnode
, &dummy
, false);
2708 compileOpcode(opSendSpecialMsg
, numArgs
);
2709 compileByte(opmCase
);
2713 void compileSwitchMsg(PyrCallNode
* node
)
2716 bool canInline
= true;
2719 PyrParseNode
*argnode
= node
->mArglist
;
2720 numArgs
= nodeListLength(argnode
);
2722 argnode
= argnode
->mNext
; // skip first arg.
2724 PyrParseNode
* nextargnode
= 0;
2725 for (; argnode
; argnode
= nextargnode
) {
2726 nextargnode
= argnode
->mNext
;
2727 if (nextargnode
!= NULL
) {
2728 if (!isAtomicLiteral(argnode
) && !isAnInlineableAtomicLiteralBlock(argnode
)) {
2732 if (!isAnInlineableBlock(nextargnode
)) {
2736 nextargnode
= nextargnode
->mNext
;
2738 if (!isAnInlineableBlock(argnode
)) {
2747 PyrParseNode
*argnode
= node
->mArglist
;
2749 int flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
2750 int arraySize
= NEXTPOWEROFTWO(numArgs
* 2);
2751 PyrObject
* array
= newPyrArray(compileGC(), arraySize
, flags
, false);
2752 array
->size
= arraySize
;
2753 nilSlots(array
->slots
, arraySize
);
2756 SetObject(&slot
, array
);
2758 COMPILENODE(argnode
, &dummy
, false);
2759 compilePushConstant(node
, &slot
);
2761 compileByte(143); // lookup slot in dictionary and jump to offset.
2764 argnode
= argnode
->mNext
; // skip first arg.
2766 PyrParseNode
* nextargnode
= 0;
2767 int absoluteOffset
= byteCodeLength(gCompilingByteCodes
);
2770 for (; argnode
; argnode
= nextargnode
) {
2771 nextargnode
= argnode
->mNext
;
2772 if (nextargnode
!= NULL
) {
2773 ByteCodes byteCodes
= compileSubExpressionWithGoto((PyrPushLitNode
*)nextargnode
, 0x6666, true);
2777 SetInt(&value
, offset
);
2778 PyrPushLitNode
* keyargnode
= (PyrPushLitNode
*)argnode
;
2779 if (isAtomicLiteral(argnode
)) {
2780 key
= &keyargnode
->mSlot
;
2782 PyrBlockNode
*bnode
= (PyrBlockNode
*)slotRawPtr(&keyargnode
->mSlot
);
2783 PyrDropNode
*dropnode
= (PyrDropNode
*)bnode
->mBody
;
2784 PyrPushLitNode
* litnode
= (PyrPushLitNode
*)dropnode
->mExpr1
;
2785 key
= &litnode
->mSlot
;
2788 int index
= arrayAtIdentityHashInPairs(array
, key
);
2789 PyrSlot
*slot
= array
->slots
+ index
;
2790 slotCopy(slot
, key
);
2791 SetInt(slot
+1, offset
);
2794 offset
+= byteCodeLength(byteCodes
);
2795 compileAndFreeByteCodes(byteCodes
);
2797 compileOpcode(opPushSpecialValue
, opsvNil
);
2801 nextargnode
= nextargnode
->mNext
;
2802 if (nextargnode
== NULL
) {
2803 compileOpcode(opPushSpecialValue
, opsvNil
);
2804 lastOffset
= offset
;
2808 ByteCodes byteCodes
= compileSubExpressionWithGoto((PyrPushLitNode
*)argnode
, 0, true);
2810 lastOffset
= offset
;
2812 offset
+= byteCodeLength(byteCodes
);
2813 compileAndFreeByteCodes(byteCodes
);
2815 compileOpcode(opPushSpecialValue
, opsvNil
);
2816 lastOffset
= offset
;
2822 Byte
*bytes
= gCompilingByteCodes
->bytes
+ absoluteOffset
;
2823 PyrSlot
*slots
= array
->slots
;
2825 int jumplen
= offset
- lastOffset
;
2826 bytes
[lastOffset
-2] = (jumplen
>> 8) & 255;
2827 bytes
[lastOffset
-1] = jumplen
& 255;
2829 for (int i
=0; i
<arraySize
; i
+=2) {
2830 PyrSlot
*key
= slots
+ i
;
2831 PyrSlot
*value
= key
+ 1;
2834 SetInt(value
, lastOffset
);
2836 int offsetToHere
= slotRawInt(value
);
2838 int jumplen
= offset
- offsetToHere
;
2839 bytes
[offsetToHere
-2] = (jumplen
>> 8) & 255;
2840 bytes
[offsetToHere
-1] = jumplen
& 255;
2846 PyrParseNode
*argnode
= node
->mArglist
;
2847 for (; argnode
; argnode
= argnode
->mNext
) {
2848 COMPILENODE(argnode
, &dummy
, false);
2851 compileOpcode(opSendSpecialMsg
, numArgs
);
2852 compileByte(opmSwitch
);
2856 void compileWhileMsg(PyrCallNodeBase2
* node
)
2859 PyrParseNode
*argnode
;
2861 ByteCodes whileByteCodes
, exprByteCodes
;
2862 int whileByteCodeLen
, exprByteCodeLen
;
2864 numArgs
= nodeListLength(node
->mArglist
);
2865 if (numArgs
== 1 && isAnInlineableBlock(node
->mArglist
)) {
2867 whileByteCodes
= compileSubExpression((PyrPushLitNode
*)node
->mArglist
, false);
2869 whileByteCodeLen
= byteCodeLength(whileByteCodes
);
2870 compileAndFreeByteCodes(whileByteCodes
);
2872 exprByteCodeLen
= 1;
2873 compileJump(opcJumpIfFalsePushNil
, exprByteCodeLen
+ 3);
2875 // opcJumpBak does a drop..
2876 compileOpcode(opPushSpecialValue
, opsvNil
);
2878 compileJump(opcJumpBak
, exprByteCodeLen
+ whileByteCodeLen
+ 4);
2880 } else if (numArgs
== 2 && isWhileTrue(node
->mArglist
)
2881 && isAnInlineableBlock(node
->mArglist
->mNext
)) {
2883 exprByteCodes
= compileSubExpression((PyrPushLitNode
*)node
->mArglist
->mNext
, false);
2885 exprByteCodeLen
= byteCodeLength(exprByteCodes
);
2886 compileAndFreeByteCodes(exprByteCodes
);
2888 compileJump(opcJumpBak
, exprByteCodeLen
+ 1);
2890 } else if (numArgs
== 2 && isAnInlineableBlock(node
->mArglist
)
2891 && isAnInlineableBlock(node
->mArglist
->mNext
)) {
2893 whileByteCodes
= compileSubExpression((PyrPushLitNode
*)node
->mArglist
, false);
2894 exprByteCodes
= compileSubExpression((PyrPushLitNode
*)node
->mArglist
->mNext
, false);
2896 whileByteCodeLen
= byteCodeLength(whileByteCodes
);
2897 compileAndFreeByteCodes(whileByteCodes
);
2899 if (exprByteCodes
) {
2900 exprByteCodeLen
= byteCodeLength(exprByteCodes
);
2901 compileJump(opcJumpIfFalsePushNil
, exprByteCodeLen
+ 3);
2902 compileAndFreeByteCodes(exprByteCodes
);
2904 exprByteCodeLen
= 1;
2905 compileJump(opcJumpIfFalsePushNil
, exprByteCodeLen
+ 3);
2906 // opcJumpBak does a drop..
2907 compileOpcode(opPushSpecialValue
, opsvNil
);
2910 compileJump(opcJumpBak
, exprByteCodeLen
+ whileByteCodeLen
+ 4);
2913 argnode
= node
->mArglist
;
2914 for (; argnode
; argnode
= argnode
->mNext
) {
2915 COMPILENODE(argnode
, &dummy
, false);
2918 compileOpcode(opSendSpecialMsg
, numArgs
);
2919 compileByte(opmWhile
);
2923 void compileLoopMsg(PyrCallNodeBase2
* node
)
2926 PyrParseNode
*argnode
;
2928 ByteCodes exprByteCodes
;
2929 int exprByteCodeLen
;
2931 numArgs
= nodeListLength(node
->mArglist
);
2932 if (numArgs
== 1 && isAnInlineableBlock(node
->mArglist
)) {
2934 exprByteCodes
= compileSubExpression((PyrPushLitNode
*)node
->mArglist
, false);
2936 exprByteCodeLen
= byteCodeLength(exprByteCodes
);
2937 compileAndFreeByteCodes(exprByteCodes
);
2939 compileJump(opcJumpBak
, exprByteCodeLen
+ 1);
2942 argnode
= node
->mArglist
;
2943 for (; argnode
; argnode
= argnode
->mNext
) {
2944 COMPILENODE(argnode
, &dummy
, false);
2947 compileOpcode(opSendSpecialMsg
, numArgs
);
2948 compileByte(opmLoop
);
2952 PyrBinopCallNode
* newPyrBinopCallNode(PyrSlotNode
* selector
,
2953 PyrParseNode
* arg1
, PyrParseNode
* arg2
, PyrParseNode
* arg3
)
2955 PyrBinopCallNode
* node
= ALLOCNODE(PyrBinopCallNode
);
2956 node
->mSelector
= selector
;
2957 node
->mArglist
= arg1
;
2963 int PyrBinopCallNode::isPartialApplication()
2966 PyrParseNode
* argnode
= mArglist
;
2967 for (; argnode
; argnode
= argnode
->mNext
) {
2968 if (argnode
->mClassno
== pn_CurryArgNode
) {
2969 ((PyrCurryArgNode
*)argnode
)->mArgNum
= sum
;
2976 void PyrBinopCallNode::compileCall(PyrSlot
*result
)
2978 int index
, selType
, isSuper
, numArgs
;
2981 PyrParseNode
*arg1
= mArglist
;
2982 PyrParseNode
*arg2
= arg1
->mNext
;
2983 PyrParseNode
*arg3
= arg2
->mNext
;
2985 //postfl("compilePyrBinopCallNode\n");
2986 isSuper
= isSuperObjNode(arg1
);
2987 slotRawSymbol(&mSelector
->mSlot
)->flags
|= sym_Called
;
2988 index
= conjureSelectorIndex((PyrParseNode
*)mSelector
, gCompilingBlock
,
2989 isSuper
, slotRawSymbol(&mSelector
->mSlot
), &selType
);
2990 numArgs
= arg3
? 3 : 2;
2992 COMPILENODE(arg1
, &dummy
, false);
2993 COMPILENODE(arg2
, &dummy
, false);
2994 if (arg3
) COMPILENODE(arg3
, &dummy
, false);
2996 compileOpcode(opSendSuper
, numArgs
);
3001 COMPILENODE(arg1
, &dummy
, false);
3002 COMPILENODE(arg2
, &dummy
, false);
3003 if (arg3
) COMPILENODE(arg3
, &dummy
, false);
3005 compileOpcode(opSendMsg
, numArgs
);
3009 COMPILENODE(arg1
, &dummy
, false);
3010 COMPILENODE(arg2
, &dummy
, false);
3011 if (arg3
) COMPILENODE(arg3
, &dummy
, false);
3013 compileOpcode(opSendSpecialMsg
, numArgs
);
3017 COMPILENODE(arg1
, &dummy
, false);
3018 COMPILENODE(arg2
, &dummy
, false);
3020 COMPILENODE(arg3
, &dummy
, false);
3023 compileOpcode(opSpecialOpcode
, opcDrop
); // drop third argument
3024 compileOpcode(opSpecialOpcode
, opcDrop
); // drop second argument
3025 compileOpcode(opSendSpecialUnaryArithMsg
, index
);
3029 COMPILENODE(arg1
, &dummy
, false);
3030 COMPILENODE(arg2
, &dummy
, false);
3031 COMPILENODE(arg3
, &dummy
, false);
3033 compileOpcode(opSpecialOpcode
, opcSpecialBinaryOpWithAdverb
);
3035 } else if (index
== opAdd
&& arg2
->mClassno
== pn_PushLitNode
3036 && IsInt(&((PyrPushLitNode
*)arg2
)->mSlot
)
3037 && slotRawInt(&((PyrPushLitNode
*)arg2
)->mSlot
) == 1) {
3038 COMPILENODE(arg1
, &dummy
, false);
3039 compileOpcode(opPushSpecialValue
, opsvPlusOne
);
3040 } else if (index
== opSub
&& arg2
->mClassno
== pn_PushLitNode
3041 && IsInt(&((PyrPushLitNode
*)arg2
)->mSlot
)
3042 && slotRawInt(&((PyrPushLitNode
*)arg2
)->mSlot
) == 1) {
3043 COMPILENODE(arg1
, &dummy
, false);
3045 compileOpcode(opPushSpecialValue
, opsvMinusOne
);
3047 COMPILENODE(arg1
, &dummy
, false);
3048 COMPILENODE(arg2
, &dummy
, false);
3050 compileOpcode(opSendSpecialBinaryArithMsg
, index
);
3054 compileAnyIfMsg(this);
3057 compileCaseMsg(this);
3060 compileWhileMsg(this);
3063 compileLoopMsg(this);
3066 compileAndMsg(arg1
, arg2
);
3069 compileOrMsg(arg1
, arg2
);
3071 case selQuestionMark
:
3072 compileQMsg(arg1
, arg2
);
3074 case selDoubleQuestionMark
:
3075 compileQQMsg(arg1
, arg2
);
3077 case selExclamationQuestionMark
:
3078 compileXQMsg(arg1
, arg2
);
3081 COMPILENODE(arg1
, &dummy
, false);
3082 COMPILENODE(arg2
, &dummy
, false);
3083 if (arg3
) COMPILENODE(arg3
, &dummy
, false);
3085 compileOpcode(opSendMsg
, numArgs
);
3092 PyrPushKeyArgNode
* newPyrPushKeyArgNode(PyrSlotNode
* selector
, PyrParseNode
* expr
)
3094 PyrPushKeyArgNode
* node
= ALLOCNODE(PyrPushKeyArgNode
);
3095 node
->mSelector
= selector
;
3100 void PyrPushKeyArgNode::compile(PyrSlot
*result
)
3103 //postfl("->compilePyrPushKeyArgNode\n");
3105 compilePushConstant((PyrParseNode
*)this, &mSelector
->mSlot
);
3107 COMPILENODE(mExpr
, &dummy
, false);
3110 PyrDropNode
* newPyrDropNode(PyrParseNode
* expr1
, PyrParseNode
* expr2
)
3112 PyrDropNode
* node
= ALLOCNODE(PyrDropNode
);
3113 node
->mExpr1
= expr1
;
3114 node
->mExpr2
= expr2
;
3118 void PyrDropNode::compile(PyrSlot
*result
)
3120 //postfl("->compilePyrDropNode\n");
3122 // eliminate as many drops as possible
3124 post("DROP EXPR2 NULL\n");
3125 COMPILENODE(mExpr1
, &dummy
, true);
3126 } else if (mExpr2
->mClassno
== pn_BlockReturnNode
) {
3127 // no drop before a block return
3128 COMPILENODE(mExpr1
, &dummy
, true);
3129 } else if (mExpr1
&& mExpr1
->mClassno
== pn_AssignNode
) {
3130 // let the store do the drop
3131 ((PyrAssignNode
*)mExpr1
)->mDrop
= 1;
3132 COMPILENODE(mExpr1
, &dummy
, false);
3133 COMPILENODE(mExpr2
, &dummy
, true);
3134 } else if (mExpr1
&& mExpr1
->mClassno
== pn_DropNode
) {
3136 // let the store do the drop, a bit more complex.
3137 // find the ultimate expression in the left subtree before the drop.
3138 znode
= (PyrDropNode
*)mExpr1
;
3139 while (znode
->mExpr2
&& znode
->mExpr2
->mClassno
== pn_DropNode
) {
3140 znode
= (PyrDropNode
*)znode
->mExpr2
;
3142 if (znode
->mExpr2
->mClassno
== pn_AssignNode
) {
3143 ((PyrAssignNode
*)znode
->mExpr2
)->mDrop
= 1;
3144 COMPILENODE(mExpr1
, &dummy
, false);
3145 COMPILENODE(mExpr2
, &dummy
, true);
3147 COMPILENODE(mExpr1
, &dummy
, false);
3148 compileOpcode(opSpecialOpcode
, opcDrop
);
3149 COMPILENODE(mExpr2
, &dummy
, true);
3152 COMPILENODE(mExpr1
, &dummy
, false);
3153 compileOpcode(opSpecialOpcode
, opcDrop
);
3154 COMPILENODE(mExpr2
, &dummy
, true);
3156 //postfl("<-compilePyrDropNode\n");
3159 PyrPushLitNode
* newPyrPushLitNode(PyrSlotNode
* literalSlot
, PyrParseNode
* literalObj
)
3161 PyrPushLitNode
* node
;
3164 node
->mClassno
= pn_PushLitNode
;
3166 node
= ALLOCSLOTNODE(PyrSlotNode
, pn_PushLitNode
);
3167 SetPtr(&node
->mSlot
, (PyrObject
*)literalObj
);
3173 void compilePushConstant(PyrParseNode
* node
, PyrSlot
*slot
)
3175 int index
= conjureConstantIndex(node
, gCompilingBlock
, slot
);
3176 if (index
< (1<<4)) {
3177 compileByte((opPushLiteral
<< 4) | index
);
3178 } else if (index
< (1<<8)) {
3180 compileByte(index
& 0xFF);
3181 } else if (index
< (1<<16)) {
3183 compileByte((index
>> 8) & 0xFF);
3184 compileByte(index
& 0xFF);
3185 } else if (index
< (1<<24)) {
3187 compileByte((index
>> 16) & 0xFF);
3188 compileByte((index
>> 8) & 0xFF);
3189 compileByte(index
& 0xFF);
3192 compileByte((index
>> 24) & 0xFF);
3193 compileByte((index
>> 16) & 0xFF);
3194 compileByte((index
>> 8) & 0xFF);
3195 compileByte(index
& 0xFF);
3199 void compilePushInt(int value
)
3201 //postfl("compilePushInt\n");
3202 if (value
>= -1 && value
<= 2) {
3203 compileOpcode(opPushSpecialValue
, opsvZero
+ value
);
3205 //printf("int %d\n", value);
3206 if (value
>= -(1<<7) && value
<= ((1<<7)-1)) {
3208 compileByte(value
& 0xFF);
3209 } else if (value
>= -(1<<15) && value
<= ((1<<15)-1)) {
3211 compileByte((value
>> 8) & 0xFF);
3212 compileByte(value
& 0xFF);
3213 } else if (value
>= -(1<<23) && value
<= ((1<<23)-1)) {
3215 compileByte((value
>> 16) & 0xFF);
3216 compileByte((value
>> 8) & 0xFF);
3217 compileByte(value
& 0xFF);
3220 compileByte((value
>> 24) & 0xFF);
3221 compileByte((value
>> 16) & 0xFF);
3222 compileByte((value
>> 8) & 0xFF);
3223 compileByte(value
& 0xFF);
3228 void PyrSlotNode::compilePushLit(PyrSlot
*result
)
3232 ByteCodes savedBytes
;
3234 //postfl("compilePyrPushLitNode\n");
3235 if (IsPtr(&mSlot
)) {
3236 PyrParseNode
*literalObj
= (PyrParseNode
*)slotRawPtr(&mSlot
);
3237 //index = conjureLiteralObjIndex(gCompilingBlock, literalObj);
3238 if (literalObj
->mClassno
== pn_BlockNode
) {
3239 savedBytes
= saveByteCodeArray();
3240 COMPILENODE(literalObj
, &slot
, false);
3241 restoreByteCodeArray(savedBytes
);
3242 index
= conjureLiteralSlotIndex(literalObj
, gCompilingBlock
, &slot
);
3243 compileOpcode(opExtended
, opPushLiteral
);
3246 PyrBlock
*block
= slotRawBlock(&slot
);
3247 if (NotNil(&block
->contextDef
)) {
3248 METHRAW(gCompilingBlock
)->needsHeapContext
= 1;
3251 COMPILENODE(literalObj
, &slot
, false);
3252 compilePushConstant((PyrParseNode
*)literalObj
, &slot
);
3257 compilePushInt(slotRawInt(&slot
));
3258 } else if (SlotEq(&slot
, &o_nil
)) {
3259 compileOpcode(opPushSpecialValue
, opsvNil
);
3260 } else if (SlotEq(&slot
, &o_true
)) {
3261 compileOpcode(opPushSpecialValue
, opsvTrue
);
3262 } else if (SlotEq(&slot
, &o_false
)) {
3263 compileOpcode(opPushSpecialValue
, opsvFalse
);
3264 } else if (SlotEq(&slot
, &o_fhalf
)) {
3265 compileOpcode(opPushSpecialValue
, opsvFHalf
);
3266 } else if (SlotEq(&slot
, &o_fnegone
)) {
3267 compileOpcode(opPushSpecialValue
, opsvFNegOne
);
3268 } else if (SlotEq(&slot
, &o_fzero
)) {
3269 compileOpcode(opPushSpecialValue
, opsvFZero
);
3270 } else if (SlotEq(&slot
, &o_fone
)) {
3271 compileOpcode(opPushSpecialValue
, opsvFOne
);
3272 } else if (SlotEq(&slot
, &o_ftwo
)) {
3273 compileOpcode(opPushSpecialValue
, opsvFTwo
);
3274 } else if (SlotEq(&slot
, &o_inf
)) {
3275 compileOpcode(opPushSpecialValue
, opsvInf
);
3276 } else if (IsFloat(&slot
)) {
3277 compilePushConstant((PyrParseNode
*)this, &slot
);
3278 } else if (IsSym(&slot
)) {
3279 compilePushConstant((PyrParseNode
*)this, &slot
);
3281 compilePushConstant((PyrParseNode
*)this, &slot
);
3286 PyrLiteralNode
* newPyrLiteralNode(PyrSlotNode
* literalSlot
, PyrParseNode
* literalObj
)
3288 PyrLiteralNode
* node
;
3291 node
->mClassno
= pn_LiteralNode
;
3293 node
= ALLOCSLOTNODE(PyrSlotNode
, pn_LiteralNode
);
3294 SetPtr(&node
->mSlot
, (PyrObject
*)literalObj
);
3299 void compilePyrLiteralNode(PyrLiteralNode
*node
, PyrSlot
*result
)
3304 node
->compileLiteral(result
);
3308 void PyrSlotNode::compileLiteral(PyrSlot
*result
)
3310 ByteCodes savedBytes
;
3312 if (IsPtr(&mSlot
)) {
3313 PyrParseNode
* literalObj
= (PyrParseNode
*)slotRawPtr(&mSlot
);
3314 if (literalObj
->mClassno
== pn_BlockNode
) {
3315 savedBytes
= saveByteCodeArray();
3316 COMPILENODE(literalObj
, result
, false);
3317 restoreByteCodeArray(savedBytes
);
3319 PyrBlock
*block
= slotRawBlock(result
);
3320 if (NotNil(&block
->contextDef
)) {
3321 METHRAW(gCompilingBlock
)->needsHeapContext
= 1;
3324 COMPILENODE(literalObj
, result
, false);
3327 *(PyrSlot
*)result
= mSlot
;
3331 PyrReturnNode
* newPyrReturnNode(PyrParseNode
* expr
)
3333 PyrReturnNode
* node
= ALLOCNODE(PyrReturnNode
);
3340 void PyrReturnNode::compile(PyrSlot
*result
)
3342 PyrPushLitNode
*lit
;
3345 //post("->compilePyrReturnNode\n");
3346 gFunctionCantBeClosed
= true;
3348 compileOpcode(opSpecialOpcode
, opcReturnSelf
);
3349 } else if (mExpr
->mClassno
== pn_PushLitNode
) {
3350 lit
= (PyrPushLitNode
*)mExpr
;
3351 if (IsSym(&(lit
->mSlot
)) && slotRawSymbol(&lit
->mSlot
) == s_this
) {
3352 compileOpcode(opSpecialOpcode
, opcReturnSelf
);
3353 } else if (IsNil(&lit
->mSlot
)) {
3354 compileOpcode(opSpecialOpcode
, opcReturnNil
);
3355 } else if (IsTrue(&lit
->mSlot
)) {
3356 compileOpcode(opSpecialOpcode
, opcReturnTrue
);
3357 } else if (IsFalse(&lit
->mSlot
)) {
3358 compileOpcode(opSpecialOpcode
, opcReturnFalse
);
3360 COMPILENODE(lit
, &dummy
, false);
3361 compileOpcode(opSpecialOpcode
, opcReturn
);
3364 SetTailBranch
branch(true);
3365 SetTailIsMethodReturn
mr(true);
3366 COMPILENODE(mExpr
, &dummy
, true);
3367 compileOpcode(opSpecialOpcode
, opcReturn
);
3369 //post("<-compilePyrReturnNode\n");
3372 PyrBlockReturnNode
* newPyrBlockReturnNode()
3374 PyrBlockReturnNode
* node
= ALLOCNODE(PyrBlockReturnNode
);
3379 void PyrBlockReturnNode::compile(PyrSlot
*result
)
3381 //postfl("compilePyrBlockReturnNode\n");
3382 //compileOpcode(opSpecialOpcode, opcFunctionReturn);
3385 PyrAssignNode
* newPyrAssignNode(PyrSlotNode
* varName
, PyrParseNode
* expr
, int flags
)
3387 PyrAssignNode
* node
= ALLOCNODE(PyrAssignNode
);
3388 node
->mVarName
= varName
;
3394 PyrSetterNode
* newPyrSetterNode(PyrSlotNode
* selector
, PyrParseNode
* expr1
, PyrParseNode
* expr2
)
3396 PyrSetterNode
* node
= ALLOCNODE(PyrSetterNode
);
3397 node
->mSelector
= selector
;
3398 node
->mExpr1
= expr1
;
3399 node
->mExpr2
= expr2
;
3403 PyrMultiAssignNode
* newPyrMultiAssignNode(PyrMultiAssignVarListNode
* varList
,
3404 PyrParseNode
* expr
, int flags
)
3406 PyrMultiAssignNode
* node
= ALLOCNODE(PyrMultiAssignNode
);
3407 node
->mVarList
= varList
;
3413 PyrMultiAssignVarListNode
* newPyrMultiAssignVarListNode(PyrSlotNode
* varNames
,
3416 PyrMultiAssignVarListNode
* node
= ALLOCNODE(PyrMultiAssignVarListNode
);
3417 node
->mVarNames
= varNames
;
3422 void compileAssignVar(PyrParseNode
* node
, PyrSymbol
* varName
, bool drop
)
3424 int level
, index
, vindex
, varType
;
3428 //postfl("compileAssignVar\n");
3429 classobj
= gCompilingClass
;
3430 if (varName
== s_this
|| varName
== s_super
|| varName
== s_curProcess
|| varName
== s_curThread
|| varName
== s_curMethod
||
3431 varName
== s_curBlock
|| varName
== s_curClosure
) {
3432 error("You may not assign to '%s'.", varName
->name
);
3433 nodePostErrorLine(node
);
3435 } else if (varName
->name
[0] >= 'A' && varName
->name
[0] <= 'Z') {
3436 // actually this shouldn't even parse, so you won't get here.
3437 error("You may not assign to a class name.");
3438 nodePostErrorLine(node
);
3440 } else if (findVarName(gCompilingBlock
, &classobj
, varName
,
3441 &varType
, &level
, &index
, &tempfunc
)) {
3446 compileByte((opStoreInstVar
<<4) | index
);
3448 compileByte(opStoreInstVar
);
3450 compileByte((opSpecialOpcode
<<4) | opcDrop
);
3453 compileByte(opStoreInstVar
);
3458 index
+= slotRawInt(&classobj
->classVarIndex
);
3461 compileByte((opStoreClassVar
<<4) | ((index
>>8) & 15));
3462 compileByte(index
& 255);
3464 compileByte(opStoreClassVar
);
3466 compileByte(vindex
); // FIXME: vindex is not initalized!!!!
3468 compileByte((opSpecialOpcode
<<4) | opcDrop
);
3471 compileByte(opStoreClassVar
);
3472 compileByte((index
>> 8) & 255);
3473 compileByte(index
& 255);
3477 error("You may not assign to a constant.");
3478 nodePostErrorLine(node
);
3482 //compileOpcode(opStoreTempVar, level);
3483 //compileByte(index);
3485 if (index
<= 15 && level
< 8) {
3486 compileByte((opStoreTempVar
<<4) | level
);
3489 compileByte(opStoreTempVar
);
3492 compileByte((opSpecialOpcode
<<4) | opcDrop
);
3495 compileByte(opStoreTempVar
);
3502 error("Variable '%s' not defined.\n", varName
->name
);
3503 nodePostErrorLine(node
);
3509 void PyrAssignNode::compile(PyrSlot
* result
)
3513 //postfl("compilePyrAssignNode\n");
3514 COMPILENODE(mExpr
, &dummy
, false);
3515 compileAssignVar((PyrParseNode
*)this, slotRawSymbol(&mVarName
->mSlot
), mDrop
);
3519 int PyrSetterNode::isPartialApplication()
3522 if (mExpr1
->mClassno
== pn_CurryArgNode
) {
3523 ((PyrCurryArgNode
*)mExpr1
)->mArgNum
= sum
;
3526 if (mExpr2
->mClassno
== pn_CurryArgNode
) {
3527 ((PyrCurryArgNode
*)mExpr2
)->mArgNum
= sum
;
3533 void PyrSetterNode::compileCall(PyrSlot
* result
)
3535 int index
, selType
, isSuper
;
3537 char setterName
[128];
3538 PyrSymbol
*setterSym
;
3540 //postfl("compilePyrSetterNode\n");
3541 if (nodeListLength(mExpr1
) > 1) {
3542 error("Setter method called with too many arguments.\n");
3543 nodePostErrorLine(mExpr1
);
3546 COMPILENODE(mExpr1
, &dummy
, false);
3547 COMPILENODE(mExpr2
, &dummy
, false);
3550 //postfl("compilePyrCallNode\n");
3551 isSuper
= isSuperObjNode(mExpr1
);
3553 sprintf(setterName
, "%s_", slotRawSymbol(&mSelector
->mSlot
)->name
);
3554 setterSym
= getsym(setterName
);
3556 slotRawSymbol(&mSelector
->mSlot
)->flags
|= sym_Called
;
3557 index
= conjureSelectorIndex((PyrParseNode
*)mSelector
, gCompilingBlock
,
3558 isSuper
, setterSym
, &selType
);
3561 compileOpcode(opSendSuper
, 2);
3565 compileOpcode(opSendMsg
, 2);
3571 void PyrMultiAssignNode::compile(PyrSlot
* result
)
3575 //postfl("compilePyrMultiAssignNode\n");
3576 COMPILENODE(mExpr
, &dummy
, false);
3577 COMPILENODE(mVarList
, &dummy
, false);
3580 void PyrMultiAssignVarListNode::compile(PyrSlot
* result
)
3583 PyrSlotNode
*varname
;
3585 //postfl("compilePyrMultiAssignVarListNode\n");
3586 numAssigns
= nodeListLength((PyrParseNode
*)mVarNames
);
3587 varname
= mVarNames
;
3588 for (i
=0; i
<numAssigns
; ++i
, varname
= (PyrSlotNode
*)varname
->mNext
) {
3589 compileOpcode(opSpecialOpcode
, opcDup
);
3591 compileOpcode(opSendSpecialMsg
, 2);
3593 compileAssignVar((PyrParseNode
*)varname
, slotRawSymbol(&varname
->mSlot
), 1);
3594 //compileOpcode(opSpecialOpcode, opcDrop);
3597 compileOpcode(opSpecialOpcode
, opcDup
);
3599 compileOpcode(opSendSpecialMsg
, 2);
3600 compileByte(opmCopyToEnd
);
3601 compileAssignVar((PyrParseNode
*)mRest
, slotRawSymbol(&mRest
->mSlot
), 1);
3602 //compileOpcode(opSpecialOpcode, opcDrop);
3607 PyrDynDictNode
* newPyrDynDictNode(PyrParseNode
*elems
)
3609 PyrDynDictNode
* node
;
3611 //if (compilingCmdLine) post("newPyrDynDictNode\n");
3612 node
= ALLOCNODE(PyrDynDictNode
);
3613 node
->mElems
= elems
;
3617 int PyrDynDictNode::isPartialApplication()
3620 int numItems
= nodeListLength(mElems
);
3621 PyrParseNode
* inode
= mElems
;
3622 for (int i
=0; i
<numItems
; ++i
) {
3623 if (inode
->mClassno
== pn_CurryArgNode
) {
3624 ((PyrCurryArgNode
*)inode
)->mArgNum
= sum
;
3627 inode
= (PyrParseNode
*)inode
->mNext
;
3632 void PyrDynDictNode::compileCall(PyrSlot
* result
)
3635 PyrParseNode
*inode
;
3638 //postfl("compilePyrDynDictNode\n");
3639 numItems
= nodeListLength(mElems
) >> 1;
3641 compilePushVar((PyrParseNode
*)this, s_event
);
3643 compilePushInt(numItems
);
3644 compileByte(110); // push nil for proto
3645 compileByte(110); // push nil for parent
3646 compileByte(108); // push true for know
3647 compileOpcode(opSendSpecialMsg
, 5);
3649 compileByte(opmNew
);
3652 for (i
=0; i
<numItems
; ++i
) {
3653 //if (compilingCmdLine) post("+ %d %d\n", i, gCompilingByteCodes->size);
3654 COMPILENODE(inode
, &dummy
, false);
3655 inode
= (PyrParseNode
*)inode
->mNext
;
3656 COMPILENODE(inode
, &dummy
, false);
3657 inode
= (PyrParseNode
*)inode
->mNext
;
3658 compileOpcode(opSendSpecialMsg
, 3);
3659 compileByte(opmPut
);
3663 PyrDynListNode
* newPyrDynListNode(PyrParseNode
*classname
, PyrParseNode
*elems
)
3665 PyrDynListNode
* node
;
3667 //if (compilingCmdLine) post("newPyrDynListNode\n");
3668 node
= ALLOCNODE(PyrDynListNode
);
3669 node
->mClassname
= classname
;
3670 node
->mElems
= elems
;
3674 int PyrDynListNode::isPartialApplication()
3677 int numItems
= nodeListLength(mElems
);
3678 PyrParseNode
* inode
= mElems
;
3679 for (int i
=0; i
<numItems
; ++i
) {
3680 if (inode
->mClassno
== pn_CurryArgNode
) {
3681 ((PyrCurryArgNode
*)inode
)->mArgNum
= sum
;
3684 inode
= (PyrParseNode
*)inode
->mNext
;
3689 void PyrDynListNode::compileCall(PyrSlot
* result
)
3692 PyrParseNode
*inode
;
3695 //postfl("compilePyrDynListNode\n");
3696 numItems
= nodeListLength(mElems
);
3699 compilePushVar((PyrParseNode
*)this, slotRawSymbol(&((PyrSlotNode
*)mClassname
)->mSlot
));
3701 compilePushVar((PyrParseNode
*)this, s_array
);
3704 //compileOpcode(opExtended, opPushSpecialValue);
3705 //compileByte(op_class_list);
3707 compilePushInt(numItems
);
3709 compileOpcode(opSendSpecialMsg
, 2);
3710 compileByte(opmNew
);
3713 for (i
=0; i
<numItems
; ++i
, inode
= (PyrParseNode
*)inode
->mNext
) {
3714 //if (compilingCmdLine) post("+ %d %d\n", i, gCompilingByteCodes->size);
3715 COMPILENODE(inode
, &dummy
, false);
3716 compileOpcode(opSendSpecialMsg
, 2);
3717 compileByte(opmAdd
);
3721 PyrLitListNode
* newPyrLitListNode(PyrParseNode
*classname
, PyrParseNode
*elems
)
3723 PyrLitListNode
* node
= ALLOCNODE(PyrLitListNode
);
3724 node
->mClassname
= classname
;
3725 node
->mElems
= elems
;
3729 void PyrLitListNode::compile(PyrSlot
* result
)
3731 PyrSlot
*resultSlot
;
3734 PyrParseNode
*inode
;
3735 int i
, numItems
, flags
;
3737 //postfl("->compilePyrLitListNode\n");
3738 if (mClassname
&& slotRawSymbol(&((PyrSlotNode
*)mClassname
)->mSlot
) != s_array
) {
3739 error("Only Array is supported as literal type.\n");
3740 post("Compiling as an Array.\n");
3742 resultSlot
= (PyrSlot
*)result
;
3743 numItems
= mElems
? nodeListLength(mElems
) : 0;
3744 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
3745 array
= newPyrArray(compileGC(), numItems
, flags
, false);
3747 for (i
=0; i
<numItems
; ++i
, inode
= (PyrParseNode
*)inode
->mNext
) {
3748 COMPILENODE(inode
, &itemSlot
, false);
3749 array
->slots
[i
] = itemSlot
;
3751 array
->size
= numItems
;
3752 SetObject(resultSlot
, array
);
3753 //postfl("<-compilePyrLitListNode\n");
3757 PyrLitDictNode
* newPyrLitDictNode(PyrParseNode
*elems
)
3759 PyrLitDictNode
* node
= ALLOCNODE(PyrLitDictNode
);
3760 node
->mElems
= elems
;
3765 int litDictPut(PyrObject
*dict
, PyrSlot
*key
, PyrSlot
*value
);
3766 int litDictPut(PyrObject
*dict
, PyrSlot
*key
, PyrSlot
*value
)
3769 PyrSlot
*slot
, *newslot
;
3773 bool knows
= IsTrue(dict
->slots
+ ivxIdentDict_know
);
3774 if (knows
&& IsSym(key
)) {
3775 if (slotRawSymbol(key
) == s_parent
) {
3776 slotCopy(&dict
->slots
[ivxIdentDict_parent
], value
);
3779 if (slotRawSymbol(key
) == s_proto
) {
3780 slotCopy(&dict
->slots
[ivxIdentDict_proto
], value
);
3784 array
= slotRawObject(&dict
->slots
[ivxIdentDict_array
]);
3785 if (!isKindOf((PyrObject
*)array
, class_array
)) return errFailed
;
3787 index
= arrayAtIdentityHashInPairs(array
, key
);
3788 slot
= array
->slots
+ index
;
3789 slotCopy(&slot
[1], value
);
3791 slotCopy(slot
, key
);
3798 void PyrLitDictNode::dump(int level
)
3802 void PyrLitDictNode::compile(PyrSlot
* result
)
3805 PyrSlot
*resultSlot
;
3808 PyrParseNode
*inode
;
3809 int i
, numItems
, flags
;
3811 //postfl("->compilePyrLitDictNode\n");
3812 if (mClassname
&& slotRawSymbol(&((PyrSlotNode
*)mClassname
)->mSlot
) != s_array
) {
3813 error("Only Array is supported as literal type.\n");
3814 post("Compiling as an Array.\n");
3816 resultSlot
= (PyrSlot
*)result
;
3817 numItems
= mElems
? nodeListLength(mElems
) : 0;
3818 int numSlots
= NEXTPOWEROFTWO(numItems
*2);
3820 PyrObject
*obj
= instantiateObject(g
->gc
, class_event
->u
.classobj
, 0, true, false);
3821 PyrSlot
*slots
= obj
->slots
;
3823 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
3824 array
= newPyrArray(compileGC(), numSlots
, flags
, false);
3825 nilSlots(array
->slots
, numSlots
);
3827 for (i
=0; i
<numItems
; ++i
, inode
= (PyrParseNode
*)inode
->mNext
) {
3828 COMPILENODE(inode
, &itemSlot
, false);
3829 array
->slots
[i
] = itemSlot
;
3831 array
->size
= numItems
;
3832 SetObject(resultSlot
, array
);
3833 //postfl("<-compilePyrLitListNode\n");
3838 extern LongStack closedFuncCharNo
;
3839 extern int lastClosedFuncCharNo
;
3841 PyrBlockNode
* newPyrBlockNode(PyrArgListNode
*arglist
, PyrVarListNode
*varlist
, PyrParseNode
*body
, bool isTopLevel
)
3843 PyrBlockNode
* node
= ALLOCNODE(PyrBlockNode
);
3844 node
->mArglist
= arglist
;
3845 catVarLists(varlist
);
3846 node
->mVarlist
= varlist
;
3848 node
->mIsTopLevel
= isTopLevel
;
3850 node
->mBeginCharNo
= lastClosedFuncCharNo
;
3855 void PyrBlockNode::compile(PyrSlot
* slotResult
)
3857 PyrBlock
*block
, *prevBlock
;
3858 PyrMethodRaw
*methraw
;
3859 int i
, j
, numArgs
, numVars
, funcVarArgs
;
3860 int numSlots
, numArgNames
, flags
;
3861 PyrVarDefNode
*vardef
;
3863 PyrSymbolArray
*argNames
, *varNames
;
3865 bool hasVarExprs
= false;
3867 //postfl("->block\n");
3869 // create a new block object
3871 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
3872 block
= newPyrBlock(flags
);
3873 SetObject(slotResult
, block
);
3875 int prevFunctionHighestExternalRef
= gFunctionHighestExternalRef
;
3876 bool prevFunctionCantBeClosed
= gFunctionCantBeClosed
;
3877 gFunctionHighestExternalRef
= 0;
3878 gFunctionCantBeClosed
= false;
3880 prevBlock
= gCompilingBlock
;
3881 PyrClass
* prevClass
= gCompilingClass
;
3883 gCompilingBlock
= block
;
3884 PyrBlock
* prevPartiallyAppliedFunction
= gPartiallyAppliedFunction
;
3885 gPartiallyAppliedFunction
= NULL
;
3887 methraw
= METHRAW(block
);
3888 methraw
->unused1
= 0;
3889 methraw
->unused2
= 0;
3891 int endCharNo
= linestarts
[mLineno
] + mCharno
;
3892 int stringLength
= endCharNo
- mBeginCharNo
;
3893 int lastChar
= text
[mBeginCharNo
+ stringLength
- 1];
3894 if (lastChar
== 0) stringLength
--;
3896 methraw
->needsHeapContext
= 0;
3898 gCompilingClass
= class_interpreter
;
3899 SetNil(&block
->contextDef
);
3901 SetObject(&block
->contextDef
, prevBlock
);
3904 methraw
->varargs
= funcVarArgs
= (mArglist
&& mArglist
->mRest
) ? 1 : 0;
3905 numArgs
= mArglist
? nodeListLength((PyrParseNode
*)mArglist
->mVarDefs
) : 0;
3906 numVars
= mVarlist
? nodeListLength((PyrParseNode
*)mVarlist
->mVarDefs
) : 0;
3908 numSlots
= numArgs
+ funcVarArgs
+ numVars
;
3909 methraw
->frameSize
= (numSlots
+ FRAMESIZE
) * sizeof(PyrSlot
);
3911 proto
= newPyrArray(compileGC(), numSlots
, flags
, false);
3912 proto
->size
= numSlots
;
3913 SetObject(&block
->prototypeFrame
, proto
);
3915 SetNil(&block
->prototypeFrame
);
3918 numArgNames
= numArgs
+ funcVarArgs
;
3921 argNames
= newPyrSymbolArray(compileGC(), numArgNames
, flags
, false);
3922 argNames
->size
= numArgNames
;
3923 SetObject(&block
->argNames
, argNames
);
3925 SetNil(&block
->argNames
);
3929 varNames
= newPyrSymbolArray(compileGC(), numVars
, flags
, false);
3930 varNames
->size
= numVars
;
3931 SetObject(&block
->varNames
, varNames
);
3933 SetNil(&block
->varNames
);
3936 methraw
->numargs
= numArgs
;
3937 methraw
->numvars
= numVars
;
3938 methraw
->posargs
= numArgs
+ funcVarArgs
;
3939 methraw
->numtemps
= numSlots
;
3940 methraw
->popSize
= numSlots
;
3944 PyrSymbol
**blockargs
;
3945 blockargs
= slotRawSymbolArray(&block
->argNames
)->symbols
;
3946 vardef
= mArglist
->mVarDefs
;
3947 for (i
=0; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
3949 varslot
= &vardef
->mVarName
->mSlot
;
3950 // already declared as arg?
3951 for (j
=0; j
<i
; ++j
) {
3952 if (blockargs
[j
] == slotRawSymbol(varslot
)) {
3953 error("Function argument '%s' already declared in %s:%s\n",
3954 slotRawSymbol(varslot
)->name
,
3955 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
3956 nodePostErrorLine((PyrParseNode
*)vardef
);
3960 // put it in mArglist
3961 blockargs
[i
] = slotRawSymbol(varslot
);
3962 //postfl("defarg %d '%s'\n", i, slotRawSymbol(slot)->name);
3968 PyrSymbol
**blockargs
;
3969 blockargs
= slotRawSymbolArray(&block
->argNames
)->symbols
;
3970 varslot
= &mArglist
->mRest
->mSlot
;
3971 // already declared as arg?
3972 for (j
=0; j
<numArgs
; ++j
) {
3973 if (blockargs
[j
] == slotRawSymbol(varslot
)) {
3974 error("Function argument '%s' already declared in %s:%s\n",
3975 slotRawSymbol(varslot
)->name
,
3976 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
3977 nodePostErrorLine((PyrParseNode
*)vardef
);
3981 // put it in mArglist
3982 blockargs
[numArgs
] = slotRawSymbol(varslot
);
3983 //postfl("defrest '%s'\n", slotRawSymbol(slot)->name);
3988 PyrSymbol
**blockargs
, **blockvars
;
3989 blockargs
= slotRawSymbolArray(&block
->argNames
)->symbols
;
3990 blockvars
= slotRawSymbolArray(&block
->varNames
)->symbols
;
3991 vardef
= mVarlist
->mVarDefs
;
3992 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
3994 varslot
= &vardef
->mVarName
->mSlot
;
3995 // already declared as arg?
3996 for (j
=0; j
<numArgNames
; ++j
) {
3997 if (blockargs
[j
] == slotRawSymbol(varslot
)) {
3998 error("Function variable '%s' already declared in %s:%s\n",
3999 slotRawSymbol(varslot
)->name
,
4000 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
4001 nodePostErrorLine((PyrParseNode
*)vardef
);
4005 // already declared as var?
4006 for (j
=0; j
<i
; ++j
) {
4007 if (blockvars
[j
] == slotRawSymbol(varslot
)) {
4008 error("Function variable '%s' already declared in %s:%s\n",
4009 slotRawSymbol(varslot
)->name
,
4010 slotRawSymbol(&gCompilingClass
->name
)->name
, slotRawSymbol(&gCompilingMethod
->name
)->name
);
4011 nodePostErrorLine((PyrParseNode
*)vardef
);
4015 // put it in varlist
4016 blockvars
[i
] = slotRawSymbol(varslot
);
4017 //postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
4022 vardef
= mArglist
->mVarDefs
;
4023 for (i
=0; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
4024 PyrSlot
*slot
, litval
;
4025 slot
= slotRawObject(&block
->prototypeFrame
)->slots
+ i
;
4026 if (vardef
->hasExpr(&litval
)) hasVarExprs
= true;
4027 //compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litval);
4033 //SetNil(&slotRawObject(&block->prototypeFrame)->slots[numArgs]);
4034 slotCopy(&slotRawObject(&block
->prototypeFrame
)->slots
[numArgs
], &o_emptyarray
);
4038 vardef
= mVarlist
->mVarDefs
;
4039 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
4040 PyrSlot
*slot
, litval
;
4041 slot
= slotRawObject(&block
->prototypeFrame
)->slots
+ i
+ numArgs
+ funcVarArgs
;
4042 if (vardef
->hasExpr(&litval
)) hasVarExprs
= true;
4043 //compilePyrLiteralNode(vardef->mDefVal, &litval);
4047 methraw
->methType
= methBlock
;
4052 SetTailBranch
branch(true);
4053 /*if (compilingCmdLine) {
4054 post("block %d\n", gIsTailCodeBranch);
4057 SetTailIsMethodReturn
mr(false);
4060 vardef
= mArglist
->mVarDefs
;
4061 for (i
=0; i
<numArgs
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
4062 vardef
->compileArg(&dummy
);
4066 vardef
= mVarlist
->mVarDefs
;
4067 for (i
=0; i
<numVars
; ++i
, vardef
= (PyrVarDefNode
*)vardef
->mNext
) {
4068 vardef
->compile(&dummy
);
4072 if (mBody
->mClassno
== pn_BlockReturnNode
) {
4073 compileOpcode(opPushSpecialValue
, opsvNil
);
4075 COMPILENODE(mBody
, &dummy
, true);
4078 compileOpcode(opSpecialOpcode
, opcFunctionReturn
);
4079 installByteCodes(block
);
4081 if ((!gFunctionCantBeClosed
&& gFunctionHighestExternalRef
== 0) || mIsTopLevel
) {
4082 SetNil(&block
->contextDef
);
4084 PyrString
* string
= newPyrStringN(compileGC(), stringLength
, flags
, false);
4085 memcpy(string
->s
, text
+mBeginCharNo
, stringLength
);
4086 SetObject(&block
->sourceCode
, string
);
4087 //static int totalLength = 0, totalStrings = 0;
4088 //totalLength += stringLength;
4090 //post("cf %4d %4d %6d %s:%s \n", totalStrings, stringLength, totalLength, slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
4093 gCompilingBlock
= prevBlock
;
4094 gCompilingClass
= prevClass
;
4095 gPartiallyAppliedFunction
= prevPartiallyAppliedFunction
;
4096 gFunctionCantBeClosed
= gFunctionCantBeClosed
|| prevFunctionCantBeClosed
;
4097 gFunctionHighestExternalRef
= sc_max(gFunctionHighestExternalRef
- 1, prevFunctionHighestExternalRef
);
4102 PyrParseNode
* linkNextNode(PyrParseNode
* a
, PyrParseNode
* b
)
4104 if (a
== NULL
) return b
;
4106 a
->mTail
->mNext
= b
;
4107 a
->mTail
= b
->mTail
;
4112 PyrParseNode
* linkAfterHead(PyrParseNode
* a
, PyrParseNode
* b
)
4114 b
->mNext
= a
->mNext
;
4115 if (!a
->mNext
) a
->mTail
= b
;
4120 bool isSuperObjNode(PyrParseNode
*node
)
4122 return node
->mClassno
== pn_PushNameNode
4123 && slotRawSymbol(&((PyrPushNameNode
*)node
)->mSlot
) == s_super
;
4126 bool isThisObjNode(PyrParseNode
*node
)
4128 return node
->mClassno
== pn_PushNameNode
4129 && slotRawSymbol(&((PyrPushNameNode
*)node
)->mSlot
) == s_this
;
4132 int nodeListLength(PyrParseNode
*node
)
4135 for (; node
; node
=node
->mNext
) length
++;
4140 int conjureSelectorIndex(PyrParseNode
*node
, PyrBlock
* func
,
4141 bool isSuper
, PyrSymbol
*selector
, int *selType
)
4144 PyrObject
*selectors
;
4148 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
4150 if (selector
== gSpecialSelectors
[opmIf
]) {
4153 } else if (selector
== gSpecialSelectors
[opmWhile
]) {
4154 *selType
= selWhile
;
4156 } else if (selector
== gSpecialSelectors
[opmAnd
]) {
4159 } else if (selector
== gSpecialSelectors
[opmOr
]) {
4162 } else if (selector
== gSpecialSelectors
[opmCase
]) {
4165 } else if (selector
== gSpecialSelectors
[opmSwitch
]) {
4166 *selType
= selSwitch
;
4168 } else if (selector
== gSpecialSelectors
[opmLoop
]) {
4171 } else if (selector
== gSpecialSelectors
[opmQuestionMark
]) {
4172 *selType
= selQuestionMark
;
4174 } else if (selector
== gSpecialSelectors
[opmDoubleQuestionMark
]) {
4175 *selType
= selDoubleQuestionMark
;
4177 } else if (selector
== gSpecialSelectors
[opmExclamationQuestionMark
]) {
4178 *selType
= selExclamationQuestionMark
;
4182 for (i
=0; i
<opmNumSpecialSelectors
; ++i
) {
4183 if (selector
== gSpecialSelectors
[i
]) {
4184 *selType
= selSpecial
;
4189 for (i
=0; i
<opNumUnarySelectors
; ++i
) {
4190 if (selector
== gSpecialUnarySelectors
[i
]) {
4191 *selType
= selUnary
;
4196 for (i
=0; i
<opNumBinarySelectors
; ++i
) {
4197 if (selector
== gSpecialBinarySelectors
[i
]) {
4198 *selType
= selBinary
;
4204 if (NotNil(&func
->selectors
)) {
4205 selectors
= slotRawObject(&func
->selectors
);
4206 for (i
=0; i
<selectors
->size
; ++i
) {
4207 if (IsSym(&selectors
->slots
[i
]) && slotRawSymbol(&selectors
->slots
[i
]) == selector
) {
4208 *selType
= selNormal
;
4213 selectors
= (PyrObject
*)newPyrArray(compileGC(), 2, flags
, false);
4214 SetObject(&func
->selectors
, selectors
);
4216 // otherwise add it to the selectors table
4218 if (selectors
->size
+1 >= 256) {
4219 error("Literal table too big. Simplify the function.\n");
4220 post("Next selector was: %s\n", selector
->name
);
4221 nodePostErrorLine(node
);
4226 if (selectors
->size
+1 > ARRAYMAXINDEXSIZE(selectors
)) {
4227 // resize literal table
4228 newsize
= ARRAYMAXINDEXSIZE(selectors
) * 2;
4229 SetRaw(&func
->selectors
, (PyrObject
*)newPyrArray(compileGC(), newsize
, flags
, false));
4230 memcpy(slotRawObject(&func
->selectors
)->slots
, selectors
->slots
, selectors
->size
* sizeof(PyrSlot
));
4231 slotRawObject(&func
->selectors
)->size
= selectors
->size
;
4232 freePyrObject(selectors
);
4233 selectors
= slotRawObject(&func
->selectors
);
4235 slot
= selectors
->slots
+ selectors
->size
++;
4236 SetSymbol(slot
, selector
);
4238 *selType
= selNormal
;
4239 return selectors
->size
-1;
4242 int conjureLiteralSlotIndex(PyrParseNode
*node
, PyrBlock
* func
, PyrSlot
*slot
)
4245 PyrObject
*selectors
;
4249 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
4250 // lookup slot in selectors table
4252 if (IsObj(&func
->selectors
)) {
4253 selectors
= slotRawObject(&func
->selectors
);
4254 /*if (selectors->classptr != class_array) {
4255 post("compiling %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
4256 post("selectors is a '%s'\n", selectors->classptr->name.us->name);
4257 dumpObjectSlot(slot);
4260 for (i
=0; i
<selectors
->size
; ++i
)
4261 if (SlotEq(&selectors
->slots
[i
], slot
))
4264 selectors
= (PyrObject
*)newPyrArray(compileGC(), 4, flags
, false);
4265 SetObject(&func
->selectors
, selectors
);
4267 // otherwise add it to the selectors table
4269 if (selectors
->size
+1 >= 256) {
4270 error("Literal table too big (>256). Simplify the function.\n");
4271 post("Next literal was:\n");
4273 nodePostErrorLine(node
);
4277 if (selectors
->size
+1 > ARRAYMAXINDEXSIZE(selectors
)) {
4278 // resize literal table
4279 newsize
= ARRAYMAXINDEXSIZE(selectors
) * 2;
4280 // resize literal table
4281 SetRaw(&func
->selectors
, (PyrObject
*)newPyrArray(compileGC(), newsize
, flags
, false));
4282 memcpy(slotRawObject(&func
->selectors
)->slots
, selectors
->slots
, selectors
->size
* sizeof(PyrSlot
));
4283 slotRawObject(&func
->selectors
)->size
= selectors
->size
;
4284 freePyrObject(selectors
);
4285 selectors
= slotRawObject(&func
->selectors
);
4287 slot2
= selectors
->slots
+ selectors
->size
++;
4288 slotCopy(slot2
, slot
);
4290 return selectors
->size
-1;
4294 int conjureConstantIndex(PyrParseNode
*node
, PyrBlock
* func
, PyrSlot
*slot
)
4297 PyrObject
*constants
;
4300 flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
4302 // lookup slot in constants table
4303 if (IsObj(&func
->constants
)) {
4304 constants
= slotRawObject(&func
->constants
);
4305 for (i
=0; i
<constants
->size
; ++i
)
4306 if (SlotEq(&constants
->slots
[i
], slot
))
4309 constants
= (PyrObject
*)newPyrArray(compileGC(), 4, flags
, false);
4310 SetObject(&func
->constants
, constants
);
4313 // otherwise add it to the constants table
4314 if (constants
->size
+1 > ARRAYMAXINDEXSIZE(constants
)) {
4315 // resize literal table
4316 newsize
= ARRAYMAXINDEXSIZE(constants
) * 2;
4317 // resize literal table
4318 SetRaw(&func
->constants
, (PyrObject
*)newPyrArray(compileGC(), newsize
, flags
, false));
4319 memcpy(slotRawObject(&func
->constants
)->slots
, constants
->slots
, constants
->size
* sizeof(PyrSlot
));
4320 slotRawObject(&func
->constants
)->size
= constants
->size
;
4321 freePyrObject((PyrObject
*)constants
);
4322 constants
= slotRawObject(&func
->constants
);
4324 slotCopy(&constants
->slots
[constants
->size
++], slot
);
4326 return constants
->size
-1;
4329 bool findVarName(PyrBlock
* func
, PyrClass
**classobj
, PyrSymbol
*name
,
4330 int *varType
, int *level
, int *index
, PyrBlock
** tempfunc
)
4334 PyrSymbol
*argname
, *varname
;
4335 PyrMethodRaw
*methraw
;
4337 //postfl("->findVarName %s\n", name->name);
4338 // find var in enclosing blocks, instance, class
4339 if (name
== s_super
) {
4340 gFunctionCantBeClosed
= true;
4343 if (name
->name
[0] >= 'A' && name
->name
[0] <= 'Z') return false;
4344 for (j
=0; func
; func
= slotRawBlock(&func
->contextDef
), ++j
) {
4345 methraw
= METHRAW(func
);
4346 numargs
= methraw
->posargs
;
4347 for (i
=0; i
<numargs
; ++i
) {
4348 argname
= slotRawSymbolArray(&func
->argNames
)->symbols
[i
];
4349 //postfl(" %d %d arg '%s' '%s'\n", j, i, argname->name, name->name);
4350 if (argname
== name
) {
4354 if (tempfunc
) *tempfunc
= func
;
4355 if (j
> gFunctionHighestExternalRef
) gFunctionHighestExternalRef
= j
;
4359 for (i
=0, k
=numargs
; i
<methraw
->numvars
; ++i
,++k
) {
4360 varname
= slotRawSymbolArray(&func
->varNames
)->symbols
[i
];
4361 //postfl(" %d %d %d var '%s' '%s'\n", j, i, k, varname->name, name->name);
4362 if (varname
== name
) {
4366 if (tempfunc
) *tempfunc
= func
;
4367 if (j
> gFunctionHighestExternalRef
) gFunctionHighestExternalRef
= j
;
4373 if (classFindInstVar(*classobj
, name
, index
)) {
4376 if (gCompilingClass
!= class_interpreter
) gFunctionCantBeClosed
= true;
4379 if (classFindClassVar(classobj
, name
, index
)) {
4380 *varType
= varClass
;
4381 if (gCompilingClass
!= class_interpreter
) gFunctionCantBeClosed
= true;
4384 if (classFindConst(classobj
, name
, index
)) {
4385 *varType
= varConst
;
4386 //if (gCompilingClass != class_interpreter) gFunctionCantBeClosed = true;
4389 if (name
== s_curProcess
) {
4390 *varType
= varPseudo
;
4391 *index
= opgProcess
;
4394 if (name
== s_curThread
) {
4395 *varType
= varPseudo
;
4399 if (name
== s_curMethod
) {
4400 *varType
= varPseudo
;
4404 if (name
== s_curBlock
) {
4405 *varType
= varPseudo
;
4406 *index
= opgFunctionDef
;
4409 if (name
== s_curClosure
) {
4410 *varType
= varPseudo
;
4411 *index
= opgFunction
;
4417 extern PyrSymbol
*s_env
;
4419 void initSpecialClasses()
4421 gSpecialClasses
[op_class_object
] = s_object
;
4422 gSpecialClasses
[op_class_symbol
] = s_symbol
;
4423 gSpecialClasses
[op_class_nil
] = s_nil
;
4424 gSpecialClasses
[op_class_boolean
] = s_boolean
;
4425 gSpecialClasses
[op_class_true
] = s_true
;
4426 gSpecialClasses
[op_class_false
] = s_false
;
4427 gSpecialClasses
[op_class_magnitude
] = s_magnitude
;
4428 gSpecialClasses
[op_class_char
] = s_char
;
4429 gSpecialClasses
[op_class_number
] = s_number
;
4430 gSpecialClasses
[op_class_complex
] = s_complex
;
4431 gSpecialClasses
[op_class_simple_number
] = s_simple_number
;
4432 gSpecialClasses
[op_class_int
] = s_int
;
4433 gSpecialClasses
[op_class_float
] = s_float
;
4434 gSpecialClasses
[op_class_method
] = s_method
;
4435 gSpecialClasses
[op_class_fundef
] = s_fundef
;
4436 gSpecialClasses
[op_class_stream
] = s_stream
;
4437 gSpecialClasses
[op_class_func
] = s_func
;
4438 gSpecialClasses
[op_class_frame
] = s_frame
;
4439 gSpecialClasses
[op_class_process
] = s_process
;
4440 gSpecialClasses
[op_class_main
] = s_main
;
4441 gSpecialClasses
[op_class_class
] = s_class
;
4442 gSpecialClasses
[op_class_string
] = s_string
;
4444 gSpecialClasses
[op_class_collection
] = s_collection
;
4445 gSpecialClasses
[op_class_sequenceable_collection
] = s_sequenceable_collection
;
4446 gSpecialClasses
[op_class_arrayed_collection
] = s_arrayed_collection
;
4447 gSpecialClasses
[op_class_array
] = s_array
;
4448 gSpecialClasses
[op_class_int8array
] = s_int8array
;
4449 gSpecialClasses
[op_class_int16array
] = s_int16array
;
4450 gSpecialClasses
[op_class_int32array
] = s_int32array
;
4451 gSpecialClasses
[op_class_floatarray
] = s_floatarray
;
4452 gSpecialClasses
[op_class_signal
] = s_signal
;
4453 gSpecialClasses
[op_class_doublearray
] = s_doublearray
;
4454 gSpecialClasses
[op_class_symbolarray
] = s_symbolarray
;
4455 gSpecialClasses
[op_class_list
] = s_list
;
4456 gSpecialClasses
[op_class_linkedlist
] = s_linkedlist
;
4457 gSpecialClasses
[op_class_bag
] = s_bag
;
4458 gSpecialClasses
[op_class_set
] = s_set
;
4459 gSpecialClasses
[op_class_identityset
] = s_identityset
;
4460 gSpecialClasses
[op_class_dictionary
] = s_dictionary
;
4461 gSpecialClasses
[op_class_identitydictionary
] = s_identitydictionary
;
4462 gSpecialClasses
[op_class_sortedlist
] = s_sortedlist
;
4464 gSpecialClasses
[op_class_synth
] = s_synth
;
4465 gSpecialClasses
[op_class_ref
] = s_ref
;
4466 gSpecialClasses
[op_class_environment
] = s_environment
;
4467 gSpecialClasses
[op_class_event
] = s_event
;
4468 gSpecialClasses
[op_class_wavetable
] = s_wavetable
;
4469 gSpecialClasses
[op_class_env
] = s_env
;
4470 gSpecialClasses
[op_class_routine
] = s_routine
;
4471 gSpecialClasses
[op_class_color
] = s_color
;
4472 gSpecialClasses
[op_class_rect
] = s_rect
;
4474 //Infinitum, Point, Rect, ??
4477 void initSpecialSelectors()
4482 sel
= gSpecialUnarySelectors
;
4483 sel
[opNeg
] = getsym("neg");
4484 sel
[opRecip
] = getsym("reciprocal");
4485 sel
[opNot
] = getsym("not");
4486 sel
[opIsNil
] = getsym("isNil");
4487 sel
[opNotNil
] = getsym("notNil");
4488 sel
[opBitNot
] = getsym("bitNot");
4489 sel
[opAbs
] = getsym("abs");
4490 sel
[opAsFloat
] = getsym("asFloat");
4491 sel
[opAsInt
] = getsym("asInt");
4492 sel
[opCeil
] = getsym("ceil"); //5
4493 sel
[opFloor
] = getsym("floor");
4494 sel
[opFrac
] = getsym("frac");
4495 sel
[opSign
] = getsym("sign");
4496 sel
[opSquared
] = getsym("squared");
4497 sel
[opCubed
] = getsym("cubed"); //10
4498 sel
[opSqrt
] = getsym("sqrt");
4499 sel
[opExp
] = getsym("exp");
4500 sel
[opMIDICPS
] = getsym("midicps");
4501 sel
[opCPSMIDI
] = getsym("cpsmidi");
4502 sel
[opMIDIRatio
] = getsym("midiratio");
4503 sel
[opRatioMIDI
] = getsym("ratiomidi");
4504 sel
[opAmpDb
] = getsym("ampdb"); //15
4505 sel
[opDbAmp
] = getsym("dbamp");
4506 sel
[opOctCPS
] = getsym("octcps");
4507 sel
[opCPSOct
] = getsym("cpsoct");
4508 sel
[opLog
] = getsym("log");
4509 sel
[opLog2
] = getsym("log2"); //20
4510 sel
[opLog10
] = getsym("log10");
4511 sel
[opSin
] = getsym("sin");
4512 sel
[opCos
] = getsym("cos");
4513 sel
[opTan
] = getsym("tan");
4514 sel
[opArcSin
] = getsym("asin"); //25
4515 sel
[opArcCos
] = getsym("acos");
4516 sel
[opArcTan
] = getsym("atan");
4517 sel
[opSinH
] = getsym("sinh");
4518 sel
[opCosH
] = getsym("cosh");
4519 sel
[opTanH
] = getsym("tanh"); //30
4520 sel
[opRand
] = getsym("rand");
4521 sel
[opRand2
] = getsym("rand2");
4522 sel
[opLinRand
] = getsym("linrand");
4523 sel
[opBiLinRand
] = getsym("bilinrand");
4524 sel
[opSum3Rand
] = getsym("sum3rand");
4526 sel[opExpRand] = getsym("exprand");
4527 sel[opBiExpRand] = getsym("biexprand");
4528 sel[opGammaRand] = getsym("gammarand");
4529 sel[opGaussRand] = getsym("gaussrand");
4530 sel[opPoiRand] = getsym("poirand");
4532 sel
[opDistort
] = getsym("distort");
4533 sel
[opSoftClip
] = getsym("softclip");
4534 sel
[opCoin
] = getsym("coin");
4536 sel
[opRectWindow
] = getsym("rectWindow");
4537 sel
[opHanWindow
] = getsym("hanWindow");
4538 sel
[opWelchWindow
] = getsym("welWindow");
4539 sel
[opTriWindow
] = getsym("triWindow");
4541 sel
[opSCurve
] = getsym("scurve");
4542 sel
[opRamp
] = getsym("ramp");
4544 sel
[opDigitValue
] = getsym("digitValue");
4545 sel
[opSilence
] = getsym("silence");
4546 sel
[opThru
] = getsym("thru");
4549 sel
= gSpecialBinarySelectors
;
4551 sel
[opAdd
] = getsym("+");
4552 sel
[opSub
] = getsym("-");
4553 sel
[opMul
] = getsym("*");
4555 sel
[opFDiv
] = getsym("/");
4556 sel
[opIDiv
] = getsym("div");
4557 sel
[opMod
] = getsym("mod");
4558 sel
[opEQ
] = getsym("==");
4559 sel
[opNE
] = getsym("!=");
4560 sel
[opLT
] = getsym("<");
4561 sel
[opGT
] = getsym(">");
4562 sel
[opLE
] = getsym("<=");
4563 sel
[opGE
] = getsym(">=");
4564 //sel[opIdentical] = getsym("===");
4565 //sel[opNotIdentical] = getsym("!==");
4566 sel
[opMin
] = getsym("min");
4567 sel
[opMax
] = getsym("max");
4568 sel
[opBitAnd
] = getsym("bitAnd");
4569 sel
[opBitOr
] = getsym("bitOr");
4570 sel
[opBitXor
] = getsym("bitXor");
4571 sel
[opLCM
] = getsym("lcm");
4572 sel
[opGCD
] = getsym("gcd");
4573 sel
[opRound
] = getsym("round");
4574 sel
[opRoundUp
] = getsym("roundUp");
4575 sel
[opTrunc
] = getsym("trunc");
4576 sel
[opAtan2
] = getsym("atan2");
4577 sel
[opHypot
] = getsym("hypot");
4578 sel
[opHypotx
] = getsym("hypotApx");
4579 sel
[opPow
] = getsym("pow");
4580 sel
[opShiftLeft
] = getsym("leftShift");
4581 sel
[opShiftRight
] = getsym("rightShift");
4582 sel
[opUnsignedShift
] = getsym("unsignedRightShift");
4583 sel
[opFill
] = getsym("fill");
4584 sel
[opRing1
] = getsym("ring1"); // a * (b + 1) == a * b + a
4585 sel
[opRing2
] = getsym("ring2"); // a * b + a + b
4586 sel
[opRing3
] = getsym("ring3"); // a*a*b
4587 sel
[opRing4
] = getsym("ring4"); // a*a*b - a*b*b
4588 sel
[opDifSqr
] = getsym("difsqr"); // a*a - b*b
4589 sel
[opSumSqr
] = getsym("sumsqr"); // a*a + b*b
4590 sel
[opSqrSum
] = getsym("sqrsum"); // (a + b)^2
4591 sel
[opSqrDif
] = getsym("sqrdif"); // (a - b)^2
4592 sel
[opAbsDif
] = getsym("absdif"); //
4593 sel
[opThresh
] = getsym("thresh"); //
4594 sel
[opAMClip
] = getsym("amclip"); //
4595 sel
[opScaleNeg
] = getsym("scaleneg"); //
4596 sel
[opClip2
] = getsym("clip2");
4597 sel
[opFold2
] = getsym("fold2");
4598 sel
[opWrap2
] = getsym("wrap2");
4599 sel
[opExcess
] = getsym("excess");
4600 sel
[opFirstArg
] = getsym("firstArg");
4601 sel
[opRandRange
] = getsym("rrand");
4602 sel
[opExpRandRange
] = getsym("exprand");
4605 sel
= gSpecialSelectors
;
4607 sel
[opmNew
] = getsym("new");
4608 sel
[opmNewClear
] = getsym("newClear");
4609 sel
[opmNewCopyArgs
] = getsym("newCopyArgs");
4610 sel
[opmInit
] = getsym("init");
4611 sel
[opmAt
] = getsym("at");
4612 sel
[opmPut
] = getsym("put");
4613 sel
[opmNext
] = getsym("next");
4614 sel
[opmReset
] = getsym("reset");
4615 sel
[opmValue
] = getsym("value");
4616 sel
[opmCopyToEnd
] = getsym("copyToEnd"); // used by multiple assignment
4617 //sel[opmIsNil] = getsym("isNil");
4618 //sel[opmNotNil] = getsym("notNil");
4619 sel
[opmSize
] = getsym("size");
4620 sel
[opmClass
] = getsym("class");
4621 sel
[opmIf
] = getsym("if");
4622 sel
[opmWhile
] = getsym("while");
4623 sel
[opmFor
] = getsym("for");
4624 sel
[opmAnd
] = getsym("and");
4625 sel
[opmOr
] = getsym("or");
4626 sel
[opmCase
] = getsym("case");
4627 sel
[opmSwitch
] = getsym("switch");
4628 sel
[opmIdentical
] = getsym("===");
4629 sel
[opmNotIdentical
] = getsym("!==");
4631 sel
[opmPrint
] = getsym("print");
4632 sel
[opmAdd
] = getsym("add");
4633 sel
[opmRemove
] = getsym("remove");
4634 sel
[opmIndexOf
] = getsym("indexOf");
4635 sel
[opmWrapAt
] = getsym("wrapAt");
4636 sel
[opmClipAt
] = getsym("clipAt");
4637 sel
[opmFoldAt
] = getsym("foldAt");
4638 sel
[opmWrapPut
] = getsym("wrapPut");
4639 sel
[opmClipPut
] = getsym("clipPut");
4640 sel
[opmFoldPut
] = getsym("foldPut");
4641 sel
[opmDo
] = getsym("do");
4642 sel
[opmCollect
] = getsym("collect");
4643 sel
[opmSelect
] = getsym("select");
4644 sel
[opmReject
] = getsym("reject");
4645 sel
[opmAny
] = getsym("any");
4646 sel
[opmEvery
] = getsym("every");
4647 sel
[opmFind
] = getsym("find");
4649 sel
[opmChoose
] = getsym("choose");
4651 sel
[opmValueList
] = getsym("valueList");
4652 sel
[opmAddFirst
] = getsym("addFirst");
4654 sel
[opmPrimitiveFailed
] = getsym("primitiveFailed");
4655 sel
[opmSubclassResponsibility
] = getsym("subclassResponsibility");
4656 sel
[opmShouldNotImplement
] = getsym("shouldNotImplement");
4657 sel
[opmDoesNotUnderstand
] = getsym("doesNotUnderstand"); // not really needed
4658 sel
[opmNotYetImplemented
] = getsym("notYetImplemented");
4660 sel
[opmAtSign
] = getsym("@");
4661 sel
[opmWrapAtSign
] = getsym("@@");
4662 sel
[opmClipAtSign
] = getsym("|@|");
4663 sel
[opmFoldAtSign
] = getsym("@|@");
4665 sel
[opmMultiNew
] = getsym("multiNew"); // UGens
4666 sel
[opmMultiNewList
] = getsym("multiNewList"); // UGens
4667 sel
[opmAR
] = getsym("ar"); // UGens
4668 sel
[opmKR
] = getsym("kr"); // UGens
4669 sel
[opmIR
] = getsym("ir"); // UGens
4671 sel
[opmEnvirGet
] = getsym("envirGet");
4672 sel
[opmEnvirPut
] = getsym("envirPut");
4674 sel
[opmHalt
] = getsym("halt");
4675 sel
[opmForBy
] = getsym("forBy");
4676 sel
[opmForSeries
] = getsym("forSeries");
4677 sel
[opmReverseDo
] = getsym("reverseDo");
4678 sel
[opmLoop
] = getsym("loop");
4679 sel
[opmNonBooleanError
] = getsym("mustBeBoolean");
4681 sel
[opmCopy
] = getsym("copy");
4682 sel
[opmPerformList
] = getsym("performList");
4683 sel
[opmIsKindOf
] = getsym("isKindOf");
4684 sel
[opmPostln
] = getsym("postln");
4685 sel
[opmAsString
] = getsym("asString");
4687 sel
[opmPlusPlus
] = getsym("++");
4688 sel
[opmLTLT
] = getsym("<<");
4689 sel
[opmQuestionMark
] = getsym("?");
4690 sel
[opmDoubleQuestionMark
] = getsym("??");
4691 sel
[opmExclamationQuestionMark
] = getsym("!?");
4693 sel
[opmYield
] = getsym("yield");
4694 sel
[opmName
] = getsym("name");
4695 sel
[opmMulAdd
] = getsym("madd");
4697 sel
[opmSeries
] = getsym("series");
4699 for (i
=0; i
<opNumUnarySelectors
; ++i
) {
4700 gSpecialUnarySelectors
[i
]->specialIndex
= i
;
4702 for (i
=0; i
<opNumBinarySelectors
; ++i
) {
4703 gSpecialBinarySelectors
[i
]->specialIndex
= i
;
4707 bool findSpecialClassName(PyrSymbol
*className
, int *index
)
4710 for (i
=0; i
<op_NumSpecialClasses
; ++i
) {
4711 if (gSpecialClasses
[i
] == className
) {