mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
127 lines
5.5 KiB
C++
127 lines
5.5 KiB
C++
#include "global_context.h"
|
|
#include "storage_cartesian_function.h"
|
|
#include <poincare/helpers.h>
|
|
#include <poincare/undefined.h>
|
|
#include <poincare/preferences.h>
|
|
#include <assert.h>
|
|
#include <ion.h>
|
|
|
|
using namespace Poincare;
|
|
|
|
namespace Shared {
|
|
|
|
constexpr char GlobalContext::expExtension[];
|
|
constexpr char GlobalContext::funcExtension[];
|
|
//constexpr char GlobalContext::seqExtension[];
|
|
|
|
bool GlobalContext::SymbolAbstractNameIsFree(const char * baseName) {
|
|
return SymbolAbstractRecordWithBaseName(baseName).isNull();
|
|
}
|
|
|
|
Poincare::Expression GlobalContext::ExpressionFromRecord(Ion::Storage::Record record) {
|
|
if (record.isNull() || record.value().size == 0) {
|
|
return Expression();
|
|
}
|
|
if (Ion::Storage::FullNameHasExtension(record.fullName(), expExtension, strlen(expExtension))) {
|
|
return ExpressionFromSymbolRecord(record);
|
|
}
|
|
assert(Ion::Storage::FullNameHasExtension(record.fullName(), funcExtension, strlen(funcExtension)));
|
|
return ExpressionFromFunctionRecord(record);
|
|
}
|
|
|
|
Poincare::Expression GlobalContext::ExpressionFromSymbolRecord(Ion::Storage::Record record) {
|
|
if (record.isNull() || record.value().size == 0) {
|
|
return Expression();
|
|
}
|
|
assert(Ion::Storage::FullNameHasExtension(record.fullName(), expExtension, strlen(expExtension)));
|
|
// An expression record value is the expression itself
|
|
Ion::Storage::Record::Data d = record.value();
|
|
return Expression::ExpressionFromAddress(d.buffer, d.size);
|
|
}
|
|
Poincare::Expression GlobalContext::ExpressionFromFunctionRecord(Ion::Storage::Record record) {
|
|
if (record.isNull() || record.value().size == 0) {
|
|
return Expression();
|
|
}
|
|
if (!Ion::Storage::FullNameHasExtension(record.fullName(), funcExtension, strlen(funcExtension))) {
|
|
return Expression();
|
|
}
|
|
/* An function record value has metadata before the expression. To get the
|
|
* expression, use the funciton record handle. */
|
|
StorageCartesianFunction f = StorageCartesianFunction(record);
|
|
return f.expressionWithSymbol();
|
|
}
|
|
|
|
const Expression GlobalContext::expressionForSymbol(const SymbolAbstract & symbol) {
|
|
Ion::Storage::Record r = SymbolAbstractRecordWithBaseName(symbol.name());
|
|
return ExpressionForSymbolAndRecord(symbol, r);
|
|
}
|
|
|
|
void GlobalContext::setExpressionForSymbol(const Expression & expression, const SymbolAbstract & symbol, Context & context) {
|
|
/* If the new expression contains the symbol, replace it because it will be
|
|
* destroyed afterwards (to be able to do A+2->A) */
|
|
Ion::Storage::Record record = SymbolAbstractRecordWithBaseName(symbol.name());
|
|
Expression e = ExpressionFromRecord(record);
|
|
if (e.isUninitialized()) {
|
|
e = Undefined();
|
|
}
|
|
Expression finalExpression = expression.clone().replaceSymbolWithExpression(symbol, e);
|
|
|
|
// Set the expression in the storage depending on the symbol type
|
|
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
|
SetExpressionForActualSymbol(finalExpression, symbol, record);
|
|
} else {
|
|
assert(symbol.type() == ExpressionNode::Type::Function);
|
|
SetExpressionForFunction(finalExpression, symbol, record);
|
|
}
|
|
}
|
|
|
|
const Expression GlobalContext::ExpressionForSymbolAndRecord(const SymbolAbstract & symbol, Ion::Storage::Record r) {
|
|
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
|
return ExpressionForActualSymbol(symbol, r);
|
|
}
|
|
assert(symbol.type() == ExpressionNode::Type::Function);
|
|
return ExpressionForFunction(symbol, r);
|
|
}
|
|
|
|
const Expression GlobalContext::ExpressionForActualSymbol(const SymbolAbstract & symbol, Ion::Storage::Record r) {
|
|
assert(symbol.type() == ExpressionNode::Type::Symbol);
|
|
if (r.isNull() || !Ion::Storage::FullNameHasExtension(r.fullName(), expExtension, strlen(expExtension))) {
|
|
return Expression();
|
|
}
|
|
// Look up the file system for symbol
|
|
return ExpressionFromSymbolRecord(r);
|
|
}
|
|
|
|
Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForActualSymbol(const Expression & expression, const SymbolAbstract & symbol, Ion::Storage::Record previousRecord) {
|
|
// Delete any record with same name (as it is going to be overriden)
|
|
previousRecord.destroy();
|
|
return Ion::Storage::sharedStorage()->createRecordWithExtension(symbol.name(), expExtension, expression.addressInPool(), expression.size());
|
|
}
|
|
|
|
Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForFunctionRecord(Expression expressionToStore, Ion::Storage::Record previousRecord, const char * baseName) {
|
|
Ion::Storage::Record recordToSet = previousRecord;
|
|
Ion::Storage::Record::ErrorStatus error = Ion::Storage::Record::ErrorStatus::None;
|
|
if (!Ion::Storage::FullNameHasExtension(previousRecord.fullName(), funcExtension, strlen(funcExtension))) {
|
|
// The previous record was not a function. Destroy it and create the new record.
|
|
previousRecord.destroy();
|
|
StorageCartesianFunction newModel = StorageCartesianFunction::NewModel(&error, baseName);
|
|
if (error != Ion::Storage::Record::ErrorStatus::None) {
|
|
return error;
|
|
}
|
|
recordToSet = newModel;
|
|
}
|
|
error = StorageCartesianFunction(recordToSet).setExpressionContent(expressionToStore);
|
|
return error;
|
|
}
|
|
|
|
Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForFunction(const Expression & expressionToStore, const SymbolAbstract & symbol, Ion::Storage::Record previousRecord) {
|
|
return SetExpressionForFunctionRecord(expressionToStore, previousRecord, symbol.name());
|
|
}
|
|
|
|
Ion::Storage::Record GlobalContext::SymbolAbstractRecordWithBaseName(const char * name) {
|
|
const char * extensions[2] = {expExtension, funcExtension/*, seqExtension*/};
|
|
return Ion::Storage::sharedStorage()->recordBaseNamedWithExtensions(name, extensions, 2);
|
|
}
|
|
|
|
}
|