Esempio n. 1
0
// Flatten out all expressions with a given head.
void Expression::Flatten(const string head)
{
	ExprVector newLeaves;
	newLeaves.reserve(leaves.size());
	for(ExprVector::const_iterator leaf = leaves.begin(); leaf != leaves.end(); ++leaf)
		if((*leaf)->FunctionName() == head)
		{
			for(ExprVector::const_iterator subLeaf = (*leaf)->Leaves().begin(); subLeaf != (*leaf)->Leaves().end(); ++subLeaf)
				newLeaves.push_back(*subLeaf);
			(*leaf)->Leaves().clear();
			delete *leaf;
		}
		else
			newLeaves.push_back(*leaf);
	leaves = newLeaves;
}
Esempio n. 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);
	}
}