#ifdef HAVE_CONFIG_H # include #endif #include "expr.hh" #include "operator.hh" #include "vehicle.hh" #include "view.hh" #include #include double BinaryExpr::calculate_assign(double value, Vector &sensations, Vehicle *vehicle) { int lvalue = _left->lvalue(vehicle); if (lvalue >= 0) { if (sensations.size() <= lvalue) sensations.resize(lvalue + 1, 0); sensations[lvalue] = value; } return value; } double BinaryExpr::calculate(Vector &sensations, Vehicle *vehicle) { double lv = _left->calculate(sensations, vehicle); double rv = _right->calculate(sensations, vehicle); switch (_op) { case '+': return lv + rv; case '-': return lv - rv; case '*': return lv * rv; case '/': return lv / rv; case opPower: return pow(lv, rv); case opLt: return lv < rv; case opLe: return lv <= rv; case opGe: return lv >= rv; case opGt: return lv > rv; case opEq: return lv == rv; case opNe: return lv != rv; case opLogAnd: return lv && rv; case opLogOr: return lv || rv; case opAssign: return calculate_assign(rv, sensations, vehicle); case opAddAssign: return calculate_assign(lv + rv, sensations, vehicle); case opSubAssign: return calculate_assign(lv - rv, sensations, vehicle); case opMulAssign: return calculate_assign(lv * rv, sensations, vehicle); case opDivAssign: return calculate_assign(lv / rv, sensations, vehicle); case opPowerAssign: return calculate_assign(pow(lv, rv), sensations, vehicle); case ',': return rv; default: return 0; } } double UnaryExpr::calculate(Vector &sensations, Vehicle *vehicle) { double cv = _child->calculate(sensations, vehicle); switch (_op) { case opCopy: return cv; case opNegate: return -cv; case '!': return !cv; case opPin: { if (cv < 0) cv = 0; if (cv > 1) cv = 1; return cv; } case opFlip: { if (cv < 0) cv = 0; if (cv > 1) cv = 1; return 1 - cv; } default: return 0; } } double ConditionalExpr::calculate(Vector &sensations, Vehicle *vehicle) { double qv = _test->calculate(sensations, vehicle); if (qv) return _true_case->calculate(sensations, vehicle); else return _false_case->calculate(sensations, vehicle); } double SensorExpr::calculate(Vector &sensations, Vehicle *vehicle) { int sensor = vehicle->sensor_id(_name); if (sensor < 0) return 0; return sensations[sensor]; } double BoundExpr::calculate(Vector &sensations, Vehicle *vehicle) { int n = vehicle->nsensors() + _number; return (n < sensations.size() ? sensations[n] : 0); } int BoundExpr::lvalue(Vehicle *vehicle) { return (vehicle ? vehicle->nsensors() + _number : _number); } void BinaryExpr::draw(Vehicle *vehicle, int actuator, View *view) { _left->draw(vehicle, actuator, view); _right->draw(vehicle, actuator, view); } void UnaryExpr::draw(Vehicle *vehicle, int actuator, View *view) { _child->draw(vehicle, actuator, view); } void ConditionalExpr::draw(Vehicle *vehicle, int actuator, View *view) { _test->draw(vehicle, actuator, view); _true_case->draw(vehicle, actuator, view); _false_case->draw(vehicle, actuator, view); } void SensorExpr::draw(Vehicle *vehicle, int actuator, View *view) { int sensor = vehicle->sensor_id(_name); if (sensor < 0) return; Point p1 = vehicle->sensor_position(sensor); Point p2 = vehicle->actuator_position(actuator); view->draw_line(vehicle->sensor_gc(), p1, p2); } void BoundExpr::draw(Vehicle *vehicle, int actuator, View *view) { if (vehicle->nsensors() <= _number) return; Point p1 = vehicle->sensor_position(_number); Point p2 = vehicle->actuator_position(actuator); view->draw_line(vehicle->sensor_gc(), p1, p2); } void ConstExpr::print() { fprintf(stderr, "%g", _v); } void BinaryExpr::print() { fputs("(", stderr); _left->print(); fprintf(stderr, ") %s (", Operator(_op).name().cc()); _right->print(); fputs(")", stderr); } void UnaryExpr::print() { fprintf(stderr, "%s(", Operator(_op).name().cc()); _child->print(); fputs(")", stderr); } void ConditionalExpr::print() { fputs("(", stderr); _test->print(); fprintf(stderr, ") ? ("); _true_case->print(); fprintf(stderr, ") : ("); _false_case->print(); fputs(")", stderr); } void SensorExpr::print() { fprintf(stderr, "%s", _name.cc()); } void BoundExpr::print() { fprintf(stderr, "bound[%d]", _number); }