-
Notifications
You must be signed in to change notification settings - Fork 76
Open
Labels
Description
given the following class hierarchy
struct Expression {};
struct ExpBinary : Expression {
Expression *left, *right;
ExpBinary(Expression *o1, Expression *o2)
: left(o1)
, right(o2) {}
};
struct ExpArith : ExpBinary {
enum function {
SUB, ADD, MUL, DIV
};
function arithOp;
ExpArith(function f, Expression *l, Expression *r)
: ExpBinary(l, r)
, arithOp(f) {}
};
struct ExpLogical : ExpBinary {
enum function_log {
GT, LT, EQ
};
function_log logicalOp;
ExpLogical(function_log f, Expression *l, Expression *r)
: ExpBinary(l, r)
, logicalOp(f) {}
};
struct ExpInteger : Expression {
int value;
ExpInteger(int v) : value(v) {}
};The following evaluator somehow does not work:
int evaluate(const Expression& exp){
var<Expression&> left, right;
var<ExpLogical::function_log> lOp;
var<ExpArith::function> aOp;
int val;
Match(exp){
Case(C<ExpBinary>(&left, &right)) {
Match(exp) {
// cout << typeid(exp).name() << endl;
Case(C<ExpArith>(aOp)) {
//cout << "exparith!\n";
Match(aOp) {
Case(ExpArith::ADD) {
return evaluate(left) + evaluate(right);
}
Case(ExpArith::SUB) {
return evaluate(left) - evaluate(right);
}
Case(ExpArith::MUL) {
return evaluate(left) * evaluate(right);
}
Case(ExpArith::DIV) {
return evaluate(left) / evaluate(right);
}
Otherwise() {
return 0;
}
} EndMatch
}
Case(C<ExpLogical>(lOp)) {
cout << "explogical!\n"; //never reached, but it should
Match(lOp) {
Case(ExpLogical::GT) {
return evaluate(left) > evaluate(right);
}
Case(ExpLogical::LT) {
return evaluate(left) < evaluate(right);
}
Case(ExpLogical::EQ) {
return evaluate(left) == evaluate(right);
}
Otherwise() {
return 0;
}
} EndMatch
}
Otherwise() {
cout << "Error in exp arith/logical matching!\n";
return 0;
}
} EndMatch
}
Case(C<ExpInteger>(val)) {
return val;
}
Otherwise() {
cout << "Error in evaluate!\n";
return 0;
}
} EndMatch
}If I build the expression
Expression *log =
new ExpLogical(ExpLogical::GT,
new ExpInteger(3),
new ExpInteger(4));and try to evaluate it using the statement,
cout << evaluate(*log) << endl;the program outputs -1 which is wrong. Somehow the statement Case(C<ExpLogical>(lOp)) is not reached, instead the second Match(exp) chooses Case(C<ExpArith>(aOp)). I don't understand why, since the patterns against which the subjecting values are being matched are clearly different. Do you have any idea? Is it disallowed to nest Match statements?
I also provided the whole (compilable) example as a gist.
Best regards