auto-sync
This commit is contained in:
parent
d910d0a572
commit
15ab5030cd
|
@ -46,7 +46,10 @@ void FLStack<T, MAXSIZE>::push(T value) {
|
||||||
|
|
||||||
template<typename T, int MAXSIZE>
|
template<typename T, int MAXSIZE>
|
||||||
T FLStack<T, MAXSIZE>::pop() {
|
T FLStack<T, MAXSIZE>::pop() {
|
||||||
return values[--index];
|
if(index==0) {
|
||||||
|
firmwareError("FLStack is empty");
|
||||||
|
}
|
||||||
|
return values[--index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, int MAXSIZE>
|
template<typename T, int MAXSIZE>
|
||||||
|
|
|
@ -18,14 +18,18 @@ static LENameOrdinalPair leAnd(LE_OPERATOR_AND, "and");
|
||||||
static LENameOrdinalPair leOr(LE_OPERATOR_OR, "or");
|
static LENameOrdinalPair leOr(LE_OPERATOR_OR, "or");
|
||||||
static LENameOrdinalPair leMore(LE_OPERATOR_MORE, ">");
|
static LENameOrdinalPair leMore(LE_OPERATOR_MORE, ">");
|
||||||
static LENameOrdinalPair leMoreOrEqual(LE_OPERATOR_MORE_OR_EQUAL, ">=");
|
static LENameOrdinalPair leMoreOrEqual(LE_OPERATOR_MORE_OR_EQUAL, ">=");
|
||||||
|
static LENameOrdinalPair leNot(LE_OPERATOR_NOT, "not");
|
||||||
|
|
||||||
|
static LENameOrdinalPair leRpm(LE_METHOD_RPM, "rpm");
|
||||||
|
static LENameOrdinalPair leFan(LE_METHOD_FAN, "fan");
|
||||||
|
static LENameOrdinalPair leCoolant(LE_METHOD_COOLANT, "coolant");
|
||||||
|
static LENameOrdinalPair leFanOnSetting(LE_METHOD_FAN_ON_SETTING, "fan_on_setting");
|
||||||
|
static LENameOrdinalPair leFanOffSetting(LE_METHOD_FAN_OFF_SETTING, "fan_off_setting");
|
||||||
|
|
||||||
LENameOrdinalPair::LENameOrdinalPair(le_action_e action, const char *name) {
|
LENameOrdinalPair::LENameOrdinalPair(le_action_e action, const char *name) {
|
||||||
this->next = NULL;
|
|
||||||
this->action = action;
|
this->action = action;
|
||||||
this->name = name;
|
this->name = name;
|
||||||
if (LE_FIRST != NULL) {
|
this->next = LE_FIRST;
|
||||||
LE_FIRST->next = this;
|
|
||||||
}
|
|
||||||
LE_FIRST = this;
|
LE_FIRST = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,38 +86,48 @@ void LECalculator::doJob(LEElement *element) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LE_OPERATOR_LESS: {
|
case LE_OPERATOR_LESS: {
|
||||||
float v1 = stack.pop();
|
// elements on stack are in reverse order
|
||||||
float v2 = stack.pop();
|
float v2 = stack.pop();
|
||||||
|
float v1 = stack.pop();
|
||||||
|
|
||||||
stack.push(v1 < v2);
|
stack.push(v1 < v2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LE_OPERATOR_NOT: {
|
||||||
|
float v = stack.pop();
|
||||||
|
stack.push(!float2bool(v));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case LE_OPERATOR_MORE: {
|
case LE_OPERATOR_MORE: {
|
||||||
float v1 = stack.pop();
|
// elements on stack are in reverse order
|
||||||
float v2 = stack.pop();
|
float v2 = stack.pop();
|
||||||
|
float v1 = stack.pop();
|
||||||
|
|
||||||
stack.push(v1 > v2);
|
stack.push(v1 > v2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LE_OPERATOR_LESS_OR_EQUAL: {
|
case LE_OPERATOR_LESS_OR_EQUAL: {
|
||||||
float v1 = stack.pop();
|
// elements on stack are in reverse order
|
||||||
float v2 = stack.pop();
|
float v2 = stack.pop();
|
||||||
|
float v1 = stack.pop();
|
||||||
|
|
||||||
stack.push(v1 <= v2);
|
stack.push(v1 <= v2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LE_OPERATOR_MORE_OR_EQUAL: {
|
case LE_OPERATOR_MORE_OR_EQUAL: {
|
||||||
float v1 = stack.pop();
|
// elements on stack are in reverse order
|
||||||
float v2 = stack.pop();
|
float v2 = stack.pop();
|
||||||
|
float v1 = stack.pop();
|
||||||
|
|
||||||
stack.push(v1 >= v2);
|
stack.push(v1 >= v2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LE_UNDEFINED:
|
||||||
|
firmwareError("Undefined not expected here");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
firmwareError("Not implemented: %d", element->action);
|
stack.push(getLEValue(NULL, element->action));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float LECalculator::getValue() {
|
float LECalculator::getValue() {
|
||||||
|
@ -180,7 +194,7 @@ le_action_e parseAction(const char * line) {
|
||||||
LENameOrdinalPair *pair = LE_FIRST;
|
LENameOrdinalPair *pair = LE_FIRST;
|
||||||
while (pair != NULL) {
|
while (pair != NULL) {
|
||||||
if (strEqualCaseInsensitive(pair->name, line)) {
|
if (strEqualCaseInsensitive(pair->name, line)) {
|
||||||
// return pair->action;
|
return pair->action;
|
||||||
}
|
}
|
||||||
pair = pair->next;
|
pair = pair->next;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +224,13 @@ LEElement * parseExpression(LEElementPool *pool, const char * line) {
|
||||||
n->init(LE_NUMERIC_VALUE, atoff(parsingBuffer));
|
n->init(LE_NUMERIC_VALUE, atoff(parsingBuffer));
|
||||||
} else {
|
} else {
|
||||||
le_action_e action = parseAction(parsingBuffer);
|
le_action_e action = parseAction(parsingBuffer);
|
||||||
|
if (action == LE_UNDEFINED) {
|
||||||
|
/**
|
||||||
|
* Cannot recognize token
|
||||||
|
*/
|
||||||
|
warning((obd_code_e) 0, "unrecognized [%s]", parsingBuffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
n->init(action);
|
n->init(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,3 +244,9 @@ LEElement * parseExpression(LEElementPool *pool, const char * line) {
|
||||||
}
|
}
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
||||||
|
float getLEValue(Engine *engine, le_action_e action) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -10,24 +10,29 @@
|
||||||
|
|
||||||
#include "rusefi_enums.h"
|
#include "rusefi_enums.h"
|
||||||
#include "fl_stack.h"
|
#include "fl_stack.h"
|
||||||
|
#include "engine.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
||||||
|
LE_UNDEFINED = 0 ,
|
||||||
|
LE_NUMERIC_VALUE = 1,
|
||||||
|
LE_OPERATOR_LESS = 2,
|
||||||
|
LE_OPERATOR_MORE = 3,
|
||||||
|
LE_OPERATOR_LESS_OR_EQUAL = 4,
|
||||||
|
LE_OPERATOR_MORE_OR_EQUAL = 5,
|
||||||
|
LE_OPERATOR_AND = 6,
|
||||||
|
LE_OPERATOR_OR = 7,
|
||||||
|
LE_OPERATOR_NOT = 8,
|
||||||
|
|
||||||
|
LE_METHOD_RPM = 100,
|
||||||
|
LE_METHOD_COOLANT = 101,
|
||||||
|
LE_METHOD_FAN = 102,
|
||||||
|
LE_METHOD_TIME_SINCE_BOOT = 103,
|
||||||
|
LE_METHOD_FAN_ON_SETTING = 104,
|
||||||
|
LE_METHOD_FAN_OFF_SETTING = 105,
|
||||||
|
|
||||||
Force_4b_le_action = ENUM_SIZE_HACK,
|
Force_4b_le_action = ENUM_SIZE_HACK,
|
||||||
|
|
||||||
LE_UNDEFINED,
|
|
||||||
LE_NUMERIC_VALUE,
|
|
||||||
LE_OPERATOR_LESS,
|
|
||||||
LE_OPERATOR_MORE,
|
|
||||||
LE_OPERATOR_LESS_OR_EQUAL,
|
|
||||||
LE_OPERATOR_MORE_OR_EQUAL,
|
|
||||||
LE_OPERATOR_AND,
|
|
||||||
LE_OPERATOR_OR,
|
|
||||||
|
|
||||||
LE_METHOD_RPM,
|
|
||||||
LE_METHOD_COOLANT,
|
|
||||||
LE_METHOD_FAN,
|
|
||||||
LE_METHOD_TIME_SINCE_BOOT,
|
|
||||||
|
|
||||||
} le_action_e;
|
} le_action_e;
|
||||||
|
|
||||||
class LEElement {
|
class LEElement {
|
||||||
|
@ -86,4 +91,6 @@ bool isNumeric(const char* line);
|
||||||
le_action_e parseAction(const char * line);
|
le_action_e parseAction(const char * line);
|
||||||
LEElement * parseExpression(LEElementPool *pool, const char * line);
|
LEElement * parseExpression(LEElementPool *pool, const char * line);
|
||||||
|
|
||||||
|
float getLEValue(Engine *engine, le_action_e action);
|
||||||
|
|
||||||
#endif /* LOGIC_EXPRESSION_H_ */
|
#endif /* LOGIC_EXPRESSION_H_ */
|
||||||
|
|
|
@ -241,5 +241,5 @@ void firmwareError(const char *fmt, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int getRusEfiVersion(void) {
|
int getRusEfiVersion(void) {
|
||||||
return 20141004;
|
return 20141005;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ uint64_t getTimeNowNt(void) {
|
||||||
|
|
||||||
void assertEqualsM(const char *msg, float expected, float actual) {
|
void assertEqualsM(const char *msg, float expected, float actual) {
|
||||||
if (cisnan(actual) && !cisnan(expected)) {
|
if (cisnan(actual) && !cisnan(expected)) {
|
||||||
printf("Unexpected: %s %.4f while expected %.4f\r\n", msg, actual, expected);
|
printf("Assert failed: %s %.4f while expected %.4f\r\n", msg, actual, expected);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,21 @@
|
||||||
#include "test_logic_expression.h"
|
#include "test_logic_expression.h"
|
||||||
#include "logic_expression.h"
|
#include "logic_expression.h"
|
||||||
#include "cli_registry.h"
|
#include "cli_registry.h"
|
||||||
|
#include "engine.h"
|
||||||
|
|
||||||
|
static float mockCoolant;
|
||||||
|
static float mockFan;
|
||||||
|
|
||||||
|
float getLEValue(Engine *engine, le_action_e action) {
|
||||||
|
switch(action) {
|
||||||
|
case LE_METHOD_FAN:
|
||||||
|
return mockFan;
|
||||||
|
case LE_METHOD_COOLANT:
|
||||||
|
return mockCoolant;
|
||||||
|
default:
|
||||||
|
firmwareError("No value for %d", action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void testParsing(void) {
|
static void testParsing(void) {
|
||||||
|
@ -37,7 +52,7 @@ static void testParsing(void) {
|
||||||
LEElementPool pool;
|
LEElementPool pool;
|
||||||
|
|
||||||
LEElement *element;
|
LEElement *element;
|
||||||
element = parseExpression(&pool, "1 3 AND");
|
element = parseExpression(&pool, "1 3 AND not");
|
||||||
assertTrue(element != NULL);
|
assertTrue(element != NULL);
|
||||||
|
|
||||||
assertEquals(element->action, LE_NUMERIC_VALUE);
|
assertEquals(element->action, LE_NUMERIC_VALUE);
|
||||||
|
@ -50,10 +65,23 @@ static void testParsing(void) {
|
||||||
element = element->next;
|
element = element->next;
|
||||||
assertEquals(element->action, LE_OPERATOR_AND);
|
assertEquals(element->action, LE_OPERATOR_AND);
|
||||||
|
|
||||||
|
element = element->next;
|
||||||
|
assertEquals(element->action, LE_OPERATOR_NOT);
|
||||||
|
|
||||||
element = element->next;
|
element = element->next;
|
||||||
assertTrue(element == NULL);
|
assertTrue(element == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testExpression(const char *line, float expected) {
|
||||||
|
LEElementPool pool;
|
||||||
|
pool.reset();
|
||||||
|
LEElement * element = parseExpression(&pool, line);
|
||||||
|
assertTrueM("Not NULL expected", element != NULL);
|
||||||
|
LECalculator c;
|
||||||
|
c.add(element);
|
||||||
|
assertEqualsM(line, expected, c.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
void testLogicExpressions(void) {
|
void testLogicExpressions(void) {
|
||||||
printf("*************************************************** testLogicExpressions\r\n");
|
printf("*************************************************** testLogicExpressions\r\n");
|
||||||
|
|
||||||
|
@ -105,8 +133,28 @@ void testLogicExpressions(void) {
|
||||||
e = pool.next();
|
e = pool.next();
|
||||||
e->init(LE_OPERATOR_OR);
|
e->init(LE_OPERATOR_OR);
|
||||||
|
|
||||||
|
pool.reset();
|
||||||
|
LEElement *element;
|
||||||
|
element = parseExpression(&pool, "fan no_such_method");
|
||||||
|
assertTrueM("NULL expected", element == NULL);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fan = (not fan && coolant > 90) OR (fan && coolant > 85)
|
* fan = (not fan && coolant > 90) OR (fan && coolant > 85)
|
||||||
* fan = fan NOT coolant 90 AND more fan coolant 85 more AND OR
|
* fan = fan NOT coolant 90 AND more fan coolant 85 more AND OR
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
mockFan = 0;
|
||||||
|
mockCoolant = 100;
|
||||||
|
|
||||||
|
testExpression("coolant", 100);
|
||||||
|
testExpression("fan", 0);
|
||||||
|
testExpression("fan not", 1);
|
||||||
|
testExpression("coolant 90 >", 1);
|
||||||
|
testExpression("fan not coolant 90 > and", 1);
|
||||||
|
|
||||||
|
|
||||||
|
testExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR", 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue