1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
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.
10
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.
15
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
19 */
20
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"
41 #include "SC_LanguageConfig.hpp"
42 #include "SC_Codecvt.hpp"
43
44 namespace bfs = boost::filesystem;
45
46 AdvancingAllocPool gParseNodePool;
47
48 PyrSymbol* gSpecialUnarySelectors[opNumUnarySelectors];
49 PyrSymbol* gSpecialBinarySelectors[opNumBinarySelectors];
50 PyrSymbol* gSpecialSelectors[opmNumSpecialSelectors];
51 PyrSymbol* gSpecialClasses[op_NumSpecialClasses];
52 PyrSlot gSpecialValues[svNumSpecialValues];
53
54 PyrParseNode* gRootParseNode;
55 intptr_t gParserResult;
56
57 int conjureConstantIndex(PyrParseNode* node, PyrBlock* func, PyrSlot* slot);
58 void compilePushConstant(PyrParseNode* node, PyrSlot* slot);
59
60 PyrClass* gCurrentClass = nullptr;
61 PyrClass* gCurrentMetaClass = nullptr;
62 PyrClass* gCompilingClass = nullptr;
63 PyrMethod* gCompilingMethod = nullptr;
64 PyrBlock* gCompilingBlock = nullptr;
65 PyrBlock* gPartiallyAppliedFunction = nullptr;
66
67 bool gIsTailCodeBranch = false;
68 bool gTailIsMethodReturn = false;
69 int gFunctionHighestExternalRef = 1;
70 bool gFunctionCantBeClosed = true;
71 #if TAILCALLOPTIMIZE
72 bool gGenerateTailCallByteCodes = true;
73 #else
74 bool gGenerateTailCallByteCodes = false;
75 #endif
76
77 long gInliningLevel;
78
79 int compileErrors = 0;
80 int numOverwrites = 0;
81 std::string overwriteMsg;
82
83 extern bool compilingCmdLine;
84 extern int errLineOffset, errCharPosOffset;
85
86 const char* nodename[] = { "ClassNode", "ClassExtNode", "MethodNode", "BlockNode", "SlotNode",
87
88 /* variable declarations */
89 "VarListNode", "VarDefNode", "DynDictNode", "DynListNode", "LitListNode", "LitDictNode",
90
91 "StaticVarListNode", "InstVarListNode", "PoolVarListNode", "ArgListNode", "SlotDefNode",
92
93 /* selectors */
94 "LiteralNode",
95
96 /* code */
97 "PushLitNode", "PushNameNode", "PushKeyArgNode", "CallNode", "BinopCallNode", "DropNode",
98 "AssignNode", "MultiAssignNode", "MultiAssignVarListNode", "SetterNode", "CurryArgNode",
99
100 "ReturnNode", "BlockReturnNode" };
101
compileTail()102 void compileTail() {
103 if (gGenerateTailCallByteCodes && gIsTailCodeBranch) {
104 // if (gCompilingClass && gCompilingMethod) post("tail call %s:%s ismethod %d\n",
105 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name,
106 // gTailIsMethodReturn);
107 if (gTailIsMethodReturn)
108 compileByte(255);
109 else
110 compileByte(176);
111 }
112 }
113
114
115 PyrGC* compileGC();
compileGC()116 PyrGC* compileGC() { return gCompilingVMGlobals ? gCompilingVMGlobals->gc : nullptr; }
117
initParser()118 void initParser() {
119 compileErrors = 0;
120 numOverwrites = 0;
121 overwriteMsg.clear();
122 }
123
finiParser()124 void finiParser() {}
125
initParseNodes()126 void initParseNodes() {}
127
initParserPool()128 void initParserPool() {
129 // postfl("initPool gParseNodePool pyr_pool_compile\n");
130 gParseNodePool.Init(pyr_pool_compile, 32000, 32000, 2000);
131 }
132
freeParserPool()133 void freeParserPool() {
134 // postfl("freePool gParseNodePool pyr_pool_compile\n");
135 gParseNodePool.FreeAll();
136 }
137
PyrParseNode(int inClassNo)138 PyrParseNode::PyrParseNode(int inClassNo) {
139 mClassno = inClassNo;
140 mNext = nullptr;
141 mTail = this;
142 mCharno = ::charno;
143 mLineno = ::lineno;
144 mParens = 0;
145 }
146
compileNodeList(PyrParseNode * node,bool onTailBranch)147 void compileNodeList(PyrParseNode* node, bool onTailBranch) {
148 PyrSlot dummy;
149 // postfl("->compileNodeList\n");
150 for (; node; node = node->mNext) {
151 // postfl("-->compileNodeList %p\n", node);
152 COMPILENODE(node, &dummy, onTailBranch);
153 // postfl("<--compileNodeList %p\n", node);
154 }
155 // postfl("<-compileNodeList\n");
156 }
157
nodePostErrorLine(PyrParseNode * node)158 void nodePostErrorLine(PyrParseNode* node) { postErrorLine(node->mLineno, linestarts[node->mLineno], node->mCharno); }
159
newPyrPushNameNode(PyrSlotNode * slotNode)160 PyrPushNameNode* newPyrPushNameNode(PyrSlotNode* slotNode) {
161 slotNode->mClassno = pn_PushNameNode;
162 return (PyrPushNameNode*)slotNode;
163 }
164
compilePushVar(PyrParseNode * node,PyrSymbol * varName)165 void compilePushVar(PyrParseNode* node, PyrSymbol* varName) {
166 int level, index, vindex, varType;
167 PyrBlock* tempfunc;
168 PyrClass* classobj;
169
170 // postfl("compilePushVar\n");
171 classobj = gCompilingClass;
172 if (varName->name[0] >= 'A' && varName->name[0] <= 'Z') {
173 if (compilingCmdLine && varName->u.classobj == nullptr) {
174 error("Class not defined.\n");
175 nodePostErrorLine(node);
176 compileErrors++;
177 } else {
178 if (findSpecialClassName(varName, &index)) {
179 compileOpcode(opExtended, opPushSpecialValue); // special op for pushing a class
180 compileByte(index);
181 } else {
182 PyrSlot slot;
183 SetSymbol(&slot, varName);
184 index = conjureLiteralSlotIndex(node, gCompilingBlock, &slot);
185 compileOpcode(opExtended, opExtended); // special op for pushing a class
186 compileByte(index);
187 }
188 }
189 } else if (varName == s_this || varName == s_super) {
190 gFunctionCantBeClosed = true;
191 compileOpcode(opPushSpecialValue, opsvSelf);
192 } else if (varName == s_true) {
193 compileOpcode(opPushSpecialValue, opsvTrue);
194 } else if (varName == s_false) {
195 compileOpcode(opPushSpecialValue, opsvFalse);
196 } else if (varName == s_nil) {
197 compileOpcode(opPushSpecialValue, opsvNil);
198 } else if (findVarName(gCompilingBlock, &classobj, varName, &varType, &level, &index, &tempfunc)) {
199 switch (varType) {
200 case varInst:
201 compileOpcode(opPushInstVar, index);
202 break;
203 case varClass: {
204 index += slotRawInt(&classobj->classVarIndex);
205 if (index < 4096) {
206 compileByte((opPushClassVar << 4) | ((index >> 8) & 15));
207 compileByte(index & 255);
208 } else {
209 compileByte(opPushClassVar);
210 compileByte((index >> 8) & 255);
211 compileByte(index & 255);
212 }
213 } break;
214 case varConst: {
215 PyrSlot* slot = slotRawObject(&classobj->constValues)->slots + index;
216 compilePushConstant(node, slot);
217 } break;
218 case varTemp:
219 vindex = index;
220 if (level == 0) {
221 compileOpcode(opPushTempZeroVar, vindex);
222 } else if (level < 8) {
223 compileOpcode(opPushTempVar, level);
224 compileByte(vindex);
225 } else {
226 compileByte(opPushTempVar);
227 compileByte(level);
228 compileByte(vindex);
229 }
230 break;
231 case varPseudo:
232 compileOpcode(opExtended, opSpecialOpcode);
233 compileByte(index);
234 break;
235 }
236 } else {
237 error("Variable '%s' not defined.\n", varName->name);
238 nodePostErrorLine(node);
239 compileErrors++;
240 // Debugger();
241 }
242 }
243
newPyrCurryArgNode()244 PyrCurryArgNode* newPyrCurryArgNode() {
245 PyrCurryArgNode* node = ALLOCNODE(PyrCurryArgNode);
246 return node;
247 }
248
compile(PyrSlot * result)249 void PyrCurryArgNode::compile(PyrSlot* result) {
250 if (gPartiallyAppliedFunction) {
251 compileOpcode(opPushTempZeroVar, mArgNum);
252 } else {
253 error("found _ argument outside of a call.\n");
254 nodePostErrorLine((PyrParseNode*)this);
255 compileErrors++;
256 }
257 }
258
newPyrSlotNode(PyrSlot * slot)259 PyrSlotNode* newPyrSlotNode(PyrSlot* slot) {
260 PyrSlotNode* node = ALLOCNODE(PyrSlotNode);
261 node->mSlot = *slot;
262 return node;
263 }
264
compile(PyrSlot * result)265 void PyrSlotNode::compile(PyrSlot* result) {
266 if (mClassno == pn_LiteralNode)
267 compileLiteral(result);
268 else if (mClassno == pn_PushLitNode)
269 compilePushLit(result);
270 else if (mClassno == pn_PushNameNode)
271 compilePushVar((PyrParseNode*)this, slotRawSymbol(&mSlot));
272 else {
273 error("compilePyrSlotNode: shouldn't get here.\n");
274 dumpObjectSlot(&mSlot);
275 nodePostErrorLine((PyrParseNode*)this);
276 compileErrors++;
277 // Debugger();
278 }
279 }
280
newPyrClassExtNode(PyrSlotNode * className,PyrMethodNode * methods)281 PyrClassExtNode* newPyrClassExtNode(PyrSlotNode* className, PyrMethodNode* methods) {
282 PyrClassExtNode* node = ALLOCNODE(PyrClassExtNode);
283 node->mClassName = className;
284
285 node->mMethods = methods;
286 return node;
287 }
288
compile(PyrSlot * result)289 void PyrClassExtNode::compile(PyrSlot* result) {
290 PyrClass* classobj = slotRawSymbol(&mClassName->mSlot)->u.classobj;
291 if (!classobj) {
292 const bfs::path relpath = relativeToCompileDir(bfs::path(gCompilingFileSym->name));
293 error("Class extension for nonexistent class '%s'\n In file:'%s'\n",
294 slotRawSymbol(&mClassName->mSlot)->name, SC_Codecvt::path_to_utf8_str(relpath).c_str());
295 return;
296 }
297 gCurrentClass = classobj;
298 gCurrentMetaClass = classobj->classptr;
299 compileExtNodeMethods(this);
300 }
301
compileExtNodeMethods(PyrClassExtNode * node)302 void compileExtNodeMethods(PyrClassExtNode* node) {
303 PyrMethodNode* method;
304 method = node->mMethods;
305 for (; method; method = (PyrMethodNode*)method->mNext) {
306 PyrSlot dummy;
307 // post("compile ext %s:%s\n",
308 method->mExtension = true;
309 compilePyrMethodNode(method, &dummy);
310 }
311 gCompilingMethod = nullptr;
312 gCompilingBlock = nullptr;
313 gPartiallyAppliedFunction = nullptr;
314 gInliningLevel = 0;
315 }
316
newPyrClassNode(PyrSlotNode * className,PyrSlotNode * superClassName,PyrVarListNode * varlists,PyrMethodNode * methods,PyrSlotNode * indexType)317 PyrClassNode* newPyrClassNode(PyrSlotNode* className, PyrSlotNode* superClassName, PyrVarListNode* varlists,
318 PyrMethodNode* methods, PyrSlotNode* indexType) {
319 PyrClassNode* node = ALLOCNODE(PyrClassNode);
320 node->mClassName = className;
321 node->mIndexType = indexType;
322
323 node->mSuperClassName = superClassName;
324 node->mVarlists = varlists;
325 node->mMethods = methods;
326 node->mVarTally[varInst] = 0;
327 node->mVarTally[varClass] = 0;
328 node->mVarTally[varTemp] = 0;
329 node->mVarTally[varConst] = 0;
330 // node->mVarTally[varPool] = 0;
331 return node;
332 }
333
compareVarDefs(PyrClassNode * node,PyrClass * classobj)334 bool compareVarDefs(PyrClassNode* node, PyrClass* classobj) {
335 int numinstvars, numclassvars;
336 int i, xinst, xclass;
337 PyrVarListNode* varlist;
338 PyrVarDefNode* vardef;
339 PyrParseNode* errnode;
340 PyrSymbol** varNames;
341 bool isIntrinsic;
342
343 isIntrinsic = slotRawInt(&classobj->classFlags) & classIsIntrinsic;
344
345 numinstvars = numInstVars(classobj);
346 numclassvars = numClassVars(classobj);
347 if (numinstvars == node->mVarTally[varInst] + node->mNumSuperInstVars
348 && numclassvars == node->mVarTally[varClass]) {
349 xclass = 0;
350 xinst = node->mNumSuperInstVars;
351 varlist = node->mVarlists;
352 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
353 int type = varlist->mFlags;
354 if (type == varInst) {
355 vardef = varlist->mVarDefs;
356 varNames = slotRawSymbolArray(&classobj->instVarNames)->symbols;
357 for (i = 0; vardef; vardef = (PyrVarDefNode*)vardef->mNext, xinst++, ++i) {
358 if (slotRawSymbol(&vardef->mVarName->mSlot) != varNames[xinst]) {
359 errnode = (PyrParseNode*)vardef;
360 // post("A %s %d %d %d\n", vardef->mVarName->slotRawSymbol(&mSlot)->name,
361 // vardef->mVarName->slotRawSymbol(&mSlot), varNames[xinst].us, xinst);
362 // post("A %s %s %d\n", vardef->mVarName->slotRawSymbol(&mSlot)->name,
363 // varNames[xinst].us->name, xinst);
364 goto differExit;
365 }
366 }
367 } else if (type == varClass) {
368 vardef = varlist->mVarDefs;
369 varNames = slotRawSymbolArray(&classobj->classVarNames)->symbols;
370 for (i = 0; vardef && xclass < numclassvars; vardef = (PyrVarDefNode*)vardef->mNext, xclass++, ++i) {
371 if (slotRawSymbol(&vardef->mVarName->mSlot) != varNames[xclass]) {
372 errnode = (PyrParseNode*)vardef;
373 // post("B %d %d %d\n", vardef->mVarName->slotRawSymbol(&mSlot), varNames[xclass].us, xclass);
374 goto differExit;
375 }
376 }
377 }
378 }
379 } else {
380 // post("C %d %d %d %d %d\n", numinstvars, node->mVarTally[varInst], node->mNumSuperInstVars,
381 // numclassvars, node->mVarTally[varClass]);
382 errnode = (node->mVarlists ? (PyrParseNode*)node->mVarlists : (PyrParseNode*)node->mClassName);
383 goto differExit;
384 }
385 return false;
386
387 differExit:
388 if (isIntrinsic) {
389 error("You may not change variable definitions of intrinsic classes.\n");
390 nodePostErrorLine(errnode);
391 compileErrors++;
392 }
393 return true;
394 }
395
countClassVarDefs(PyrClassNode * node,int * numClassMethods,int * numInstMethods)396 void countClassVarDefs(PyrClassNode* node, int* numClassMethods, int* numInstMethods) {
397 PyrVarListNode* varlist;
398 PyrVarDefNode* vardef;
399
400 //*numClassMethods = 0;
401 //*numInstMethods = 0;
402
403 node->mVarTally[varInst] = 0;
404 node->mVarTally[varClass] = 0;
405 node->mVarTally[varTemp] = 0;
406 node->mVarTally[varConst] = 0;
407
408 // count number of variables of each type
409 varlist = node->mVarlists;
410 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
411 int type = varlist->mFlags;
412 vardef = varlist->mVarDefs;
413 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
414 node->mVarTally[type]++;
415 if (type == varClass) {
416 if (vardef->mFlags & rwReadOnly) {
417 *numClassMethods = *numClassMethods + 1;
418 }
419 if (vardef->mFlags & rwWriteOnly) {
420 *numClassMethods = *numClassMethods + 1;
421 }
422 } else if (type == varInst) {
423 if (vardef->mFlags & rwReadOnly) {
424 *numInstMethods = *numInstMethods + 1;
425 }
426 if (vardef->mFlags & rwWriteOnly) {
427 *numInstMethods = *numInstMethods + 1;
428 }
429 }
430 }
431 }
432 }
433
countNodeMethods(PyrClassNode * node,int * numClassMethods,int * numInstMethods)434 void countNodeMethods(PyrClassNode* node, int* numClassMethods, int* numInstMethods) {
435 // count methods
436 PyrMethodNode* method;
437 //*numClassMethods = 0;
438 //*numInstMethods = 0;
439 method = node->mMethods;
440 for (; method; method = (PyrMethodNode*)method->mNext) {
441 if (method->mIsClassMethod)
442 *numClassMethods = *numClassMethods + 1;
443 else
444 *numInstMethods = *numInstMethods + 1;
445 }
446 }
447
compileNodeMethods(PyrClassNode * node)448 void compileNodeMethods(PyrClassNode* node) {
449 PyrMethodNode* method;
450 method = node->mMethods;
451 for (; method; method = (PyrMethodNode*)method->mNext) {
452 PyrSlot dummy;
453 method->mExtension = false;
454 compilePyrMethodNode(method, &dummy);
455 }
456 gCompilingMethod = nullptr;
457 gCompilingBlock = nullptr;
458 gPartiallyAppliedFunction = nullptr;
459 gInliningLevel = 0;
460 }
461
getNodeSuperclass(PyrClassNode * node)462 PyrClass* getNodeSuperclass(PyrClassNode* node) {
463 PyrClass* superclassobj = nullptr;
464 // postfl("getNodeSuperclass node %d\n", node);
465 // postfl("getNodeSuperclass node->mSuperClassName %d\n", node->mSuperClassName);
466 // postfl("getNodeSuperclass node->mSuperClassName->mSlot.utag %d\n",
467 // node->mSuperClassName->mSlot.utag);
468 if (node->mSuperClassName && IsSym(&node->mSuperClassName->mSlot)) {
469 superclassobj = slotRawSymbol(&node->mSuperClassName->mSlot)->u.classobj;
470 if (superclassobj == nullptr) {
471 error("Cannot find superclass '%s' for class '%s'\n", slotSymString(&node->mSuperClassName->mSlot),
472 slotSymString(&node->mClassName->mSlot));
473 nodePostErrorLine((PyrParseNode*)node->mSuperClassName);
474 superclassobj = (PyrClass*)-1;
475 compileErrors++;
476 }
477 } else {
478 if (slotRawSymbol(&node->mClassName->mSlot) != s_object) {
479 superclassobj = class_object;
480 } // else this is object and there is no superclass
481 }
482 return superclassobj;
483 }
484
fillClassPrototypes(PyrClassNode * node,PyrClass * classobj,PyrClass * superclassobj)485 void fillClassPrototypes(PyrClassNode* node, PyrClass* classobj, PyrClass* superclassobj) {
486 PyrVarListNode* varlist;
487 PyrVarDefNode* vardef;
488 PyrSlot *islot, *cslot, *kslot;
489 PyrSymbol **inameslot, **cnameslot, **knameslot;
490 PyrClass* metaclassobj;
491 PyrMethod* method;
492 PyrMethodRaw* methraw;
493 int instVarIndex, classVarIndex;
494
495 // copy superclass's prototype to here
496 if (superclassobj && NotNil(&superclassobj->iprototype) && slotRawObject(&superclassobj->iprototype)->size) {
497 memcpy(slotRawObject(&classobj->iprototype)->slots, slotRawObject(&superclassobj->iprototype)->slots,
498 sizeof(PyrSlot) * slotRawObject(&superclassobj->iprototype)->size);
499 // slotRawObject(&classobj->iprototype)->size = slotRawObject(&superclassobj->iprototype)->size;
500 slotRawObject(&classobj->iprototype)->size = node->mNumSuperInstVars;
501
502 memcpy(slotRawSymbolArray(&classobj->instVarNames)->symbols,
503 slotRawSymbolArray(&superclassobj->instVarNames)->symbols,
504 sizeof(PyrSymbol*) * slotRawObject(&superclassobj->instVarNames)->size);
505 // slotRawObject(&classobj->instVarNames)->size = slotRawObject(&superclassobj->iprototype)->size;
506 slotRawObject(&classobj->instVarNames)->size = node->mNumSuperInstVars;
507 }
508 // fill the class' own part of prototypes
509 metaclassobj = classobj->classptr;
510 varlist = node->mVarlists;
511 if (NotNil(&classobj->iprototype)) {
512 islot = slotRawObject(&classobj->iprototype)->slots + node->mNumSuperInstVars;
513 }
514 if (NotNil(&classobj->cprototype)) {
515 cslot = slotRawObject(&classobj->cprototype)->slots;
516 }
517 if (NotNil(&classobj->constValues)) {
518 kslot = slotRawObject(&classobj->constValues)->slots;
519 }
520 if (NotNil(&classobj->instVarNames)) {
521 inameslot = slotRawSymbolArray(&classobj->instVarNames)->symbols + node->mNumSuperInstVars;
522 }
523 if (NotNil(&classobj->classVarNames)) {
524 cnameslot = slotRawSymbolArray(&classobj->classVarNames)->symbols;
525 }
526 if (NotNil(&classobj->constNames)) {
527 knameslot = slotRawSymbolArray(&classobj->constNames)->symbols;
528 }
529 instVarIndex = node->mNumSuperInstVars;
530 classVarIndex = 0;
531 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
532 int type = varlist->mFlags;
533 switch (type) {
534 case varInst:
535 vardef = varlist->mVarDefs;
536 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
537 PyrSlot litslot;
538 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
539 *islot++ = litslot;
540 slotRawObject(&classobj->iprototype)->size++;
541 *inameslot++ = slotRawSymbol(&vardef->mVarName->mSlot);
542 slotRawSymbolArray(&classobj->instVarNames)->size++;
543 if (vardef->mFlags & rwReadOnly) {
544 // create getter method
545 method = newPyrMethod();
546 methraw = METHRAW(method);
547 methraw->unused1 = 0;
548 methraw->unused2 = 0;
549 methraw->numargs = 1;
550 methraw->numvars = 0;
551 methraw->posargs = 1;
552 methraw->varargs = 0;
553 methraw->numtemps = 1;
554 methraw->popSize = 0;
555 SetNil(&method->contextDef);
556 SetNil(&method->varNames);
557 SetObject(&method->ownerclass, classobj);
558 if (gCompilingFileSym)
559 SetSymbol(&method->filenameSym, gCompilingFileSym);
560 SetInt(&method->charPos, linestarts[vardef->mVarName->mLineno] + errCharPosOffset);
561 slotCopy(&method->name, &vardef->mVarName->mSlot);
562 methraw->methType = methReturnInstVar;
563 methraw->specialIndex = instVarIndex;
564 addMethod(classobj, method);
565 }
566 if (vardef->mFlags & rwWriteOnly) {
567 char setterName[256];
568 PyrSymbol* setterSym;
569 sprintf(setterName, "%s_", slotRawSymbol(&vardef->mVarName->mSlot)->name);
570 // underscore = strcpy(setterName, slotRawSymbol(&vardef->mVarName->mSlot)->name);
571 // underscore[0] = '_';
572 // underscore[1] = 0;
573 setterSym = getsym(setterName);
574 // create setter method
575 method = newPyrMethod();
576 methraw = METHRAW(method);
577 methraw->unused1 = 0;
578 methraw->unused2 = 0;
579 methraw->numargs = 2;
580 methraw->numvars = 0;
581 methraw->posargs = 2;
582 methraw->varargs = 0;
583 methraw->numtemps = 2;
584 methraw->popSize = 1;
585 SetNil(&method->contextDef);
586 SetNil(&method->varNames);
587 SetObject(&method->ownerclass, classobj);
588 SetSymbol(&method->name, setterSym);
589 if (gCompilingFileSym)
590 SetSymbol(&method->filenameSym, gCompilingFileSym);
591 SetInt(&method->charPos, linestarts[vardef->mVarName->mLineno] + errCharPosOffset);
592
593 methraw->methType = methAssignInstVar;
594 methraw->specialIndex = instVarIndex;
595 addMethod(classobj, method);
596 }
597 instVarIndex++;
598 }
599 break;
600 case varClass:
601 vardef = varlist->mVarDefs;
602 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
603 PyrSlot litslot;
604 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
605 *cslot++ = litslot;
606 slotRawObject(&classobj->cprototype)->size++;
607 *cnameslot++ = slotRawSymbol(&vardef->mVarName->mSlot);
608 slotRawSymbolArray(&classobj->classVarNames)->size++;
609 if (vardef->mFlags & rwReadOnly) {
610 // create getter method
611 method = newPyrMethod();
612 methraw = METHRAW(method);
613 methraw->unused1 = 0;
614 methraw->unused2 = 0;
615 methraw->numargs = 1;
616 methraw->numvars = 0;
617 methraw->posargs = 1;
618 methraw->varargs = 0;
619 methraw->numtemps = 1;
620 methraw->popSize = 0;
621 SetNil(&method->contextDef);
622 SetNil(&method->varNames);
623 SetObject(&method->ownerclass, metaclassobj);
624 slotCopy(&method->name, &vardef->mVarName->mSlot);
625 SetSymbol(&method->selectors, slotRawSymbol(&classobj->name));
626 if (gCompilingFileSym)
627 SetSymbol(&method->filenameSym, gCompilingFileSym);
628 SetInt(&method->charPos, linestarts[vardef->mVarName->mLineno] + errCharPosOffset);
629
630 methraw->methType = methReturnClassVar;
631 methraw->specialIndex = classVarIndex + slotRawInt(&classobj->classVarIndex);
632 addMethod(metaclassobj, method);
633 }
634 if (vardef->mFlags & rwWriteOnly) {
635 char setterName[256];
636 PyrSymbol* setterSym;
637 sprintf(setterName, "%s_", slotRawSymbol(&vardef->mVarName->mSlot)->name);
638 // underscore = strcpy(setterName, slotRawSymbol(&vardef->mVarName->mSlot)->name);
639 // underscore[0] = '_';
640 // underscore[1] = 0;
641 setterSym = getsym(setterName);
642 // create setter method
643 method = newPyrMethod();
644 methraw = METHRAW(method);
645 methraw->numargs = 2;
646 methraw->numvars = 0;
647 methraw->posargs = 2;
648 methraw->varargs = 0;
649 methraw->numtemps = 2;
650 methraw->popSize = 1;
651 SetNil(&method->contextDef);
652 SetNil(&method->varNames);
653 SetObject(&method->ownerclass, metaclassobj);
654 SetSymbol(&method->name, setterSym);
655 SetSymbol(&method->selectors, slotRawSymbol(&classobj->name));
656 if (gCompilingFileSym)
657 SetSymbol(&method->filenameSym, gCompilingFileSym);
658 SetInt(&method->charPos, linestarts[vardef->mVarName->mLineno] + errCharPosOffset);
659
660 methraw->methType = methAssignClassVar;
661 methraw->specialIndex = classVarIndex + slotRawInt(&classobj->classVarIndex);
662 addMethod(metaclassobj, method);
663 }
664 classVarIndex++;
665 }
666 break;
667 case varConst:
668 vardef = varlist->mVarDefs;
669 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
670 PyrSlot litslot;
671 compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litslot);
672 *kslot++ = litslot;
673 slotRawObject(&classobj->constValues)->size++;
674 *knameslot++ = slotRawSymbol(&vardef->mVarName->mSlot);
675 slotRawSymbolArray(&classobj->constNames)->size++;
676 if (vardef->mFlags & rwReadOnly) {
677 // create getter method
678 method = newPyrMethod();
679 methraw = METHRAW(method);
680 methraw->unused1 = 0;
681 methraw->unused2 = 0;
682 methraw->numargs = 1;
683 methraw->numvars = 0;
684 methraw->posargs = 1;
685 methraw->varargs = 0;
686 methraw->numtemps = 1;
687 methraw->popSize = 0;
688 SetNil(&method->contextDef);
689 SetNil(&method->varNames);
690 SetObject(&method->ownerclass, metaclassobj);
691 slotCopy(&method->name, &vardef->mVarName->mSlot);
692 if (gCompilingFileSym)
693 SetSymbol(&method->filenameSym, gCompilingFileSym);
694 SetInt(&method->charPos, linestarts[vardef->mVarName->mLineno] + errCharPosOffset);
695
696 methraw->methType = methReturnLiteral;
697 slotCopy(&method->selectors, &litslot);
698 addMethod(metaclassobj, method);
699 }
700 }
701 break;
702 }
703 }
704 }
705
getIndexType(PyrClassNode * classnode)706 int getIndexType(PyrClassNode* classnode) {
707 PyrSlotNode* node;
708 int res;
709
710 node = classnode->mIndexType;
711 if (node == nullptr)
712 res = obj_notindexed;
713 else {
714 char* name;
715 name = slotRawSymbol(&node->mSlot)->name;
716 if (strcmp(name, "slot") == 0)
717 res = obj_slot;
718 else if (strcmp(name, "double") == 0)
719 res = obj_double;
720 else if (strcmp(name, "float") == 0)
721 res = obj_float;
722 else if (strcmp(name, "int32") == 0)
723 res = obj_int32;
724 else if (strcmp(name, "int16") == 0)
725 res = obj_int16;
726 else if (strcmp(name, "int8") == 0)
727 res = obj_int8;
728 else if (strcmp(name, "char") == 0)
729 res = obj_char;
730 else if (strcmp(name, "symbol") == 0)
731 res = obj_symbol;
732 else {
733 error("Illegal indexed type. Must be one of:\n"
734 " slot, double, float, int8, int16, int32, char\n");
735 res = obj_slot;
736 compileErrors++;
737 }
738 }
739 return res;
740 }
741
compile(PyrSlot * result)742 void PyrClassNode::compile(PyrSlot* result) {
743 PyrClass *classobj, *superclassobj, *metaclassobj;
744 int numClassMethods, numInstMethods;
745 bool isIntrinsic;
746 bool varsDiffer, superclassesDiffer, indexTypesDiffer;
747 bool shouldRecompileSubclasses = false;
748 int indexType;
749
750 // find num instvars in superclass
751 // postfl("class '%s'\n", slotRawSymbol(&mClassName->mSlot)->name);
752 superclassobj = getNodeSuperclass(this);
753 indexType = getIndexType(this);
754 // postfl("%s %d\n", slotRawSymbol(&mClassName->mSlot)->name, indexType);
755
756 if ((size_t)superclassobj == -1) {
757 // redundant error message removed:
758 // error("Can't find superclass of '%s'\n", slotRawSymbol(&mClassName->mSlot)->name);
759 // nodePostErrorLine(node);
760 return; // can't find superclass
761 }
762 mNumSuperInstVars = numSuperInstVars(superclassobj);
763
764 numClassMethods = 0;
765 numInstMethods = 0;
766 countClassVarDefs(this, &numClassMethods, &numInstMethods);
767 // postfl("accessor methods %d %d\n", numClassMethods, numInstMethods);
768 countNodeMethods(this, &numClassMethods, &numInstMethods);
769 // postfl("total methods %d %d\n", numClassMethods, numInstMethods);
770
771 // get or make a class object
772 // see if it already exists
773 classobj = slotRawSymbol(&mClassName->mSlot)->u.classobj;
774 if (classobj) {
775 // deal with intrinsic classes or other classes being recompiled here.
776 // recompile of subclasses not necessary if inst and class vars are
777 // unchanged.
778 metaclassobj = (PyrClass*)classobj->classptr;
779 isIntrinsic = slotRawInt(&classobj->classFlags) & classIsIntrinsic;
780
781 varsDiffer = compareVarDefs(this, classobj);
782 if (varsDiffer) {
783 if (isIntrinsic) {
784 // error("Class '%s' declaration doesn't match intrinsic definition.\n",
785 // slotRawSymbol(&mClassName->mSlot)->name);
786 return;
787 } else {
788 shouldRecompileSubclasses = true;
789 }
790 }
791 superclassesDiffer = superclassobj != slotRawSymbol(&classobj->superclass)->u.classobj;
792 indexTypesDiffer = indexType != slotRawInt(&classobj->instanceFormat);
793 // postfl("%d %d %d\n", indexType, slotRawInt(&classobj->instanceFormat));
794 // if (varsDiffer || superclassesDiffer || indexTypesDiffer) {
795 if (varsDiffer || superclassesDiffer || indexTypesDiffer) {
796 if (isIntrinsic) {
797 if (superclassesDiffer) {
798 error("Superclass of '%s' does not match intrinsic definition.\n",
799 slotRawSymbol(&mClassName->mSlot)->name);
800 nodePostErrorLine((PyrParseNode*)(mSuperClassName ? mSuperClassName : mClassName));
801 compileErrors++;
802 }
803 if (indexTypesDiffer) {
804 error("Index type of '%s' does not match intrinsic definition.\n",
805 slotRawSymbol(&mClassName->mSlot)->name);
806 nodePostErrorLine((indexType ? (PyrParseNode*)mIndexType : (PyrParseNode*)mClassName));
807 compileErrors++;
808 }
809 error("Class '%s' declaration doesn't match intrinsic definition.\n",
810 slotRawSymbol(&mClassName->mSlot)->name);
811 return;
812 } else {
813 shouldRecompileSubclasses = true;
814 }
815 }
816 // reallocate fields in the class object
817 reallocClassObj(metaclassobj, classClassNumInstVars, 0, 0, numClassMethods, indexType, 0);
818
819 // postfl("^3 %d %d\n", metaclassobj, class_class);
820 // postfl("^4 %d %d\n", slotRawObject(&metaclassobj->iprototype), slotRawObject(&class_class->iprototype));
821 memcpy(slotRawObject(&metaclassobj->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
822 sizeof(PyrSlot) * classClassNumInstVars);
823 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
824 slotRawSymbolArray(&class_class->instVarNames)->symbols, sizeof(PyrSymbol*) * classClassNumInstVars);
825 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
826 slotRawSymbolArray(&metaclassobj->instVarNames)->size = classClassNumInstVars;
827
828 reallocClassObj(classobj, mVarTally[varInst] + mNumSuperInstVars, mVarTally[varClass], mVarTally[varConst],
829 numInstMethods, indexType, 0);
830
831 } else {
832 PyrSymbol *superClassName, *metaClassName, *metaSuperClassName;
833
834 superClassName = superclassobj ? slotRawSymbol(&superclassobj->name) : nullptr;
835 metaClassName = getmetasym(slotRawSymbol(&mClassName->mSlot)->name);
836 metaClassName->flags |= sym_MetaClass;
837 metaSuperClassName = superClassName ? getmetasym(superClassName->name) : nullptr;
838
839 metaclassobj = newClassObj(class_class, metaClassName, metaSuperClassName, classClassNumInstVars, 0, 0,
840 numClassMethods, indexType, 0);
841 // test
842 // postfl("^1 %d %d\n", metaclassobj, class_class);
843 // postfl("^2 %d %d\n", slotRawObject(&metaclassobj->iprototype), slotRawObject(&class_class->iprototype));
844
845 memcpy(slotRawObject(&metaclassobj->iprototype)->slots, slotRawObject(&class_class->iprototype)->slots,
846 sizeof(PyrSlot) * classClassNumInstVars);
847 memcpy(slotRawSymbolArray(&metaclassobj->instVarNames)->symbols,
848 slotRawSymbolArray(&class_class->instVarNames)->symbols, sizeof(PyrSymbol*) * classClassNumInstVars);
849 slotRawObject(&metaclassobj->iprototype)->size = classClassNumInstVars;
850 slotRawObject(&metaclassobj->instVarNames)->size = classClassNumInstVars;
851 // end test
852 classobj = newClassObj(metaclassobj, slotRawSymbol(&mClassName->mSlot), superClassName,
853 mVarTally[varInst] + mNumSuperInstVars, mVarTally[varClass], mVarTally[varConst],
854 numInstMethods, indexType, 0);
855 }
856 gCurrentClass = classobj;
857 gCurrentMetaClass = metaclassobj;
858 if (gCompilingFileSym) {
859 SetSymbol(&classobj->filenameSym, gCompilingFileSym);
860 SetInt(&classobj->charPos, linestarts[mClassName->mLineno] + errCharPosOffset);
861 SetSymbol(&metaclassobj->filenameSym, gCompilingFileSym);
862 SetInt(&metaclassobj->charPos, linestarts[mClassName->mLineno] + errCharPosOffset);
863 } else {
864 SetNil(&classobj->filenameSym);
865 SetNil(&metaclassobj->filenameSym);
866 }
867
868 // fill inst and class prototypes
869 fillClassPrototypes(this, classobj, superclassobj);
870
871 // compile methods
872 compileNodeMethods(this);
873
874 // recompileSubclasses
875 if (shouldRecompileSubclasses) {
876 recompileSubclasses(classobj);
877 }
878 }
879
recompileSubclasses(PyrClass * classobj)880 void recompileSubclasses(PyrClass* classobj) {}
881
882 #if 0
883 void catVarLists(PyrVarListNode *varlist);
884 void catVarLists(PyrVarListNode *varlist)
885 {
886 PyrVarListNode *prevvarlist;
887 PyrVarDefNode *vardef, *lastvardef;
888
889 if (varlist) {
890 // find end of this list
891 vardef = varlist->mVarDefs;
892 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
893 lastvardef = vardef;
894 }
895 prevvarlist = varlist;
896 varlist = (PyrVarListNode*)varlist->mNext;
897
898 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
899 vardef = varlist->mVarDefs;
900 if (lastvardef) {
901 lastvardef->mNext = (PyrParseNode*)vardef;
902 } else {
903 prevvarlist->mVarDefs = vardef;
904 }
905 // find end of this list
906 for (; vardef; vardef = (PyrVarDefNode*)vardef->mNext) {
907 lastvardef = vardef;
908 }
909 }
910 }
911 }
912
913 #else
914
915 void catVarLists(PyrVarListNode* varlist);
catVarLists(PyrVarListNode * varlist)916 void catVarLists(PyrVarListNode* varlist) {
917 PyrVarListNode* prevvarlist;
918 PyrVarDefNode *vardef, *lastvardef;
919
920 if (varlist) {
921 // find end of this list
922 vardef = varlist->mVarDefs;
923 lastvardef = (PyrVarDefNode*)vardef->mTail;
924 prevvarlist = varlist;
925 varlist = (PyrVarListNode*)varlist->mNext;
926
927 for (; varlist; varlist = (PyrVarListNode*)varlist->mNext) {
928 vardef = varlist->mVarDefs;
929 lastvardef->mNext = (PyrParseNode*)vardef;
930
931 // find end of this list
932 lastvardef = (PyrVarDefNode*)vardef->mTail;
933 }
934 }
935 }
936 #endif
937
newPyrMethodNode(PyrSlotNode * methodName,PyrSlotNode * primitiveName,PyrArgListNode * arglist,PyrVarListNode * varlist,PyrParseNode * body,int isClassMethod)938 PyrMethodNode* newPyrMethodNode(PyrSlotNode* methodName, PyrSlotNode* primitiveName, PyrArgListNode* arglist,
939 PyrVarListNode* varlist, PyrParseNode* body, int isClassMethod) {
940 PyrMethodNode* node = ALLOCNODE(PyrMethodNode);
941 node->mMethodName = methodName;
942 node->mPrimitiveName = primitiveName;
943 node->mArglist = arglist;
944 catVarLists(varlist);
945 node->mVarlist = varlist;
946 node->mBody = body;
947 node->mIsClassMethod = isClassMethod;
948 return node;
949 }
950
951 enum { push_Normal, push_AllArgs, push_AllButFirstArg, push_AllButFirstArg2 };
952
953 int checkPushAllArgs(PyrParseNode* actualArg, int numArgs);
checkPushAllArgs(PyrParseNode * actualArg,int numArgs)954 int checkPushAllArgs(PyrParseNode* actualArg, int numArgs) {
955 PyrBlock* block;
956 PyrPushNameNode* nameNode;
957 block = gCompilingBlock;
958 int i;
959
960 // if (strcmp("ar", slotRawSymbol(&gCompilingMethod->name)->name)==0) Debugger();
961 if (actualArg->mClassno != pn_PushNameNode) {
962 if (numArgs < 3) {
963 return push_Normal;
964 }
965 actualArg = actualArg->mNext;
966 for (i = 1; i < numArgs; ++i) {
967 if (actualArg->mClassno != pn_PushNameNode) {
968 return push_Normal;
969 }
970 nameNode = (PyrPushNameNode*)actualArg;
971 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbolArray(&block->argNames)->symbols[i]) {
972 return push_Normal;
973 }
974
975 actualArg = actualArg->mNext;
976 }
977 return push_AllButFirstArg;
978
979 } else {
980 for (i = 0; i < numArgs; ++i) {
981 if (actualArg->mClassno != pn_PushNameNode) {
982 return push_Normal;
983 }
984 nameNode = (PyrPushNameNode*)actualArg;
985 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbolArray(&block->argNames)->symbols[i]) {
986 return push_Normal;
987 }
988 actualArg = actualArg->mNext;
989 }
990 return push_AllArgs;
991 }
992 }
993
994
995 int checkPushAllButFirstTwoArgs(PyrParseNode* actualArg, int numArgs);
checkPushAllButFirstTwoArgs(PyrParseNode * actualArg,int numArgs)996 int checkPushAllButFirstTwoArgs(PyrParseNode* actualArg, int numArgs) {
997 PyrBlock* block;
998 PyrPushNameNode* nameNode;
999 block = gCompilingBlock;
1000 int i;
1001
1002 if (numArgs >= 2) {
1003 actualArg = actualArg->mNext;
1004 actualArg = actualArg->mNext;
1005 for (i = 1; i < numArgs; ++i) {
1006 if (actualArg->mClassno != pn_PushNameNode) {
1007 return push_Normal;
1008 }
1009 nameNode = (PyrPushNameNode*)actualArg;
1010 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbolArray(&block->argNames)->symbols[i]) {
1011 return push_Normal;
1012 }
1013
1014 actualArg = actualArg->mNext;
1015 }
1016 return push_AllButFirstArg2;
1017 }
1018 return push_Normal;
1019 }
1020
compareCallArgs(PyrMethodNode * node,PyrCallNode * cnode,int * varIndex,PyrClass ** specialClass)1021 int compareCallArgs(PyrMethodNode* node, PyrCallNode* cnode, int* varIndex, PyrClass** specialClass) {
1022 int i, numFormalArgs, numActualArgs;
1023 int special, varType, varLevel;
1024 PyrParseNode* actualArg;
1025 PyrVarDefNode* formalArg;
1026 PyrPushNameNode* nameNode;
1027
1028 // fail if has a rest arg .. too much trouble?
1029 if (node->mArglist && node->mArglist->mRest) {
1030 return methNormal;
1031 }
1032
1033 // check first actual arg is 'this'
1034 actualArg = cnode->mArglist;
1035 if (actualArg->mClassno != pn_PushNameNode) {
1036 return methNormal;
1037 }
1038 nameNode = (PyrPushNameNode*)actualArg;
1039 if (slotRawSymbol(&nameNode->mSlot) == s_this) {
1040 special = methRedirect;
1041 } else if (slotRawSymbol(&nameNode->mSlot) == s_super) {
1042 special = methRedirectSuper;
1043 } else {
1044 bool varFound;
1045 PyrClass* classobj;
1046
1047 classobj = gCompilingClass;
1048 varFound = findVarName(gCompilingBlock, &classobj, slotRawSymbol(&nameNode->mSlot), &varType, &varLevel,
1049 varIndex, nullptr);
1050 if (!varFound)
1051 return methNormal;
1052
1053 if (varType == varInst)
1054 special = methForwardInstVar;
1055 else if (varType == varClass) {
1056 special = methForwardClassVar;
1057 *varIndex += slotRawInt(&classobj->classVarIndex);
1058 *specialClass = classobj;
1059 } else
1060 return methNormal;
1061 }
1062
1063 actualArg = actualArg->mNext;
1064 numActualArgs = nodeListLength((PyrParseNode*)cnode->mArglist);
1065
1066 if (!node->mArglist) {
1067 numFormalArgs = 1;
1068 if (numActualArgs != numFormalArgs) {
1069 return methNormal;
1070 }
1071 } else {
1072 numFormalArgs = 1 + nodeListLength((PyrParseNode*)node->mArglist->mVarDefs);
1073 if (numActualArgs != numFormalArgs) {
1074 return methNormal;
1075 }
1076
1077 formalArg = node->mArglist->mVarDefs;
1078 for (i = 0; i < numActualArgs - 1; ++i) {
1079 if (actualArg->mClassno != pn_PushNameNode) {
1080 return methNormal;
1081 }
1082
1083 nameNode = (PyrPushNameNode*)actualArg;
1084 if (slotRawSymbol(&nameNode->mSlot) != slotRawSymbol(&formalArg->mVarName->mSlot)) {
1085 return methNormal;
1086 }
1087
1088 formalArg = (PyrVarDefNode*)formalArg->mNext;
1089 actualArg = actualArg->mNext;
1090 }
1091 }
1092 /*
1093 if (special == methForwardInstVar) {
1094 postfl("methForwardInstVar %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1095 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1096 }
1097 if (special == methForwardClassVar) {
1098 postfl("methForwardClassVar %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1099 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1100 }
1101 if (special == methRedirectSuper) {
1102 postfl("methRedirectSuper %s:%s formal %d actual %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1103 slotRawSymbol(&gCompilingMethod->name)->name, numFormalArgs, numActualArgs);
1104 }
1105 */
1106
1107 // if (special == methTempDelegate) {
1108 // postfl("methTempDelegate %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
1109 // slotRawSymbol(&gCompilingMethod->name)->name);
1110 // }
1111 return special;
1112 }
1113
installByteCodes(PyrBlock * block)1114 void installByteCodes(PyrBlock* block) {
1115 PyrInt8Array* byteArray;
1116 long length, flags;
1117 ByteCodes byteCodes;
1118 byteCodes = getByteCodes();
1119 if (byteCodes) {
1120 length = byteCodeLength(byteCodes);
1121 if (length) {
1122 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
1123 byteArray = newPyrInt8Array(compileGC(), length, flags, false);
1124 copyByteCodes(byteArray->b, byteCodes);
1125 byteArray->size = length;
1126 freeByteCodes(byteCodes);
1127 SetObject(&block->code, byteArray);
1128 } else {
1129 error("installByteCodes: zero length byte codes\n");
1130 }
1131 } else {
1132 error("installByteCodes: NULL byte codes\n");
1133 }
1134 }
1135
1136 PyrMethod* initPyrMethod(PyrMethod* method);
1137
compilePyrMethodNode(PyrMethodNode * node,PyrSlot * result)1138 void compilePyrMethodNode(PyrMethodNode* node, PyrSlot* result) { node->compile(result); }
1139
compile(PyrSlot * result)1140 void PyrMethodNode::compile(PyrSlot* result) {
1141 PyrMethod *method, *oldmethod;
1142 PyrMethodRaw* methraw;
1143 int i, j, numArgs, numVars, methType, funcVarArgs, firstKeyIndex;
1144 int index, numSlots, numArgNames;
1145 bool hasPrimitive = false;
1146 bool hasVarExprs = false;
1147 PyrVarDefNode* vardef;
1148 PyrObject* proto;
1149 PyrSymbolArray *argNames, *varNames;
1150
1151 SetTailBranch branch(false);
1152
1153 // postfl("->method '%s'\n", slotRawSymbol(&mMethodName->mSlot)->name);
1154 gCompilingClass = mIsClassMethod ? gCurrentMetaClass : gCurrentClass;
1155 oldmethod = classFindDirectMethod(gCompilingClass, slotRawSymbol(&mMethodName->mSlot));
1156
1157 if (oldmethod && !mExtension) {
1158 error("Method %s:%s already defined.\n", slotRawSymbol(&slotRawClass(&oldmethod->ownerclass)->name)->name,
1159 slotRawSymbol(&oldmethod->name)->name);
1160 nodePostErrorLine((PyrParseNode*)mMethodName);
1161 compileErrors++;
1162 return;
1163 }
1164
1165 if (oldmethod) {
1166 ++numOverwrites;
1167
1168 // accumulate overwrite message onto the string buffer
1169 overwriteMsg.append(slotRawSymbol(&slotRawClass(&oldmethod->ownerclass)->name)->name)
1170 .append(":")
1171 .append(slotRawSymbol(&oldmethod->name)->name)
1172 .append("\t")
1173 .append(gCompilingFileSym->name)
1174 .append("\t")
1175 .append(slotRawSymbol(&oldmethod->filenameSym)->name)
1176 .append("\n");
1177
1178 method = oldmethod;
1179 freePyrSlot(&method->code);
1180 freePyrSlot(&method->selectors);
1181 freePyrSlot(&method->prototypeFrame);
1182 freePyrSlot(&method->argNames);
1183 freePyrSlot(&method->varNames);
1184 initPyrMethod(method);
1185 } else {
1186 method = newPyrMethod();
1187 }
1188 SetObject(&method->ownerclass, gCompilingClass);
1189
1190 methraw = METHRAW(method);
1191 methraw->unused1 = 0;
1192 methraw->unused2 = 0;
1193
1194 // postfl("method %p raw %p\n", method, methraw);
1195 method->contextDef = o_nil;
1196 method->name = mMethodName->mSlot;
1197 if (gCompilingFileSym)
1198 SetSymbol(&method->filenameSym, gCompilingFileSym);
1199 SetInt(&method->charPos, linestarts[mMethodName->mLineno] + errCharPosOffset);
1200 if (mPrimitiveName) {
1201 hasPrimitive = true;
1202 method->primitiveName = mPrimitiveName->mSlot;
1203 methraw->specialIndex = slotRawSymbol(&mPrimitiveName->mSlot)->u.index;
1204 }
1205 gCompilingBlock = (PyrBlock*)method;
1206 gCompilingMethod = (PyrMethod*)method;
1207 gPartiallyAppliedFunction = nullptr;
1208 gInliningLevel = 0;
1209
1210 methraw->needsHeapContext = 0;
1211
1212 methraw->varargs = funcVarArgs = (mArglist && mArglist->mRest) ? 1 : 0;
1213 numArgs = mArglist ? nodeListLength((PyrParseNode*)mArglist->mVarDefs) + 1 : 1;
1214 numVars = mVarlist ? nodeListLength((PyrParseNode*)mVarlist->mVarDefs) : 0;
1215
1216 numSlots = numArgs + funcVarArgs + numVars;
1217 methraw->frameSize = (numSlots + FRAMESIZE) * sizeof(PyrSlot);
1218
1219 methraw->numargs = numArgs;
1220 methraw->numvars = numVars;
1221 methraw->posargs = numArgs + funcVarArgs;
1222 methraw->numtemps = numSlots;
1223 methraw->popSize = numSlots - 1;
1224 firstKeyIndex = numArgs + funcVarArgs;
1225
1226 numArgNames = methraw->posargs;
1227
1228 if (numSlots == 1) {
1229 slotCopy(&method->argNames, &o_argnamethis);
1230 slotCopy(&method->prototypeFrame, &o_onenilarray);
1231 } else {
1232 argNames = newPyrSymbolArray(nullptr, numArgNames, obj_permanent | obj_immutable, false);
1233 argNames->size = numArgNames;
1234 SetObject(&method->argNames, argNames);
1235
1236 proto = newPyrArray(nullptr, numSlots, obj_permanent | obj_immutable, false);
1237 proto->size = numSlots;
1238 SetObject(&method->prototypeFrame, proto);
1239
1240 // declare args
1241 slotRawSymbolArray(&method->argNames)->symbols[0] = s_this;
1242 if (mArglist) {
1243 PyrSymbol** methargs;
1244 methargs = slotRawSymbolArray(&method->argNames)->symbols;
1245 vardef = mArglist->mVarDefs;
1246 for (i = 1; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1247 PyrSlot* varslot;
1248 varslot = &vardef->mVarName->mSlot;
1249 // already declared as arg?
1250 for (j = 0; j < i; ++j) {
1251 if (methargs[j] == slotRawSymbol(varslot)) {
1252 error("Argument '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
1253 slotRawSymbol(&gCompilingClass->name)->name,
1254 slotRawSymbol(&gCompilingMethod->name)->name);
1255 nodePostErrorLine((PyrParseNode*)vardef);
1256 compileErrors++;
1257 }
1258 }
1259 // put it in arglist
1260 methargs[i] = slotRawSymbol(varslot);
1261 // postfl("defarg %d '%s'\n", i, slotRawSymbol(slot)->name);
1262 /*if (slotRawSymbol(varslot)->name[0] == 'a'
1263 && slotRawSymbol(varslot)->name[1] == 'r'
1264 && slotRawSymbol(varslot)->name[2] == 'g')
1265 {
1266 post("%d %s:%s '%s'\n", i,
1267 slotRawSymbol(&gCompilingClass->name)->name,
1268 slotRawSymbol(&gCompilingMethod->name)->name,
1269 slotRawSymbol(varslot)->name);
1270 }*/
1271 }
1272 if (funcVarArgs) {
1273 PyrSlot* varslot;
1274 varslot = &mArglist->mRest->mSlot;
1275 // already declared as arg?
1276 for (j = 0; j < numArgs; ++j) {
1277 if (methargs[j] == slotRawSymbol(varslot)) {
1278 error("Argument '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
1279 slotRawSymbol(&gCompilingClass->name)->name,
1280 slotRawSymbol(&gCompilingMethod->name)->name);
1281 nodePostErrorLine((PyrParseNode*)vardef);
1282 compileErrors++;
1283 }
1284 }
1285 // put it in arglist
1286 methargs[i] = slotRawSymbol(varslot);
1287 // postfl("defrest '%s'\n", slotRawSymbol(slot)->name);
1288 }
1289 }
1290 // fill prototype args
1291 if (NotNil(&method->prototypeFrame)) {
1292 SetNil(&slotRawObject(&method->prototypeFrame)->slots[0]);
1293 }
1294 if (mArglist) {
1295 vardef = mArglist->mVarDefs;
1296 for (i = 1; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1297 PyrSlot *slot, litval;
1298 slot = slotRawObject(&method->prototypeFrame)->slots + i;
1299 // compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litval);
1300 if (vardef->hasExpr(&litval))
1301 hasVarExprs = true;
1302 *slot = litval;
1303 }
1304 if (funcVarArgs) {
1305 slotCopy(&slotRawObject(&method->prototypeFrame)->slots[numArgs], &o_emptyarray);
1306 }
1307 }
1308 }
1309
1310 if (numVars) {
1311 varNames = newPyrSymbolArray(nullptr, numVars, obj_permanent | obj_immutable, false);
1312 varNames->size = numVars;
1313 SetObject(&method->varNames, varNames);
1314 } else {
1315 SetNil(&method->varNames);
1316 }
1317
1318 // declare vars
1319 if (mVarlist) {
1320 PyrSymbol **methargs, **methvars;
1321 methargs = slotRawSymbolArray(&method->argNames)->symbols;
1322 methvars = slotRawSymbolArray(&method->varNames)->symbols;
1323 vardef = mVarlist->mVarDefs;
1324 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1325 PyrSlot* varslot;
1326 varslot = &vardef->mVarName->mSlot;
1327 // already declared as arg?
1328 for (j = 0; j < numArgNames; ++j) {
1329 if (methargs[j] == slotRawSymbol(varslot)) {
1330 error("Variable '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
1331 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1332 nodePostErrorLine((PyrParseNode*)vardef);
1333 compileErrors++;
1334 }
1335 }
1336 // already declared as var?
1337 for (j = 0; j < i; ++j) {
1338 if (methvars[j] == slotRawSymbol(varslot)) {
1339 error("Variable '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
1340 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1341 nodePostErrorLine((PyrParseNode*)vardef);
1342 compileErrors++;
1343 }
1344 }
1345 // put it in mVarlist
1346 methvars[i] = slotRawSymbol(varslot);
1347 // postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
1348 }
1349 }
1350
1351 if (mVarlist) {
1352 vardef = mVarlist->mVarDefs;
1353 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1354 PyrSlot *slot, litval;
1355 slot = slotRawObject(&method->prototypeFrame)->slots + i + numArgs + funcVarArgs;
1356 if (vardef->hasExpr(&litval))
1357 hasVarExprs = true;
1358 // compilePyrLiteralNode(vardef->mDefVal, &litval);
1359 *slot = litval;
1360 }
1361 }
1362
1363 methType = methNormal;
1364 if (hasVarExprs) {
1365 methType = methNormal;
1366 } else if (hasPrimitive) {
1367 methType = methPrimitive;
1368 /*
1369 if (getPrimitiveNumArgs(methraw->specialIndex) != numArgs) {
1370 post("warning: number of arguments for method %s:%s does not match primitive %s. %d vs %d\n",
1371 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name,
1372 getPrimitiveName(methraw->specialIndex)->name,
1373 numArgs, getPrimitiveNumArgs(methraw->specialIndex));
1374 }
1375 */
1376 } else if (slotRawSymbol(&gCompilingMethod->name) == s_doesNotUnderstand) {
1377 methType = methNormal;
1378 } else {
1379 int bodyType = mBody->mClassno;
1380 if (bodyType == pn_ReturnNode) {
1381 PyrReturnNode* rnode;
1382 PyrParseNode* xnode;
1383 int rtype;
1384 PyrSlot rslot;
1385
1386 rnode = (PyrReturnNode*)mBody;
1387 xnode = (PyrParseNode*)rnode->mExpr;
1388 if (xnode) {
1389 rtype = xnode->mClassno;
1390 if (rtype == pn_PushLitNode) { // return literal ?
1391 compilePyrLiteralNode((PyrLiteralNode*)xnode, &rslot);
1392 if (IsObj(&rslot) && slotRawObject(&rslot)->classptr == class_fundef) {
1393 methType = methNormal;
1394 } else {
1395 methType = methReturnLiteral;
1396 method->selectors = rslot;
1397 }
1398 } else if (rtype == pn_PushNameNode) {
1399 PyrSlot* rslot;
1400 rslot = &((PyrPushNameNode*)xnode)->mSlot;
1401 if (slotRawSymbol(rslot) == s_this) { // return this
1402 methType = methReturnSelf;
1403 } else {
1404 if (funcFindArg((PyrBlock*)method, slotRawSymbol(rslot), &index)) { // return arg ?
1405 // eliminate the case where its an ellipsis or keyword argument
1406 if (index < methraw->numargs) {
1407 methType = methReturnArg;
1408 methraw->specialIndex = index; // when you change sp to sp - 1
1409 // methraw->specialIndex = index - 1;
1410 }
1411 } else if (classFindInstVar(gCompilingClass, slotRawSymbol(rslot), &index)) {
1412 // return inst var
1413 methType = methReturnInstVar;
1414 methraw->specialIndex = index;
1415 }
1416 }
1417 } else if (rtype == pn_CallNode) {
1418 // need to do this for binary opcodes too..
1419 int specialIndex;
1420 PyrCallNode* cnode;
1421 PyrClass* specialClass = nullptr;
1422 cnode = (PyrCallNode*)xnode;
1423 methType = compareCallArgs(this, cnode, &specialIndex, &specialClass);
1424 if (methType != methNormal) {
1425 methraw->specialIndex = specialIndex;
1426 method->selectors = cnode->mSelector->mSlot;
1427 if (specialClass)
1428 method->constants = specialClass->name;
1429 }
1430 }
1431 } else {
1432 methType = methReturnSelf;
1433 }
1434 } else if (bodyType == pn_AssignNode && numArgs == 2) { // assign inst var ?
1435 PyrAssignNode* anode;
1436 // post("methAssignInstVar 1 %s:%s\n",
1437 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1438 anode = (PyrAssignNode*)mBody;
1439 if (anode->mNext && anode->mNext->mClassno == pn_ReturnNode
1440 && ((PyrReturnNode*)anode->mNext)->mExpr == nullptr) {
1441 // post("methAssignInstVar 2 %s:%s\n",
1442 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1443 if (classFindInstVar(gCompilingClass, slotRawSymbol(&anode->mVarName->mSlot), &index)) {
1444 methType = methAssignInstVar;
1445 methraw->specialIndex = index;
1446 // post("methAssignInstVar 3 %s:%s\n",
1447 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
1448 }
1449 }
1450 }
1451 }
1452
1453 methraw->methType = methType;
1454 // set primitive
1455 // optimize common cases
1456
1457 if (methType == methNormal || methType == methPrimitive) {
1458 PyrSlot dummy;
1459 PyrSymbol* name;
1460
1461 // compile body
1462 initByteCodes();
1463
1464 if (gCompilingClass == class_int) {
1465 // handle some special cases
1466 name = slotRawSymbol(&method->name);
1467 if (name == gSpecialSelectors[opmDo]) {
1468 compileByte(143);
1469 compileByte(0);
1470 compileByte(143);
1471 compileByte(1);
1472 } else if (name == gSpecialSelectors[opmReverseDo]) {
1473 compileByte(143);
1474 compileByte(2);
1475 compileByte(143);
1476 compileByte(3);
1477 compileByte(143);
1478 compileByte(4);
1479 } else if (name == gSpecialSelectors[opmFor]) {
1480 compileByte(143);
1481 compileByte(5);
1482 compileByte(143);
1483 compileByte(6);
1484 compileByte(143);
1485 compileByte(16);
1486 } else if (name == gSpecialSelectors[opmForBy]) {
1487 compileByte(143);
1488 compileByte(7);
1489 compileByte(143);
1490 compileByte(8);
1491 compileByte(143);
1492 compileByte(9);
1493 } else
1494 goto compile_body;
1495 } else if (gCompilingClass == class_arrayed_collection) {
1496 name = slotRawSymbol(&method->name);
1497 if (name == gSpecialSelectors[opmDo]) {
1498 compileByte(143);
1499 compileByte(10);
1500 compileByte(143);
1501 compileByte(1);
1502 } else if (name == gSpecialSelectors[opmReverseDo]) {
1503 compileByte(143);
1504 compileByte(11);
1505 compileByte(143);
1506 compileByte(12);
1507 compileByte(143);
1508 compileByte(4);
1509 } else
1510 goto compile_body;
1511 } else if (slotRawSymbol(&gCompilingClass->name) == s_dictionary) {
1512 name = slotRawSymbol(&method->name);
1513 if (name == getsym("keysValuesArrayDo")) {
1514 compileByte(143);
1515 compileByte(13);
1516 compileByte(143);
1517 compileByte(14);
1518 } else
1519 goto compile_body;
1520 } else if (gCompilingClass == class_number) {
1521 name = slotRawSymbol(&method->name);
1522 if (name == gSpecialSelectors[opmForSeries]) {
1523 compileByte(143);
1524 compileByte(29);
1525 compileByte(143);
1526 compileByte(30);
1527 compileByte(143);
1528 compileByte(31);
1529 } else
1530 goto compile_body;
1531 } else if (gCompilingClass == class_float) {
1532 // handle some special cases
1533 name = slotRawSymbol(&method->name);
1534 if (name == gSpecialSelectors[opmDo]) {
1535 compileByte(143);
1536 compileByte(17);
1537 compileByte(143);
1538 compileByte(18);
1539 } else if (name == gSpecialSelectors[opmReverseDo]) {
1540 compileByte(143);
1541 compileByte(19);
1542 compileByte(143);
1543 compileByte(20);
1544 compileByte(143);
1545 compileByte(21);
1546 } else
1547 goto compile_body;
1548 } else {
1549 compile_body:
1550 SetTailIsMethodReturn mr(false);
1551 if (mArglist) {
1552 vardef = mArglist->mVarDefs;
1553 for (i = 1; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1554 vardef->compileArg(&dummy);
1555 }
1556 }
1557 if (mVarlist) {
1558 vardef = mVarlist->mVarDefs;
1559 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
1560 vardef->compile(&dummy);
1561 }
1562 }
1563 COMPILENODE(mBody, &dummy, true);
1564 }
1565 installByteCodes((PyrBlock*)method);
1566 }
1567
1568 if (!oldmethod) {
1569 addMethod(gCompilingClass, method);
1570 }
1571
1572 gCompilingMethod = nullptr;
1573 gCompilingBlock = nullptr;
1574 gPartiallyAppliedFunction = nullptr;
1575
1576 // postfl("<-method '%s'\n", slotRawSymbol(&mMethodName->mSlot)->name);
1577 }
1578
newPyrArgListNode(PyrVarDefNode * varDefs,PyrSlotNode * rest)1579 PyrArgListNode* newPyrArgListNode(PyrVarDefNode* varDefs, PyrSlotNode* rest) {
1580 PyrArgListNode* node = ALLOCNODE(PyrArgListNode);
1581 node->mVarDefs = varDefs;
1582 node->mRest = rest;
1583 return node;
1584 }
1585
compile(PyrSlot * result)1586 void PyrArgListNode::compile(PyrSlot* result) {
1587 error("compilePyrArgListNode: shouldn't get here.\n");
1588 compileErrors++;
1589 }
1590
1591
newPyrVarListNode(PyrVarDefNode * vardefs,int flags)1592 PyrVarListNode* newPyrVarListNode(PyrVarDefNode* vardefs, int flags) {
1593 PyrVarListNode* node = ALLOCNODE(PyrVarListNode);
1594 node->mVarDefs = vardefs;
1595 node->mFlags = flags;
1596 return node;
1597 }
1598
compile(PyrSlot * result)1599 void PyrVarListNode::compile(PyrSlot* result) {
1600 error("compilePyrVarListNode: shouldn't get here.\n");
1601 compileErrors++;
1602 }
1603
newPyrVarDefNode(PyrSlotNode * varName,PyrParseNode * defVal,int flags)1604 PyrVarDefNode* newPyrVarDefNode(PyrSlotNode* varName, PyrParseNode* defVal, int flags) {
1605 PyrVarDefNode* node = ALLOCNODE(PyrVarDefNode);
1606 node->mVarName = varName;
1607 node->mDefVal = defVal;
1608 node->mFlags = flags;
1609 node->mDrop = true;
1610 return node;
1611 }
1612
hasExpr(PyrSlot * result)1613 bool PyrVarDefNode::hasExpr(PyrSlot* result) {
1614 if (result)
1615 SetNil(result);
1616 if (!mDefVal)
1617 return false;
1618 if (mDefVal->mClassno != pn_PushLitNode && mDefVal->mClassno != pn_LiteralNode) {
1619 // post("hasExpr A %s:%s %s %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1620 // slotRawSymbol(&gCompilingMethod->name)->name, mVarName->slotRawSymbol(&mSlot)->name, mDefVal->mClassno);
1621 return true;
1622 }
1623 PyrPushLitNode* node = (PyrPushLitNode*)mDefVal;
1624
1625 if (IsPtr(&node->mSlot)) {
1626 PyrParseNode* litnode = (PyrParseNode*)slotRawPtr(&node->mSlot);
1627 if (litnode) {
1628 if (litnode->mClassno == pn_BlockNode) {
1629 // post("hasExpr B %s:%s %s %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1630 // slotRawSymbol(&gCompilingMethod->name)->name, mVarName->slotRawSymbol(&mSlot)->name, node->mClassno);
1631 return true;
1632 } else {
1633 if (result)
1634 node->compileLiteral(result);
1635 }
1636 }
1637 } else if (result)
1638 *result = node->mSlot;
1639 if (node->mParens)
1640 return true;
1641 return false;
1642 }
1643
compile(PyrSlot * result)1644 void PyrVarDefNode::compile(PyrSlot* result) {
1645 if (hasExpr(nullptr)) {
1646 COMPILENODE(mDefVal, result, false);
1647 compileAssignVar((PyrParseNode*)this, slotRawSymbol(&mVarName->mSlot), mDrop);
1648 }
1649
1650 // error("compilePyrVarDefNode: shouldn't get here.\n");
1651 // compileErrors++;
1652 }
1653
compileArg(PyrSlot * result)1654 void PyrVarDefNode::compileArg(PyrSlot* result) {
1655 if (hasExpr(nullptr)) {
1656 ByteCodes trueByteCodes;
1657
1658 compilePushVar((PyrParseNode*)this, slotRawSymbol(&mVarName->mSlot));
1659
1660 mDrop = false;
1661 trueByteCodes = compileBodyWithGoto(this, 0, true);
1662 int jumplen = byteCodeLength(trueByteCodes);
1663
1664 compileByte(143); // special opcodes
1665 compileByte(26);
1666 compileByte((jumplen >> 8) & 0xFF);
1667 compileByte(jumplen & 0xFF);
1668 compileAndFreeByteCodes(trueByteCodes);
1669 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
1670 }
1671
1672 // error("compilePyrVarDefNode: shouldn't get here.\n");
1673 // compileErrors++;
1674 }
1675
1676
newPyrCallNode(PyrSlotNode * selector,PyrParseNode * arglist,PyrParseNode * keyarglist,PyrParseNode * blocklist)1677 PyrCallNode* newPyrCallNode(PyrSlotNode* selector, PyrParseNode* arglist, PyrParseNode* keyarglist,
1678 PyrParseNode* blocklist) {
1679 PyrCallNode* node = ALLOCNODE(PyrCallNode);
1680 node->mSelector = selector;
1681
1682 arglist = linkNextNode(arglist, blocklist);
1683
1684 node->mArglist = arglist;
1685 node->mKeyarglist = keyarglist;
1686 return node;
1687 }
1688
isPartialApplication()1689 int PyrCallNode::isPartialApplication() {
1690 int sum = 0;
1691 PyrParseNode* argnode = mArglist;
1692 for (; argnode; argnode = argnode->mNext) {
1693 if (argnode->mClassno == pn_CurryArgNode) {
1694 ((PyrCurryArgNode*)argnode)->mArgNum = sum;
1695 sum++;
1696 }
1697 }
1698
1699 PyrParseNode* keynode = mKeyarglist;
1700 for (; keynode; keynode = keynode->mNext) {
1701 if (keynode->mClassno == pn_CurryArgNode) {
1702 ((PyrCurryArgNode*)keynode)->mArgNum = sum;
1703 sum++;
1704 }
1705 }
1706 return sum;
1707 }
1708
compilePartialApplication(int numCurryArgs,PyrSlot * result)1709 void PyrCallNodeBase::compilePartialApplication(int numCurryArgs, PyrSlot* result) {
1710 // create a function
1711 // compile the call
1712
1713 ByteCodes savedBytes = saveByteCodeArray();
1714
1715 int flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
1716 PyrBlock* block = newPyrBlock(flags);
1717
1718 PyrSlot blockSlot;
1719 SetObject(&blockSlot, block);
1720
1721 int prevFunctionHighestExternalRef = gFunctionHighestExternalRef;
1722 bool prevFunctionCantBeClosed = gFunctionCantBeClosed;
1723 gFunctionHighestExternalRef = 0;
1724 gFunctionCantBeClosed = false;
1725
1726 PyrClass* prevClass = gCompilingClass;
1727 PyrBlock* prevBlock = gCompilingBlock;
1728 gCompilingBlock = block;
1729
1730 PyrBlock* prevPartiallyAppliedFunction = gPartiallyAppliedFunction;
1731 gPartiallyAppliedFunction = block;
1732
1733 PyrMethodRaw* methraw = METHRAW(block);
1734 methraw->unused1 = 0;
1735 methraw->unused2 = 0;
1736
1737 methraw->needsHeapContext = 0;
1738
1739 SetObject(&block->contextDef, prevBlock);
1740 ////
1741 methraw->varargs = 0;
1742
1743 methraw->frameSize = (numCurryArgs + FRAMESIZE) * sizeof(PyrSlot);
1744 PyrObject* proto = newPyrArray(compileGC(), numCurryArgs, flags, false);
1745 proto->size = numCurryArgs;
1746 SetObject(&block->prototypeFrame, proto);
1747
1748 PyrSymbolArray* argNames = newPyrSymbolArray(compileGC(), numCurryArgs, flags, false);
1749 argNames->size = numCurryArgs;
1750 SetObject(&block->argNames, argNames);
1751
1752 SetNil(&block->varNames);
1753
1754 methraw->numargs = numCurryArgs;
1755 methraw->numvars = 0;
1756 methraw->posargs = numCurryArgs;
1757 methraw->numtemps = numCurryArgs;
1758 methraw->popSize = numCurryArgs;
1759 methraw->methType = methBlock;
1760
1761 {
1762 PyrSymbol* s_empty = getsym("_");
1763 PyrSymbol** blockargs = slotRawSymbolArray(&block->argNames)->symbols;
1764 for (int i = 0; i < numCurryArgs; ++i) {
1765 // put it in mArglist
1766 blockargs[i] = s_empty;
1767 SetNil(proto->slots + i);
1768 }
1769 }
1770
1771 initByteCodes();
1772 {
1773 SetTailBranch branch(true);
1774 SetTailIsMethodReturn mr(false);
1775 PyrSlot body;
1776 compileCall(&body);
1777 }
1778 compileOpcode(opSpecialOpcode, opcFunctionReturn);
1779 installByteCodes(block);
1780
1781 gCompilingBlock = prevBlock;
1782 gPartiallyAppliedFunction = prevPartiallyAppliedFunction;
1783
1784 restoreByteCodeArray(savedBytes);
1785 int index = conjureLiteralSlotIndex(this, gCompilingBlock, &blockSlot);
1786 compileOpcode(opExtended, opPushLiteral);
1787 compileByte(index);
1788
1789 if (!gFunctionCantBeClosed && gFunctionHighestExternalRef == 0) {
1790 SetNil(&block->contextDef);
1791 } else {
1792 METHRAW(prevBlock)->needsHeapContext = 1;
1793 }
1794
1795 gCompilingBlock = prevBlock;
1796 gCompilingClass = prevClass;
1797 gPartiallyAppliedFunction = prevPartiallyAppliedFunction;
1798 gFunctionCantBeClosed = gFunctionCantBeClosed || prevFunctionCantBeClosed;
1799 gFunctionHighestExternalRef = sc_max(gFunctionHighestExternalRef - 1, prevFunctionHighestExternalRef);
1800 }
1801
compile(PyrSlot * result)1802 void PyrCallNodeBase::compile(PyrSlot* result) {
1803 int numCurryArgs = isPartialApplication();
1804 if (numCurryArgs) {
1805 compilePartialApplication(numCurryArgs, result);
1806 } else {
1807 compileCall(result);
1808 }
1809 }
1810
isSeries(PyrParseNode * node,PyrParseNode ** args)1811 bool isSeries(PyrParseNode* node, PyrParseNode** args) {
1812 if (node->mClassno != pn_CallNode)
1813 return false;
1814 PyrCallNode* callnode = (PyrCallNode*)node;
1815 if (slotRawSymbol(&callnode->mSelector->mSlot) != s_series)
1816 return false;
1817 if (callnode->mKeyarglist)
1818 return false;
1819 *args = callnode->mArglist;
1820 return true;
1821 }
1822
compileCall(PyrSlot * result)1823 void PyrCallNode::compileCall(PyrSlot* result) {
1824 int index, selType;
1825 PyrSlot dummy;
1826 bool varFound;
1827 PyrParseNode* argnode2;
1828
1829 // postfl("compilePyrCallNode\n");
1830 PyrParseNode* argnode = mArglist;
1831 PyrParseNode* keynode = mKeyarglist;
1832 int numArgs = nodeListLength(argnode);
1833 int numKeyArgs = nodeListLength(keynode);
1834 int isSuper = isSuperObjNode(argnode);
1835 int numBlockArgs = METHRAW(gCompilingBlock)->numargs;
1836
1837 slotRawSymbol(&mSelector->mSlot)->flags |= sym_Called;
1838 index = conjureSelectorIndex((PyrParseNode*)mSelector, gCompilingBlock, isSuper, slotRawSymbol(&mSelector->mSlot),
1839 &selType);
1840
1841 if (numKeyArgs > 0 || (numArgs > 15 && !(selType == selSwitch || selType == selCase))) {
1842 for (; argnode; argnode = argnode->mNext) {
1843 COMPILENODE(argnode, &dummy, false);
1844 }
1845 for (; keynode; keynode = keynode->mNext) {
1846 COMPILENODE(keynode, &dummy, false);
1847 }
1848 if (isSuper) {
1849 compileTail();
1850 compileByte(opSendSuper);
1851 compileByte(numArgs + 2 * numKeyArgs);
1852 compileByte(numKeyArgs);
1853 compileByte(index);
1854 } else {
1855 switch (selType) {
1856 case selNormal:
1857 compileTail();
1858 compileByte(opSendMsg);
1859 compileByte(numArgs + 2 * numKeyArgs);
1860 compileByte(numKeyArgs);
1861 compileByte(index);
1862 break;
1863 case selSpecial:
1864 compileTail();
1865 compileByte(opSendSpecialMsg);
1866 compileByte(numArgs + 2 * numKeyArgs);
1867 compileByte(numKeyArgs);
1868 compileByte(index);
1869 break;
1870 case selUnary:
1871 case selBinary:
1872 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector, gCompilingBlock, &mSelector->mSlot);
1873 // fall through
1874 default:
1875 compileTail();
1876 compileByte(opSendMsg);
1877 compileByte(numArgs + 2 * numKeyArgs);
1878 compileByte(numKeyArgs);
1879 compileByte(index);
1880 break;
1881 }
1882 }
1883 } else if (isSuper) {
1884 if (numArgs == 1) {
1885 // pushes this as well, don't compile arg
1886 gFunctionCantBeClosed = true;
1887 compileTail();
1888 compileOpcode(opSendSuper, numArgs);
1889 compileByte(index);
1890 } else {
1891 for (; argnode; argnode = argnode->mNext) {
1892 COMPILENODE(argnode, &dummy, false);
1893 }
1894 compileTail();
1895 compileOpcode(opSendSuper, numArgs);
1896 compileByte(index);
1897 }
1898 } else {
1899 PyrSymbol* varname;
1900 if (argnode->mClassno == pn_PushNameNode) {
1901 varname = slotRawSymbol(&((PyrPushNameNode*)argnode)->mSlot);
1902 } else {
1903 varname = nullptr;
1904 }
1905 if (varname == s_this) {
1906 gFunctionCantBeClosed = true;
1907 }
1908 switch (selType) {
1909 case selNormal:
1910 if (numArgs == 1 && varname == s_this) {
1911 compileTail();
1912 compileOpcode(opSendMsg, 0);
1913 compileByte(index);
1914 //} else if (numArgs>1 && numArgs == numBlockArgs) {
1915 } else if (numArgs > 1 && numArgs == numBlockArgs) {
1916 // try for multiple push optimization
1917 int code;
1918 code = checkPushAllArgs(argnode, numArgs);
1919 if (code == push_Normal)
1920 goto normal;
1921 else if (code == push_AllArgs) {
1922 compileTail();
1923 compileByte(137); // push all args, send msg
1924 compileByte(index);
1925 // post("137 pushAllArgs %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
1926 // slotRawSymbol(&gCompilingMethod->name)->name);
1927 } else if (code == push_AllButFirstArg) {
1928 COMPILENODE(argnode, &dummy, false);
1929 compileTail();
1930 compileByte(138); // push all but first arg, send msg
1931 compileByte(index);
1932 // post("138 pushAllButFirstArg %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
1933 // slotRawSymbol(&gCompilingMethod->name)->name);
1934 } else
1935 goto normal;
1936 } else if (numArgs > 2 && numArgs == numBlockArgs + 1) {
1937 int code;
1938 code = checkPushAllButFirstTwoArgs(argnode, numBlockArgs);
1939 if (code == push_Normal)
1940 goto normal;
1941 else if (code == push_AllButFirstArg2) {
1942 COMPILENODE(argnode, &dummy, false);
1943 COMPILENODE(argnode->mNext, &dummy, false);
1944 compileTail();
1945 compileByte(141); // one arg pushed, push all but first arg, send msg
1946 compileByte(index);
1947 // post("141 pushAllButFirstArg2 %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
1948 // slotRawSymbol(&gCompilingMethod->name)->name);
1949 } else
1950 goto normal;
1951
1952 } else {
1953 normal:
1954 for (; argnode; argnode = argnode->mNext) {
1955 COMPILENODE(argnode, &dummy, false);
1956 }
1957 compileTail();
1958 compileOpcode(opSendMsg, numArgs);
1959 compileByte(index);
1960 }
1961 break;
1962 case selSpecial:
1963 if (numArgs == 1) {
1964 if (varname == s_this) {
1965 compileTail();
1966 compileOpcode(opSendSpecialMsg, 0);
1967 compileByte(index);
1968 } else if (varname) {
1969 PyrClass* classobj;
1970 PyrBlock* tempFunc;
1971 int varType, varLevel, varIndex;
1972 classobj = gCompilingClass;
1973 varFound =
1974 findVarName(gCompilingBlock, &classobj, varname, &varType, &varLevel, &varIndex, &tempFunc);
1975 if (varFound && varType == varInst) {
1976 // post("136 pushInstVar(sp) %s:%s '%s' %d %d\n", slotRawSymbol(&gCompilingClass->name)->name,
1977 // slotRawSymbol(&gCompilingMethod->name)->name, varname->name, varIndex, index);
1978 compileTail();
1979 compileByte(136);
1980 compileByte(varIndex);
1981 compileByte(index);
1982 } else
1983 goto special;
1984 } else
1985 goto special;
1986 } else if (index == opmDo && isSeries(argnode, &argnode)) {
1987 index = opmForSeries;
1988 mArglist = linkNextNode(argnode, mArglist->mNext);
1989 numArgs = nodeListLength(mArglist);
1990 goto special;
1991 } else if (numArgs > 1 && numArgs == numBlockArgs) {
1992 //} else if (numArgs>1 && numArgs == numBlockArgs) {
1993 // try for multiple push optimization
1994 int code;
1995 code = checkPushAllArgs(argnode, numArgs);
1996 if (code == push_Normal)
1997 goto special;
1998 else if (code == push_AllArgs) {
1999 compileTail();
2000 compileByte(139); // push all args, send special msg
2001 compileByte(index);
2002 // post("139 pushAllArgs(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2003 // slotRawSymbol(&gCompilingMethod->name)->name);
2004 } else if (code == push_AllButFirstArg) {
2005 COMPILENODE(argnode, &dummy, false);
2006 compileTail();
2007 compileByte(140); // push all but first arg, send special msg
2008 compileByte(index);
2009 // post("140 pushAllButFirstArg(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2010 // slotRawSymbol(&gCompilingMethod->name)->name);
2011 } else
2012 goto special;
2013 } else if (numArgs > 2 && numArgs == numBlockArgs + 1) {
2014 int code;
2015 code = checkPushAllButFirstTwoArgs(argnode, numBlockArgs);
2016 if (code == push_Normal)
2017 goto special;
2018 else if (code == push_AllButFirstArg2) {
2019 COMPILENODE(argnode, &dummy, false);
2020 COMPILENODE(argnode->mNext, &dummy, false);
2021 compileTail();
2022 compileByte(142); // one arg pushed, push all but first arg, send msg
2023 compileByte(index);
2024 // post("142 pushAllButFirstArg2(sp) %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
2025 // slotRawSymbol(&gCompilingMethod->name)->name);
2026 } else
2027 goto special;
2028 } else {
2029 int i;
2030 special:
2031 for (i = 0; argnode; argnode = argnode->mNext, i++) {
2032 COMPILENODE(argnode, &dummy, false);
2033 }
2034 compileTail();
2035 compileOpcode(opSendSpecialMsg, numArgs);
2036 compileByte(index);
2037 }
2038 break;
2039 case selUnary:
2040 if (numArgs != 1) {
2041 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector, gCompilingBlock, &mSelector->mSlot);
2042 goto defaultCase;
2043 }
2044 for (; argnode; argnode = argnode->mNext) {
2045 COMPILENODE(argnode, &dummy, false);
2046 }
2047 compileTail();
2048 compileOpcode(opSendSpecialUnaryArithMsg, index);
2049 break;
2050 case selBinary:
2051 if (numArgs != 2) {
2052 index = conjureLiteralSlotIndex((PyrParseNode*)mSelector, gCompilingBlock, &mSelector->mSlot);
2053 goto defaultCase;
2054 }
2055 // for (; argnode; argnode = argnode->mNext) {
2056 // COMPILENODE(argnode, &dummy, false);
2057 //}
2058 argnode2 = argnode->mNext;
2059 if (index == opAdd && argnode2->mClassno == pn_PushLitNode && IsInt(&((PyrPushLitNode*)argnode2)->mSlot)
2060 && slotRawInt(&((PyrPushLitNode*)argnode2)->mSlot) == 1) {
2061 COMPILENODE(argnode, &dummy, false);
2062 compileOpcode(opPushSpecialValue, opsvPlusOne);
2063 } else if (index == opSub && argnode2->mClassno == pn_PushLitNode
2064 && IsInt(&((PyrPushLitNode*)argnode2)->mSlot)
2065 && slotRawInt(&((PyrPushLitNode*)argnode2)->mSlot) == 1) {
2066 COMPILENODE(argnode, &dummy, false);
2067 compileOpcode(opPushSpecialValue, opsvMinusOne);
2068 } else {
2069 COMPILENODE(argnode, &dummy, false);
2070 COMPILENODE(argnode->mNext, &dummy, false);
2071 compileTail();
2072 compileOpcode(opSendSpecialBinaryArithMsg, index);
2073 }
2074 break;
2075 case selIf:
2076 compileAnyIfMsg(this);
2077 break;
2078 case selCase:
2079 compileCaseMsg(this);
2080 break;
2081 case selSwitch:
2082 compileSwitchMsg(this);
2083 break;
2084 case selWhile:
2085 compileWhileMsg(this);
2086 break;
2087 case selLoop:
2088 compileLoopMsg(this);
2089 break;
2090 case selAnd:
2091 if (numArgs == 2)
2092 compileAndMsg(argnode, argnode->mNext);
2093 else
2094 goto special;
2095 break;
2096 case selOr:
2097 if (numArgs == 2)
2098 compileOrMsg(argnode, argnode->mNext);
2099 else
2100 goto special;
2101 break;
2102 case selQuestionMark:
2103 if (numArgs == 2)
2104 compileQMsg(argnode, argnode->mNext);
2105 break;
2106 case selDoubleQuestionMark:
2107 if (numArgs == 2)
2108 compileQQMsg(argnode, argnode->mNext);
2109 break;
2110 case selExclamationQuestionMark:
2111 if (numArgs == 2)
2112 compileXQMsg(argnode, argnode->mNext);
2113 break;
2114 default:
2115 defaultCase:
2116 if (numArgs == 1 && varname == s_this) {
2117 compileTail();
2118 compileOpcode(opSendMsg, 0);
2119 compileByte(index);
2120 } else {
2121 for (; argnode; argnode = argnode->mNext) {
2122 COMPILENODE(argnode, &dummy, false);
2123 }
2124 compileTail();
2125 compileOpcode(opSendMsg, numArgs);
2126 compileByte(index);
2127 }
2128 break;
2129 }
2130 }
2131 }
2132
compileSubExpression(PyrPushLitNode * litnode,bool onTailBranch)2133 ByteCodes compileSubExpression(PyrPushLitNode* litnode, bool onTailBranch) {
2134 return compileSubExpressionWithGoto(litnode, 0, onTailBranch);
2135 }
2136
compileSubExpressionWithGoto(PyrPushLitNode * litnode,int branchLen,bool onTailBranch)2137 ByteCodes compileSubExpressionWithGoto(PyrPushLitNode* litnode, int branchLen, bool onTailBranch) {
2138 PyrBlockNode* bnode = (PyrBlockNode*)slotRawPtr(&litnode->mSlot);
2139 return compileBodyWithGoto(bnode->mBody, branchLen, onTailBranch);
2140 }
2141
compileBodyWithGoto(PyrParseNode * body,int branchLen,bool onTailBranch)2142 ByteCodes compileBodyWithGoto(PyrParseNode* body, int branchLen, bool onTailBranch) {
2143 ByteCodes currentByteCodes, subExprByteCodes;
2144 PyrSlot dummy;
2145
2146 PyrBlock* prevPartiallyAppliedFunction = gPartiallyAppliedFunction;
2147 gPartiallyAppliedFunction = nullptr;
2148
2149 currentByteCodes = saveByteCodeArray();
2150
2151 COMPILENODE(body, &dummy, onTailBranch);
2152 if (branchLen) {
2153 if (!byteCodeLength(gCompilingByteCodes)) {
2154 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2155 }
2156 compileJump(opcJumpFwd, branchLen);
2157 }
2158
2159 subExprByteCodes = getByteCodes();
2160 restoreByteCodeArray(currentByteCodes);
2161
2162 gPartiallyAppliedFunction = prevPartiallyAppliedFunction;
2163
2164 return subExprByteCodes;
2165 }
2166
2167 #if 0
2168 ByteCodes compileDefaultValue(int litIndex, int realExprLen)
2169 {
2170 ByteCodes currentByteCodes, defaultByteCodes;
2171
2172 currentByteCodes = saveByteCodeArray();
2173
2174 compileOpcode(opPushSpecialValue, litIndex);
2175 compileJump(realExprLen, unconditionalJump);
2176
2177 defaultByteCodes = getByteCodes();
2178 restoreByteCodeArray(currentByteCodes);
2179
2180 return (defaultByteCodes);
2181 }
2182 #endif
2183
isAnInlineableBlock(PyrParseNode * node)2184 bool isAnInlineableBlock(PyrParseNode* node) {
2185 bool res = false;
2186 if (node->mClassno == pn_PushLitNode) {
2187 PyrPushLitNode* anode;
2188 PyrBlockNode* bnode;
2189 anode = (PyrPushLitNode*)node;
2190 if (IsPtr(&anode->mSlot) && (bnode = (PyrBlockNode*)(slotRawPtr(&anode->mSlot)))->mClassno == pn_BlockNode) {
2191 if (bnode->mArglist || bnode->mVarlist) {
2192 if (SC_LanguageConfig::getPostInlineWarnings()) {
2193 post("WARNING: FunctionDef contains variable declarations and so"
2194 " will not be inlined.\n");
2195 if (bnode->mArglist)
2196 nodePostErrorLine((PyrParseNode*)bnode->mArglist);
2197 else
2198 nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2199 }
2200 } else
2201 res = true;
2202 }
2203 }
2204 return res;
2205 }
2206
isAnInlineableAtomicLiteralBlock(PyrParseNode * node)2207 bool isAnInlineableAtomicLiteralBlock(PyrParseNode* node) {
2208 bool res = false;
2209 if (node->mClassno == pn_PushLitNode) {
2210 PyrPushLitNode* anode;
2211 PyrBlockNode* bnode;
2212 anode = (PyrPushLitNode*)node;
2213 if (IsPtr(&anode->mSlot) && (bnode = (PyrBlockNode*)(slotRawPtr(&anode->mSlot)))->mClassno == pn_BlockNode) {
2214 if (bnode->mArglist || bnode->mVarlist) {
2215 if (SC_LanguageConfig::getPostInlineWarnings()) {
2216 post("WARNING: FunctionDef contains variable declarations and so"
2217 " will not be inlined.\n");
2218 if (bnode->mArglist)
2219 nodePostErrorLine((PyrParseNode*)bnode->mArglist);
2220 else
2221 nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2222 }
2223 } else {
2224 if (bnode->mBody->mClassno == pn_DropNode
2225 && ((PyrDropNode*)bnode->mBody)->mExpr2->mClassno == pn_BlockReturnNode)
2226 res = isAtomicLiteral(((PyrDropNode*)bnode->mBody)->mExpr1);
2227 else
2228 res = false;
2229 }
2230 }
2231 }
2232 return res;
2233 }
2234
isAtomicLiteral(PyrParseNode * node)2235 bool isAtomicLiteral(PyrParseNode* node) {
2236 bool res = false;
2237 if (node->mClassno == pn_PushLitNode) {
2238 PyrPushLitNode* anode;
2239 anode = (PyrPushLitNode*)node;
2240 if (NotObj(&anode->mSlot) && !IsPtr(&anode->mSlot))
2241 res = true;
2242 }
2243 return res;
2244 }
2245
isWhileTrue(PyrParseNode * node)2246 bool isWhileTrue(PyrParseNode* node) {
2247 bool res = false;
2248 if (node->mClassno == pn_PushLitNode) {
2249 PyrPushLitNode* anode;
2250 PyrBlockNode* bnode;
2251 anode = (PyrPushLitNode*)node;
2252 if (IsPtr(&anode->mSlot) && (bnode = (PyrBlockNode*)(slotRawPtr(&anode->mSlot)))->mClassno == pn_BlockNode) {
2253 if (bnode->mArglist || bnode->mVarlist) {
2254 /*
2255 post("WARNING: FunctionDef contains variable declarations and so"
2256 " will not be inlined.\n");
2257 if (bnode->mArglist) nodePostErrorLine((PyrParseNode*)bnode->mArglist);
2258 else nodePostErrorLine((PyrParseNode*)bnode->mVarlist);
2259 */
2260 } else {
2261 if (bnode->mBody->mClassno == pn_PushLitNode && IsTrue(&((PyrPushLitNode*)bnode->mBody)->mSlot)) {
2262 res = true;
2263 }
2264 }
2265 } else if (IsTrue(&anode->mSlot)) {
2266 res = true;
2267 }
2268 }
2269 return res;
2270 }
2271
compileAndMsg(PyrParseNode * arg1,PyrParseNode * arg2)2272 void compileAndMsg(PyrParseNode* arg1, PyrParseNode* arg2) {
2273 PyrSlot dummy;
2274 ByteCodes trueByteCodes;
2275
2276 COMPILENODE(arg1, &dummy, false);
2277 if (isAnInlineableBlock(arg2)) {
2278 trueByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2279
2280 compileJump(opcJumpIfFalsePushFalse, byteCodeLength(trueByteCodes));
2281 compileAndFreeByteCodes(trueByteCodes);
2282 } else {
2283 COMPILENODE(arg2, &dummy, false);
2284 compileTail();
2285 compileOpcode(opSendSpecialMsg, 2);
2286 compileByte(opmAnd);
2287 }
2288 }
2289
compileOrMsg(PyrParseNode * arg1,PyrParseNode * arg2)2290 void compileOrMsg(PyrParseNode* arg1, PyrParseNode* arg2) {
2291 PyrSlot dummy;
2292 ByteCodes falseByteCodes;
2293
2294 COMPILENODE(arg1, &dummy, false);
2295 if (isAnInlineableBlock(arg2)) {
2296 falseByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2297
2298 compileJump(opcJumpIfTruePushTrue, byteCodeLength(falseByteCodes));
2299 compileAndFreeByteCodes(falseByteCodes);
2300 } else {
2301 COMPILENODE(arg2, &dummy, false);
2302 compileTail();
2303 compileOpcode(opSendSpecialMsg, 2);
2304 compileByte(opmOr);
2305 }
2306 }
2307
compileQMsg(PyrParseNode * arg1,PyrParseNode * arg2)2308 void compileQMsg(PyrParseNode* arg1, PyrParseNode* arg2) {
2309 // question mark.
2310 PyrSlot dummy;
2311
2312 COMPILENODE(arg1, &dummy, false);
2313 COMPILENODE(arg2, &dummy, false);
2314 compileByte(143); // special opcodes
2315 compileByte(22); // ??
2316 }
2317
compileQQMsg(PyrParseNode * arg1,PyrParseNode * arg2)2318 void compileQQMsg(PyrParseNode* arg1, PyrParseNode* arg2) {
2319 // double question mark. ?? {|obj| ^if (this.notNil, this, func) }
2320 PyrSlot dummy;
2321
2322 COMPILENODE(arg1, &dummy, false);
2323 if (isAnInlineableBlock(arg2)) {
2324 ByteCodes nilByteCodes;
2325 nilByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2326
2327 int jumplen = byteCodeLength(nilByteCodes);
2328 compileByte(143); // special opcodes
2329 compileByte(23); // ??
2330 compileByte((jumplen >> 8) & 0xFF);
2331 compileByte(jumplen & 0xFF);
2332 compileAndFreeByteCodes(nilByteCodes);
2333 } else {
2334 COMPILENODE(arg2, &dummy, false);
2335 compileTail();
2336 compileOpcode(opSendSpecialMsg, 2);
2337 compileByte(opmDoubleQuestionMark);
2338 }
2339 }
2340
compileXQMsg(PyrParseNode * arg1,PyrParseNode * arg2)2341 void compileXQMsg(PyrParseNode* arg1, PyrParseNode* arg2) {
2342 // double question mark. !? {|obj| ^if (this.isNil, this, func) }
2343 PyrSlot dummy;
2344
2345 COMPILENODE(arg1, &dummy, false);
2346 if (isAnInlineableBlock(arg2)) {
2347 ByteCodes nilByteCodes;
2348 nilByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2349
2350 int jumplen = byteCodeLength(nilByteCodes);
2351 compileByte(143); // special opcodes
2352 compileByte(27); // !?
2353 compileByte((jumplen >> 8) & 0xFF);
2354 compileByte(jumplen & 0xFF);
2355 compileAndFreeByteCodes(nilByteCodes);
2356 } else {
2357 COMPILENODE(arg2, &dummy, false);
2358 compileTail();
2359 compileOpcode(opSendSpecialMsg, 2);
2360 compileByte(opmExclamationQuestionMark);
2361 }
2362 }
2363
compileAnyIfMsg(PyrCallNodeBase2 * node)2364 void compileAnyIfMsg(PyrCallNodeBase2* node) {
2365 PyrParseNode* arg1 = node->mArglist;
2366
2367 if (arg1->mClassno == pn_CallNode) {
2368 PyrCallNode* callNode = (PyrCallNode*)arg1;
2369 int numCallArgs = nodeListLength(callNode->mArglist);
2370 int numCallKeyArgs = nodeListLength(callNode->mKeyarglist);
2371 if (numCallArgs == 1 && numCallKeyArgs == 0) {
2372 if (slotRawSymbol(&callNode->mSelector->mSlot) == gSpecialUnarySelectors[opIsNil]) {
2373 compileIfNilMsg(node, true);
2374 return;
2375 } else if (slotRawSymbol(&callNode->mSelector->mSlot) == gSpecialUnarySelectors[opNotNil]) {
2376 compileIfNilMsg(node, false);
2377 return;
2378 }
2379 }
2380 }
2381 compileIfMsg(node);
2382 }
2383
compileIfMsg(PyrCallNodeBase2 * node)2384 void compileIfMsg(PyrCallNodeBase2* node) {
2385 PyrSlot dummy;
2386 ByteCodes trueByteCodes, falseByteCodes;
2387
2388 int numArgs = nodeListLength(node->mArglist);
2389 PyrParseNode* arg1 = node->mArglist;
2390 PyrParseNode *arg2, *arg3;
2391
2392 if (numArgs == 2) {
2393 arg2 = arg1->mNext;
2394
2395 if (isAnInlineableBlock(arg2)) {
2396 COMPILENODE(arg1, &dummy, false);
2397
2398 trueByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2399 if (byteCodeLength(trueByteCodes)) {
2400 compileJump(opcJumpIfFalsePushNil, byteCodeLength(trueByteCodes));
2401 compileAndFreeByteCodes(trueByteCodes);
2402 } else {
2403 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2404 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2405 }
2406 } else
2407 goto unoptimized;
2408 } else if (numArgs == 3) {
2409 arg2 = arg1->mNext;
2410 arg3 = arg2->mNext;
2411 if (isAnInlineableBlock(arg2) && isAnInlineableBlock(arg3)) {
2412 COMPILENODE(arg1, &dummy, false);
2413 falseByteCodes = compileSubExpression((PyrPushLitNode*)arg3, true);
2414 trueByteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)arg2, byteCodeLength(falseByteCodes), true);
2415 if (byteCodeLength(falseByteCodes)) {
2416 compileJump(opcJumpIfFalse, byteCodeLength(trueByteCodes));
2417 compileAndFreeByteCodes(trueByteCodes);
2418 compileAndFreeByteCodes(falseByteCodes);
2419 } else if (byteCodeLength(trueByteCodes)) {
2420 compileJump(opcJumpIfFalsePushNil, byteCodeLength(trueByteCodes));
2421 compileAndFreeByteCodes(trueByteCodes);
2422 } else {
2423 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2424 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2425 }
2426 } else
2427 goto unoptimized;
2428 } else {
2429 unoptimized:
2430 for (; arg1; arg1 = arg1->mNext) {
2431 COMPILENODE(arg1, &dummy, false);
2432 }
2433 compileTail();
2434 compileOpcode(opSendSpecialMsg, numArgs);
2435 compileByte(opmIf);
2436 }
2437 }
2438
compileIfNilMsg(PyrCallNodeBase2 * node,bool flag)2439 void compileIfNilMsg(PyrCallNodeBase2* node, bool flag) {
2440 PyrSlot dummy;
2441 ByteCodes trueByteCodes, falseByteCodes;
2442 PyrParseNode *arg2, *arg3;
2443
2444 int numArgs = nodeListLength(node->mArglist);
2445 PyrParseNode* arg1 = node->mArglist;
2446
2447 if (numArgs < 2) {
2448 COMPILENODE(arg1, &dummy, false);
2449 compileTail();
2450 compileOpcode(opSendSpecialMsg, numArgs);
2451 compileByte(opmIf);
2452 } else if (numArgs == 2) {
2453 arg2 = arg1->mNext;
2454 if (isAnInlineableBlock(arg2)) {
2455 PyrCallNode* callNode = (PyrCallNode*)arg1;
2456 COMPILENODE(callNode->mArglist, &dummy, false);
2457
2458 trueByteCodes = compileSubExpression((PyrPushLitNode*)arg2, true);
2459 int jumplen = byteCodeLength(trueByteCodes);
2460 if (jumplen) {
2461 compileByte(143); // special opcodes
2462 compileByte(flag ? 26 : 27);
2463 compileByte((jumplen >> 8) & 0xFF);
2464 compileByte(jumplen & 0xFF);
2465 compileAndFreeByteCodes(trueByteCodes);
2466 } else {
2467 compileOpcode(opSpecialOpcode, opcDrop); // drop the value
2468 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2469 }
2470 } else {
2471 COMPILENODE(arg1, &dummy, false);
2472 COMPILENODE(arg2, &dummy, false);
2473 compileTail();
2474 compileOpcode(opSendSpecialMsg, numArgs);
2475 compileByte(opmIf);
2476 }
2477 } else if (numArgs == 3) {
2478 arg2 = arg1->mNext;
2479 arg3 = arg2->mNext;
2480 if (isAnInlineableBlock(arg2) && isAnInlineableBlock(arg3)) {
2481 PyrCallNode* callNode = (PyrCallNode*)arg1;
2482 COMPILENODE(callNode->mArglist, &dummy, false);
2483
2484 falseByteCodes = compileSubExpression((PyrPushLitNode*)arg3, true);
2485 int falseLen = byteCodeLength(falseByteCodes);
2486 trueByteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)arg2, falseLen, true);
2487 int trueLen = byteCodeLength(trueByteCodes);
2488 if (falseLen) {
2489 compileByte(143); // special opcodes
2490 compileByte(flag ? 24 : 25);
2491 compileByte((trueLen >> 8) & 0xFF);
2492 compileByte(trueLen & 0xFF);
2493 compileAndFreeByteCodes(trueByteCodes);
2494 compileAndFreeByteCodes(falseByteCodes);
2495 } else if (trueLen) {
2496 compileByte(143); // special opcodes
2497 compileByte(flag ? 26 : 27);
2498 compileByte((trueLen >> 8) & 0xFF);
2499 compileByte(trueLen & 0xFF);
2500 compileAndFreeByteCodes(trueByteCodes);
2501 } else {
2502 compileOpcode(opSpecialOpcode, opcDrop); // drop the boolean
2503 compileOpcode(opPushSpecialValue, opsvNil); // push nil
2504 }
2505 } else {
2506 COMPILENODE(arg1, &dummy, false);
2507 COMPILENODE(arg2, &dummy, false);
2508 COMPILENODE(arg3, &dummy, false);
2509 compileTail();
2510 compileOpcode(opSendSpecialMsg, numArgs);
2511 compileByte(opmIf);
2512 }
2513 } else {
2514 for (; arg1; arg1 = arg1->mNext) {
2515 COMPILENODE(arg1, &dummy, false);
2516 }
2517 compileTail();
2518 compileOpcode(opSendSpecialMsg, numArgs);
2519 compileByte(opmIf);
2520 }
2521 }
2522
reverseNodeList(PyrParseNode ** list)2523 PyrParseNode* reverseNodeList(PyrParseNode** list) {
2524 PyrParseNode* temp1 = *list;
2525 PyrParseNode* temp2 = nullptr;
2526 PyrParseNode* temp3 = nullptr;
2527 while (temp1) {
2528 *list = temp1;
2529 temp2 = temp1->mNext;
2530 temp1->mNext = temp3;
2531 temp3 = temp1;
2532 temp1 = temp2;
2533 }
2534 return *list;
2535 }
2536
2537
buildCase(PyrParseNode * arg1)2538 PyrCallNode* buildCase(PyrParseNode* arg1) {
2539 // transform case statement into nested if statements.
2540 // int numArgs = nodeListLength(arg1);
2541
2542 // post("->buildCase %d\n", numArgs);
2543
2544 PyrParseNode* arg2 = arg1->mNext;
2545
2546 PyrPushLitNode* litnode = (PyrPushLitNode*)arg1;
2547 PyrBlockNode* bnode = (PyrBlockNode*)slotRawPtr(&litnode->mSlot);
2548 PyrParseNode* bbody = bnode->mBody;
2549 if (bbody->mClassno == pn_DropNode) {
2550 PyrDropNode* dropNode = (PyrDropNode*)bbody;
2551 if (dropNode->mExpr2->mClassno == pn_BlockReturnNode) {
2552 arg1 = dropNode->mExpr1;
2553 } else {
2554 arg1 = dropNode;
2555 }
2556 } else {
2557 arg1 = bbody;
2558 }
2559 arg1->mNext = arg2;
2560
2561 PyrParseNode* arg3 = nullptr;
2562 if (arg2) {
2563 arg3 = arg2->mNext;
2564 if (arg3) {
2565 PyrParseNode* arg4 = arg3->mNext;
2566 if (arg4) {
2567 arg3 = buildCase(arg3);
2568 PyrBlockNode* bnode = newPyrBlockNode(nullptr, nullptr, arg3, false);
2569 arg3 = newPyrPushLitNode(nullptr, bnode);
2570 arg2->mNext = arg3;
2571 arg3->mNext = nullptr;
2572 arg1->mTail = arg3;
2573 }
2574 } else {
2575 arg1->mTail = arg2;
2576 }
2577 } else {
2578 arg1->mTail = arg1;
2579 }
2580
2581 /*
2582 post("arg1->mNext %p arg2 %p\n", arg1->mNext, arg2);
2583 if (arg2) {
2584 post("arg2->mNext %p arg3 %p\n", arg2->mNext, arg3);
2585 post("isAnInlineableBlock arg2 %d\n", isAnInlineableBlock(arg2));
2586 }
2587 if (arg3) {
2588 post("isAnInlineableBlock arg3 %d\n", isAnInlineableBlock(arg3));
2589 post("arg3->mNext %p\n", arg3->mNext);
2590 }
2591 DUMPNODE(arg1, 0);
2592 */
2593
2594 PyrSlot selector;
2595 SetSymbol(&selector, gSpecialSelectors[opmIf]);
2596 PyrSlotNode* selectorNode = newPyrSlotNode(&selector);
2597 PyrCallNode* callNode = newPyrCallNode(selectorNode, arg1, nullptr, nullptr);
2598
2599 // post("<-buildCase %d\n", numArgs);
2600
2601 return callNode;
2602 }
2603
compileCaseMsg(PyrCallNodeBase2 * node)2604 void compileCaseMsg(PyrCallNodeBase2* node) {
2605 PyrParseNode* argnode = node->mArglist;
2606 bool canInline = true;
2607 for (; argnode; argnode = argnode->mNext) {
2608 if (!isAnInlineableBlock(argnode)) {
2609 canInline = false;
2610 break;
2611 }
2612 }
2613 PyrSlot dummy;
2614 if (canInline) {
2615 PyrCallNode* callNode = buildCase(node->mArglist);
2616 callNode->compile(&dummy);
2617 } else {
2618 int numArgs = 0;
2619 argnode = node->mArglist;
2620 for (; argnode; argnode = argnode->mNext, ++numArgs) {
2621 COMPILENODE(argnode, &dummy, false);
2622 }
2623 compileTail();
2624 compileOpcode(opSendSpecialMsg, numArgs);
2625 compileByte(opmCase);
2626 }
2627 }
2628
compileSwitchMsg(PyrCallNode * node)2629 void compileSwitchMsg(PyrCallNode* node) {
2630 PyrSlot dummy;
2631 bool canInline = true;
2632 int numArgs;
2633 {
2634 PyrParseNode* argnode = node->mArglist;
2635 numArgs = nodeListLength(argnode);
2636
2637 if (numArgs <= 2) {
2638 error("Missing argument in switch statement");
2639 nodePostErrorLine(node);
2640 compileErrors++;
2641 };
2642
2643 argnode = argnode->mNext; // skip first arg.
2644
2645 PyrParseNode* nextargnode = nullptr;
2646 for (; argnode; argnode = nextargnode) {
2647 nextargnode = argnode->mNext;
2648 if (nextargnode != nullptr) {
2649 if (!isAtomicLiteral(argnode) && !isAnInlineableAtomicLiteralBlock(argnode)) {
2650 canInline = false;
2651 break;
2652 }
2653 if (!isAnInlineableBlock(nextargnode)) {
2654 canInline = false;
2655 break;
2656 }
2657 nextargnode = nextargnode->mNext;
2658 } else {
2659 if (!isAnInlineableBlock(argnode)) {
2660 canInline = false;
2661 }
2662 break;
2663 }
2664 }
2665 }
2666
2667 if (canInline) {
2668 PyrParseNode* argnode = node->mArglist;
2669
2670 int flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
2671 int arraySize = NEXTPOWEROFTWO(numArgs * 2);
2672 PyrObject* array = newPyrArray(compileGC(), arraySize, flags, false);
2673 array->size = arraySize;
2674 nilSlots(array->slots, arraySize);
2675
2676 PyrSlot slot;
2677 SetObject(&slot, array);
2678
2679 COMPILENODE(argnode, &dummy, false);
2680 compilePushConstant(node, &slot);
2681
2682 compileByte(143); // lookup slot in dictionary and jump to offset.
2683 compileByte(28);
2684
2685 argnode = argnode->mNext; // skip first arg.
2686
2687 PyrParseNode* nextargnode = nullptr;
2688 int absoluteOffset = byteCodeLength(gCompilingByteCodes);
2689 int offset = 0;
2690 int lastOffset = 0;
2691 for (; argnode; argnode = nextargnode) {
2692 nextargnode = argnode->mNext;
2693 if (nextargnode != nullptr) {
2694 ByteCodes byteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)nextargnode, 0x6666, true);
2695
2696 PyrSlot* key;
2697 PyrSlot value;
2698 SetInt(&value, offset);
2699 PyrPushLitNode* keyargnode = (PyrPushLitNode*)argnode;
2700 if (isAtomicLiteral(argnode)) {
2701 key = &keyargnode->mSlot;
2702 } else {
2703 PyrBlockNode* bnode = (PyrBlockNode*)slotRawPtr(&keyargnode->mSlot);
2704 PyrDropNode* dropnode = (PyrDropNode*)bnode->mBody;
2705 PyrPushLitNode* litnode = (PyrPushLitNode*)dropnode->mExpr1;
2706 key = &litnode->mSlot;
2707 }
2708
2709 int index = arrayAtIdentityHashInPairs(array, key);
2710 PyrSlot* slot = array->slots + index;
2711 slotCopy(slot, key);
2712 SetInt(slot + 1, offset);
2713
2714 if (byteCodes) {
2715 offset += byteCodeLength(byteCodes);
2716 compileAndFreeByteCodes(byteCodes);
2717 } else {
2718 compileOpcode(opPushSpecialValue, opsvNil);
2719 offset += 1;
2720 }
2721
2722 nextargnode = nextargnode->mNext;
2723 if (nextargnode == nullptr) {
2724 compileOpcode(opPushSpecialValue, opsvNil);
2725 lastOffset = offset;
2726 offset += 1;
2727 }
2728 } else {
2729 ByteCodes byteCodes = compileSubExpressionWithGoto((PyrPushLitNode*)argnode, 0, true);
2730
2731 lastOffset = offset;
2732 if (byteCodes) {
2733 offset += byteCodeLength(byteCodes);
2734 compileAndFreeByteCodes(byteCodes);
2735 } else {
2736 compileOpcode(opPushSpecialValue, opsvNil);
2737 lastOffset = offset;
2738 offset += 1;
2739 }
2740 }
2741 }
2742
2743 Byte* bytes = gCompilingByteCodes->bytes + absoluteOffset;
2744 PyrSlot* slots = array->slots;
2745 {
2746 int jumplen = offset - lastOffset;
2747 bytes[lastOffset - 2] = (jumplen >> 8) & 255;
2748 bytes[lastOffset - 1] = jumplen & 255;
2749 }
2750 for (int i = 0; i < arraySize; i += 2) {
2751 PyrSlot* key = slots + i;
2752 PyrSlot* value = key + 1;
2753
2754 if (IsNil(value)) {
2755 SetInt(value, lastOffset);
2756 } else {
2757 int offsetToHere = slotRawInt(value);
2758 if (offsetToHere) {
2759 int jumplen = offset - offsetToHere;
2760 bytes[offsetToHere - 2] = (jumplen >> 8) & 255;
2761 bytes[offsetToHere - 1] = jumplen & 255;
2762 }
2763 }
2764 }
2765
2766 } else {
2767 PyrParseNode* argnode = node->mArglist;
2768 for (; argnode; argnode = argnode->mNext) {
2769 COMPILENODE(argnode, &dummy, false);
2770 }
2771 compileTail();
2772 compileOpcode(opSendSpecialMsg, numArgs);
2773 compileByte(opmSwitch);
2774 }
2775 }
2776
compileWhileMsg(PyrCallNodeBase2 * node)2777 void compileWhileMsg(PyrCallNodeBase2* node) {
2778 int numArgs;
2779 PyrParseNode* argnode;
2780 PyrSlot dummy;
2781 ByteCodes whileByteCodes, exprByteCodes;
2782 int whileByteCodeLen, exprByteCodeLen;
2783
2784 numArgs = nodeListLength(node->mArglist);
2785 if (numArgs == 1 && isAnInlineableBlock(node->mArglist)) {
2786 whileByteCodes = compileSubExpression((PyrPushLitNode*)node->mArglist, false);
2787
2788 whileByteCodeLen = byteCodeLength(whileByteCodes);
2789 compileAndFreeByteCodes(whileByteCodes);
2790
2791 exprByteCodeLen = 1;
2792 compileJump(opcJumpIfFalsePushNil, exprByteCodeLen + 3);
2793
2794 // opcJumpBak does a drop..
2795 compileOpcode(opPushSpecialValue, opsvNil);
2796
2797 compileJump(opcJumpBak, exprByteCodeLen + whileByteCodeLen + 4);
2798
2799 } else if (numArgs == 2 && isWhileTrue(node->mArglist) && isAnInlineableBlock(node->mArglist->mNext)) {
2800 exprByteCodes = compileSubExpression((PyrPushLitNode*)node->mArglist->mNext, false);
2801
2802 exprByteCodeLen = byteCodeLength(exprByteCodes);
2803 compileAndFreeByteCodes(exprByteCodes);
2804
2805 compileJump(opcJumpBak, exprByteCodeLen + 1);
2806
2807 } else if (numArgs == 2 && isAnInlineableBlock(node->mArglist) && isAnInlineableBlock(node->mArglist->mNext)) {
2808 whileByteCodes = compileSubExpression((PyrPushLitNode*)node->mArglist, false);
2809 exprByteCodes = compileSubExpression((PyrPushLitNode*)node->mArglist->mNext, false);
2810
2811 whileByteCodeLen = byteCodeLength(whileByteCodes);
2812 compileAndFreeByteCodes(whileByteCodes);
2813
2814 if (exprByteCodes) {
2815 exprByteCodeLen = byteCodeLength(exprByteCodes);
2816 compileJump(opcJumpIfFalsePushNil, exprByteCodeLen + 3);
2817 compileAndFreeByteCodes(exprByteCodes);
2818 } else {
2819 exprByteCodeLen = 1;
2820 compileJump(opcJumpIfFalsePushNil, exprByteCodeLen + 3);
2821 // opcJumpBak does a drop..
2822 compileOpcode(opPushSpecialValue, opsvNil);
2823 }
2824
2825 compileJump(opcJumpBak, exprByteCodeLen + whileByteCodeLen + 4);
2826
2827 } else {
2828 argnode = node->mArglist;
2829 for (; argnode; argnode = argnode->mNext) {
2830 COMPILENODE(argnode, &dummy, false);
2831 }
2832 compileTail();
2833 compileOpcode(opSendSpecialMsg, numArgs);
2834 compileByte(opmWhile);
2835 }
2836 }
2837
compileLoopMsg(PyrCallNodeBase2 * node)2838 void compileLoopMsg(PyrCallNodeBase2* node) {
2839 int numArgs;
2840 PyrParseNode* argnode;
2841 PyrSlot dummy;
2842 ByteCodes exprByteCodes;
2843 int exprByteCodeLen;
2844
2845 numArgs = nodeListLength(node->mArglist);
2846 if (numArgs == 1 && isAnInlineableBlock(node->mArglist)) {
2847 exprByteCodes = compileSubExpression((PyrPushLitNode*)node->mArglist, false);
2848
2849 exprByteCodeLen = byteCodeLength(exprByteCodes);
2850 compileAndFreeByteCodes(exprByteCodes);
2851
2852 compileJump(opcJumpBak, exprByteCodeLen + 1);
2853
2854 } else {
2855 argnode = node->mArglist;
2856 for (; argnode; argnode = argnode->mNext) {
2857 COMPILENODE(argnode, &dummy, false);
2858 }
2859 compileTail();
2860 compileOpcode(opSendSpecialMsg, numArgs);
2861 compileByte(opmLoop);
2862 }
2863 }
2864
newPyrBinopCallNode(PyrSlotNode * selector,PyrParseNode * arg1,PyrParseNode * arg2,PyrParseNode * arg3)2865 PyrBinopCallNode* newPyrBinopCallNode(PyrSlotNode* selector, PyrParseNode* arg1, PyrParseNode* arg2,
2866 PyrParseNode* arg3) {
2867 PyrBinopCallNode* node = ALLOCNODE(PyrBinopCallNode);
2868 node->mSelector = selector;
2869 node->mArglist = arg1;
2870 arg1->mNext = arg2;
2871 arg2->mNext = arg3;
2872 return node;
2873 }
2874
isPartialApplication()2875 int PyrBinopCallNode::isPartialApplication() {
2876 int sum = 0;
2877 PyrParseNode* argnode = mArglist;
2878 for (; argnode; argnode = argnode->mNext) {
2879 if (argnode->mClassno == pn_CurryArgNode) {
2880 ((PyrCurryArgNode*)argnode)->mArgNum = sum;
2881 sum++;
2882 }
2883 }
2884 return sum;
2885 }
2886
compileCall(PyrSlot * result)2887 void PyrBinopCallNode::compileCall(PyrSlot* result) {
2888 int index, selType, isSuper, numArgs;
2889 PyrSlot dummy;
2890
2891 PyrParseNode* arg1 = mArglist;
2892 PyrParseNode* arg2 = arg1->mNext;
2893 PyrParseNode* arg3 = arg2->mNext;
2894
2895 // postfl("compilePyrBinopCallNode\n");
2896 isSuper = isSuperObjNode(arg1);
2897 slotRawSymbol(&mSelector->mSlot)->flags |= sym_Called;
2898 index = conjureSelectorIndex((PyrParseNode*)mSelector, gCompilingBlock, isSuper, slotRawSymbol(&mSelector->mSlot),
2899 &selType);
2900 numArgs = arg3 ? 3 : 2;
2901 if (isSuper) {
2902 COMPILENODE(arg1, &dummy, false);
2903 COMPILENODE(arg2, &dummy, false);
2904 if (arg3)
2905 COMPILENODE(arg3, &dummy, false);
2906 compileTail();
2907 compileOpcode(opSendSuper, numArgs);
2908 compileByte(index);
2909 } else {
2910 switch (selType) {
2911 case selNormal:
2912 COMPILENODE(arg1, &dummy, false);
2913 COMPILENODE(arg2, &dummy, false);
2914 if (arg3)
2915 COMPILENODE(arg3, &dummy, false);
2916 compileTail();
2917 compileOpcode(opSendMsg, numArgs);
2918 compileByte(index);
2919 break;
2920 case selSpecial:
2921 COMPILENODE(arg1, &dummy, false);
2922 COMPILENODE(arg2, &dummy, false);
2923 if (arg3)
2924 COMPILENODE(arg3, &dummy, false);
2925 compileTail();
2926 compileOpcode(opSendSpecialMsg, numArgs);
2927 compileByte(index);
2928 break;
2929 case selUnary:
2930 COMPILENODE(arg1, &dummy, false);
2931 COMPILENODE(arg2, &dummy, false);
2932 if (arg3)
2933 COMPILENODE(arg3, &dummy, false);
2934 compileTail();
2935 if (arg3)
2936 compileOpcode(opSpecialOpcode, opcDrop); // drop third argument
2937 compileOpcode(opSpecialOpcode, opcDrop); // drop second argument
2938 compileOpcode(opSendSpecialUnaryArithMsg, index);
2939 break;
2940 case selBinary:
2941 if (arg3) {
2942 COMPILENODE(arg1, &dummy, false);
2943 COMPILENODE(arg2, &dummy, false);
2944 COMPILENODE(arg3, &dummy, false);
2945 compileTail();
2946 compileOpcode(opSpecialOpcode, opcSpecialBinaryOpWithAdverb);
2947 compileByte(index);
2948 } else if (index == opAdd && arg2->mClassno == pn_PushLitNode && IsInt(&((PyrPushLitNode*)arg2)->mSlot)
2949 && slotRawInt(&((PyrPushLitNode*)arg2)->mSlot) == 1) {
2950 COMPILENODE(arg1, &dummy, false);
2951 compileOpcode(opPushSpecialValue, opsvPlusOne);
2952 } else if (index == opSub && arg2->mClassno == pn_PushLitNode && IsInt(&((PyrPushLitNode*)arg2)->mSlot)
2953 && slotRawInt(&((PyrPushLitNode*)arg2)->mSlot) == 1) {
2954 COMPILENODE(arg1, &dummy, false);
2955 compileTail();
2956 compileOpcode(opPushSpecialValue, opsvMinusOne);
2957 } else {
2958 COMPILENODE(arg1, &dummy, false);
2959 COMPILENODE(arg2, &dummy, false);
2960 compileTail();
2961 compileOpcode(opSendSpecialBinaryArithMsg, index);
2962 }
2963 break;
2964 case selIf:
2965 compileAnyIfMsg(this);
2966 break;
2967 case selCase:
2968 compileCaseMsg(this);
2969 break;
2970 case selWhile:
2971 compileWhileMsg(this);
2972 break;
2973 case selLoop:
2974 compileLoopMsg(this);
2975 break;
2976 case selAnd:
2977 compileAndMsg(arg1, arg2);
2978 break;
2979 case selOr:
2980 compileOrMsg(arg1, arg2);
2981 break;
2982 case selQuestionMark:
2983 compileQMsg(arg1, arg2);
2984 break;
2985 case selDoubleQuestionMark:
2986 compileQQMsg(arg1, arg2);
2987 break;
2988 case selExclamationQuestionMark:
2989 compileXQMsg(arg1, arg2);
2990 break;
2991 default:
2992 COMPILENODE(arg1, &dummy, false);
2993 COMPILENODE(arg2, &dummy, false);
2994 if (arg3)
2995 COMPILENODE(arg3, &dummy, false);
2996 compileTail();
2997 compileOpcode(opSendMsg, numArgs);
2998 compileByte(index);
2999 break;
3000 }
3001 }
3002 }
3003
newPyrPushKeyArgNode(PyrSlotNode * selector,PyrParseNode * expr)3004 PyrPushKeyArgNode* newPyrPushKeyArgNode(PyrSlotNode* selector, PyrParseNode* expr) {
3005 PyrPushKeyArgNode* node = ALLOCNODE(PyrPushKeyArgNode);
3006 node->mSelector = selector;
3007 node->mExpr = expr;
3008 return node;
3009 }
3010
compile(PyrSlot * result)3011 void PyrPushKeyArgNode::compile(PyrSlot* result) {
3012 PyrSlot dummy;
3013 // postfl("->compilePyrPushKeyArgNode\n");
3014
3015 compilePushConstant((PyrParseNode*)this, &mSelector->mSlot);
3016
3017 COMPILENODE(mExpr, &dummy, false);
3018 }
3019
newPyrDropNode(PyrParseNode * expr1,PyrParseNode * expr2)3020 PyrDropNode* newPyrDropNode(PyrParseNode* expr1, PyrParseNode* expr2) {
3021 PyrDropNode* node = ALLOCNODE(PyrDropNode);
3022 node->mExpr1 = expr1;
3023 node->mExpr2 = expr2;
3024 return node;
3025 }
3026
compile(PyrSlot * result)3027 void PyrDropNode::compile(PyrSlot* result) {
3028 // postfl("->compilePyrDropNode\n");
3029 PyrSlot dummy;
3030 // eliminate as many drops as possible
3031 if (!mExpr2) {
3032 post("DROP EXPR2 NULL\n");
3033 COMPILENODE(mExpr1, &dummy, true);
3034 } else if (mExpr2->mClassno == pn_BlockReturnNode) {
3035 // no drop before a block return
3036 COMPILENODE(mExpr1, &dummy, true);
3037 } else if (mExpr1 && mExpr1->mClassno == pn_AssignNode) {
3038 // let the store do the drop
3039 ((PyrAssignNode*)mExpr1)->mDrop = 1;
3040 COMPILENODE(mExpr1, &dummy, false);
3041 COMPILENODE(mExpr2, &dummy, true);
3042 } else if (mExpr1 && mExpr1->mClassno == pn_DropNode) {
3043 PyrDropNode* znode;
3044 // let the store do the drop, a bit more complex.
3045 // find the ultimate expression in the left subtree before the drop.
3046 znode = (PyrDropNode*)mExpr1;
3047 while (znode->mExpr2 && znode->mExpr2->mClassno == pn_DropNode) {
3048 znode = (PyrDropNode*)znode->mExpr2;
3049 }
3050 if (znode->mExpr2->mClassno == pn_AssignNode) {
3051 ((PyrAssignNode*)znode->mExpr2)->mDrop = 1;
3052 COMPILENODE(mExpr1, &dummy, false);
3053 COMPILENODE(mExpr2, &dummy, true);
3054 } else {
3055 COMPILENODE(mExpr1, &dummy, false);
3056 compileOpcode(opSpecialOpcode, opcDrop);
3057 COMPILENODE(mExpr2, &dummy, true);
3058 }
3059 } else {
3060 COMPILENODE(mExpr1, &dummy, false);
3061 compileOpcode(opSpecialOpcode, opcDrop);
3062 COMPILENODE(mExpr2, &dummy, true);
3063 }
3064 // postfl("<-compilePyrDropNode\n");
3065 }
3066
newPyrPushLitNode(PyrSlotNode * literalSlot,PyrParseNode * literalObj)3067 PyrPushLitNode* newPyrPushLitNode(PyrSlotNode* literalSlot, PyrParseNode* literalObj) {
3068 PyrPushLitNode* node;
3069 if (literalSlot) {
3070 node = literalSlot;
3071 node->mClassno = pn_PushLitNode;
3072 } else {
3073 node = ALLOCSLOTNODE(PyrSlotNode, pn_PushLitNode);
3074 SetPtr(&node->mSlot, (PyrObject*)literalObj);
3075 }
3076 return node;
3077 }
3078
3079
compilePushConstant(PyrParseNode * node,PyrSlot * slot)3080 void compilePushConstant(PyrParseNode* node, PyrSlot* slot) {
3081 int index = conjureConstantIndex(node, gCompilingBlock, slot);
3082 if (index < (1 << 4)) {
3083 compileByte((opPushLiteral << 4) | index);
3084 } else if (index < (1 << 8)) {
3085 compileByte(40);
3086 compileByte(index & 0xFF);
3087 } else if (index < (1 << 16)) {
3088 compileByte(41);
3089 compileByte((index >> 8) & 0xFF);
3090 compileByte(index & 0xFF);
3091 } else if (index < (1 << 24)) {
3092 compileByte(42);
3093 compileByte((index >> 16) & 0xFF);
3094 compileByte((index >> 8) & 0xFF);
3095 compileByte(index & 0xFF);
3096 } else {
3097 compileByte(43);
3098 compileByte((index >> 24) & 0xFF);
3099 compileByte((index >> 16) & 0xFF);
3100 compileByte((index >> 8) & 0xFF);
3101 compileByte(index & 0xFF);
3102 }
3103 }
3104
compilePushInt(int value)3105 void compilePushInt(int value) {
3106 // postfl("compilePushInt\n");
3107 if (value >= -1 && value <= 2) {
3108 compileOpcode(opPushSpecialValue, opsvZero + value);
3109 } else {
3110 // printf("int %d\n", value);
3111 if (value >= -(1 << 7) && value <= ((1 << 7) - 1)) {
3112 compileByte(44);
3113 compileByte(value & 0xFF);
3114 } else if (value >= -(1 << 15) && value <= ((1 << 15) - 1)) {
3115 compileByte(45);
3116 compileByte((value >> 8) & 0xFF);
3117 compileByte(value & 0xFF);
3118 } else if (value >= -(1 << 23) && value <= ((1 << 23) - 1)) {
3119 compileByte(46);
3120 compileByte((value >> 16) & 0xFF);
3121 compileByte((value >> 8) & 0xFF);
3122 compileByte(value & 0xFF);
3123 } else {
3124 compileByte(47);
3125 compileByte((value >> 24) & 0xFF);
3126 compileByte((value >> 16) & 0xFF);
3127 compileByte((value >> 8) & 0xFF);
3128 compileByte(value & 0xFF);
3129 }
3130 }
3131 }
3132
compilePushLit(PyrSlot * result)3133 void PyrSlotNode::compilePushLit(PyrSlot* result) {
3134 int index;
3135 PyrSlot slot;
3136 ByteCodes savedBytes;
3137
3138 // postfl("compilePyrPushLitNode\n");
3139 if (IsPtr(&mSlot)) {
3140 PyrParseNode* literalObj = (PyrParseNode*)slotRawPtr(&mSlot);
3141 // index = conjureLiteralObjIndex(gCompilingBlock, literalObj);
3142 if (literalObj->mClassno == pn_BlockNode) {
3143 savedBytes = saveByteCodeArray();
3144 COMPILENODE(literalObj, &slot, false);
3145 restoreByteCodeArray(savedBytes);
3146 index = conjureLiteralSlotIndex(literalObj, gCompilingBlock, &slot);
3147 compileOpcode(opExtended, opPushLiteral);
3148 compileByte(index);
3149
3150 PyrBlock* block = slotRawBlock(&slot);
3151 if (NotNil(&block->contextDef)) {
3152 METHRAW(gCompilingBlock)->needsHeapContext = 1;
3153 }
3154 } else {
3155 COMPILENODE(literalObj, &slot, false);
3156 compilePushConstant((PyrParseNode*)literalObj, &slot);
3157 }
3158 } else {
3159 slot = mSlot;
3160 if (IsInt(&slot)) {
3161 compilePushInt(slotRawInt(&slot));
3162 } else if (SlotEq(&slot, &o_nil)) {
3163 compileOpcode(opPushSpecialValue, opsvNil);
3164 } else if (SlotEq(&slot, &o_true)) {
3165 compileOpcode(opPushSpecialValue, opsvTrue);
3166 } else if (SlotEq(&slot, &o_false)) {
3167 compileOpcode(opPushSpecialValue, opsvFalse);
3168 } else if (SlotEq(&slot, &o_fhalf)) {
3169 compileOpcode(opPushSpecialValue, opsvFHalf);
3170 } else if (SlotEq(&slot, &o_fnegone)) {
3171 compileOpcode(opPushSpecialValue, opsvFNegOne);
3172 } else if (SlotEq(&slot, &o_fzero)) {
3173 compileOpcode(opPushSpecialValue, opsvFZero);
3174 } else if (SlotEq(&slot, &o_fone)) {
3175 compileOpcode(opPushSpecialValue, opsvFOne);
3176 } else if (SlotEq(&slot, &o_ftwo)) {
3177 compileOpcode(opPushSpecialValue, opsvFTwo);
3178 } else if (SlotEq(&slot, &o_inf)) {
3179 compileOpcode(opPushSpecialValue, opsvInf);
3180 } else if (IsFloat(&slot)) {
3181 compilePushConstant((PyrParseNode*)this, &slot);
3182 } else if (IsSym(&slot)) {
3183 compilePushConstant((PyrParseNode*)this, &slot);
3184 } else {
3185 compilePushConstant((PyrParseNode*)this, &slot);
3186 }
3187 }
3188 }
3189
newPyrLiteralNode(PyrSlotNode * literalSlot,PyrParseNode * literalObj)3190 PyrLiteralNode* newPyrLiteralNode(PyrSlotNode* literalSlot, PyrParseNode* literalObj) {
3191 PyrLiteralNode* node;
3192 if (literalSlot) {
3193 node = literalSlot;
3194 node->mClassno = pn_LiteralNode;
3195 } else {
3196 node = ALLOCSLOTNODE(PyrSlotNode, pn_LiteralNode);
3197 SetPtr(&node->mSlot, (PyrObject*)literalObj);
3198 }
3199 return node;
3200 }
3201
compilePyrLiteralNode(PyrLiteralNode * node,PyrSlot * result)3202 void compilePyrLiteralNode(PyrLiteralNode* node, PyrSlot* result) {
3203 if (!node) {
3204 SetNil(result);
3205 } else {
3206 node->compileLiteral(result);
3207 }
3208 }
3209
compileLiteral(PyrSlot * result)3210 void PyrSlotNode::compileLiteral(PyrSlot* result) {
3211 ByteCodes savedBytes;
3212
3213 if (IsPtr(&mSlot)) {
3214 PyrParseNode* literalObj = (PyrParseNode*)slotRawPtr(&mSlot);
3215 if (literalObj->mClassno == pn_BlockNode) {
3216 savedBytes = saveByteCodeArray();
3217 COMPILENODE(literalObj, result, false);
3218 restoreByteCodeArray(savedBytes);
3219
3220 PyrBlock* block = slotRawBlock(result);
3221 if (NotNil(&block->contextDef)) {
3222 METHRAW(gCompilingBlock)->needsHeapContext = 1;
3223 }
3224 } else {
3225 COMPILENODE(literalObj, result, false);
3226 }
3227 } else {
3228 *(PyrSlot*)result = mSlot;
3229 }
3230 }
3231
newPyrReturnNode(PyrParseNode * expr)3232 PyrReturnNode* newPyrReturnNode(PyrParseNode* expr) {
3233 PyrReturnNode* node = ALLOCNODE(PyrReturnNode);
3234 node->mExpr = expr;
3235 return node;
3236 }
3237
3238
compile(PyrSlot * result)3239 void PyrReturnNode::compile(PyrSlot* result) {
3240 PyrPushLitNode* lit;
3241 PyrSlot dummy;
3242
3243 // post("->compilePyrReturnNode\n");
3244 gFunctionCantBeClosed = true;
3245 if (!mExpr) {
3246 compileOpcode(opSpecialOpcode, opcReturnSelf);
3247 } else if (mExpr->mClassno == pn_PushLitNode) {
3248 lit = (PyrPushLitNode*)mExpr;
3249 if (IsSym(&(lit->mSlot)) && slotRawSymbol(&lit->mSlot) == s_this) {
3250 compileOpcode(opSpecialOpcode, opcReturnSelf);
3251 } else if (IsNil(&lit->mSlot)) {
3252 compileOpcode(opSpecialOpcode, opcReturnNil);
3253 } else if (IsTrue(&lit->mSlot)) {
3254 compileOpcode(opSpecialOpcode, opcReturnTrue);
3255 } else if (IsFalse(&lit->mSlot)) {
3256 compileOpcode(opSpecialOpcode, opcReturnFalse);
3257 } else {
3258 COMPILENODE(lit, &dummy, false);
3259 compileOpcode(opSpecialOpcode, opcReturn);
3260 }
3261 } else {
3262 SetTailBranch branch(true);
3263 SetTailIsMethodReturn mr(true);
3264 COMPILENODE(mExpr, &dummy, true);
3265 compileOpcode(opSpecialOpcode, opcReturn);
3266 }
3267 // post("<-compilePyrReturnNode\n");
3268 }
3269
newPyrBlockReturnNode()3270 PyrBlockReturnNode* newPyrBlockReturnNode() {
3271 PyrBlockReturnNode* node = ALLOCNODE(PyrBlockReturnNode);
3272 return node;
3273 }
3274
3275
compile(PyrSlot * result)3276 void PyrBlockReturnNode::compile(PyrSlot* result) {
3277 // postfl("compilePyrBlockReturnNode\n");
3278 // compileOpcode(opSpecialOpcode, opcFunctionReturn);
3279 }
3280
newPyrAssignNode(PyrSlotNode * varName,PyrParseNode * expr,int flags)3281 PyrAssignNode* newPyrAssignNode(PyrSlotNode* varName, PyrParseNode* expr, int flags) {
3282 PyrAssignNode* node = ALLOCNODE(PyrAssignNode);
3283 node->mVarName = varName;
3284 node->mExpr = expr;
3285 node->mDrop = 0;
3286 return node;
3287 }
3288
newPyrSetterNode(PyrSlotNode * selector,PyrParseNode * expr1,PyrParseNode * expr2)3289 PyrSetterNode* newPyrSetterNode(PyrSlotNode* selector, PyrParseNode* expr1, PyrParseNode* expr2) {
3290 PyrSetterNode* node = ALLOCNODE(PyrSetterNode);
3291 node->mSelector = selector;
3292 node->mExpr1 = expr1;
3293 node->mExpr2 = expr2;
3294 return node;
3295 }
3296
newPyrMultiAssignNode(PyrMultiAssignVarListNode * varList,PyrParseNode * expr,int flags)3297 PyrMultiAssignNode* newPyrMultiAssignNode(PyrMultiAssignVarListNode* varList, PyrParseNode* expr, int flags) {
3298 PyrMultiAssignNode* node = ALLOCNODE(PyrMultiAssignNode);
3299 node->mVarList = varList;
3300 node->mExpr = expr;
3301 node->mDrop = 0;
3302 return node;
3303 }
3304
newPyrMultiAssignVarListNode(PyrSlotNode * varNames,PyrSlotNode * rest)3305 PyrMultiAssignVarListNode* newPyrMultiAssignVarListNode(PyrSlotNode* varNames, PyrSlotNode* rest) {
3306 PyrMultiAssignVarListNode* node = ALLOCNODE(PyrMultiAssignVarListNode);
3307 node->mVarNames = varNames;
3308 node->mRest = rest;
3309 return node;
3310 }
3311
compileAssignVar(PyrParseNode * node,PyrSymbol * varName,bool drop)3312 void compileAssignVar(PyrParseNode* node, PyrSymbol* varName, bool drop) {
3313 int level, index, vindex, varType;
3314 PyrBlock* tempfunc;
3315 PyrClass* classobj;
3316
3317 // postfl("compileAssignVar\n");
3318 classobj = gCompilingClass;
3319 if (varName == s_this || varName == s_super || varName == s_curProcess || varName == s_curThread
3320 || varName == s_curMethod || varName == s_curBlock || varName == s_curClosure) {
3321 error("You may not assign to '%s'.", varName->name);
3322 nodePostErrorLine(node);
3323 compileErrors++;
3324 } else if (varName->name[0] >= 'A' && varName->name[0] <= 'Z') {
3325 // actually this shouldn't even parse, so you won't get here.
3326 error("You may not assign to a class name.");
3327 nodePostErrorLine(node);
3328 compileErrors++;
3329 } else if (findVarName(gCompilingBlock, &classobj, varName, &varType, &level, &index, &tempfunc)) {
3330 switch (varType) {
3331 case varInst:
3332 if (drop) {
3333 if (index <= 15) {
3334 compileByte((opStoreInstVar << 4) | index);
3335 } else {
3336 compileByte(opStoreInstVar);
3337 compileByte(index);
3338 compileByte((opSpecialOpcode << 4) | opcDrop);
3339 }
3340 } else {
3341 compileByte(opStoreInstVar);
3342 compileByte(index);
3343 }
3344 break;
3345 case varClass: {
3346 index += slotRawInt(&classobj->classVarIndex);
3347 if (drop) {
3348 if (index < 4096) {
3349 compileByte((opStoreClassVar << 4) | ((index >> 8) & 15));
3350 compileByte(index & 255);
3351 } else {
3352 compileByte(opStoreClassVar);
3353 assert(false);
3354 vindex = 0;
3355 compileByte(vindex); // FIXME: vindex is not initalized!!!!
3356 compileByte(index);
3357 compileByte((opSpecialOpcode << 4) | opcDrop);
3358 }
3359 } else {
3360 compileByte(opStoreClassVar);
3361 compileByte((index >> 8) & 255);
3362 compileByte(index & 255);
3363 }
3364 } break;
3365 case varConst: {
3366 error("You may not assign to a constant.");
3367 nodePostErrorLine(node);
3368 compileErrors++;
3369 } break;
3370 case varTemp:
3371 // compileOpcode(opStoreTempVar, level);
3372 // compileByte(index);
3373 if (drop) {
3374 if (index <= 15 && level < 8) {
3375 compileByte((opStoreTempVar << 4) | level);
3376 compileByte(index);
3377 } else {
3378 compileByte(opStoreTempVar);
3379 compileByte(level);
3380 compileByte(index);
3381 compileByte((opSpecialOpcode << 4) | opcDrop);
3382 }
3383 } else {
3384 compileByte(opStoreTempVar);
3385 compileByte(level);
3386 compileByte(index);
3387 }
3388 break;
3389 }
3390 } else {
3391 error("Variable '%s' not defined.\n", varName->name);
3392 nodePostErrorLine(node);
3393 compileErrors++;
3394 // Debugger();
3395 }
3396 }
3397
compile(PyrSlot * result)3398 void PyrAssignNode::compile(PyrSlot* result) {
3399 PyrSlot dummy;
3400
3401 // postfl("compilePyrAssignNode\n");
3402 COMPILENODE(mExpr, &dummy, false);
3403 compileAssignVar((PyrParseNode*)this, slotRawSymbol(&mVarName->mSlot), mDrop);
3404 }
3405
3406
isPartialApplication()3407 int PyrSetterNode::isPartialApplication() {
3408 int sum = 0;
3409 if (mExpr1->mClassno == pn_CurryArgNode) {
3410 ((PyrCurryArgNode*)mExpr1)->mArgNum = sum;
3411 sum++;
3412 }
3413 if (mExpr2->mClassno == pn_CurryArgNode) {
3414 ((PyrCurryArgNode*)mExpr2)->mArgNum = sum;
3415 sum++;
3416 }
3417 return sum;
3418 }
3419
compileCall(PyrSlot * result)3420 void PyrSetterNode::compileCall(PyrSlot* result) {
3421 int index, selType, isSuper;
3422 PyrSlot dummy;
3423 char setterName[128];
3424 PyrSymbol* setterSym;
3425
3426 // postfl("compilePyrSetterNode\n");
3427 if (nodeListLength(mExpr1) > 1) {
3428 error("Setter method called with too many arguments.\n");
3429 nodePostErrorLine(mExpr1);
3430 compileErrors++;
3431 } else {
3432 COMPILENODE(mExpr1, &dummy, false);
3433 COMPILENODE(mExpr2, &dummy, false);
3434
3435
3436 // postfl("compilePyrCallNode\n");
3437 isSuper = isSuperObjNode(mExpr1);
3438
3439 sprintf(setterName, "%s_", slotRawSymbol(&mSelector->mSlot)->name);
3440 setterSym = getsym(setterName);
3441
3442 slotRawSymbol(&mSelector->mSlot)->flags |= sym_Called;
3443 index = conjureSelectorIndex((PyrParseNode*)mSelector, gCompilingBlock, isSuper, setterSym, &selType);
3444 if (isSuper) {
3445 compileTail();
3446 compileOpcode(opSendSuper, 2);
3447 compileByte(index);
3448 } else {
3449 compileTail();
3450 compileOpcode(opSendMsg, 2);
3451 compileByte(index);
3452 }
3453 }
3454 }
3455
compile(PyrSlot * result)3456 void PyrMultiAssignNode::compile(PyrSlot* result) {
3457 PyrSlot dummy;
3458
3459 // postfl("compilePyrMultiAssignNode\n");
3460 COMPILENODE(mExpr, &dummy, false);
3461 COMPILENODE(mVarList, &dummy, false);
3462 }
3463
compile(PyrSlot * result)3464 void PyrMultiAssignVarListNode::compile(PyrSlot* result) {
3465 int i, numAssigns;
3466 PyrSlotNode* varname;
3467
3468 // postfl("compilePyrMultiAssignVarListNode\n");
3469 numAssigns = nodeListLength((PyrParseNode*)mVarNames);
3470 varname = mVarNames;
3471 for (i = 0; i < numAssigns; ++i, varname = (PyrSlotNode*)varname->mNext) {
3472 compileOpcode(opSpecialOpcode, opcDup);
3473 compilePushInt(i);
3474 compileOpcode(opSendSpecialMsg, 2);
3475 compileByte(opmAt);
3476 compileAssignVar((PyrParseNode*)varname, slotRawSymbol(&varname->mSlot), 1);
3477 // compileOpcode(opSpecialOpcode, opcDrop);
3478 }
3479 if (mRest) {
3480 compileOpcode(opSpecialOpcode, opcDup);
3481 compilePushInt(i);
3482 compileOpcode(opSendSpecialMsg, 2);
3483 compileByte(opmCopyToEnd);
3484 compileAssignVar((PyrParseNode*)mRest, slotRawSymbol(&mRest->mSlot), 1);
3485 // compileOpcode(opSpecialOpcode, opcDrop);
3486 }
3487 }
3488
3489
newPyrDynDictNode(PyrParseNode * elems)3490 PyrDynDictNode* newPyrDynDictNode(PyrParseNode* elems) {
3491 PyrDynDictNode* node;
3492
3493 // if (compilingCmdLine) post("newPyrDynDictNode\n");
3494 node = ALLOCNODE(PyrDynDictNode);
3495 node->mElems = elems;
3496 return node;
3497 }
3498
isPartialApplication()3499 int PyrDynDictNode::isPartialApplication() {
3500 int sum = 0;
3501 int numItems = nodeListLength(mElems);
3502 PyrParseNode* inode = mElems;
3503 for (int i = 0; i < numItems; ++i) {
3504 if (inode->mClassno == pn_CurryArgNode) {
3505 ((PyrCurryArgNode*)inode)->mArgNum = sum;
3506 sum++;
3507 }
3508 inode = (PyrParseNode*)inode->mNext;
3509 }
3510 return sum;
3511 }
3512
compileCall(PyrSlot * result)3513 void PyrDynDictNode::compileCall(PyrSlot* result) {
3514 int i, numItems;
3515 PyrParseNode* inode;
3516 PyrSlot dummy;
3517
3518 // postfl("compilePyrDynDictNode\n");
3519 numItems = nodeListLength(mElems) >> 1;
3520
3521 compilePushVar((PyrParseNode*)this, s_event);
3522
3523 compilePushInt(numItems);
3524 compileByte(110); // push nil for proto
3525 compileByte(110); // push nil for parent
3526 compileByte(108); // push true for know
3527 compileOpcode(opSendSpecialMsg, 5);
3528
3529 compileByte(opmNew);
3530
3531 inode = mElems;
3532 for (i = 0; i < numItems; ++i) {
3533 // if (compilingCmdLine) post("+ %d %d\n", i, gCompilingByteCodes->size);
3534 COMPILENODE(inode, &dummy, false);
3535 inode = (PyrParseNode*)inode->mNext;
3536 COMPILENODE(inode, &dummy, false);
3537 inode = (PyrParseNode*)inode->mNext;
3538 compileOpcode(opSendSpecialMsg, 3);
3539 compileByte(opmPut);
3540 }
3541 }
3542
newPyrDynListNode(PyrParseNode * classname,PyrParseNode * elems)3543 PyrDynListNode* newPyrDynListNode(PyrParseNode* classname, PyrParseNode* elems) {
3544 PyrDynListNode* node;
3545
3546 // if (compilingCmdLine) post("newPyrDynListNode\n");
3547 node = ALLOCNODE(PyrDynListNode);
3548 node->mClassname = classname;
3549 node->mElems = elems;
3550 return node;
3551 }
3552
isPartialApplication()3553 int PyrDynListNode::isPartialApplication() {
3554 int sum = 0;
3555 int numItems = nodeListLength(mElems);
3556 PyrParseNode* inode = mElems;
3557 for (int i = 0; i < numItems; ++i) {
3558 if (inode->mClassno == pn_CurryArgNode) {
3559 ((PyrCurryArgNode*)inode)->mArgNum = sum;
3560 sum++;
3561 }
3562 inode = (PyrParseNode*)inode->mNext;
3563 }
3564 return sum;
3565 }
3566
compileCall(PyrSlot * result)3567 void PyrDynListNode::compileCall(PyrSlot* result) {
3568 int i, numItems;
3569 PyrParseNode* inode;
3570 PyrSlot dummy;
3571
3572 // postfl("compilePyrDynListNode\n");
3573 numItems = nodeListLength(mElems);
3574
3575 if (mClassname) {
3576 compilePushVar((PyrParseNode*)this, slotRawSymbol(&((PyrSlotNode*)mClassname)->mSlot));
3577 } else {
3578 compilePushVar((PyrParseNode*)this, s_array);
3579 }
3580
3581 // compileOpcode(opExtended, opPushSpecialValue);
3582 // compileByte(op_class_list);
3583
3584 compilePushInt(numItems);
3585
3586 compileOpcode(opSendSpecialMsg, 2);
3587 compileByte(opmNew);
3588
3589 inode = mElems;
3590 for (i = 0; i < numItems; ++i, inode = (PyrParseNode*)inode->mNext) {
3591 // if (compilingCmdLine) post("+ %d %d\n", i, gCompilingByteCodes->size);
3592 COMPILENODE(inode, &dummy, false);
3593 compileOpcode(opSendSpecialMsg, 2);
3594 compileByte(opmAdd);
3595 }
3596 }
3597
newPyrLitListNode(PyrParseNode * classname,PyrParseNode * elems)3598 PyrLitListNode* newPyrLitListNode(PyrParseNode* classname, PyrParseNode* elems) {
3599 PyrLitListNode* node = ALLOCNODE(PyrLitListNode);
3600 node->mClassname = classname;
3601 node->mElems = elems;
3602 return node;
3603 }
3604
compile(PyrSlot * result)3605 void PyrLitListNode::compile(PyrSlot* result) {
3606 PyrSlot* resultSlot;
3607 PyrSlot itemSlot;
3608 PyrObject* array;
3609 PyrParseNode* inode;
3610 int i, numItems, flags;
3611
3612 // postfl("->compilePyrLitListNode\n");
3613 if (mClassname && slotRawSymbol(&((PyrSlotNode*)mClassname)->mSlot) != s_array) {
3614 error("Only Array is supported as literal type.\n");
3615 post("Compiling as an Array.\n");
3616 }
3617 resultSlot = (PyrSlot*)result;
3618 numItems = mElems ? nodeListLength(mElems) : 0;
3619 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
3620 array = newPyrArray(compileGC(), numItems, flags, false);
3621 inode = mElems;
3622 for (i = 0; i < numItems; ++i, inode = (PyrParseNode*)inode->mNext) {
3623 COMPILENODE(inode, &itemSlot, false);
3624 array->slots[i] = itemSlot;
3625 }
3626 array->size = numItems;
3627 SetObject(resultSlot, array);
3628 // postfl("<-compilePyrLitListNode\n");
3629 }
3630
3631
newPyrLitDictNode(PyrParseNode * elems)3632 PyrLitDictNode* newPyrLitDictNode(PyrParseNode* elems) {
3633 PyrLitDictNode* node = ALLOCNODE(PyrLitDictNode);
3634 node->mElems = elems;
3635
3636 return node;
3637 }
3638
3639 int litDictPut(PyrObject* dict, PyrSlot* key, PyrSlot* value);
litDictPut(PyrObject * dict,PyrSlot * key,PyrSlot * value)3640 int litDictPut(PyrObject* dict, PyrSlot* key, PyrSlot* value) {
3641 #if 0
3642 PyrSlot *slot, *newslot;
3643 int i, index, size;
3644 PyrObject *array;
3645
3646 bool knows = IsTrue(dict->slots + ivxIdentDict_know);
3647 if (knows && IsSym(key)) {
3648 if (slotRawSymbol(key) == s_parent) {
3649 slotCopy(&dict->slots[ivxIdentDict_parent], value);
3650 return errNone;
3651 }
3652 if (slotRawSymbol(key) == s_proto) {
3653 slotCopy(&dict->slots[ivxIdentDict_proto], value);
3654 return errNone;
3655 }
3656 }
3657 array = slotRawObject(&dict->slots[ivxIdentDict_array]);
3658 if (!isKindOf((PyrObject*)array, class_array)) return errFailed;
3659
3660 index = arrayAtIdentityHashInPairs(array, key);
3661 slot = array->slots + index;
3662 slotCopy(&slot[1], value);
3663 if (IsNil(slot)) {
3664 slotCopy(slot, key);
3665 }
3666 #endif
3667 return errNone;
3668 }
3669
3670
dump(int level)3671 void PyrLitDictNode::dump(int level) {}
3672
compile(PyrSlot * result)3673 void PyrLitDictNode::compile(PyrSlot* result) {
3674 #if 0
3675 PyrSlot *resultSlot;
3676 PyrSlot itemSlot;
3677 PyrObject *array;
3678 PyrParseNode *inode;
3679 int i, numItems, flags;
3680
3681 //postfl("->compilePyrLitDictNode\n");
3682 if (mClassname && slotRawSymbol(&((PyrSlotNode*)mClassname)->mSlot) != s_array) {
3683 error("Only Array is supported as literal type.\n");
3684 post("Compiling as an Array.\n");
3685 }
3686 resultSlot = (PyrSlot*)result;
3687 numItems = mElems ? nodeListLength(mElems) : 0;
3688 int numSlots = NEXTPOWEROFTWO(numItems*2);
3689
3690 PyrObject *obj = instantiateObject(g->gc, class_event->u.classobj, 0, true, false);
3691 PyrSlot *slots = obj->slots;
3692
3693 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
3694 array = newPyrArray(compileGC(), numSlots, flags, false);
3695 nilSlots(array->slots, numSlots);
3696 inode = mElems;
3697 for (i=0; i<numItems; ++i, inode = (PyrParseNode*)inode->mNext) {
3698 COMPILENODE(inode, &itemSlot, false);
3699 array->slots[i] = itemSlot;
3700 }
3701 array->size = numItems;
3702 SetObject(resultSlot, array);
3703 //postfl("<-compilePyrLitListNode\n");
3704 #endif
3705 }
3706
3707
3708 extern LongStack closedFuncCharNo;
3709 extern int lastClosedFuncCharNo;
3710
newPyrBlockNode(PyrArgListNode * arglist,PyrVarListNode * varlist,PyrParseNode * body,bool isTopLevel)3711 PyrBlockNode* newPyrBlockNode(PyrArgListNode* arglist, PyrVarListNode* varlist, PyrParseNode* body, bool isTopLevel) {
3712 PyrBlockNode* node = ALLOCNODE(PyrBlockNode);
3713 node->mArglist = arglist;
3714 catVarLists(varlist);
3715 node->mVarlist = varlist;
3716 node->mBody = body;
3717 node->mIsTopLevel = isTopLevel;
3718
3719 node->mBeginCharNo = lastClosedFuncCharNo;
3720
3721 return node;
3722 }
3723
compile(PyrSlot * slotResult)3724 void PyrBlockNode::compile(PyrSlot* slotResult) {
3725 PyrBlock *block, *prevBlock;
3726 PyrMethodRaw* methraw;
3727 int i, j, numArgs, numVars, funcVarArgs;
3728 int numSlots, numArgNames, flags;
3729 PyrVarDefNode* vardef;
3730 PyrObject* proto;
3731 PyrSymbolArray *argNames, *varNames;
3732 PyrSlot dummy;
3733 bool hasVarExprs = false;
3734
3735 // postfl("->block\n");
3736
3737 // create a new block object
3738
3739 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
3740 block = newPyrBlock(flags);
3741 SetObject(slotResult, block);
3742
3743 int prevFunctionHighestExternalRef = gFunctionHighestExternalRef;
3744 bool prevFunctionCantBeClosed = gFunctionCantBeClosed;
3745 gFunctionHighestExternalRef = 0;
3746 gFunctionCantBeClosed = false;
3747
3748 prevBlock = gCompilingBlock;
3749 PyrClass* prevClass = gCompilingClass;
3750
3751 gCompilingBlock = block;
3752 PyrBlock* prevPartiallyAppliedFunction = gPartiallyAppliedFunction;
3753 gPartiallyAppliedFunction = nullptr;
3754
3755 methraw = METHRAW(block);
3756 methraw->unused1 = 0;
3757 methraw->unused2 = 0;
3758
3759 int endCharNo = linestarts[mLineno] + mCharno;
3760 int stringLength = endCharNo - mBeginCharNo;
3761 int lastChar = text[mBeginCharNo + stringLength - 1];
3762 if (lastChar == 0)
3763 stringLength--;
3764
3765 methraw->needsHeapContext = 0;
3766 if (mIsTopLevel) {
3767 gCompilingClass = class_interpreter;
3768 SetNil(&block->contextDef);
3769 } else {
3770 SetObject(&block->contextDef, prevBlock);
3771 }
3772
3773 methraw->varargs = funcVarArgs = (mArglist && mArglist->mRest) ? 1 : 0;
3774 numArgs = mArglist ? nodeListLength((PyrParseNode*)mArglist->mVarDefs) : 0;
3775 numVars = mVarlist ? nodeListLength((PyrParseNode*)mVarlist->mVarDefs) : 0;
3776
3777 if (numArgs > 255) {
3778 error("Too many arguments in function definition (> 255)\n");
3779 nodePostErrorLine((PyrParseNode*)mArglist->mVarDefs);
3780 compileErrors++;
3781 }
3782
3783 if (numArgs > 255) {
3784 error("Too many arguments in function definition (> 255).\n");
3785 nodePostErrorLine((PyrParseNode*)mArglist->mVarDefs);
3786 compileErrors++;
3787 }
3788
3789 numSlots = numArgs + funcVarArgs + numVars;
3790 methraw->frameSize = (numSlots + FRAMESIZE) * sizeof(PyrSlot);
3791 if (numSlots) {
3792 proto = newPyrArray(compileGC(), numSlots, flags, false);
3793 proto->size = numSlots;
3794 SetObject(&block->prototypeFrame, proto);
3795 } else {
3796 SetNil(&block->prototypeFrame);
3797 }
3798
3799 numArgNames = numArgs + funcVarArgs;
3800
3801 if (numArgNames) {
3802 argNames = newPyrSymbolArray(compileGC(), numArgNames, flags, false);
3803 argNames->size = numArgNames;
3804 SetObject(&block->argNames, argNames);
3805 } else {
3806 SetNil(&block->argNames);
3807 }
3808
3809 if (numVars) {
3810 varNames = newPyrSymbolArray(compileGC(), numVars, flags, false);
3811 varNames->size = numVars;
3812 SetObject(&block->varNames, varNames);
3813 } else {
3814 SetNil(&block->varNames);
3815 }
3816
3817 methraw->numargs = numArgs;
3818 methraw->numvars = numVars;
3819 methraw->posargs = numArgs + funcVarArgs;
3820 methraw->numtemps = numSlots;
3821 methraw->popSize = numSlots;
3822
3823 // declare args
3824 if (numArgs) {
3825 PyrSymbol** blockargs;
3826 blockargs = slotRawSymbolArray(&block->argNames)->symbols;
3827 vardef = mArglist->mVarDefs;
3828 for (i = 0; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3829 PyrSlot* varslot;
3830 varslot = &vardef->mVarName->mSlot;
3831 // already declared as arg?
3832 for (j = 0; j < i; ++j) {
3833 if (blockargs[j] == slotRawSymbol(varslot)) {
3834 error("Function argument '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
3835 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
3836 nodePostErrorLine((PyrParseNode*)vardef);
3837 compileErrors++;
3838 }
3839 }
3840 // put it in mArglist
3841 blockargs[i] = slotRawSymbol(varslot);
3842 // postfl("defarg %d '%s'\n", i, slotRawSymbol(slot)->name);
3843 }
3844 }
3845
3846 if (funcVarArgs) {
3847 PyrSlot* varslot;
3848 PyrSymbol** blockargs;
3849 blockargs = slotRawSymbolArray(&block->argNames)->symbols;
3850 varslot = &mArglist->mRest->mSlot;
3851 // already declared as arg?
3852 for (j = 0; j < numArgs; ++j) {
3853 if (blockargs[j] == slotRawSymbol(varslot)) {
3854 error("Function argument '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
3855 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
3856 nodePostErrorLine((PyrParseNode*)vardef);
3857 compileErrors++;
3858 }
3859 }
3860 // put it in mArglist
3861 blockargs[numArgs] = slotRawSymbol(varslot);
3862 // postfl("defrest '%s'\n", slotRawSymbol(slot)->name);
3863 }
3864
3865 // declare vars
3866 if (numVars) {
3867 PyrSymbol **blockargs, **blockvars;
3868 blockargs = slotRawSymbolArray(&block->argNames)->symbols;
3869 blockvars = slotRawSymbolArray(&block->varNames)->symbols;
3870 vardef = mVarlist->mVarDefs;
3871 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3872 PyrSlot* varslot;
3873 varslot = &vardef->mVarName->mSlot;
3874 // already declared as arg?
3875 for (j = 0; j < numArgNames; ++j) {
3876 if (blockargs[j] == slotRawSymbol(varslot)) {
3877 error("Function variable '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
3878 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
3879 nodePostErrorLine((PyrParseNode*)vardef);
3880 compileErrors++;
3881 }
3882 }
3883 // already declared as var?
3884 for (j = 0; j < i; ++j) {
3885 if (blockvars[j] == slotRawSymbol(varslot)) {
3886 error("Function variable '%s' already declared in %s:%s\n", slotRawSymbol(varslot)->name,
3887 slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
3888 nodePostErrorLine((PyrParseNode*)vardef);
3889 compileErrors++;
3890 }
3891 }
3892 // put it in varlist
3893 blockvars[i] = slotRawSymbol(varslot);
3894 // postfl("defvar %d '%s'\n", i, slotRawSymbol(slot)->name);
3895 }
3896 }
3897
3898 if (numArgs) {
3899 vardef = mArglist->mVarDefs;
3900 for (i = 0; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3901 PyrSlot *slot, litval;
3902 slot = slotRawObject(&block->prototypeFrame)->slots + i;
3903 if (vardef->hasExpr(&litval))
3904 hasVarExprs = true;
3905 // compilePyrLiteralNode((PyrLiteralNode*)vardef->mDefVal, &litval);
3906 *slot = litval;
3907 }
3908 }
3909
3910 if (funcVarArgs) {
3911 // SetNil(&slotRawObject(&block->prototypeFrame)->slots[numArgs]);
3912 slotCopy(&slotRawObject(&block->prototypeFrame)->slots[numArgs], &o_emptyarray);
3913 }
3914
3915 if (numVars) {
3916 vardef = mVarlist->mVarDefs;
3917 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3918 PyrSlot *slot, litval;
3919 slot = slotRawObject(&block->prototypeFrame)->slots + i + numArgs + funcVarArgs;
3920 if (vardef->hasExpr(&litval))
3921 hasVarExprs = true;
3922 // compilePyrLiteralNode(vardef->mDefVal, &litval);
3923 *slot = litval;
3924 }
3925 }
3926 methraw->methType = methBlock;
3927
3928 // compile body
3929 initByteCodes();
3930 {
3931 SetTailBranch branch(true);
3932 /*if (compilingCmdLine) {
3933 post("block %d\n", gIsTailCodeBranch);
3934 DUMPNODE(mBody, 0);
3935 }*/
3936 SetTailIsMethodReturn mr(false);
3937 if (hasVarExprs) {
3938 if (mArglist) {
3939 vardef = mArglist->mVarDefs;
3940 for (i = 0; i < numArgs; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3941 vardef->compileArg(&dummy);
3942 }
3943 }
3944 if (mVarlist) {
3945 vardef = mVarlist->mVarDefs;
3946 for (i = 0; i < numVars; ++i, vardef = (PyrVarDefNode*)vardef->mNext) {
3947 vardef->compile(&dummy);
3948 }
3949 }
3950 }
3951 if (mBody->mClassno == pn_BlockReturnNode) {
3952 compileOpcode(opPushSpecialValue, opsvNil);
3953 } else {
3954 COMPILENODE(mBody, &dummy, true);
3955 }
3956 }
3957 compileOpcode(opSpecialOpcode, opcFunctionReturn);
3958 installByteCodes(block);
3959
3960 if ((!gFunctionCantBeClosed && gFunctionHighestExternalRef == 0) || mIsTopLevel) {
3961 SetNil(&block->contextDef);
3962
3963 PyrString* string = newPyrStringN(compileGC(), stringLength, flags, false);
3964 memcpy(string->s, text + mBeginCharNo, stringLength);
3965 SetObject(&block->sourceCode, string);
3966 // static int totalLength = 0, totalStrings = 0;
3967 // totalLength += stringLength;
3968 // totalStrings++;
3969 // post("cf %4d %4d %6d %s:%s \n", totalStrings, stringLength, totalLength,
3970 // slotRawSymbol(&gCompilingClass->name)->name, slotRawSymbol(&gCompilingMethod->name)->name);
3971 }
3972
3973 gCompilingBlock = prevBlock;
3974 gCompilingClass = prevClass;
3975 gPartiallyAppliedFunction = prevPartiallyAppliedFunction;
3976 gFunctionCantBeClosed = gFunctionCantBeClosed || prevFunctionCantBeClosed;
3977 gFunctionHighestExternalRef = sc_max(gFunctionHighestExternalRef - 1, prevFunctionHighestExternalRef);
3978 }
3979
3980
linkNextNode(PyrParseNode * a,PyrParseNode * b)3981 PyrParseNode* linkNextNode(PyrParseNode* a, PyrParseNode* b) {
3982 if (a == nullptr)
3983 return b;
3984 if (b) {
3985 a->mTail->mNext = b;
3986 a->mTail = b->mTail;
3987 }
3988 return a;
3989 }
3990
linkAfterHead(PyrParseNode * a,PyrParseNode * b)3991 PyrParseNode* linkAfterHead(PyrParseNode* a, PyrParseNode* b) {
3992 b->mNext = a->mNext;
3993 if (!a->mNext)
3994 a->mTail = b;
3995 a->mNext = b;
3996 return a;
3997 }
3998
isSuperObjNode(PyrParseNode * node)3999 bool isSuperObjNode(PyrParseNode* node) {
4000 return node->mClassno == pn_PushNameNode && slotRawSymbol(&((PyrPushNameNode*)node)->mSlot) == s_super;
4001 }
4002
isThisObjNode(PyrParseNode * node)4003 bool isThisObjNode(PyrParseNode* node) {
4004 return node->mClassno == pn_PushNameNode && slotRawSymbol(&((PyrPushNameNode*)node)->mSlot) == s_this;
4005 }
4006
nodeListLength(PyrParseNode * node)4007 int nodeListLength(PyrParseNode* node) {
4008 int length = 0;
4009 for (; node; node = node->mNext)
4010 length++;
4011 return length;
4012 }
4013
4014
conjureSelectorIndex(PyrParseNode * node,PyrBlock * func,bool isSuper,PyrSymbol * selector,int * selType)4015 int conjureSelectorIndex(PyrParseNode* node, PyrBlock* func, bool isSuper, PyrSymbol* selector, int* selType) {
4016 int i;
4017 PyrObject* selectors;
4018 PyrSlot* slot;
4019 int newsize, flags;
4020
4021 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
4022 if (!isSuper) {
4023 if (selector == gSpecialSelectors[opmIf]) {
4024 *selType = selIf;
4025 return opmIf;
4026 } else if (selector == gSpecialSelectors[opmWhile]) {
4027 *selType = selWhile;
4028 return opmWhile;
4029 } else if (selector == gSpecialSelectors[opmAnd]) {
4030 *selType = selAnd;
4031 return opmAnd;
4032 } else if (selector == gSpecialSelectors[opmOr]) {
4033 *selType = selOr;
4034 return opmOr;
4035 } else if (selector == gSpecialSelectors[opmCase]) {
4036 *selType = selCase;
4037 return opmCase;
4038 } else if (selector == gSpecialSelectors[opmSwitch]) {
4039 *selType = selSwitch;
4040 return opmSwitch;
4041 } else if (selector == gSpecialSelectors[opmLoop]) {
4042 *selType = selLoop;
4043 return opmLoop;
4044 } else if (selector == gSpecialSelectors[opmQuestionMark]) {
4045 *selType = selQuestionMark;
4046 return opmAnd;
4047 } else if (selector == gSpecialSelectors[opmDoubleQuestionMark]) {
4048 *selType = selDoubleQuestionMark;
4049 return opmAnd;
4050 } else if (selector == gSpecialSelectors[opmExclamationQuestionMark]) {
4051 *selType = selExclamationQuestionMark;
4052 return opmAnd;
4053 }
4054
4055 for (i = 0; i < opmNumSpecialSelectors; ++i) {
4056 if (selector == gSpecialSelectors[i]) {
4057 *selType = selSpecial;
4058 return i;
4059 }
4060 }
4061
4062 for (i = 0; i < opNumUnarySelectors; ++i) {
4063 if (selector == gSpecialUnarySelectors[i]) {
4064 *selType = selUnary;
4065 return i;
4066 }
4067 }
4068
4069 for (i = 0; i < opNumBinarySelectors; ++i) {
4070 if (selector == gSpecialBinarySelectors[i]) {
4071 *selType = selBinary;
4072 return i;
4073 }
4074 }
4075 }
4076
4077 if (NotNil(&func->selectors)) {
4078 selectors = slotRawObject(&func->selectors);
4079 for (i = 0; i < selectors->size; ++i) {
4080 if (IsSym(&selectors->slots[i]) && slotRawSymbol(&selectors->slots[i]) == selector) {
4081 *selType = selNormal;
4082 return i;
4083 }
4084 }
4085 } else {
4086 selectors = (PyrObject*)newPyrArray(compileGC(), 2, flags, false);
4087 SetObject(&func->selectors, selectors);
4088 }
4089 // otherwise add it to the selectors table
4090
4091 if (selectors->size + 1 >= 256) {
4092 error("Selector table too big: too many classes, method selectors or function definitions in this function. "
4093 "Simplify the function.\n");
4094 post("Next selector was: %s\n", selector->name);
4095 nodePostErrorLine(node);
4096 compileErrors++;
4097 return 0;
4098 }
4099
4100 if (selectors->size + 1 > ARRAYMAXINDEXSIZE(selectors)) {
4101 // resize literal table
4102 newsize = ARRAYMAXINDEXSIZE(selectors) * 2;
4103 SetRaw(&func->selectors, (PyrObject*)newPyrArray(compileGC(), newsize, flags, false));
4104 memcpy(slotRawObject(&func->selectors)->slots, selectors->slots, selectors->size * sizeof(PyrSlot));
4105 slotRawObject(&func->selectors)->size = selectors->size;
4106 freePyrObject(selectors);
4107 selectors = slotRawObject(&func->selectors);
4108 }
4109 slot = selectors->slots + selectors->size++;
4110 SetSymbol(slot, selector);
4111
4112 *selType = selNormal;
4113 return selectors->size - 1;
4114 }
4115
conjureLiteralSlotIndex(PyrParseNode * node,PyrBlock * func,PyrSlot * slot)4116 int conjureLiteralSlotIndex(PyrParseNode* node, PyrBlock* func, PyrSlot* slot) {
4117 int i;
4118 PyrObject* selectors;
4119 PyrSlot* slot2;
4120 int newsize, flags;
4121
4122 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
4123 // lookup slot in selectors table
4124
4125 if (IsObj(&func->selectors)) {
4126 selectors = slotRawObject(&func->selectors);
4127 /*if (selectors->classptr != class_array) {
4128 post("compiling %s:%s\n", slotRawSymbol(&gCompilingClass->name)->name,
4129 slotRawSymbol(&gCompilingMethod->name)->name); post("selectors is a '%s'\n",
4130 selectors->classptr->name.us->name); dumpObjectSlot(slot); Debugger();
4131 }*/
4132 for (i = 0; i < selectors->size; ++i)
4133 if (SlotEq(&selectors->slots[i], slot))
4134 return i;
4135 } else {
4136 selectors = (PyrObject*)newPyrArray(compileGC(), 4, flags, false);
4137 SetObject(&func->selectors, selectors);
4138 }
4139 // otherwise add it to the selectors table
4140
4141 if (selectors->size + 1 >= 256) {
4142 error("Selector table too big: too many classes, method selectors or function definitions in this function. "
4143 "Simplify the function.\n");
4144 post("Next literal was:\n");
4145 dumpPyrSlot(slot);
4146 nodePostErrorLine(node);
4147 compileErrors++;
4148 return 0;
4149 }
4150 if (selectors->size + 1 > ARRAYMAXINDEXSIZE(selectors)) {
4151 // resize literal table
4152 newsize = ARRAYMAXINDEXSIZE(selectors) * 2;
4153 // resize literal table
4154 SetRaw(&func->selectors, (PyrObject*)newPyrArray(compileGC(), newsize, flags, false));
4155 memcpy(slotRawObject(&func->selectors)->slots, selectors->slots, selectors->size * sizeof(PyrSlot));
4156 slotRawObject(&func->selectors)->size = selectors->size;
4157 freePyrObject(selectors);
4158 selectors = slotRawObject(&func->selectors);
4159 }
4160 slot2 = selectors->slots + selectors->size++;
4161 slotCopy(slot2, slot);
4162
4163 return selectors->size - 1;
4164 }
4165
4166
conjureConstantIndex(PyrParseNode * node,PyrBlock * func,PyrSlot * slot)4167 int conjureConstantIndex(PyrParseNode* node, PyrBlock* func, PyrSlot* slot) {
4168 int i;
4169 PyrObject* constants;
4170 int newsize, flags;
4171
4172 flags = compilingCmdLine ? obj_immutable : obj_permanent | obj_immutable;
4173
4174 // lookup slot in constants table
4175 if (IsObj(&func->constants)) {
4176 constants = slotRawObject(&func->constants);
4177 for (i = 0; i < constants->size; ++i)
4178 if (SlotEq(&constants->slots[i], slot))
4179 return i;
4180 } else {
4181 constants = (PyrObject*)newPyrArray(compileGC(), 4, flags, false);
4182 SetObject(&func->constants, constants);
4183 }
4184
4185 // otherwise add it to the constants table
4186 if (constants->size + 1 > ARRAYMAXINDEXSIZE(constants)) {
4187 // resize literal table
4188 newsize = ARRAYMAXINDEXSIZE(constants) * 2;
4189 // resize literal table
4190 SetRaw(&func->constants, (PyrObject*)newPyrArray(compileGC(), newsize, flags, false));
4191 memcpy(slotRawObject(&func->constants)->slots, constants->slots, constants->size * sizeof(PyrSlot));
4192 slotRawObject(&func->constants)->size = constants->size;
4193 freePyrObject((PyrObject*)constants);
4194 constants = slotRawObject(&func->constants);
4195 }
4196 slotCopy(&constants->slots[constants->size++], slot);
4197
4198 return constants->size - 1;
4199 }
4200
findVarName(PyrBlock * func,PyrClass ** classobj,PyrSymbol * name,int * varType,int * level,int * index,PyrBlock ** tempfunc)4201 bool findVarName(PyrBlock* func, PyrClass** classobj, PyrSymbol* name, int* varType, int* level, int* index,
4202 PyrBlock** tempfunc) {
4203 int i, j, k;
4204 int numargs;
4205 PyrSymbol *argname, *varname;
4206 PyrMethodRaw* methraw;
4207
4208 // postfl("->findVarName %s\n", name->name);
4209 // find var in enclosing blocks, instance, class
4210 if (name == s_super) {
4211 gFunctionCantBeClosed = true;
4212 name = s_this;
4213 }
4214 if (name->name[0] >= 'A' && name->name[0] <= 'Z')
4215 return false;
4216 for (j = 0; func; func = slotRawBlock(&func->contextDef), ++j) {
4217 methraw = METHRAW(func);
4218 numargs = methraw->posargs;
4219 for (i = 0; i < numargs; ++i) {
4220 argname = slotRawSymbolArray(&func->argNames)->symbols[i];
4221 // postfl(" %d %d arg '%s' '%s'\n", j, i, argname->name, name->name);
4222 if (argname == name) {
4223 *level = j;
4224 *index = i;
4225 *varType = varTemp;
4226 if (tempfunc)
4227 *tempfunc = func;
4228 if (j > gFunctionHighestExternalRef)
4229 gFunctionHighestExternalRef = j;
4230 return true;
4231 }
4232 }
4233 for (i = 0, k = numargs; i < methraw->numvars; ++i, ++k) {
4234 varname = slotRawSymbolArray(&func->varNames)->symbols[i];
4235 // postfl(" %d %d %d var '%s' '%s'\n", j, i, k, varname->name, name->name);
4236 if (varname == name) {
4237 *level = j;
4238 *index = k;
4239 *varType = varTemp;
4240 if (tempfunc)
4241 *tempfunc = func;
4242 if (j > gFunctionHighestExternalRef)
4243 gFunctionHighestExternalRef = j;
4244 return true;
4245 }
4246 }
4247 }
4248
4249 if (classFindInstVar(*classobj, name, index)) {
4250 *level = 0;
4251 *varType = varInst;
4252 if (gCompilingClass != class_interpreter)
4253 gFunctionCantBeClosed = true;
4254 return true;
4255 }
4256 if (classFindClassVar(classobj, name, index)) {
4257 *varType = varClass;
4258 if (gCompilingClass != class_interpreter)
4259 gFunctionCantBeClosed = true;
4260 return true;
4261 }
4262 if (classFindConst(classobj, name, index)) {
4263 *varType = varConst;
4264 // if (gCompilingClass != class_interpreter) gFunctionCantBeClosed = true;
4265 return true;
4266 }
4267 if (name == s_curProcess) {
4268 *varType = varPseudo;
4269 *index = opgProcess;
4270 return true;
4271 }
4272 if (name == s_curThread) {
4273 *varType = varPseudo;
4274 *index = opgThread;
4275 return true;
4276 }
4277 if (name == s_curMethod) {
4278 *varType = varPseudo;
4279 *index = opgMethod;
4280 return true;
4281 }
4282 if (name == s_curBlock) {
4283 *varType = varPseudo;
4284 *index = opgFunctionDef;
4285 return true;
4286 }
4287 if (name == s_curClosure) {
4288 *varType = varPseudo;
4289 *index = opgFunction;
4290 return true;
4291 }
4292 return false;
4293 }
4294
4295 extern PyrSymbol* s_env;
4296
initSpecialClasses()4297 void initSpecialClasses() {
4298 gSpecialClasses[op_class_object] = s_object;
4299 gSpecialClasses[op_class_symbol] = s_symbol;
4300 gSpecialClasses[op_class_nil] = s_nil;
4301 gSpecialClasses[op_class_boolean] = s_boolean;
4302 gSpecialClasses[op_class_true] = s_true;
4303 gSpecialClasses[op_class_false] = s_false;
4304 gSpecialClasses[op_class_magnitude] = s_magnitude;
4305 gSpecialClasses[op_class_char] = s_char;
4306 gSpecialClasses[op_class_number] = s_number;
4307 gSpecialClasses[op_class_complex] = s_complex;
4308 gSpecialClasses[op_class_simple_number] = s_simple_number;
4309 gSpecialClasses[op_class_int] = s_int;
4310 gSpecialClasses[op_class_float] = s_float;
4311 gSpecialClasses[op_class_method] = s_method;
4312 gSpecialClasses[op_class_fundef] = s_fundef;
4313 gSpecialClasses[op_class_stream] = s_stream;
4314 gSpecialClasses[op_class_func] = s_func;
4315 gSpecialClasses[op_class_frame] = s_frame;
4316 gSpecialClasses[op_class_process] = s_process;
4317 gSpecialClasses[op_class_main] = s_main;
4318 gSpecialClasses[op_class_class] = s_class;
4319 gSpecialClasses[op_class_string] = s_string;
4320
4321 gSpecialClasses[op_class_collection] = s_collection;
4322 gSpecialClasses[op_class_sequenceable_collection] = s_sequenceable_collection;
4323 gSpecialClasses[op_class_arrayed_collection] = s_arrayed_collection;
4324 gSpecialClasses[op_class_array] = s_array;
4325 gSpecialClasses[op_class_int8array] = s_int8array;
4326 gSpecialClasses[op_class_int16array] = s_int16array;
4327 gSpecialClasses[op_class_int32array] = s_int32array;
4328 gSpecialClasses[op_class_floatarray] = s_floatarray;
4329 gSpecialClasses[op_class_signal] = s_signal;
4330 gSpecialClasses[op_class_doublearray] = s_doublearray;
4331 gSpecialClasses[op_class_symbolarray] = s_symbolarray;
4332 gSpecialClasses[op_class_list] = s_list;
4333 gSpecialClasses[op_class_linkedlist] = s_linkedlist;
4334 gSpecialClasses[op_class_bag] = s_bag;
4335 gSpecialClasses[op_class_set] = s_set;
4336 gSpecialClasses[op_class_identityset] = s_identityset;
4337 gSpecialClasses[op_class_dictionary] = s_dictionary;
4338 gSpecialClasses[op_class_identitydictionary] = s_identitydictionary;
4339 gSpecialClasses[op_class_sortedlist] = s_sortedlist;
4340
4341 gSpecialClasses[op_class_synth] = s_synth;
4342 gSpecialClasses[op_class_ref] = s_ref;
4343 gSpecialClasses[op_class_environment] = s_environment;
4344 gSpecialClasses[op_class_event] = s_event;
4345 gSpecialClasses[op_class_wavetable] = s_wavetable;
4346 gSpecialClasses[op_class_env] = s_env;
4347 gSpecialClasses[op_class_routine] = s_routine;
4348 gSpecialClasses[op_class_color] = s_color;
4349 gSpecialClasses[op_class_rect] = s_rect;
4350
4351 // Infinitum, Point, Rect, ??
4352 }
4353
initSpecialSelectors()4354 void initSpecialSelectors() {
4355 PyrSymbol** sel;
4356 long i;
4357
4358 sel = gSpecialUnarySelectors;
4359 sel[opNeg] = getsym("neg");
4360 sel[opRecip] = getsym("reciprocal");
4361 sel[opNot] = getsym("not");
4362 sel[opIsNil] = getsym("isNil");
4363 sel[opNotNil] = getsym("notNil");
4364 sel[opBitNot] = getsym("bitNot");
4365 sel[opAbs] = getsym("abs");
4366 sel[opAsFloat] = getsym("asFloat");
4367 sel[opAsInteger] = getsym("asInteger");
4368 sel[opCeil] = getsym("ceil"); // 5
4369 sel[opFloor] = getsym("floor");
4370 sel[opFrac] = getsym("frac");
4371 sel[opSign] = getsym("sign");
4372 sel[opSquared] = getsym("squared");
4373 sel[opCubed] = getsym("cubed"); // 10
4374 sel[opSqrt] = getsym("sqrt");
4375 sel[opExp] = getsym("exp");
4376 sel[opMIDICPS] = getsym("midicps");
4377 sel[opCPSMIDI] = getsym("cpsmidi");
4378 sel[opMIDIRatio] = getsym("midiratio");
4379 sel[opRatioMIDI] = getsym("ratiomidi");
4380 sel[opAmpDb] = getsym("ampdb"); // 15
4381 sel[opDbAmp] = getsym("dbamp");
4382 sel[opOctCPS] = getsym("octcps");
4383 sel[opCPSOct] = getsym("cpsoct");
4384 sel[opLog] = getsym("log");
4385 sel[opLog2] = getsym("log2"); // 20
4386 sel[opLog10] = getsym("log10");
4387 sel[opSin] = getsym("sin");
4388 sel[opCos] = getsym("cos");
4389 sel[opTan] = getsym("tan");
4390 sel[opArcSin] = getsym("asin"); // 25
4391 sel[opArcCos] = getsym("acos");
4392 sel[opArcTan] = getsym("atan");
4393 sel[opSinH] = getsym("sinh");
4394 sel[opCosH] = getsym("cosh");
4395 sel[opTanH] = getsym("tanh"); // 30
4396 sel[opRand] = getsym("rand");
4397 sel[opRand2] = getsym("rand2");
4398 sel[opLinRand] = getsym("linrand");
4399 sel[opBiLinRand] = getsym("bilinrand");
4400 sel[opSum3Rand] = getsym("sum3rand");
4401 /*
4402 sel[opExpRand] = getsym("exprand");
4403 sel[opBiExpRand] = getsym("biexprand");
4404 sel[opGammaRand] = getsym("gammarand");
4405 sel[opGaussRand] = getsym("gaussrand");
4406 sel[opPoiRand] = getsym("poirand");
4407 */
4408 sel[opDistort] = getsym("distort");
4409 sel[opSoftClip] = getsym("softclip");
4410 sel[opCoin] = getsym("coin");
4411
4412 sel[opRectWindow] = getsym("rectWindow");
4413 sel[opHanWindow] = getsym("hanWindow");
4414 sel[opWelchWindow] = getsym("welWindow");
4415 sel[opTriWindow] = getsym("triWindow");
4416
4417 sel[opSCurve] = getsym("scurve");
4418 sel[opRamp] = getsym("ramp");
4419
4420 sel[opDigitValue] = getsym("digitValue");
4421 sel[opSilence] = getsym("silence");
4422 sel[opThru] = getsym("thru");
4423
4424
4425 sel = gSpecialBinarySelectors;
4426
4427 sel[opAdd] = getsym("+");
4428 sel[opSub] = getsym("-");
4429 sel[opMul] = getsym("*");
4430
4431 sel[opFDiv] = getsym("/");
4432 sel[opIDiv] = getsym("div");
4433 sel[opMod] = getsym("mod");
4434 sel[opEQ] = getsym("==");
4435 sel[opNE] = getsym("!=");
4436 sel[opLT] = getsym("<");
4437 sel[opGT] = getsym(">");
4438 sel[opLE] = getsym("<=");
4439 sel[opGE] = getsym(">=");
4440 // sel[opIdentical] = getsym("===");
4441 // sel[opNotIdentical] = getsym("!==");
4442 sel[opMin] = getsym("min");
4443 sel[opMax] = getsym("max");
4444 sel[opBitAnd] = getsym("bitAnd");
4445 sel[opBitOr] = getsym("bitOr");
4446 sel[opBitXor] = getsym("bitXor");
4447 sel[opLCM] = getsym("lcm");
4448 sel[opGCD] = getsym("gcd");
4449 sel[opRound] = getsym("round");
4450 sel[opRoundUp] = getsym("roundUp");
4451 sel[opTrunc] = getsym("trunc");
4452 sel[opAtan2] = getsym("atan2");
4453 sel[opHypot] = getsym("hypot");
4454 sel[opHypotx] = getsym("hypotApx");
4455 sel[opPow] = getsym("pow");
4456 sel[opShiftLeft] = getsym("leftShift");
4457 sel[opShiftRight] = getsym("rightShift");
4458 sel[opUnsignedShift] = getsym("unsignedRightShift");
4459 sel[opFill] = getsym("fill");
4460 sel[opRing1] = getsym("ring1"); // a * (b + 1) == a * b + a
4461 sel[opRing2] = getsym("ring2"); // a * b + a + b
4462 sel[opRing3] = getsym("ring3"); // a*a*b
4463 sel[opRing4] = getsym("ring4"); // a*a*b - a*b*b
4464 sel[opDifSqr] = getsym("difsqr"); // a*a - b*b
4465 sel[opSumSqr] = getsym("sumsqr"); // a*a + b*b
4466 sel[opSqrSum] = getsym("sqrsum"); // (a + b)^2
4467 sel[opSqrDif] = getsym("sqrdif"); // (a - b)^2
4468 sel[opAbsDif] = getsym("absdif"); //
4469 sel[opThresh] = getsym("thresh"); //
4470 sel[opAMClip] = getsym("amclip"); //
4471 sel[opScaleNeg] = getsym("scaleneg"); //
4472 sel[opClip2] = getsym("clip2");
4473 sel[opFold2] = getsym("fold2");
4474 sel[opWrap2] = getsym("wrap2");
4475 sel[opExcess] = getsym("excess");
4476 sel[opFirstArg] = getsym("firstArg");
4477 sel[opRandRange] = getsym("rrand");
4478 sel[opExpRandRange] = getsym("exprand");
4479
4480
4481 sel = gSpecialSelectors;
4482
4483 sel[opmNew] = getsym("new");
4484 sel[opmNewClear] = getsym("newClear");
4485 sel[opmNewCopyArgs] = getsym("newCopyArgs");
4486 sel[opmInit] = getsym("init");
4487 sel[opmAt] = getsym("at");
4488 sel[opmPut] = getsym("put");
4489 sel[opmNext] = getsym("next");
4490 sel[opmReset] = getsym("reset");
4491 sel[opmValue] = getsym("value");
4492 sel[opmCopyToEnd] = getsym("copyToEnd"); // used by multiple assignment
4493 // sel[opmIsNil] = getsym("isNil");
4494 // sel[opmNotNil] = getsym("notNil");
4495 sel[opmSize] = getsym("size");
4496 sel[opmClass] = getsym("class");
4497 sel[opmIf] = getsym("if");
4498 sel[opmWhile] = getsym("while");
4499 sel[opmFor] = getsym("for");
4500 sel[opmAnd] = getsym("and");
4501 sel[opmOr] = getsym("or");
4502 sel[opmCase] = getsym("case");
4503 sel[opmSwitch] = getsym("switch");
4504 sel[opmIdentical] = getsym("===");
4505 sel[opmNotIdentical] = getsym("!==");
4506
4507 sel[opmPrint] = getsym("print");
4508 sel[opmAdd] = getsym("add");
4509 sel[opmRemove] = getsym("remove");
4510 sel[opmIndexOf] = getsym("indexOf");
4511 sel[opmWrapAt] = getsym("wrapAt");
4512 sel[opmClipAt] = getsym("clipAt");
4513 sel[opmFoldAt] = getsym("foldAt");
4514 sel[opmWrapPut] = getsym("wrapPut");
4515 sel[opmClipPut] = getsym("clipPut");
4516 sel[opmFoldPut] = getsym("foldPut");
4517 sel[opmDo] = getsym("do");
4518 sel[opmCollect] = getsym("collect");
4519 sel[opmSelect] = getsym("select");
4520 sel[opmReject] = getsym("reject");
4521 sel[opmAny] = getsym("any");
4522 sel[opmEvery] = getsym("every");
4523 sel[opmFind] = getsym("find");
4524
4525 sel[opmChoose] = getsym("choose");
4526
4527 sel[opmValueList] = getsym("valueList");
4528 sel[opmAddFirst] = getsym("addFirst");
4529
4530 sel[opmPrimitiveFailed] = getsym("primitiveFailed");
4531 sel[opmSubclassResponsibility] = getsym("subclassResponsibility");
4532 sel[opmShouldNotImplement] = getsym("shouldNotImplement");
4533 sel[opmDoesNotUnderstand] = getsym("doesNotUnderstand"); // not really needed
4534 sel[opmNotYetImplemented] = getsym("notYetImplemented");
4535
4536 sel[opmAtSign] = getsym("@");
4537 sel[opmWrapAtSign] = getsym("@@");
4538 sel[opmClipAtSign] = getsym("|@|");
4539 sel[opmFoldAtSign] = getsym("@|@");
4540
4541 sel[opmMultiNew] = getsym("multiNew"); // UGens
4542 sel[opmMultiNewList] = getsym("multiNewList"); // UGens
4543 sel[opmAR] = getsym("ar"); // UGens
4544 sel[opmKR] = getsym("kr"); // UGens
4545 sel[opmIR] = getsym("ir"); // UGens
4546
4547 sel[opmEnvirGet] = getsym("envirGet");
4548 sel[opmEnvirPut] = getsym("envirPut");
4549
4550 sel[opmHalt] = getsym("halt");
4551 sel[opmForBy] = getsym("forBy");
4552 sel[opmForSeries] = getsym("forSeries");
4553 sel[opmReverseDo] = getsym("reverseDo");
4554 sel[opmLoop] = getsym("loop");
4555 sel[opmNonBooleanError] = getsym("mustBeBoolean");
4556
4557 sel[opmCopy] = getsym("copy");
4558 sel[opmPerformList] = getsym("performList");
4559 sel[opmIsKindOf] = getsym("isKindOf");
4560 sel[opmPostln] = getsym("postln");
4561 sel[opmAsString] = getsym("asString");
4562
4563 sel[opmPlusPlus] = getsym("++");
4564 sel[opmLTLT] = getsym("<<");
4565 sel[opmQuestionMark] = getsym("?");
4566 sel[opmDoubleQuestionMark] = getsym("??");
4567 sel[opmExclamationQuestionMark] = getsym("!?");
4568
4569 sel[opmYield] = getsym("yield");
4570 sel[opmName] = getsym("name");
4571 sel[opmMulAdd] = getsym("madd");
4572
4573 sel[opmSeries] = getsym("series");
4574
4575 for (i = 0; i < opNumUnarySelectors; ++i) {
4576 gSpecialUnarySelectors[i]->specialIndex = i;
4577 }
4578 for (i = 0; i < opNumBinarySelectors; ++i) {
4579 gSpecialBinarySelectors[i]->specialIndex = i;
4580 }
4581 }
4582
findSpecialClassName(PyrSymbol * className,int * index)4583 bool findSpecialClassName(PyrSymbol* className, int* index) {
4584 int i;
4585 for (i = 0; i < op_NumSpecialClasses; ++i) {
4586 if (gSpecialClasses[i] == className) {
4587 *index = i;
4588 return true;
4589 }
4590 }
4591 return false;
4592 }
4593