bumping version to 3.5-rc1
[supercollider.git] / lang / LangSource / PyrParseNode.cpp
blob958160b4ece6e103e6d2bc52aae1c83168a3d201
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "SCBase.h"
22 #include "PyrParseNode.h"
23 #include "PyrLexer.h"
24 #include "PyrKernel.h"
25 #include "PyrListPrim.h"
26 #include "PyrSymbolTable.h"
27 #include "Opcodes.h"
28 #include "PyrKernelProto.h"
29 #include "PyrObjectProto.h"
30 #include "GC.h"
31 #include <new>
32 #include <string>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdarg.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;
51 int gParserResult;
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;
67 #if TAILCALLOPTIMIZE
68 bool gGenerateTailCallByteCodes = true;
69 #else
70 bool gGenerateTailCallByteCodes = false;
71 #endif
73 long gInliningLevel;
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[] = {
85 "ClassNode",
86 "ClassExtNode",
87 "MethodNode",
88 "BlockNode",
89 "SlotNode",
91 /* variable declarations */
92 "VarListNode",
93 "VarDefNode",
94 "DynDictNode",
95 "DynListNode",
96 "LitListNode",
97 "LitDictNode",
99 "StaticVarListNode",
100 "InstVarListNode",
101 "PoolVarListNode",
102 "ArgListNode",
103 "SlotDefNode",
105 /* selectors */
106 "LiteralNode",
108 /* code */
109 "PushLitNode",
110 "PushNameNode",
111 "PushKeyArgNode",
112 "CallNode",
113 "BinopCallNode",
114 "DropNode",
115 "AssignNode",
116 "MultiAssignNode",
117 "MultiAssignVarListNode",
118 "SetterNode",
119 "CurryArgNode",
121 "ReturnNode",
122 "BlockReturnNode"
125 void compileTail()
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)
132 compileByte(255);
133 else
134 compileByte(176);
140 PyrGC* compileGC();
141 PyrGC* compileGC()
143 return gCompilingVMGlobals ? gCompilingVMGlobals->gc : 0;
146 void initParser()
148 compileErrors = 0;
149 numOverwrites = 0;
150 overwriteMsg.clear();
153 void finiParser()
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;
176 mNext = 0;
177 mTail = this;
178 mCharno = ::charno;
179 mLineno = ::lineno;
180 mParens = 0;
183 void compileNodeList(PyrParseNode *node, bool onTailBranch)
185 PyrSlot dummy;
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;
209 PyrBlock *tempfunc;
210 PyrClass *classobj;
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);
218 compileErrors++;
219 } else {
220 if (findSpecialClassName(varName, &index)) {
221 compileOpcode(opExtended, opPushSpecialValue); // special op for pushing a class
222 compileByte(index);
223 } else {
224 PyrSlot slot;
225 SetSymbol(&slot, varName);
226 index = conjureLiteralSlotIndex(node, gCompilingBlock, &slot);
227 compileOpcode(opExtended, opExtended); // special op for pushing a class
228 compileByte(index);
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)) {
243 switch (varType) {
244 case varInst :
245 compileOpcode(opPushInstVar, index);
246 break;
247 case varClass : {
248 index += slotRawInt(&classobj->classVarIndex);
249 if (index < 4096) {
250 compileByte((opPushClassVar<<4) | ((index >> 8) & 15));
251 compileByte(index & 255);
252 } else {
253 compileByte(opPushClassVar);
254 compileByte((index >> 8) & 255);
255 compileByte(index & 255);
257 } break;
258 case varConst : {
259 PyrSlot *slot = slotRawObject(&classobj->constValues)->slots + index;
260 compilePushConstant(node, slot);
261 } break;
262 case varTemp :
263 vindex = index;
264 if (level == 0) {
265 compileOpcode(opPushTempZeroVar, vindex);
266 } else if (level < 8) {
267 compileOpcode(opPushTempVar, level);
268 compileByte(vindex);
269 } else {
270 compileByte(opPushTempVar);
271 compileByte(level);
272 compileByte(vindex);
274 break;
275 case varPseudo :
276 compileOpcode(opExtended, opSpecialOpcode);
277 compileByte(index);
278 break;
280 } else {
281 error("Variable '%s' not defined.\n", varName->name);
282 nodePostErrorLine(node);
283 compileErrors++;
284 //Debugger();
288 PyrCurryArgNode* newPyrCurryArgNode()
290 PyrCurryArgNode* node = ALLOCNODE(PyrCurryArgNode);
291 return node;
294 void PyrCurryArgNode::compile(PyrSlot *result)
296 if (gPartiallyAppliedFunction) {
297 compileOpcode(opPushTempZeroVar, mArgNum);
298 } else {
299 error("found _ argument outside of a call.\n");
300 nodePostErrorLine((PyrParseNode*)this);
301 compileErrors++;
305 PyrSlotNode* newPyrSlotNode(PyrSlot *slot)
307 PyrSlotNode* node = ALLOCNODE(PyrSlotNode);
308 node->mSlot = *slot;
309 return node;
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));
320 else {
321 error("compilePyrSlotNode: shouldn't get here.\n");
322 dumpObjectSlot(&mSlot);
323 nodePostErrorLine((PyrParseNode*)this);
324 compileErrors++;
325 //Debugger();
330 PyrClassExtNode* newPyrClassExtNode(PyrSlotNode* className, PyrMethodNode* methods)
332 PyrClassExtNode* node = ALLOCNODE(PyrClassExtNode);
333 node->mClassName = className;
335 node->mMethods = methods;
336 return node;
339 void PyrClassExtNode::compile(PyrSlot *result)
341 PyrClass *classobj = slotRawSymbol(&mClassName->mSlot)->u.classobj;
342 if (!classobj) {
343 char extPath[1024];
344 asRelativePath(gCompilingFileSym->name, extPath);
345 error("Class extension for nonexistent class '%s'\n In file:'%s'\n",
346 slotRawSymbol(&mClassName->mSlot)->name,
347 extPath
349 return;
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) {
361 PyrSlot dummy;
362 //post("compile ext %s:%s\n",
363 method->mExtension = true;
364 compilePyrMethodNode(method, &dummy);
366 gCompilingMethod = NULL;
367 gCompilingBlock = NULL;
368 gPartiallyAppliedFunction = NULL;
369 gInliningLevel = 0;
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;
387 return node;
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;
398 bool isIntrinsic;
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]) {
407 xclass = 0;
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);
422 goto differExit;
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);
432 goto differExit;
437 } else {
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);
441 goto differExit;
443 return false;
445 differExit:
446 if (isIntrinsic) {
447 error("You may not change variable definitions of intrinsic classes.\n");
448 nodePostErrorLine(errnode);
449 compileErrors++;
451 return true;
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)
495 // count methods
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) {
511 PyrSlot dummy;
512 method->mExtension = false;
513 compilePyrMethodNode(method, &dummy);
515 gCompilingMethod = NULL;
516 gCompilingBlock = NULL;
517 gPartiallyAppliedFunction = NULL;
518 gInliningLevel = 0;
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;
536 compileErrors++;
538 } else {
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;
553 PyrMethod *method;
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;
594 classVarIndex = 0;
595 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
596 int type = varlist->mFlags;
597 switch (type) {
598 case varInst :
599 vardef = varlist->mVarDefs;
600 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
601 PyrSlot litslot;
602 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
603 *islot++ = 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] = '_';
635 //underscore[1] = 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);
659 instVarIndex++;
661 break;
662 case varClass :
663 vardef = varlist->mVarDefs;
664 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
665 PyrSlot litslot;
666 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
667 *cslot++ = 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] = '_';
701 //underscore[1] = 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);
724 classVarIndex++;
726 break;
727 case varConst :
728 vardef = varlist->mVarDefs;
729 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
730 PyrSlot litslot;
731 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
732 *kslot++ = 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);
760 break;
765 int getIndexType(PyrClassNode *classnode)
767 PyrSlotNode *node;
768 int res;
770 node = classnode->mIndexType;
771 if (node == NULL) res = obj_notindexed;
772 else {
773 char *name;
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;
783 else {
784 error("Illegal indexed type. Must be one of:\n"
785 " slot, double, float, int8, int16, int32, char\n");
786 res = obj_slot;
787 compileErrors++;
791 return res;
794 void PyrClassNode::compile(PyrSlot *result)
796 PyrClass *classobj, *superclassobj, *metaclassobj;
797 int numClassMethods, numInstMethods;
798 bool isIntrinsic;
799 bool varsDiffer, superclassesDiffer, indexTypesDiffer;
800 bool shouldRecompileSubclasses = false;
801 int indexType;
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);
817 numClassMethods = 0;
818 numInstMethods = 0;
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;
827 if (classobj) {
828 // deal with intrinsic classes or other classes being recompiled here.
829 // recompile of subclasses not necessary if inst and class vars are
830 // unchanged.
831 metaclassobj = (PyrClass*)classobj->classptr;
832 isIntrinsic = slotRawInt(&classobj->classFlags) & classIsIntrinsic;
834 varsDiffer = compareVarDefs(this, classobj);
835 if (varsDiffer) {
836 if (isIntrinsic) {
837 //error("Class '%s' declaration doesn't match intrinsic definition.\n",
838 // slotRawSymbol(&mClassName->mSlot)->name);
839 return;
840 } else {
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) {
849 if (isIntrinsic) {
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));
855 compileErrors++;
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));
861 compileErrors++;
863 error("Class '%s' declaration doesn't match intrinsic definition.\n",
864 slotRawSymbol(&mClassName->mSlot)->name);
865 return;
866 } else {
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,
887 mVarTally[varClass],
888 mVarTally[varConst],
889 numInstMethods, indexType, 0);
891 } else {
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);
902 // test
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;
913 // end test
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);
926 } else {
927 SetNil(&classobj->filenameSym);
928 SetNil(&metaclassobj->filenameSym);
931 // fill inst and class prototypes
932 fillClassPrototypes(this, classobj, superclassobj);
934 // compile methods
935 compileNodeMethods(this);
937 // recompileSubclasses
938 if (shouldRecompileSubclasses) {
939 recompileSubclasses(classobj);
943 void recompileSubclasses(PyrClass* classobj)
947 #if 0
948 void catVarLists(PyrVarListNode *varlist);
949 void catVarLists(PyrVarListNode *varlist)
951 PyrVarListNode *prevvarlist;
952 PyrVarDefNode *vardef, *lastvardef;
954 if (varlist) {
955 // find end of this list
956 vardef = varlist->mVarDefs;
957 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
958 lastvardef = vardef;
960 prevvarlist = varlist;
961 varlist = (PyrVarListNode*)varlist->mNext;
963 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
964 vardef = varlist->mVarDefs;
965 if (lastvardef) {
966 lastvardef->mNext = (PyrParseNode*)vardef;
967 } else {
968 prevvarlist->mVarDefs = vardef;
970 // find end of this list
971 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
972 lastvardef = vardef;
978 #else
980 void catVarLists(PyrVarListNode *varlist);
981 void catVarLists(PyrVarListNode *varlist)
983 PyrVarListNode *prevvarlist;
984 PyrVarDefNode *vardef, *lastvardef;
986 if (varlist) {
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;
1002 #endif
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;
1013 node->mBody = body;
1014 node->mIsClassMethod = isClassMethod;
1015 return node;
1018 enum { push_Normal, push_AllArgs, push_AllButFirstArg, push_AllButFirstArg2 };
1020 int checkPushAllArgs(PyrParseNode *actualArg, int numArgs);
1021 int checkPushAllArgs(PyrParseNode *actualArg, int numArgs)
1023 PyrBlock *block;
1024 PyrPushNameNode *nameNode;
1025 block = gCompilingBlock;
1026 int i;
1028 //if (strcmp("ar", slotRawSymbol(&gCompilingMethod->name)->name)==0) Debugger();
1029 if (actualArg->mClassno != pn_PushNameNode) {
1030 if (numArgs < 3) {
1031 return push_Normal;
1033 actualArg = actualArg->mNext;
1034 for (i=1; i<numArgs; ++i) {
1035 if (actualArg->mClassno != pn_PushNameNode) {
1036 return push_Normal;
1038 nameNode = (PyrPushNameNode*)actualArg;
1039 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbolArray(&block->argNames)->symbols[i]) {
1040 return push_Normal;
1043 actualArg = actualArg->mNext;
1045 return push_AllButFirstArg;
1047 } else {
1048 for (i=0; i<numArgs; ++i) {
1049 if (actualArg->mClassno != pn_PushNameNode) {
1050 return push_Normal;
1052 nameNode = (PyrPushNameNode*)actualArg;
1053 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbolArray(&block->argNames)->symbols[i]) {
1054 return push_Normal;
1056 actualArg = actualArg->mNext;
1058 return push_AllArgs;
1063 int checkPushAllButFirstTwoArgs(PyrParseNode *actualArg, int numArgs);
1064 int checkPushAllButFirstTwoArgs(PyrParseNode *actualArg, int numArgs)
1066 PyrBlock *block;
1067 PyrPushNameNode *nameNode;
1068 block = gCompilingBlock;
1069 int i;
1071 if (numArgs >= 2) {
1072 actualArg = actualArg->mNext;
1073 actualArg = actualArg->mNext;
1074 for (i=1; i<numArgs; ++i) {
1075 if (actualArg->mClassno != pn_PushNameNode) {
1076 return push_Normal;
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]) {
1085 return push_Normal;
1088 actualArg = actualArg->mNext;
1090 return push_AllButFirstArg2;
1092 return push_Normal;
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) {
1105 return methNormal;
1108 // check first actual arg is 'this'
1109 actualArg = cnode->mArglist;
1110 if (actualArg->mClassno != pn_PushNameNode) {
1111 return methNormal;
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;
1118 } else {
1119 bool varFound;
1120 PyrClass *classobj;
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) {
1140 numFormalArgs = 1;
1141 if (numActualArgs != numFormalArgs) {
1142 return methNormal;
1144 } else {
1145 numFormalArgs = 1 + nodeListLength((PyrParseNode*)node->mArglist->mVarDefs);
1146 if (numActualArgs != numFormalArgs) {
1147 return methNormal;
1150 formalArg = node->mArglist->mVarDefs;
1151 for (i=0; i<numActualArgs-1; ++i) {
1152 if (actualArg->mClassno != pn_PushNameNode) {
1153 return methNormal;
1156 nameNode = (PyrPushNameNode*)actualArg;
1157 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbol(&formalArg->mVarName->mSlot)) {
1158 return methNormal;
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);
1183 // }
1184 return special;
1187 void installByteCodes(PyrBlock *block)
1189 PyrInt8Array *byteArray;
1190 long length, flags;
1191 ByteCodes byteCodes;
1192 byteCodes = getByteCodes();
1193 if (byteCodes) {
1194 length = byteCodeLength(byteCodes);
1195 if (length) {
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);
1202 } else {
1203 error("installByteCodes: zero length byte codes\n");
1205 } else {
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;
1226 PyrObject *proto;
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);
1239 compileErrors++;
1240 return;
1243 if (oldmethod) {
1244 ++numOverwrites;
1246 // accumulate overwrite message onto the string buffer
1247 overwriteMsg
1248 .append(slotRawSymbol(&slotRawClass(&oldmethod->ownerclass)->name)->name)
1249 .append(":")
1250 .append(slotRawSymbol(&oldmethod->name)->name)
1251 .append("\t")
1252 .append(gCompilingFileSym->name)
1253 .append("\t")
1254 .append(slotRawSymbol(&oldmethod->filenameSym)->name)
1255 .append("\n");
1257 method = oldmethod;
1258 freePyrSlot(&method->code);
1259 freePyrSlot(&method->selectors);
1260 freePyrSlot(&method->prototypeFrame);
1261 freePyrSlot(&method->argNames);
1262 freePyrSlot(&method->varNames);
1263 initPyrMethod(method);
1264 } else {
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;
1286 gInliningLevel = 0;
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);
1309 } else {
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);
1318 // declare args
1319 slotRawSymbolArray(&method->argNames)->symbols[0] = s_this;
1320 if (mArglist) {
1321 PyrSymbol **methargs;
1322 methargs = slotRawSymbolArray(&method->argNames)->symbols;
1323 vardef = mArglist->mVarDefs;
1324 for (i=1; i<numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1325 PyrSlot *varslot;
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);
1334 compileErrors++;
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);
1350 if (funcVarArgs) {
1351 PyrSlot *varslot;
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);
1360 compileErrors++;
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]);
1372 if (mArglist) {
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;
1379 *slot = litval;
1381 if (funcVarArgs) {
1382 slotCopy(&slotRawObject(&method->prototypeFrame)->slots[numArgs], &o_emptyarray);
1387 if (numVars) {
1388 varNames = newPyrSymbolArray(NULL, numVars, obj_permanent | obj_immutable, false);
1389 varNames->size = numVars;
1390 SetObject(&method->varNames, varNames);
1391 } else {
1392 SetNil(&method->varNames);
1395 // declare vars
1396 if (mVarlist) {
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) {
1402 PyrSlot *varslot;
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);
1411 compileErrors++;
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);
1421 compileErrors++;
1424 // put it in mVarlist
1425 methvars[i] = slotRawSymbol(varslot);
1426 //postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
1430 if (mVarlist) {
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);
1437 *slot = litval;
1441 methType = methNormal;
1442 if (hasVarExprs) {
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;
1456 } else {
1457 int bodyType = mBody->mClassno;
1458 if (bodyType == pn_ReturnNode) {
1459 PyrReturnNode *rnode;
1460 PyrParseNode *xnode;
1461 int rtype;
1462 PyrSlot rslot;
1464 rnode = (PyrReturnNode*)mBody;
1465 xnode = (PyrParseNode*)rnode->mExpr;
1466 if (xnode) {
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;
1472 } else {
1473 methType = methReturnLiteral;
1474 method->selectors = rslot;
1476 } else if (rtype == pn_PushNameNode) {
1477 PyrSlot *rslot;
1478 rslot = &((PyrPushNameNode*)xnode)->mSlot;
1479 if (slotRawSymbol(rslot) == s_this) { // return this
1480 methType = methReturnSelf;
1481 } else {
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)) {
1490 // return inst var
1491 methType = methReturnInstVar;
1492 methraw->specialIndex = index;
1495 } else if (rtype == pn_CallNode) {
1496 // need to do this for binary opcodes too..
1497 int specialIndex;
1498 PyrCallNode *cnode;
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;
1508 } else {
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;
1531 // set primitive
1532 // optimize common cases
1534 if (methType == methNormal || methType == methPrimitive) {
1535 PyrSlot dummy;
1536 PyrSymbol *name;
1538 // compile body
1539 initByteCodes();
1541 if (gCompilingClass == class_int) {
1542 // handle some special cases
1543 name = slotRawSymbol(&method->name);
1544 if (name == gSpecialSelectors[opmDo]) {
1545 compileByte(143);
1546 compileByte(0);
1547 compileByte(143);
1548 compileByte(1);
1549 } else if (name == gSpecialSelectors[opmReverseDo]) {
1550 compileByte(143);
1551 compileByte(2);
1552 compileByte(143);
1553 compileByte(3);
1554 compileByte(143);
1555 compileByte(4);
1556 } else if (name == gSpecialSelectors[opmFor]) {
1557 compileByte(143);
1558 compileByte(5);
1559 compileByte(143);
1560 compileByte(6);
1561 compileByte(143);
1562 compileByte(16);
1563 } else if (name == gSpecialSelectors[opmForBy]) {
1564 compileByte(143);
1565 compileByte(7);
1566 compileByte(143);
1567 compileByte(8);
1568 compileByte(143);
1569 compileByte(9);
1570 } else goto compile_body;
1571 } else if (gCompilingClass == class_arrayed_collection) {
1572 name = slotRawSymbol(&method->name);
1573 if (name == gSpecialSelectors[opmDo]) {
1574 compileByte(143);
1575 compileByte(10);
1576 compileByte(143);
1577 compileByte(1);
1578 } else if (name == gSpecialSelectors[opmReverseDo]) {
1579 compileByte(143);
1580 compileByte(11);
1581 compileByte(143);
1582 compileByte(12);
1583 compileByte(143);
1584 compileByte(4);
1585 } else goto compile_body;
1586 } else if (slotRawSymbol(&gCompilingClass->name) == s_dictionary) {
1587 name = slotRawSymbol(&method->name);
1588 if (name == getsym("keysValuesArrayDo")) {
1589 compileByte(143);
1590 compileByte(13);
1591 compileByte(143);
1592 compileByte(14);
1593 } else goto compile_body;
1594 } else if (gCompilingClass == class_number) {
1595 name = slotRawSymbol(&method->name);
1596 if (name == gSpecialSelectors[opmForSeries]) {
1597 compileByte(143);
1598 compileByte(29);
1599 compileByte(143);
1600 compileByte(30);
1601 compileByte(143);
1602 compileByte(31);
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]) {
1608 compileByte(143);
1609 compileByte(17);
1610 compileByte(143);
1611 compileByte(18);
1612 } else if (name == gSpecialSelectors[opmReverseDo]) {
1613 compileByte(143);
1614 compileByte(19);
1615 compileByte(143);
1616 compileByte(20);
1617 compileByte(143);
1618 compileByte(21);
1619 } else goto compile_body;
1620 } else {
1621 compile_body:
1622 SetTailIsMethodReturn mr(false);
1623 if (mArglist) {
1624 vardef = mArglist->mVarDefs;
1625 for (i=1; i<numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1626 vardef->compileArg(&dummy);
1629 if (mVarlist) {
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);
1640 if (!oldmethod) {
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;
1655 node->mRest = rest;
1656 return node;
1659 void PyrArgListNode::compile(PyrSlot *result)
1661 error("compilePyrArgListNode: shouldn't get here.\n");
1662 compileErrors++;
1666 PyrVarListNode* newPyrVarListNode(PyrVarDefNode* vardefs, int flags)
1668 PyrVarListNode* node = ALLOCNODE(PyrVarListNode);
1669 node->mVarDefs = vardefs;
1670 node->mFlags = flags;
1671 return node;
1674 void PyrVarListNode::compile(PyrSlot *result)
1676 error("compilePyrVarListNode: shouldn't get here.\n");
1677 compileErrors++;
1680 PyrVarDefNode* newPyrVarDefNode(PyrSlotNode* varName, PyrParseNode* defVal,
1681 int flags)
1683 PyrVarDefNode* node = ALLOCNODE(PyrVarDefNode);
1684 node->mVarName = varName;
1685 node->mDefVal = defVal;
1686 node->mFlags = flags;
1687 node->mDrop = true;
1688 return node;
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);
1697 return true;
1699 PyrPushLitNode *node = (PyrPushLitNode*)mDefVal;
1701 if (IsPtr(&node->mSlot)) {
1702 PyrParseNode* litnode = (PyrParseNode*)slotRawPtr(&node->mSlot);
1703 if (litnode) {
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);
1706 return true;
1707 } else {
1708 if (result) node->compileLiteral(result);
1711 } else if (result) *result = node->mSlot;
1712 if (node->mParens) return true;
1713 return false;
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");
1724 //compileErrors++;
1727 void PyrVarDefNode::compileArg(PyrSlot *result)
1729 if (hasExpr(NULL)) {
1730 ByteCodes trueByteCodes;
1732 compilePushVar((PyrParseNode*)this, slotRawSymbol(&mVarName->mSlot));
1734 mDrop = false;
1735 trueByteCodes = compileBodyWithGoto(this, 0, true);
1736 int jumplen = byteCodeLength(trueByteCodes);
1738 compileByte(143); // special opcodes
1739 compileByte(26);
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");
1747 //compileErrors++;
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;
1761 return node;
1764 int PyrCallNode::isPartialApplication()
1766 int sum = 0;
1767 PyrParseNode* argnode = mArglist;
1768 for (; argnode; argnode = argnode->mNext) {
1769 if (argnode->mClassno == pn_CurryArgNode) {
1770 ((PyrCurryArgNode*)argnode)->mArgNum = sum;
1771 sum ++;
1775 PyrParseNode* keynode = mKeyarglist;
1776 for (; keynode; keynode = keynode->mNext) {
1777 if (keynode->mClassno == pn_CurryArgNode) {
1778 ((PyrCurryArgNode*)keynode)->mArgNum = sum;
1779 sum ++;
1782 return sum;
1785 void PyrCallNodeBase::compilePartialApplication(int numCurryArgs, PyrSlot *result)
1787 // create a function
1788 // compile the call
1790 ByteCodes savedBytes = saveByteCodeArray();
1792 int flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
1793 PyrBlock* block = newPyrBlock(flags);
1795 PyrSlot blockSlot;
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);
1817 ////
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);
1848 initByteCodes();
1850 SetTailBranch branch(true);
1851 SetTailIsMethodReturn mr(false);
1852 PyrSlot body;
1853 compileCall(&body);
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);
1864 compileByte(index);
1866 if (!gFunctionCantBeClosed && gFunctionHighestExternalRef == 0) {
1867 SetNil(&block->contextDef);
1868 } else {
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();
1883 if (numCurryArgs) {
1884 compilePartialApplication(numCurryArgs, result);
1885 } else {
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;
1897 return true;
1900 void PyrCallNode::compileCall(PyrSlot *result)
1902 int index, selType;
1903 PyrSlot dummy;
1904 bool varFound;
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);
1926 if (isSuper) {
1927 compileTail();
1928 compileByte(opSendSuper);
1929 compileByte(numArgs + 2*numKeyArgs);
1930 compileByte(numKeyArgs);
1931 compileByte(index);
1932 } else {
1933 switch (selType) {
1934 case selNormal :
1935 compileTail();
1936 compileByte(opSendMsg);
1937 compileByte(numArgs + 2*numKeyArgs);
1938 compileByte(numKeyArgs);
1939 compileByte(index);
1940 break;
1941 case selSpecial :
1942 compileTail();
1943 compileByte(opSendSpecialMsg);
1944 compileByte(numArgs + 2*numKeyArgs);
1945 compileByte(numKeyArgs);
1946 compileByte(index);
1947 break;
1948 case selUnary :
1949 case selBinary :
1950 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector,
1951 gCompilingBlock, &mSelector->mSlot);
1952 // fall through
1953 default:
1954 compileTail();
1955 compileByte(opSendMsg);
1956 compileByte(numArgs + 2*numKeyArgs);
1957 compileByte(numKeyArgs);
1958 compileByte(index);
1959 break;
1962 } else if (isSuper) {
1963 if (numArgs == 1) {
1964 // pushes this as well, don't compile arg
1965 gFunctionCantBeClosed = true;
1966 compileTail();
1967 compileOpcode(opSendSuper, numArgs);
1968 compileByte(index);
1969 } else {
1970 for (; argnode; argnode = argnode->mNext) {
1971 COMPILENODE(argnode, &dummy, false);
1973 compileTail();
1974 compileOpcode(opSendSuper, numArgs);
1975 compileByte(index);
1977 } else {
1978 PyrSymbol *varname;
1979 if (argnode->mClassno == pn_PushNameNode) {
1980 varname = slotRawSymbol(&((PyrPushNameNode*)argnode)->mSlot);
1981 } else {
1982 varname = NULL;
1984 if (varname == s_this) {
1985 gFunctionCantBeClosed = true;
1987 switch (selType) {
1988 case selNormal :
1989 if (numArgs == 1 && varname == s_this) {
1990 compileTail();
1991 compileOpcode(opSendMsg, 0);
1992 compileByte(index);
1993 //} else if (numArgs>1 && numArgs == numBlockArgs) {
1994 } else if (numArgs>1 && numArgs == numBlockArgs) {
1995 // try for multiple push optimization
1996 int code;
1997 code = checkPushAllArgs(argnode, numArgs);
1998 if (code == push_Normal) goto normal;
1999 else if (code == push_AllArgs) {
2000 compileTail();
2001 compileByte(137); // push all args, send msg
2002 compileByte(index);
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);
2007 compileTail();
2008 compileByte(138); // push all but first arg, send msg
2009 compileByte(index);
2010 //post("138 pushAllButFirstArg %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2011 // slotRawSymbol(&gCompilingMethod->name)->name);
2012 } else goto normal;
2013 } else if (numArgs>2 && numArgs == numBlockArgs+1) {
2014 int code;
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);
2020 compileTail();
2021 compileByte(141); // one arg pushed, push all but first arg, send msg
2022 compileByte(index);
2023 //post("141 pushAllButFirstArg2 %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2024 // slotRawSymbol(&gCompilingMethod->name)->name);
2025 } else goto normal;
2027 } else {
2028 normal:
2029 for (; argnode; argnode = argnode->mNext) {
2030 COMPILENODE(argnode, &dummy, false);
2032 compileTail();
2033 compileOpcode(opSendMsg, numArgs);
2034 compileByte(index);
2036 break;
2037 case selSpecial :
2038 if (numArgs == 1) {
2039 if (varname == s_this) {
2040 compileTail();
2041 compileOpcode(opSendSpecialMsg, 0);
2042 compileByte(index);
2043 } else if (varname) {
2044 PyrClass *classobj;
2045 PyrBlock *tempFunc;
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);
2053 compileTail();
2054 compileByte(136);
2055 compileByte(varIndex);
2056 compileByte(index);
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);
2063 goto special;
2064 } else if (numArgs>1 && numArgs == numBlockArgs) {
2065 //} else if (numArgs>1 && numArgs == numBlockArgs) {
2066 // try for multiple push optimization
2067 int code;
2068 code = checkPushAllArgs(argnode, numArgs);
2069 if (code == push_Normal) goto special;
2070 else if (code == push_AllArgs) {
2071 compileTail();
2072 compileByte(139); // push all args, send special msg
2073 compileByte(index);
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);
2078 compileTail();
2079 compileByte(140); // push all but first arg, send special msg
2080 compileByte(index);
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) {
2085 int code;
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);
2091 compileTail();
2092 compileByte(142); // one arg pushed, push all but first arg, send msg
2093 compileByte(index);
2094 //post("142 pushAllButFirstArg2(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2095 // slotRawSymbol(&gCompilingMethod->name)->name);
2096 } else goto special;
2097 } else {
2098 int i;
2099 special:
2100 for (i=0; argnode; argnode = argnode->mNext,i++) {
2101 COMPILENODE(argnode, &dummy, false);
2103 compileTail();
2104 compileOpcode(opSendSpecialMsg, numArgs);
2105 compileByte(index);
2107 break;
2108 case selUnary :
2109 if (numArgs != 1) {
2110 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector, gCompilingBlock,
2111 &mSelector->mSlot);
2112 goto defaultCase;
2114 for (; argnode; argnode = argnode->mNext) {
2115 COMPILENODE(argnode, &dummy, false);
2117 compileTail();
2118 compileOpcode(opSendSpecialUnaryArithMsg, index);
2119 break;
2120 case selBinary :
2121 if (numArgs != 2) {
2122 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector, gCompilingBlock,
2123 &mSelector->mSlot);
2124 goto defaultCase;
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);
2140 } else {
2141 COMPILENODE(argnode, &dummy, false);
2142 COMPILENODE(argnode->mNext, &dummy, false);
2143 compileTail();
2144 compileOpcode(opSendSpecialBinaryArithMsg, index);
2146 break;
2147 case selIf :
2148 compileAnyIfMsg(this);
2149 break;
2150 case selCase :
2151 compileCaseMsg(this);
2152 break;
2153 case selSwitch :
2154 compileSwitchMsg(this);
2155 break;
2156 case selWhile :
2157 compileWhileMsg(this);
2158 break;
2159 case selLoop :
2160 compileLoopMsg(this);
2161 break;
2162 case selAnd :
2163 if (numArgs == 2) compileAndMsg(argnode, argnode->mNext);
2164 else goto special;
2165 break;
2166 case selOr :
2167 if (numArgs == 2) compileOrMsg(argnode, argnode->mNext);
2168 else goto special;
2169 break;
2170 case selQuestionMark :
2171 if (numArgs == 2) compileQMsg(argnode, argnode->mNext);
2172 break;
2173 case selDoubleQuestionMark :
2174 if (numArgs == 2) compileQQMsg(argnode, argnode->mNext);
2175 break;
2176 case selExclamationQuestionMark :
2177 if (numArgs == 2) compileXQMsg(argnode, argnode->mNext);
2178 break;
2179 default :
2180 defaultCase:
2181 if (numArgs == 1 && varname == s_this) {
2182 compileTail();
2183 compileOpcode(opSendMsg, 0);
2184 compileByte(index);
2185 } else {
2186 for (; argnode; argnode = argnode->mNext) {
2187 COMPILENODE(argnode, &dummy, false);
2189 compileTail();
2190 compileOpcode(opSendMsg, numArgs);
2191 compileByte(index);
2193 break;
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;
2212 PyrSlot dummy;
2214 PyrBlock* prevPartiallyAppliedFunction = gPartiallyAppliedFunction;
2215 gPartiallyAppliedFunction = NULL;
2217 currentByteCodes = saveByteCodeArray();
2219 COMPILENODE(body, &dummy, onTailBranch);
2220 if (branchLen) {
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;
2235 #if 0
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);
2250 #endif
2252 bool isAnInlineableBlock(PyrParseNode *node)
2254 bool res = false;
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);
2267 else
2268 nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2270 } else
2271 res = true;
2274 return res;
2277 bool isAnInlineableAtomicLiteralBlock(PyrParseNode *node)
2279 bool res = false;
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);
2292 else
2293 nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2295 } else {
2296 if (bnode->mBody->mClassno == pn_DropNode && ((PyrDropNode*)bnode->mBody)->mExpr2->mClassno == pn_BlockReturnNode)
2297 res = isAtomicLiteral(((PyrDropNode*)bnode->mBody)->mExpr1);
2298 else
2299 res = false;
2303 return res;
2306 bool isAtomicLiteral(PyrParseNode *node)
2308 bool res = false;
2309 if (node->mClassno == pn_PushLitNode) {
2310 PyrPushLitNode *anode;
2311 anode = (PyrPushLitNode*)node;
2312 if (NotObj(&anode->mSlot) && !IsPtr(&anode->mSlot)) res = true;
2314 return res;
2317 bool isWhileTrue(PyrParseNode *node)
2319 bool res = false;
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);
2333 } else {
2334 if (bnode->mBody->mClassno == pn_PushLitNode
2335 && IsTrue(&((PyrPushLitNode*)bnode->mBody)->mSlot)) {
2336 res = true;
2339 } else if (IsTrue(&anode->mSlot)) {
2340 res = true;
2343 return res;
2346 void compileAndMsg(PyrParseNode* arg1, PyrParseNode* arg2)
2348 PyrSlot dummy;
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);
2357 } else {
2358 COMPILENODE(arg2, &dummy, false);
2359 compileTail();
2360 compileOpcode(opSendSpecialMsg, 2);
2361 compileByte(opmAnd);
2365 void compileOrMsg(PyrParseNode* arg1, PyrParseNode* arg2)
2367 PyrSlot dummy;
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);
2376 } else {
2377 COMPILENODE(arg2, &dummy, false);
2378 compileTail();
2379 compileOpcode(opSendSpecialMsg, 2);
2380 compileByte(opmOr);
2384 void compileQMsg(PyrParseNode* arg1, PyrParseNode* arg2)
2386 // question mark.
2387 PyrSlot dummy;
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) }
2398 PyrSlot dummy;
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);
2411 } else {
2412 COMPILENODE(arg2, &dummy, false);
2413 compileTail();
2414 compileOpcode(opSendSpecialMsg, 2);
2415 compileByte(opmDoubleQuestionMark);
2419 void compileXQMsg(PyrParseNode* arg1, PyrParseNode* arg2)
2421 // double question mark. !? {|obj| ^if (this.isNil, this, func) }
2422 PyrSlot dummy;
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);
2435 } else {
2436 COMPILENODE(arg2, &dummy, false);
2437 compileTail();
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);
2454 return;
2455 } else if (slotRawSymbol(&callNode->mSelector->mSlot) == gSpecialUnarySelectors[opNotNil]) {
2456 compileIfNilMsg(node, false);
2457 return;
2461 compileIfMsg(node);
2464 void compileIfMsg(PyrCallNodeBase2* node)
2466 PyrSlot dummy;
2467 ByteCodes trueByteCodes, falseByteCodes;
2469 int numArgs = nodeListLength(node->mArglist);
2470 PyrParseNode* arg1 = node->mArglist;
2471 PyrParseNode *arg2, *arg3;
2473 if (numArgs == 2) {
2474 arg2 = arg1->mNext;
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);
2483 } else {
2484 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2485 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2487 } else goto unoptimized;
2488 } else if (numArgs == 3) {
2489 arg2 = arg1->mNext;
2490 arg3 = arg2->mNext;
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);
2502 } else {
2503 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2504 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2506 } else goto unoptimized;
2507 } else {
2508 unoptimized:
2509 for (; arg1; arg1 = arg1->mNext) {
2510 COMPILENODE(arg1, &dummy, false);
2512 compileTail();
2513 compileOpcode(opSendSpecialMsg, numArgs);
2514 compileByte(opmIf);
2518 void compileIfNilMsg(PyrCallNodeBase2* node, bool flag)
2520 PyrSlot dummy;
2521 ByteCodes trueByteCodes, falseByteCodes;
2522 PyrParseNode *arg2, *arg3;
2524 int numArgs = nodeListLength(node->mArglist);
2525 PyrParseNode* arg1 = node->mArglist;
2527 if (numArgs < 2) {
2528 COMPILENODE(arg1, &dummy, false);
2529 compileTail();
2530 compileOpcode(opSendSpecialMsg, numArgs);
2531 compileByte(opmIf);
2532 } else if (numArgs == 2) {
2533 arg2 = arg1->mNext;
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);
2540 if (jumplen) {
2541 compileByte(143); // special opcodes
2542 compileByte(flag ? 26 : 27);
2543 compileByte((jumplen >> 8) & 0xFF);
2544 compileByte(jumplen & 0xFF);
2545 compileAndFreeByteCodes(trueByteCodes);
2546 } else {
2547 compileOpcode(opSpecialOpcode, opcDrop); // drop the value
2548 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2550 } else {
2551 COMPILENODE(arg1, &dummy, false);
2552 COMPILENODE(arg2, &dummy, false);
2553 compileTail();
2554 compileOpcode(opSendSpecialMsg, numArgs);
2555 compileByte(opmIf);
2557 } else if (numArgs == 3) {
2558 arg2 = arg1->mNext;
2559 arg3 = arg2->mNext;
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);
2568 if (falseLen) {
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);
2581 } else {
2582 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2583 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2585 } else {
2586 COMPILENODE(arg1, &dummy, false);
2587 COMPILENODE(arg2, &dummy, false);
2588 COMPILENODE(arg3, &dummy, false);
2589 compileTail();
2590 compileOpcode(opSendSpecialMsg, numArgs);
2591 compileByte(opmIf);
2593 } else {
2594 for (; arg1; arg1 = arg1->mNext) {
2595 COMPILENODE(arg1, &dummy, false);
2597 compileTail();
2598 compileOpcode(opSendSpecialMsg, numArgs);
2599 compileByte(opmIf);
2603 PyrParseNode* reverseNodeList(PyrParseNode** list)
2605 PyrParseNode* temp1 = *list;
2606 PyrParseNode* temp2 = NULL;
2607 PyrParseNode* temp3 = NULL;
2608 while (temp1) {
2609 *list = temp1;
2610 temp2 = temp1->mNext;
2611 temp1->mNext = temp3;
2612 temp3 = temp1;
2613 temp1 = temp2;
2615 return *list;
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;
2635 } else {
2636 arg1 = dropNode;
2638 } else {
2639 arg1 = bbody;
2641 arg1->mNext = arg2;
2643 PyrParseNode *arg3 = 0;
2644 if (arg2) {
2645 arg3 = arg2->mNext;
2646 if (arg3) {
2647 PyrParseNode *arg4 = arg3->mNext;
2648 if (arg4) {
2649 arg3 = buildCase(arg3);
2650 PyrBlockNode* bnode = newPyrBlockNode(NULL, NULL, arg3, false);
2651 arg3 = newPyrPushLitNode(NULL, bnode);
2652 arg2->mNext = arg3;
2653 arg3->mNext = NULL;
2654 arg1->mTail = arg3;
2657 } else {
2658 arg1->mTail = arg2;
2660 } else {
2661 arg1->mTail = arg1;
2665 post("arg1->mNext %p arg2 %p\n", arg1->mNext, arg2);
2666 if (arg2) {
2667 post("arg2->mNext %p arg3 %p\n", arg2->mNext, arg3);
2668 post("isAnInlineableBlock arg2 %d\n", isAnInlineableBlock(arg2));
2670 if (arg3) {
2671 post("isAnInlineableBlock arg3 %d\n", isAnInlineableBlock(arg3));
2672 post("arg3->mNext %p\n", arg3->mNext);
2674 DUMPNODE(arg1, 0);
2677 PyrSlot selector;
2678 SetSymbol(&selector, gSpecialSelectors[opmIf]);
2679 PyrSlotNode* selectorNode = newPyrSlotNode(&selector);
2680 PyrCallNode *callNode = newPyrCallNode(selectorNode, arg1, NULL, NULL);
2682 //post("<-buildCase %d\n", numArgs);
2684 return callNode;
2687 void compileCaseMsg(PyrCallNodeBase2* node)
2689 PyrParseNode *argnode = node->mArglist;
2690 bool canInline = true;
2691 for (; argnode; argnode = argnode->mNext) {
2692 if (!isAnInlineableBlock(argnode)) {
2693 canInline = false;
2694 break;
2697 PyrSlot dummy;
2698 if (canInline) {
2699 PyrCallNode* callNode = buildCase(node->mArglist);
2700 callNode->compile(&dummy);
2701 } else {
2702 int numArgs = 0;
2703 argnode = node->mArglist;
2704 for (; argnode; argnode = argnode->mNext, ++numArgs) {
2705 COMPILENODE(argnode, &dummy, false);
2707 compileTail();
2708 compileOpcode(opSendSpecialMsg, numArgs);
2709 compileByte(opmCase);
2713 void compileSwitchMsg(PyrCallNode* node)
2715 PyrSlot dummy;
2716 bool canInline = true;
2717 int numArgs;
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)) {
2729 canInline = false;
2730 break;
2732 if (!isAnInlineableBlock(nextargnode)) {
2733 canInline = false;
2734 break;
2736 nextargnode = nextargnode->mNext;
2737 } else {
2738 if (!isAnInlineableBlock(argnode)) {
2739 canInline = false;
2741 break;
2746 if (canInline) {
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);
2755 PyrSlot slot;
2756 SetObject(&slot, array);
2758 COMPILENODE(argnode, &dummy, false);
2759 compilePushConstant(node, &slot);
2761 compileByte(143); // lookup slot in dictionary and jump to offset.
2762 compileByte(28);
2764 argnode = argnode->mNext; // skip first arg.
2766 PyrParseNode* nextargnode = 0;
2767 int absoluteOffset = byteCodeLength(gCompilingByteCodes);
2768 int offset = 0;
2769 int lastOffset = 0;
2770 for (; argnode; argnode = nextargnode) {
2771 nextargnode = argnode->mNext;
2772 if (nextargnode != NULL) {
2773 ByteCodes byteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)nextargnode, 0x6666, true);
2775 PyrSlot *key;
2776 PyrSlot value;
2777 SetInt(&value, offset);
2778 PyrPushLitNode* keyargnode = (PyrPushLitNode*)argnode;
2779 if (isAtomicLiteral(argnode)) {
2780 key = &keyargnode->mSlot;
2781 } else {
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);
2793 if (byteCodes) {
2794 offset += byteCodeLength(byteCodes);
2795 compileAndFreeByteCodes(byteCodes);
2796 } else {
2797 compileOpcode(opPushSpecialValue, opsvNil);
2798 offset += 1;
2801 nextargnode = nextargnode->mNext;
2802 if (nextargnode == NULL) {
2803 compileOpcode(opPushSpecialValue, opsvNil);
2804 lastOffset = offset;
2805 offset += 1;
2807 } else {
2808 ByteCodes byteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)argnode, 0, true);
2810 lastOffset = offset;
2811 if (byteCodes) {
2812 offset += byteCodeLength(byteCodes);
2813 compileAndFreeByteCodes(byteCodes);
2814 } else {
2815 compileOpcode(opPushSpecialValue, opsvNil);
2816 lastOffset = offset;
2817 offset += 1;
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;
2833 if (IsNil(value)) {
2834 SetInt(value, lastOffset);
2835 } else {
2836 int offsetToHere = slotRawInt(value);
2837 if (offsetToHere) {
2838 int jumplen = offset - offsetToHere;
2839 bytes[offsetToHere-2] = (jumplen >> 8) & 255;
2840 bytes[offsetToHere-1] = jumplen & 255;
2845 } else {
2846 PyrParseNode *argnode = node->mArglist;
2847 for (; argnode; argnode = argnode->mNext) {
2848 COMPILENODE(argnode, &dummy, false);
2850 compileTail();
2851 compileOpcode(opSendSpecialMsg, numArgs);
2852 compileByte(opmSwitch);
2856 void compileWhileMsg(PyrCallNodeBase2* node)
2858 int numArgs;
2859 PyrParseNode *argnode;
2860 PyrSlot dummy;
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);
2903 } else {
2904 exprByteCodeLen = 1;
2905 compileJump(opcJumpIfFalsePushNil, exprByteCodeLen + 3);
2906 // opcJumpBak does a drop..
2907 compileOpcode(opPushSpecialValue, opsvNil);
2910 compileJump(opcJumpBak, exprByteCodeLen + whileByteCodeLen + 4);
2912 } else {
2913 argnode = node->mArglist;
2914 for (; argnode; argnode = argnode->mNext) {
2915 COMPILENODE(argnode, &dummy, false);
2917 compileTail();
2918 compileOpcode(opSendSpecialMsg, numArgs);
2919 compileByte(opmWhile);
2923 void compileLoopMsg(PyrCallNodeBase2* node)
2925 int numArgs;
2926 PyrParseNode *argnode;
2927 PyrSlot dummy;
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);
2941 } else {
2942 argnode = node->mArglist;
2943 for (; argnode; argnode = argnode->mNext) {
2944 COMPILENODE(argnode, &dummy, false);
2946 compileTail();
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;
2958 arg1->mNext = arg2;
2959 arg2->mNext = arg3;
2960 return node;
2963 int PyrBinopCallNode::isPartialApplication()
2965 int sum = 0;
2966 PyrParseNode* argnode = mArglist;
2967 for (; argnode; argnode = argnode->mNext) {
2968 if (argnode->mClassno == pn_CurryArgNode) {
2969 ((PyrCurryArgNode*)argnode)->mArgNum = sum;
2970 sum ++;
2973 return sum;
2976 void PyrBinopCallNode::compileCall(PyrSlot *result)
2978 int index, selType, isSuper, numArgs;
2979 PyrSlot dummy;
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;
2991 if (isSuper) {
2992 COMPILENODE(arg1, &dummy, false);
2993 COMPILENODE(arg2, &dummy, false);
2994 if (arg3) COMPILENODE(arg3, &dummy, false);
2995 compileTail();
2996 compileOpcode(opSendSuper, numArgs);
2997 compileByte(index);
2998 } else {
2999 switch (selType) {
3000 case selNormal :
3001 COMPILENODE(arg1, &dummy, false);
3002 COMPILENODE(arg2, &dummy, false);
3003 if (arg3) COMPILENODE(arg3, &dummy, false);
3004 compileTail();
3005 compileOpcode(opSendMsg, numArgs);
3006 compileByte(index);
3007 break;
3008 case selSpecial :
3009 COMPILENODE(arg1, &dummy, false);
3010 COMPILENODE(arg2, &dummy, false);
3011 if (arg3) COMPILENODE(arg3, &dummy, false);
3012 compileTail();
3013 compileOpcode(opSendSpecialMsg, numArgs);
3014 compileByte(index);
3015 break;
3016 case selUnary :
3017 COMPILENODE(arg1, &dummy, false);
3018 COMPILENODE(arg2, &dummy, false);
3019 if (arg3)
3020 COMPILENODE(arg3, &dummy, false);
3021 compileTail();
3022 if (arg3)
3023 compileOpcode(opSpecialOpcode, opcDrop); // drop third argument
3024 compileOpcode(opSpecialOpcode, opcDrop); // drop second argument
3025 compileOpcode(opSendSpecialUnaryArithMsg, index);
3026 break;
3027 case selBinary :
3028 if (arg3) {
3029 COMPILENODE(arg1, &dummy, false);
3030 COMPILENODE(arg2, &dummy, false);
3031 COMPILENODE(arg3, &dummy, false);
3032 compileTail();
3033 compileOpcode(opSpecialOpcode, opcSpecialBinaryOpWithAdverb);
3034 compileByte(index);
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);
3044 compileTail();
3045 compileOpcode(opPushSpecialValue, opsvMinusOne);
3046 } else {
3047 COMPILENODE(arg1, &dummy, false);
3048 COMPILENODE(arg2, &dummy, false);
3049 compileTail();
3050 compileOpcode(opSendSpecialBinaryArithMsg, index);
3052 break;
3053 case selIf :
3054 compileAnyIfMsg(this);
3055 break;
3056 case selCase :
3057 compileCaseMsg(this);
3058 break;
3059 case selWhile :
3060 compileWhileMsg(this);
3061 break;
3062 case selLoop :
3063 compileLoopMsg(this);
3064 break;
3065 case selAnd :
3066 compileAndMsg(arg1, arg2);
3067 break;
3068 case selOr :
3069 compileOrMsg(arg1, arg2);
3070 break;
3071 case selQuestionMark :
3072 compileQMsg(arg1, arg2);
3073 break;
3074 case selDoubleQuestionMark :
3075 compileQQMsg(arg1, arg2);
3076 break;
3077 case selExclamationQuestionMark :
3078 compileXQMsg(arg1, arg2);
3079 break;
3080 default :
3081 COMPILENODE(arg1, &dummy, false);
3082 COMPILENODE(arg2, &dummy, false);
3083 if (arg3) COMPILENODE(arg3, &dummy, false);
3084 compileTail();
3085 compileOpcode(opSendMsg, numArgs);
3086 compileByte(index);
3087 break;
3092 PyrPushKeyArgNode* newPyrPushKeyArgNode(PyrSlotNode* selector, PyrParseNode* expr)
3094 PyrPushKeyArgNode* node = ALLOCNODE(PyrPushKeyArgNode);
3095 node->mSelector = selector;
3096 node->mExpr = expr;
3097 return node;
3100 void PyrPushKeyArgNode::compile(PyrSlot *result)
3102 PyrSlot dummy;
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;
3115 return node;
3118 void PyrDropNode::compile(PyrSlot *result)
3120 //postfl("->compilePyrDropNode\n");
3121 PyrSlot dummy;
3122 // eliminate as many drops as possible
3123 if (!mExpr2) {
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) {
3135 PyrDropNode *znode;
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);
3146 } else {
3147 COMPILENODE(mExpr1, &dummy, false);
3148 compileOpcode(opSpecialOpcode, opcDrop);
3149 COMPILENODE(mExpr2, &dummy, true);
3151 } else {
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;
3162 if (literalSlot) {
3163 node = literalSlot;
3164 node->mClassno = pn_PushLitNode;
3165 } else {
3166 node = ALLOCSLOTNODE(PyrSlotNode, pn_PushLitNode);
3167 SetPtr(&node->mSlot, (PyrObject*)literalObj);
3169 return node;
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)) {
3179 compileByte(40);
3180 compileByte(index & 0xFF);
3181 } else if (index < (1<<16)) {
3182 compileByte(41);
3183 compileByte((index >> 8) & 0xFF);
3184 compileByte(index & 0xFF);
3185 } else if (index < (1<<24)) {
3186 compileByte(42);
3187 compileByte((index >> 16) & 0xFF);
3188 compileByte((index >> 8) & 0xFF);
3189 compileByte(index & 0xFF);
3190 } else {
3191 compileByte(43);
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);
3204 } else{
3205 //printf("int %d\n", value);
3206 if (value >= -(1<<7) && value <= ((1<<7)-1)) {
3207 compileByte(44);
3208 compileByte(value & 0xFF);
3209 } else if (value >= -(1<<15) && value <= ((1<<15)-1)) {
3210 compileByte(45);
3211 compileByte((value >> 8) & 0xFF);
3212 compileByte(value & 0xFF);
3213 } else if (value >= -(1<<23) && value <= ((1<<23)-1)) {
3214 compileByte(46);
3215 compileByte((value >> 16) & 0xFF);
3216 compileByte((value >> 8) & 0xFF);
3217 compileByte(value & 0xFF);
3218 } else {
3219 compileByte(47);
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)
3230 int index;
3231 PyrSlot slot;
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);
3244 compileByte(index);
3246 PyrBlock *block = slotRawBlock(&slot);
3247 if (NotNil(&block->contextDef)) {
3248 METHRAW(gCompilingBlock)->needsHeapContext = 1;
3250 } else {
3251 COMPILENODE(literalObj, &slot, false);
3252 compilePushConstant((PyrParseNode*)literalObj, &slot);
3254 } else {
3255 slot = mSlot;
3256 if (IsInt(&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);
3280 } else {
3281 compilePushConstant((PyrParseNode*)this, &slot);
3286 PyrLiteralNode* newPyrLiteralNode(PyrSlotNode* literalSlot, PyrParseNode* literalObj)
3288 PyrLiteralNode* node;
3289 if (literalSlot) {
3290 node = literalSlot;
3291 node->mClassno = pn_LiteralNode;
3292 } else {
3293 node = ALLOCSLOTNODE(PyrSlotNode, pn_LiteralNode);
3294 SetPtr(&node->mSlot, (PyrObject*)literalObj);
3296 return node;
3299 void compilePyrLiteralNode(PyrLiteralNode *node, PyrSlot *result)
3301 if (!node) {
3302 SetNil(result);
3303 } else {
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;
3323 } else {
3324 COMPILENODE(literalObj, result, false);
3326 } else {
3327 *(PyrSlot*)result = mSlot;
3331 PyrReturnNode* newPyrReturnNode(PyrParseNode* expr)
3333 PyrReturnNode* node = ALLOCNODE(PyrReturnNode);
3334 node->mExpr = expr;
3335 return node;
3340 void PyrReturnNode::compile(PyrSlot *result)
3342 PyrPushLitNode *lit;
3343 PyrSlot dummy;
3345 //post("->compilePyrReturnNode\n");
3346 gFunctionCantBeClosed = true;
3347 if (!mExpr) {
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);
3359 } else {
3360 COMPILENODE(lit, &dummy, false);
3361 compileOpcode(opSpecialOpcode, opcReturn);
3363 } else {
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);
3375 return node;
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;
3389 node->mExpr = expr;
3390 node->mDrop = 0;
3391 return node;
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;
3400 return node;
3403 PyrMultiAssignNode* newPyrMultiAssignNode(PyrMultiAssignVarListNode* varList,
3404 PyrParseNode* expr, int flags)
3406 PyrMultiAssignNode* node = ALLOCNODE(PyrMultiAssignNode);
3407 node->mVarList = varList;
3408 node->mExpr = expr;
3409 node->mDrop = 0;
3410 return node;
3413 PyrMultiAssignVarListNode* newPyrMultiAssignVarListNode(PyrSlotNode* varNames,
3414 PyrSlotNode* rest)
3416 PyrMultiAssignVarListNode* node = ALLOCNODE(PyrMultiAssignVarListNode);
3417 node->mVarNames = varNames;
3418 node->mRest = rest;
3419 return node;
3422 void compileAssignVar(PyrParseNode* node, PyrSymbol* varName, bool drop)
3424 int level, index, vindex, varType;
3425 PyrBlock *tempfunc;
3426 PyrClass *classobj;
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);
3434 compileErrors++;
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);
3439 compileErrors++;
3440 } else if (findVarName(gCompilingBlock, &classobj, varName,
3441 &varType, &level, &index, &tempfunc)) {
3442 switch (varType) {
3443 case varInst :
3444 if (drop) {
3445 if (index <= 15) {
3446 compileByte((opStoreInstVar<<4) | index);
3447 } else {
3448 compileByte(opStoreInstVar);
3449 compileByte(index);
3450 compileByte((opSpecialOpcode<<4) | opcDrop);
3452 } else {
3453 compileByte(opStoreInstVar);
3454 compileByte(index);
3456 break;
3457 case varClass : {
3458 index += slotRawInt(&classobj->classVarIndex);
3459 if (drop) {
3460 if (index < 4096) {
3461 compileByte((opStoreClassVar<<4) | ((index>>8) & 15));
3462 compileByte(index & 255);
3463 } else {
3464 compileByte(opStoreClassVar);
3465 assert(false);
3466 compileByte(vindex); // FIXME: vindex is not initalized!!!!
3467 compileByte(index);
3468 compileByte((opSpecialOpcode<<4) | opcDrop);
3470 } else {
3471 compileByte(opStoreClassVar);
3472 compileByte((index >> 8) & 255);
3473 compileByte(index & 255);
3475 } break;
3476 case varConst : {
3477 error("You may not assign to a constant.");
3478 nodePostErrorLine(node);
3479 compileErrors++;
3480 } break;
3481 case varTemp :
3482 //compileOpcode(opStoreTempVar, level);
3483 //compileByte(index);
3484 if (drop) {
3485 if (index <= 15 && level < 8) {
3486 compileByte((opStoreTempVar<<4) | level);
3487 compileByte(index);
3488 } else {
3489 compileByte(opStoreTempVar);
3490 compileByte(level);
3491 compileByte(index);
3492 compileByte((opSpecialOpcode<<4) | opcDrop);
3494 } else {
3495 compileByte(opStoreTempVar);
3496 compileByte(level);
3497 compileByte(index);
3499 break;
3501 } else {
3502 error("Variable '%s' not defined.\n", varName->name);
3503 nodePostErrorLine(node);
3504 compileErrors++;
3505 //Debugger();
3509 void PyrAssignNode::compile(PyrSlot* result)
3511 PyrSlot dummy;
3513 //postfl("compilePyrAssignNode\n");
3514 COMPILENODE(mExpr, &dummy, false);
3515 compileAssignVar((PyrParseNode*)this, slotRawSymbol(&mVarName->mSlot), mDrop);
3519 int PyrSetterNode::isPartialApplication()
3521 int sum = 0;
3522 if (mExpr1->mClassno == pn_CurryArgNode) {
3523 ((PyrCurryArgNode*)mExpr1)->mArgNum = sum;
3524 sum ++;
3526 if (mExpr2->mClassno == pn_CurryArgNode) {
3527 ((PyrCurryArgNode*)mExpr2)->mArgNum = sum;
3528 sum ++;
3530 return sum;
3533 void PyrSetterNode::compileCall(PyrSlot* result)
3535 int index, selType, isSuper;
3536 PyrSlot dummy;
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);
3544 compileErrors++;
3545 } else {
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);
3559 if (isSuper) {
3560 compileTail();
3561 compileOpcode(opSendSuper, 2);
3562 compileByte(index);
3563 } else {
3564 compileTail();
3565 compileOpcode(opSendMsg, 2);
3566 compileByte(index);
3571 void PyrMultiAssignNode::compile(PyrSlot* result)
3573 PyrSlot dummy;
3575 //postfl("compilePyrMultiAssignNode\n");
3576 COMPILENODE(mExpr, &dummy, false);
3577 COMPILENODE(mVarList, &dummy, false);
3580 void PyrMultiAssignVarListNode::compile(PyrSlot* result)
3582 int i, numAssigns;
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);
3590 compilePushInt(i);
3591 compileOpcode(opSendSpecialMsg, 2);
3592 compileByte(opmAt);
3593 compileAssignVar((PyrParseNode*)varname, slotRawSymbol(&varname->mSlot), 1);
3594 //compileOpcode(opSpecialOpcode, opcDrop);
3596 if (mRest) {
3597 compileOpcode(opSpecialOpcode, opcDup);
3598 compilePushInt(i);
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;
3614 return node;
3617 int PyrDynDictNode::isPartialApplication()
3619 int sum = 0;
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;
3625 sum ++;
3627 inode = (PyrParseNode*)inode->mNext;
3629 return sum;
3632 void PyrDynDictNode::compileCall(PyrSlot* result)
3634 int i, numItems;
3635 PyrParseNode *inode;
3636 PyrSlot dummy;
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);
3651 inode = mElems;
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;
3671 return node;
3674 int PyrDynListNode::isPartialApplication()
3676 int sum = 0;
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;
3682 sum ++;
3684 inode = (PyrParseNode*)inode->mNext;
3686 return sum;
3689 void PyrDynListNode::compileCall(PyrSlot* result)
3691 int i, numItems;
3692 PyrParseNode *inode;
3693 PyrSlot dummy;
3695 //postfl("compilePyrDynListNode\n");
3696 numItems = nodeListLength(mElems);
3698 if (mClassname) {
3699 compilePushVar((PyrParseNode*)this, slotRawSymbol(&((PyrSlotNode*)mClassname)->mSlot));
3700 } else {
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);
3712 inode = mElems;
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;
3726 return node;
3729 void PyrLitListNode::compile(PyrSlot* result)
3731 PyrSlot *resultSlot;
3732 PyrSlot itemSlot;
3733 PyrObject *array;
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);
3746 inode = mElems;
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;
3762 return node;
3765 int litDictPut(PyrObject *dict, PyrSlot *key, PyrSlot *value);
3766 int litDictPut(PyrObject *dict, PyrSlot *key, PyrSlot *value)
3768 #if 0
3769 PyrSlot *slot, *newslot;
3770 int i, index, size;
3771 PyrObject *array;
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);
3777 return errNone;
3779 if (slotRawSymbol(key) == s_proto) {
3780 slotCopy(&dict->slots[ivxIdentDict_proto], value);
3781 return errNone;
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);
3790 if (IsNil(slot)) {
3791 slotCopy(slot, key);
3793 #endif
3794 return errNone;
3798 void PyrLitDictNode::dump(int level)
3802 void PyrLitDictNode::compile(PyrSlot* result)
3804 #if 0
3805 PyrSlot *resultSlot;
3806 PyrSlot itemSlot;
3807 PyrObject *array;
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);
3826 inode = mElems;
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");
3834 #endif
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;
3847 node->mBody = body;
3848 node->mIsTopLevel = isTopLevel;
3850 node->mBeginCharNo = lastClosedFuncCharNo;
3852 return node;
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;
3862 PyrObject *proto;
3863 PyrSymbolArray *argNames, *varNames;
3864 PyrSlot dummy;
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;
3897 if (mIsTopLevel) {
3898 gCompilingClass = class_interpreter;
3899 SetNil(&block->contextDef);
3900 } else {
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);
3910 if (numSlots) {
3911 proto = newPyrArray(compileGC(), numSlots, flags, false);
3912 proto->size = numSlots;
3913 SetObject(&block->prototypeFrame, proto);
3914 } else {
3915 SetNil(&block->prototypeFrame);
3918 numArgNames = numArgs + funcVarArgs;
3920 if (numArgNames) {
3921 argNames = newPyrSymbolArray(compileGC(), numArgNames, flags, false);
3922 argNames->size = numArgNames;
3923 SetObject(&block->argNames, argNames);
3924 } else {
3925 SetNil(&block->argNames);
3928 if (numVars) {
3929 varNames = newPyrSymbolArray(compileGC(), numVars, flags, false);
3930 varNames->size = numVars;
3931 SetObject(&block->varNames, varNames);
3932 } else {
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;
3942 // declare args
3943 if (numArgs) {
3944 PyrSymbol **blockargs;
3945 blockargs = slotRawSymbolArray(&block->argNames)->symbols;
3946 vardef = mArglist->mVarDefs;
3947 for (i=0; i<numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3948 PyrSlot *varslot;
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);
3957 compileErrors++;
3960 // put it in mArglist
3961 blockargs[i] = slotRawSymbol(varslot);
3962 //postfl("defarg %d '%s'\n", i, slotRawSymbol(slot)->name);
3966 if (funcVarArgs) {
3967 PyrSlot *varslot;
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);
3978 compileErrors++;
3981 // put it in mArglist
3982 blockargs[numArgs] = slotRawSymbol(varslot);
3983 //postfl("defrest '%s'\n", slotRawSymbol(slot)->name);
3986 // declare vars
3987 if (numVars) {
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) {
3993 PyrSlot *varslot;
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);
4002 compileErrors++;
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);
4012 compileErrors++;
4015 // put it in varlist
4016 blockvars[i] = slotRawSymbol(varslot);
4017 //postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
4021 if (numArgs) {
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);
4028 *slot = litval;
4032 if (funcVarArgs) {
4033 //SetNil(&slotRawObject(&block->prototypeFrame)->slots[numArgs]);
4034 slotCopy(&slotRawObject(&block->prototypeFrame)->slots[numArgs], &o_emptyarray);
4037 if (numVars) {
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);
4044 *slot = litval;
4047 methraw->methType = methBlock;
4049 // compile body
4050 initByteCodes();
4052 SetTailBranch branch(true);
4053 /*if (compilingCmdLine) {
4054 post("block %d\n", gIsTailCodeBranch);
4055 DUMPNODE(mBody, 0);
4057 SetTailIsMethodReturn mr(false);
4058 if (hasVarExprs) {
4059 if (mArglist) {
4060 vardef = mArglist->mVarDefs;
4061 for (i=0; i<numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
4062 vardef->compileArg(&dummy);
4065 if (mVarlist) {
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);
4074 } else {
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;
4089 //totalStrings++;
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;
4105 if (b) {
4106 a->mTail->mNext = b;
4107 a->mTail = b->mTail;
4109 return a;
4112 PyrParseNode* linkAfterHead(PyrParseNode* a, PyrParseNode* b)
4114 b->mNext = a->mNext;
4115 if (!a->mNext) a->mTail = b;
4116 a->mNext = b;
4117 return a;
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)
4134 int length = 0;
4135 for (; node; node=node->mNext) length++;
4136 return length;
4140 int conjureSelectorIndex(PyrParseNode *node, PyrBlock* func,
4141 bool isSuper, PyrSymbol *selector, int *selType)
4143 int i;
4144 PyrObject *selectors;
4145 PyrSlot *slot;
4146 int newsize, flags;
4148 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
4149 if (!isSuper) {
4150 if (selector == gSpecialSelectors[opmIf]) {
4151 *selType = selIf;
4152 return opmIf;
4153 } else if (selector == gSpecialSelectors[opmWhile]) {
4154 *selType = selWhile;
4155 return opmWhile;
4156 } else if (selector == gSpecialSelectors[opmAnd]) {
4157 *selType = selAnd;
4158 return opmAnd;
4159 } else if (selector == gSpecialSelectors[opmOr]) {
4160 *selType = selOr;
4161 return opmOr;
4162 } else if (selector == gSpecialSelectors[opmCase]) {
4163 *selType = selCase;
4164 return opmCase;
4165 } else if (selector == gSpecialSelectors[opmSwitch]) {
4166 *selType = selSwitch;
4167 return opmSwitch;
4168 } else if (selector == gSpecialSelectors[opmLoop]) {
4169 *selType = selLoop;
4170 return opmLoop;
4171 } else if (selector == gSpecialSelectors[opmQuestionMark]) {
4172 *selType = selQuestionMark;
4173 return opmAnd;
4174 } else if (selector == gSpecialSelectors[opmDoubleQuestionMark]) {
4175 *selType = selDoubleQuestionMark;
4176 return opmAnd;
4177 } else if (selector == gSpecialSelectors[opmExclamationQuestionMark]) {
4178 *selType = selExclamationQuestionMark;
4179 return opmAnd;
4182 for (i=0; i<opmNumSpecialSelectors; ++i) {
4183 if (selector == gSpecialSelectors[i]) {
4184 *selType = selSpecial;
4185 return i;
4189 for (i=0; i<opNumUnarySelectors; ++i) {
4190 if (selector == gSpecialUnarySelectors[i]) {
4191 *selType = selUnary;
4192 return i;
4196 for (i=0; i<opNumBinarySelectors; ++i) {
4197 if (selector == gSpecialBinarySelectors[i]) {
4198 *selType = selBinary;
4199 return i;
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;
4209 return i;
4212 } else {
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);
4222 compileErrors++;
4223 return 0;
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)
4244 int i;
4245 PyrObject *selectors;
4246 PyrSlot *slot2;
4247 int newsize, flags;
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);
4258 Debugger();
4260 for (i=0; i<selectors->size; ++i)
4261 if (SlotEq(&selectors->slots[i], slot))
4262 return i;
4263 } else {
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");
4272 dumpPyrSlot(slot);
4273 nodePostErrorLine(node);
4274 compileErrors++;
4275 return 0;
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)
4296 int i;
4297 PyrObject *constants;
4298 int newsize, flags;
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))
4307 return i;
4308 } else {
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)
4332 int i, j, k;
4333 int numargs;
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;
4341 name = s_this;
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) {
4351 *level = j;
4352 *index = i;
4353 *varType = varTemp;
4354 if (tempfunc) *tempfunc = func;
4355 if (j > gFunctionHighestExternalRef) gFunctionHighestExternalRef = j;
4356 return true;
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) {
4363 *level = j;
4364 *index = k;
4365 *varType = varTemp;
4366 if (tempfunc) *tempfunc = func;
4367 if (j > gFunctionHighestExternalRef) gFunctionHighestExternalRef = j;
4368 return true;
4373 if (classFindInstVar(*classobj, name, index)) {
4374 *level = 0;
4375 *varType = varInst;
4376 if (gCompilingClass != class_interpreter) gFunctionCantBeClosed = true;
4377 return true;
4379 if (classFindClassVar(classobj, name, index)) {
4380 *varType = varClass;
4381 if (gCompilingClass != class_interpreter) gFunctionCantBeClosed = true;
4382 return true;
4384 if (classFindConst(classobj, name, index)) {
4385 *varType = varConst;
4386 //if (gCompilingClass != class_interpreter) gFunctionCantBeClosed = true;
4387 return true;
4389 if (name == s_curProcess) {
4390 *varType = varPseudo;
4391 *index = opgProcess;
4392 return true;
4394 if (name == s_curThread) {
4395 *varType = varPseudo;
4396 *index = opgThread;
4397 return true;
4399 if (name == s_curMethod) {
4400 *varType = varPseudo;
4401 *index = opgMethod;
4402 return true;
4404 if (name == s_curBlock) {
4405 *varType = varPseudo;
4406 *index = opgFunctionDef;
4407 return true;
4409 if (name == s_curClosure) {
4410 *varType = varPseudo;
4411 *index = opgFunction;
4412 return true;
4414 return false;
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()
4479 PyrSymbol **sel;
4480 long i;
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)
4709 int i;
4710 for (i=0; i<op_NumSpecialClasses; ++i) {
4711 if (gSpecialClasses[i] == className) {
4712 *index = i;
4713 return true;
4716 return false;