[poincare] Put setjmp in apps_container and in Expression::parse

This commit is contained in:
Léa Saviot
2018-09-05 14:37:11 +02:00
parent c762b31bc2
commit 679f9815c1
4 changed files with 48 additions and 37 deletions

View File

@@ -1,6 +1,7 @@
#include "apps_container.h"
#include "global_preferences.h"
#include <ion.h>
#include <poincare/tree_pool.h>
extern "C" {
#include <assert.h>
@@ -82,8 +83,18 @@ void AppsContainer::suspend(bool checkIfPowerKeyReleased) {
}
bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
bool alphaLockWantsRedraw = updateAlphaLock();
jmp_buf jumpEnvironment;
Poincare::TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment);
int res = setjmp(jumpEnvironment);
if (res != 0) {
// There has been an exception, return an uninitialized node
Poincare::TreePool::sharedPool()->resetJumpEnvironment();// TODO Needed?
switchTo(appSnapshotAtIndex(0));
//displayMemoryExhaustionPopUp(); TODO
return true;
}
bool alphaLockWantsRedraw = updateAlphaLock();
bool didProcessEvent = false;
if (event == Ion::Events::USBEnumeration) {
@@ -114,8 +125,10 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
}
if (!didProcessEvent && alphaLockWantsRedraw) {
window()->redraw();
Poincare::TreePool::sharedPool()->resetJumpEnvironment(); // TODO Needed?
return true;
}
Poincare::TreePool::sharedPool()->resetJumpEnvironment(); // TODO Needed?
return didProcessEvent || alphaLockWantsRedraw;
}

View File

@@ -1,5 +1,6 @@
#include <escher/container.h>
#include <assert.h>
#include <setjmp.h>
Container::Container() :
RunLoop(),
@@ -36,7 +37,11 @@ App * Container::activeApp() {
}
bool Container::dispatchEvent(Ion::Events::Event event) {
if (event == Ion::Events::TimerFire || m_activeApp->processEvent(event)) {
if (event == Ion::Events::TimerFire ) {
window()->redraw();
return true;
}
if (m_activeApp->processEvent(event)) {
window()->redraw();
return true;
}

View File

@@ -160,25 +160,27 @@ public:
bool isEqualToItsApproximationLayout(Expression approximation, int bufferSize, Preferences::AngleUnit angleUnit, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits, Context & context);
/* Layout Helper */
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const;
LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return node()->createLayout(floatDisplayMode, numberOfSignificantDigits);
}
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode = Preferences::PrintFloatMode::Decimal, int numberOfSignificantDigits = PrintFloat::k_numberOfStoredSignificantDigits) const { return this->node()->serialize(buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits); }
/* Simplification */
static Expression ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit);
Expression simplify(Context & context, Preferences::AngleUnit angleUnit);
Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit);
Expression deepReduce(Context & context, Preferences::AngleUnit angleUnit); //TODO put private
/* Approximation Helper */
template<typename U> static U epsilon();
template<typename U> Evaluation<U> approximateToEvaluation(Context& context, Preferences::AngleUnit angleUnit) const {
return node()->approximate(U(), context, angleUnit);
return node()->approximate(U(), context, angleUnit); //TODO put private
}
template<typename U> Expression approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::ComplexFormat complexFormat) const;
template<typename U> U approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const;
template<typename U> static U approximateToScalar(const char * text, Context& context, Preferences::AngleUnit angleUnit);
template<typename U> U approximateWithValueForSymbol(char symbol, U x, Context & context, Preferences::AngleUnit angleUnit) const;
/* Expression roots/extrema solver*/
/* Expression roots/extrema solver */
struct Coordinate2D {
double abscissa;
double value;

View File

@@ -9,7 +9,6 @@
#include <ion.h>
#include <cmath>
#include <float.h>
#include <setjmp.h>
#include "expression_lexer_parser.h"
#include "expression_parser.hpp"
@@ -28,19 +27,26 @@ Expression Expression::parse(char const * string) {
if (string[0] == 0) {
return Expression();
}
YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string);
jmp_buf jumpEnvironment;
TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment);
int res = setjmp(jumpEnvironment);
if (res != 0) {
// There has been an exception, return an uninitialized node
TreePool::sharedPool()->resetJumpEnvironment();
poincare_expression_yylval.expression = Expression();
poincare_expression_yy_delete_buffer(buf);
return Expression();
}
Expression expression;
/* The lexer/parser mallocs memory that needs to be freed once the parsing
* finishes, even if the parsing was interrupted by a memory exhaustion
* exception. We thus create another setjmp/lngjmp routine here to catch
* exceptions, delete the malloced memory and restore the previous jump
* environment */
jmp_buf * previousJumpEnvironment = TreePool::sharedPool()->jumpEnvironment();
jmp_buf jumpEnvironment;
TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment);
int res = setjmp(jumpEnvironment);
if (res != 0) {
// There has been an exception. Delete malloced memory and jump.
poincare_expression_yylval.expression = Expression();
poincare_expression_yy_delete_buffer(buf);
TreePool::sharedPool()->resetJumpEnvironment();
longjmp(*previousJumpEnvironment, 1);
}
TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment);
int res = setjmp(jumpEnvironment); YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string);
Expression expression;
if (poincare_expression_yyparse(&expression) != 0) {
// Parsing failed because of invalid input or memory exhaustion
expression = Expression();
@@ -49,7 +55,7 @@ Expression Expression::parse(char const * string) {
* expression alive if only YYVAL refers to it so we reset YYVAL here. */
poincare_expression_yylval.expression = Expression();
poincare_expression_yy_delete_buffer(buf);
TreePool::sharedPool()->resetJumpEnvironment();
TreePool::sharedPool()->setJumpEnvironment(&previousJumpEnvironment);
return expression;
}
@@ -226,21 +232,6 @@ bool Expression::isEqualToItsApproximationLayout(Expression approximation, int b
return equal;
}
LayoutRef Expression::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
jmp_buf jumpEnvironment;
TreePool::sharedPool()->setJumpEnvironment(&jumpEnvironment);
int res = setjmp(jumpEnvironment);
if (res != 0) {
assert(false);
// There has been an exception, return an uninitialized layout
TreePool::sharedPool()->resetJumpEnvironment();
return LayoutRef();
}
LayoutRef result = node()->createLayout(floatDisplayMode, numberOfSignificantDigits);
TreePool::sharedPool()->resetJumpEnvironment();
return result;
}
/* Simplification */
Expression Expression::ParseAndSimplify(const char * text, Context & context, Preferences::AngleUnit angleUnit) {
@@ -293,13 +284,13 @@ Expression Expression::deepBeautify(Context & context, Preferences::AngleUnit an
template<typename U>
Expression Expression::approximate(Context& context, Preferences::AngleUnit angleUnit, Preferences::Preferences::ComplexFormat complexFormat) const {
Evaluation<U> e = node()->approximate(U(), context, angleUnit);
Evaluation<U> e = node()->approximate(U(), context, angleUnit); //TODO approximateToEval
return e.complexToExpression(complexFormat);
}
template<typename U>
U Expression::approximateToScalar(Context& context, Preferences::AngleUnit angleUnit) const {
Evaluation<U> evaluation = node()->approximate(U(), context, angleUnit);
Evaluation<U> evaluation = node()->approximate(U(), context, angleUnit);//TODO approximateToEval
return evaluation.toScalar();
}