Node* AssignmentNode::expandToAsebaTree(std::wostream *dump, unsigned int index) { assert(children.size() == 2); MemoryVectorNode* leftVector = dynamic_cast<MemoryVectorNode*>(children[0]); if (!leftVector) throw TranslatableError(sourcePos, ERROR_INCORRECT_LEFT_VALUE).arg(children[0]->toNodeName()); leftVector->setWrite(true); Node* rightVector = children[1]; std::auto_ptr<BlockNode> block(new BlockNode(sourcePos)); for (unsigned int i = 0; i < leftVector->getVectorSize(); i++) { // expand to left[i] = right[i] std::auto_ptr<AssignmentNode> assignment(new AssignmentNode(sourcePos)); assignment->children.push_back(leftVector->expandToAsebaTree(dump, i)); assignment->children.push_back(rightVector->expandToAsebaTree(dump, i)); block->children.push_back(assignment.release()); } delete this; return block.release(); }
//! Assignment between vectors is expanded into multiple scalar assignments Node* AssignmentNode::expandVectorialNodes(std::wostream *dump, Compiler* compiler, unsigned int index) { assert(children.size() == 2); // left vector should reference a memory location MemoryVectorNode* leftVector = dynamic_cast<MemoryVectorNode*>(children[0]); if (!leftVector) throw TranslatableError(sourcePos, ERROR_INCORRECT_LEFT_VALUE).arg(children[0]->toNodeName()); leftVector->setWrite(true); // right vector can be anything Node* rightVector = children[1]; // check if the left vector appears somewhere on the right side if (matchNameInMemoryVector(rightVector, leftVector->arrayName) && leftVector->getVectorSize() > 1) { // in such case, there is a risk of involuntary overwriting the content // we need to throw in a temporary variable to avoid this risk std::auto_ptr<BlockNode> tempBlock(new BlockNode(sourcePos)); // tempVar = rightVector std::auto_ptr<AssignmentNode> temp(compiler->allocateTemporaryVariable(sourcePos, rightVector->deepCopy())); MemoryVectorNode* tempVar = dynamic_cast<MemoryVectorNode*>(temp->children[0]); assert(tempVar); tempBlock->children.push_back(temp.release()); // leftVector = tempVar temp.reset(new AssignmentNode(sourcePos, leftVector->deepCopy(), tempVar->deepCopy())); tempBlock->children.push_back(temp.release()); return tempBlock->expandVectorialNodes(dump, compiler); // tempBlock will be reclaimed } // else std::auto_ptr<BlockNode> block(new BlockNode(sourcePos)); // top-level block for (unsigned int i = 0; i < leftVector->getVectorSize(); i++) { // expand to left[i] = right[i] block->children.push_back(new AssignmentNode(sourcePos, leftVector->expandVectorialNodes(dump, compiler, i), rightVector->expandVectorialNodes(dump, compiler, i))); } return block.release(); }