Files
Upsilon/poincare/src/symbol_abstract.cpp
Hugo Saint-Vignes 04b2683af2 [poincare] Replaced an escape case with an assert only
Change-Id: I5ea501beeb42577a25dd752f8b9492210abd38fc
2020-11-16 17:12:42 +01:00

91 lines
3.6 KiB
C++

#include <poincare/symbol_abstract.h>
#include <poincare/complex_cartesian.h>
#include <poincare/constant.h>
#include <poincare/function.h>
#include <poincare/rational.h>
#include <poincare/sequence.h>
#include <poincare/symbol.h>
#include <poincare/undefined.h>
#include <poincare/helpers.h>
#include <ion/unicode/utf8_decoder.h>
#include <ion/unicode/utf8_helper.h>
#include <string.h>
#include <algorithm>
namespace Poincare {
size_t SymbolAbstractNode::size() const {
return nodeSize() + strlen(name()) + 1;
}
ExpressionNode::Sign SymbolAbstractNode::sign(Context * context) const {
SymbolAbstract s(this);
Expression e = SymbolAbstract::Expand(s, context, true);
if (e.isUninitialized()) {
return Sign::Unknown;
}
return e.sign(context);
}
Expression SymbolAbstractNode::setSign(ExpressionNode::Sign s, ReductionContext reductionContext) {
SymbolAbstract sa(this);
Expression e = SymbolAbstract::Expand(sa, reductionContext.context(), true);
assert(!e.isUninitialized());
sa.replaceWithInPlace(e);
return e.setSign(s, reductionContext);
}
int SymbolAbstractNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted, bool ignoreParentheses) const {
assert(type() == e->type());
return strcmp(name(), static_cast<const SymbolAbstractNode *>(e)->name());
}
int SymbolAbstractNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return std::min<int>(strlcpy(buffer, name(), bufferSize), bufferSize - 1);
}
template <typename T, typename U>
T SymbolAbstract::Builder(const char * name, int length) {
size_t size = sizeof(U) + length + 1;
void * bufferNode = TreePool::sharedPool()->alloc(size);
U * node = new (bufferNode) U(name, length);
TreeHandle h = TreeHandle::BuildWithGhostChildren(node);
return static_cast<T &>(h);
}
bool SymbolAbstract::hasSameNameAs(const SymbolAbstract & other) const {
return strcmp(other.name(), name()) == 0;
}
size_t SymbolAbstract::TruncateExtension(char * dst, const char * src, size_t len) {
return UTF8Helper::CopyUntilCodePoint(dst, len, src, '.');
}
bool SymbolAbstract::matches(const SymbolAbstract & symbol, ExpressionTest test, Context * context) {
Expression e = SymbolAbstract::Expand(symbol, context, false);
return !e.isUninitialized() && e.recursivelyMatches(test, context, ExpressionNode::SymbolicComputation::DoNotReplaceAnySymbol);
}
Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context * context, bool clone, ExpressionNode::SymbolicComputation symbolicComputation) {
bool shouldNotReplaceSymbols = symbolicComputation == ExpressionNode::SymbolicComputation::ReplaceDefinedFunctionsWithDefinitions;
if (symbolicComputation == ExpressionNode::SymbolicComputation::DoNotReplaceAnySymbol
|| (symbol.type() == ExpressionNode::Type::Symbol && shouldNotReplaceSymbols))
{
return clone ? symbol.clone() : *const_cast<SymbolAbstract *>(&symbol);
}
assert(context);
Expression e = context->expressionForSymbolAbstract(symbol, clone);
/* Replace all the symbols iteratively. This prevents a memory failure when
* symbols are defined circularly. */
e = Expression::ExpressionWithoutSymbols(e, context, shouldNotReplaceSymbols);
return e;
}
template Constant SymbolAbstract::Builder<Constant, ConstantNode>(char const*, int);
template Function SymbolAbstract::Builder<Function, FunctionNode>(char const*, int);
template Sequence SymbolAbstract::Builder<Sequence, SequenceNode>(char const*, int);
template Symbol SymbolAbstract::Builder<Symbol, SymbolNode>(char const*, int);
}