in libraries/value/src/CppEmitterContext.cpp [771:880]
Value CppEmitterContext::BinaryOperationImpl(ValueBinaryOperation op, Value destination, Value source)
{
if (destination.IsConstant() && source.IsConstant())
{
return _computeContext.BinaryOperation(op, destination, source);
}
std::string opStr;
bool canSelfAssign;
std::tie(opStr, canSelfAssign) = [op]() -> std::pair<std::string, bool> {
switch (op)
{
case ValueBinaryOperation::add:
return { " += ", true };
case ValueBinaryOperation::divide:
return { " /= ", true };
case ValueBinaryOperation::modulus:
return { " %= ", true };
case ValueBinaryOperation::multiply:
return { " *= ", true };
case ValueBinaryOperation::subtract:
return { " -= ", true };
case ValueBinaryOperation::logicalAnd:
return { " && ", false };
case ValueBinaryOperation::logicalOr:
return { " || ", false };
default:
throw LogicException(LogicExceptionErrors::illegalState);
}
}();
if (destination.IsDefined())
{
if (destination.GetLayout() != source.GetLayout())
{
throw LogicException(LogicExceptionErrors::illegalState);
}
if (destination.GetBaseType() != source.GetBaseType())
{
throw LogicException(LogicExceptionErrors::illegalState);
}
}
else
{
if (!source.IsConstrained())
{
throw LogicException(LogicExceptionErrors::illegalState);
}
return source;
}
const auto& layout = destination.GetLayout();
auto destStr = GetNameImpl(destination);
auto srcStr = GetNameImpl(source);
if (layout == ScalarLayout)
{
auto sourceString = ScalarToString(source);
switch (op)
{
case ValueBinaryOperation::add:
[[fallthrough]];
case ValueBinaryOperation::subtract:
if (sourceString == "0") // destination = destination { +, - } 0
{
return destination;
}
break;
case ValueBinaryOperation::divide:
[[fallthrough]];
case ValueBinaryOperation::multiply:
if (sourceString == "1") // destination = destination { /, * } 1
{
return destination;
}
break;
default:
break;
}
if (canSelfAssign)
{
Out() << destStr << "[0]" << opStr << sourceString << ";\n";
}
else
{
Out() << destStr << "[0] = " << destStr << "[0]" << opStr << sourceString << ";\n";
}
}
else
{
auto emittableSource = EnsureEmittable(source);
srcStr = emittableSource.GetName();
auto iterationVariable = UniqueName("index");
Out() << "for (size_t " << iterationVariable << " = 0; " << iterationVariable << " < " << layout.GetMemorySize() << "; " << iterationVariable << " += " << layout.GetCumulativeIncrement(layout.NumDimensions() - 1) << ") {\n";
Indented([&] {
if (canSelfAssign)
{
Out() << destStr << "[" << iterationVariable << "]" << opStr << srcStr << "[" << iterationVariable << "];\n";
}
else
{
Out() << destStr << "[" << iterationVariable << "] = " << destStr << "[" << iterationVariable << "]" << opStr << srcStr << "[" << iterationVariable << "];\n";
}
});
Out() << "}\n\n";
}
return destination;
}