feat(Evaluator): add some binary operators

This commit is contained in:
Matthieu Bessat 2022-05-06 13:13:58 +02:00
parent 11fa2b1e6f
commit 14717958c6
5 changed files with 174 additions and 59 deletions

View file

@ -18,16 +18,16 @@ I didn't really study how others languages works beforehand, I'm just guessing h
ToDo List: ToDo List:
- [X] pow operator - [X] pow operator
- [ ] binary operators - [X] binary operators
- [X] implement basic math functions - [X] implement basic math functions
- [X] implement random_int(min, max) - [X] implement random_int(min, max)
- [ ] implement print_number(message) - [X] implement print_number(message)
- [ ] implement input_number() - [ ] implement input_number()
- [ ] base of the CLI - [ ] base of the CLI
- [ ] evaluate expression from stdin - [ ] evaluate expression from stdin
- [ ] read a file - [ ] read a file
- [ ] allow to set variables - [X] allow to set variables
- [ ] read line comments - [X] read line comments
- [ ] conditionals - [ ] conditionals
- [ ] add unit tests - [ ] add unit tests
- [ ] function call stack - [ ] function call stack

View file

@ -44,7 +44,7 @@ int evaluator_reduce_operator_pattern(struct List* evalList) {
list_get(evalList, patternPos+2, &b); list_get(evalList, patternPos+2, &b);
int res = 0; int res = 0;
unsigned char typeRes = 0; byte typeRes = 0;
int operateStatus = operate(operator, typeA, a, typeB, b, &typeRes, &res); int operateStatus = operate(operator, typeA, a, typeB, b, &typeRes, &res);
if (operateStatus != 0) { if (operateStatus != 0) {
// the pattern that matched, did not worked as expected // the pattern that matched, did not worked as expected
@ -80,24 +80,21 @@ int evaluator_reduce_minus_pattern(struct List* evalList) {
for (int i = 0; i < evalList->num_elements; i++) { for (int i = 0; i < evalList->num_elements; i++) {
if ( if (
((i >= 1 && !is_type_number(list_get_type(evalList, i-1))) || (i == 0)) && ((i >= 1 && !is_type_number(list_get_type(evalList, i-1))) || (i == 0)) &&
((i >= 1 && list_get_type(evalList, i-1) != TYPE_CLOSE_PARENTHESIS) || (i == 0)) &&
list_get_type(evalList, i) == TYPE_OPERATOR && list_get_type(evalList, i) == TYPE_OPERATOR &&
is_type_number(list_get_type(evalList, i+1)) is_type_number(list_get_type(evalList, i+1))
) { ) {
char candidateOperator; char candidateOperator;
list_get(evalList, i, &candidateOperator); list_get(evalList, i, &candidateOperator);
if (candidateOperator != '-') { if (candidateOperator != '-') continue;
continue;
}
patternPos = i; patternPos = i;
break; break;
} }
} }
if (patternPos == -1) { if (patternPos == -1) return -1;
// we did not find anything to reduce we return negative
return -1;
}
// we found a positive pattern, we gonna reduce // we found a positive pattern, we gonna reduce
int type = list_get_type(evalList, patternPos+1); int type = list_get_type(evalList, patternPos+1);
int val; int val;
@ -124,6 +121,43 @@ int evaluator_reduce_minus_pattern(struct List* evalList) {
return 0; return 0;
} }
int evaluator_reduce_not_pattern(struct List* evalList) {
int patternPos = -1;
for (int i = 0; i < evalList->num_elements; i++) {
if (
list_get_type(evalList, i) == TYPE_OPERATOR &&
is_type_number(list_get_type(evalList, i+1))
) {
char candidateOperator;
list_get(evalList, i, &candidateOperator);
if (candidateOperator != '!') continue;
patternPos = i;
break;
}
}
if (patternPos == -1) return -1;
int type = list_get_type(evalList, patternPos+1);
int val;
list_get(evalList, patternPos+1, &val);
int res = 0;
byte typeRes = 0;
int operateStatus = operate('!', 0, 0, type, val, &typeRes, &res);
if (operateStatus != 0) {
printf("ERR Evaluator: cannot operate \n");
return 400;
}
if (typeRes != TYPE_INT) return 300;
list_set(evalList, patternPos, typeRes, &res);
list_delete(evalList, patternPos+1);
return 0;
}
/** /**
This sub script will look for pattern like ({Number}) This sub script will look for pattern like ({Number})
@ -525,37 +559,34 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
while (evalList.num_elements > 1) { while (evalList.num_elements > 1) {
list_print(&evalList); list_print(&evalList);
// int reduceVarOpStat = evaluator_reduce_var(state, &evalList);
// int reduceFuncOpStat = evaluator_reduce_function_call(&evalList, 0);
// int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList);
// int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
// int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
// we are going to look for pattern to reduce // we are going to look for pattern to reduce
// the order is really important here // the order is really important here
int reduceVarOpStat = evaluator_reduce_var(state, &evalList); byte didReduced = 0;
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList, 0); for (int m = 0; m < 6; m++) {
int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList); short stat = 0;
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList); if (m == 0) stat = evaluator_reduce_var(state, &evalList);
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList); if (m == 1) stat = evaluator_reduce_function_call(&evalList, 0);
if (m == 2) stat = evaluator_reduce_minus_pattern(&evalList);
if (reduceVarOpStat > 0) { if (m == 3) stat = evaluator_reduce_not_pattern(&evalList);
printf("ERR Evaluator: var name reducing failed, dumping evalList: \n"); if (m == 4) stat = evaluator_reduce_operator_pattern(&evalList);
if (m == 5) stat = evaluator_reduce_parenthesis_pattern(&evalList);
printf("Tried mod %d got stat %d \n", m, stat);
if (stat > 0) {
printf("ERR Evaluator: mode %d reducing failed, dumping evalList: \n", m);
list_print(&evalList); list_print(&evalList);
return reduceVarOpStat;
} }
if (reduceFuncOpStat > 0) { if (stat == 0) {
printf("ERR Evaluator: function reducing failed, dumping evalList: \n"); didReduced = 1;
list_print(&evalList);
return reduceFuncOpStat;
} }
if (reduceOperatorOpStat > 0) {
printf("ERR Evaluator: operator reducing failed, dumping evalList: \n");
list_print(&evalList);
return reduceOperatorOpStat;
} }
if ( if (!didReduced) {
reduceVarOpStat == -1 &&
reduceFuncOpStat == -1 &&
reduceOperatorOpStat == -1 &&
reduceParenthesisOpStat == -1 &&
reduceMinusOpStat == -1
) {
// all scans failed to find things to reduce // all scans failed to find things to reduce
// this is actually a failure because we can't do anything to get down to 1 element in the eval list // this is actually a failure because we can't do anything to get down to 1 element in the eval list
printf("ERR Evaluator: could not reduce more, dumping evalList: \n"); printf("ERR Evaluator: could not reduce more, dumping evalList: \n");

View file

@ -10,36 +10,74 @@ int is_operator(char candidate) {
candidate == '/' || candidate == '/' ||
candidate == '+' || candidate == '+' ||
candidate == '-' || candidate == '-' ||
candidate == '^' candidate == '^' ||
candidate == '=' ||
candidate == '!' ||
candidate == '&' ||
candidate == '|'
); );
} }
int convert_to_int(byte type, int repr) {
if (type == TYPE_FLOAT) return (int) *((int*) &repr);
return repr;
}
float convert_to_float(byte type, int repr) {
if (type == TYPE_INT) return (float) repr;
return *((float*) &repr);
}
int operate( int operate(
unsigned char operator, byte operator,
unsigned char typeA, int aRepr, byte typeA, int aRepr,
unsigned char typeB, int bRepr, byte typeB, int bRepr,
unsigned char* typeRes, int* resPtr byte* typeRes, int* resPtr
) )
{ {
if (operator == '!') {
*typeRes = TYPE_INT;
// we will only take type B to emphezize that this unary operator is at the left of the only argument
int x = 0;
if (typeB == TYPE_FLOAT) x = (int) *((float*) &bRepr);
if (typeB == TYPE_INT) x = bRepr;
if (x == 0) *resPtr = 1;
if (x != 0) *resPtr = 0;
return 0;
}
if (operator == '=') {
*typeRes = TYPE_INT;
if (typeA == TYPE_FLOAT || typeB == TYPE_FLOAT) {
*resPtr = (int) convert_to_float(typeA, aRepr) == convert_to_float(typeB, bRepr);
}
if (typeA == TYPE_INT && typeB == TYPE_INT) {
*resPtr = (int) aRepr == bRepr;
}
return 0;
}
if (operator == '&') {
*typeRes = TYPE_INT;
*resPtr = (int) (convert_to_int(typeA, aRepr) & convert_to_int(typeB, bRepr));
return 0;
}
if (operator == '|') {
*typeRes = TYPE_INT;
*resPtr = (int) (convert_to_int(typeA, aRepr) | convert_to_int(typeB, bRepr));
return 0;
}
if ( if (
typeA == TYPE_FLOAT || typeB == TYPE_FLOAT || typeA == TYPE_FLOAT || typeB == TYPE_FLOAT ||
operator == '/' operator == '/'
) { ) {
*typeRes = TYPE_FLOAT; *typeRes = TYPE_FLOAT;
float a, b, res; float a, b, res;
if (typeA == TYPE_FLOAT) { a = convert_to_float(typeA, aRepr);
*((int*) &a) = aRepr; b = convert_to_float(typeB, bRepr);
}
if (typeB == TYPE_FLOAT) {
*((int*) &b) = bRepr;
}
if (typeA == TYPE_INT) {
a = (float) aRepr;
}
if (typeB == TYPE_INT) {
b = (float) bRepr;
}
printf("Appling operation: %f %c %f \n", a, operator, b); printf("Appling operation: %f %c %f \n", a, operator, b);
@ -53,6 +91,8 @@ int operate(
res = a/b; res = a/b;
} else if (operator == '^') { } else if (operator == '^') {
res = m_float_pow(a, b); res = m_float_pow(a, b);
} else if (operator == '=') {
res = (int) (a == b);
} else { } else {
return 2; return 2;
} }
@ -73,6 +113,8 @@ int operate(
res = aRepr*bRepr; res = aRepr*bRepr;
} else if (operator == '^') { } else if (operator == '^') {
res = integer_pow(aRepr, bRepr); res = integer_pow(aRepr, bRepr);
} else if (operator == '=') {
res = (int) (aRepr == bRepr);
} else { } else {
return 2; return 2;
} }

View file

@ -81,4 +81,44 @@ void test_evaluation()
evaluate(state, "abs(abs(-2))", &resVal, &resType); evaluate(state, "abs(abs(-2))", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(2 == resVal); assert(2 == resVal);
evaluate(state, "2 = 2", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
evaluate(state, "2 = 3", &resVal, &resType);
assert(resType == TYPE_INT);
assert(0 == resVal);
evaluate(state, "2 = 3.2", &resVal, &resType);
assert(resType == TYPE_INT);
assert(0 == resVal);
evaluate(state, "!(2 = 3)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
evaluate(state, "!! 0", &resVal, &resType);
assert(resType == TYPE_INT);
assert(0 == resVal);
evaluate(state, "(! (! 1)) + 0", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
evaluate(state, "!!2", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
evaluate(state, "1 & 1", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
evaluate(state, "1 & ((1+0)-1)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(0 == resVal);
evaluate(state, "1 & (1 | 0)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(1 == resVal);
} }

View file

@ -29,4 +29,6 @@ void test_line_processing()
assert(process_line(state, "set VAR_D to VAR_A+VAR_B")); assert(process_line(state, "set VAR_D to VAR_A+VAR_B"));
assert(float_almost_equal(10, var_store_get_float(state->varStore, "VAR_D"))); assert(float_almost_equal(10, var_store_get_float(state->varStore, "VAR_D")));
assert(process_line(state, "set VAR_D to VAR_A+VAR_B"));
assert(float_almost_equal(10, var_store_get_float(state->varStore, "VAR_D")));
} }