void LeafSubsetCallback::Execute(ExprVectorPositions selection, bool &continueGenerating)
{
	MatchLeafCallback leafCallback;
	leafCallback.Initialize(expression, pattern, calculator, parentCallback);
	leafCallback.InitializeLeaf(subsetGenerator, curPatternLeaf);
	if(selection.size() != 1)
	{
		Definition *functionDef = pattern->FunctionDefinition(calculator);
		AttributeSet attributes;
		if(functionDef)
			attributes = functionDef->Attributes();
		auto_ptr<Expression> sequence(new Expression);
		sequence->Leaves().reserve(selection.size());
		for(ExprVectorPositions::const_iterator leaf = selection.begin(); leaf != selection.end(); ++leaf)
			sequence->AppendLeaf(**leaf);
		if(attributes.Contains(atFlat) && selection.size() > 1)
		{
			sequence->Head(pattern->Head()->Clone());
			continueGenerating = sequence->Matches(*curPatternLeaf, calculator, subs, true, leafCallback);
			delete sequence->Head();
			sequence->Head(0);
			if(!continueGenerating)
			{
				sequence->Leaves().clear();
				return;
			}
		}
		sequence->Head(new Expression("Sequence"));
		continueGenerating = sequence->Matches(*curPatternLeaf, calculator, subs, true, leafCallback);
		sequence->Leaves().clear();
	}
	else
	{
		Expression *leaf = **selection.begin();
		continueGenerating = leaf->Matches(*curPatternLeaf, calculator, subs, true, leafCallback);
	}
}
Exemple #2
0
// Evaluates an expression. Considers all rules etc. In some cases there are simply
// no changes possible and the expression remains unchanged (e.g. a+b).
void Expression::Evaluate(Calculator *calculator, int32 recursions)
{
	// Since the expression is expected to be already structured, it must have a head.
	if(!head)
		throw DefinitionException("Expression::Evaluate: Expression has no head.");
	if(recursions > Max_Evaluate_Recursions)
		throw LimitationException("Maximum number of recursive definitions reached.");
	head->Evaluate(calculator, recursions);
	// If Expression is a symbol
	Definition *symbolDef = SymbolDefinition(calculator);
	if(symbolDef)
	{
		// Look if value is defined
		if(symbolDef->Value())
		{
			bool changed = !SameExpression(symbolDef->Value());
			AssignCloned(symbolDef->Value());
			if(changed)
				Evaluate(calculator, recursions + 1);
		}
	}
	// If head is a pure function
	if(head->FunctionName() == "Function" && head->LeafCount() == 1)
	{
		ExprPtr body(head->leaves.at(0));
		body->SubstituteSlots(leaves);
		body->Evaluate(calculator, recursions);
		head->leaves.clear();
		MoveNotCloned(body);
	}
	// If Expression is Function call
	Definition *def = FunctionDefinition(calculator);
	if(def)
	{
		AttributeSet attributes = def->Attributes();
		// Evaluate child leaves if no Hold attribute
		if(!attributes.Contains(atHoldAll) && !attributes.Contains(atHoldAllComplete))
		{
			if(!attributes.Contains(atHoldFirst))
				if(!leaves.empty())
					leaves.at(0)->Evaluate(calculator, recursions);
			if(!attributes.Contains(atHoldRest))
				if(leaves.size() > 1)
					for(ExprVector::const_iterator leaf = leaves.begin()+1; leaf != leaves.end(); ++leaf)
						(*leaf)->Evaluate(calculator, recursions);
		}
		// Flatten out sequences
		if(!attributes.Contains(atSequenceHold))
		{
			Flatten("Sequence");
		}
		// Apply down values
		for(ExprVector::const_iterator leaf = leaves.begin(); leaf != leaves.end(); ++leaf)
		{
			Definition *def(0);
			if((*leaf)->SymbolHead())
				def = (*leaf)->SymbolDefinition(calculator);
			else if((*leaf)->IsFunctionCall())
				def = (*leaf)->FrontFunctionDefinition(calculator);
			if(def)
			{
				bool changed(false);
				if(def->ApplyUpValues(this, calculator, &changed) && changed)
				{
					Evaluate(calculator, recursions + 1);
					return;
				}
			}
		}
		// Apply Flat attribute
		if(attributes.Contains(atFlat))
		{
			Flatten(FunctionName());
		}
		// Apply OneIdentity attribute
		if(attributes.Contains(atOneIdentity))
		{
			if(ApplyOneIdentity())
				return;
		}
		// Apply Listable attribute
		if(attributes.Contains(atListable))
		{
			// Determine resulting list length, check if there are lists with different lengths
			bool listFound(false);
			ExprVector::size_type listSize(0);
			for(ExprVector::const_iterator leaf = leaves.begin(); leaf != leaves.end(); ++leaf)
				if((*leaf)->FunctionName() == "List")
					if(!listFound)
					{
						listSize = (*leaf)->LeafCount();
						listFound = true;
					}
					else
						if(listSize != (*leaf)->LeafCount())
							throw EvaluateException("Listable operation requires lists of the same length.");
			// Construct resulting list
			if(listFound)
			{
				ExprVector items;
				// Number of resulting list items = items in operand list
				items.reserve(listSize);
				// Loop through list items
				for(ExprVector::size_type position = 0; position < listSize; ++position)
				{
					// List item = function call, number of operands = number of original operands
					Expression *item = new Expression(FunctionName(), leaves.size());
					for(ExprVector::iterator itemLeaf = leaves.begin(); itemLeaf != leaves.end(); ++itemLeaf)
					{
						if((*itemLeaf)->FunctionName() == "List")
						{
							// Add corresponding list item
							item->AppendLeaf(*((*itemLeaf)->leaves.begin() + position));
						}
						else
						{
							// Add "whole" item (clone if necessary)
							if(position == 0)
								item->AppendLeaf(*itemLeaf);
							else
								item->AppendLeaf((*itemLeaf)->Clone());
						}
					}
					items.push_back(item);
				}
				// Delete lists (elements are now in resulting list)
				for(ExprVector::iterator itemLeaf = leaves.begin(); itemLeaf != leaves.end(); ++itemLeaf)
					if((*itemLeaf)->FunctionName() == "List")
					{
						(*itemLeaf)->leaves.clear();
						delete *itemLeaf;
					}
				delete head;
				head = new Expression("List");
				leaves = items;
				// Evaluate the list for itself
				Evaluate(calculator, recursions);
				return;
			}
		}
		// Apply Orderless attribute
		if(attributes.Contains(atOrderless))
		{
			std::sort(leaves.begin(), leaves.end(), &Compare);
		}
		// Apply down value rules
		bool changed(false);
		if(def->ApplyDownValues(this, calculator, &changed))
		{
			if(changed)
				Evaluate(calculator, recursions + 1);
			return;
		}
		// Execute linked operator, if specified
		if(def->Predef())
			def->Predef()->Apply(this, calculator, recursions);
	}
	else
	{
		// Otherwise simply evaluate the leaves
		for(ExprVector::const_iterator leaf = leaves.begin(); leaf != leaves.end(); ++leaf)
			(*leaf)->Evaluate(calculator, recursions);
	}
}