visitBinary method

  1. @override
dynamic visitBinary(
  1. BinaryExpression node
)

Implementation

@override
visitBinary(BinaryExpression node) {
  try {
    dynamic left = getValueFromExpression(node.left);
    //special check in case of || to avoid evaluating the right expression
    //https://github.com/EnsembleUI/ensemble/issues/574
    if (node.operator == '||') {
      if (left != false &&
          left != null &&
          left != 0 &&
          left != '' &&
          !(left is num && left.isNaN)) {
        return left;
      } else {
        return getValueFromExpression(node.right);
      }
    } else if (node.operator == '&&') {
      if (left == false ||
          left == null ||
          left == 0 ||
          left == '' ||
          (left is num && left.isNaN)) {
        return left;
      } else {
        return getValueFromExpression(node.right);
      }
    }
    dynamic right = getValueFromExpression(node.right);
    dynamic rtn = false;
    if (left is SupportsPrimitiveOperations) {
      return left.runOperation(node.operator!, right);
    }
    if (node.operator == '+') {
      if (left == null && right == null) {
        left = 0;
        right = 0;
      } else if (left is String || right is String) {
        left = left?.toString() ?? "null";
        right = right?.toString() ?? "null";
      } else {
        left = left ?? 0;
        right = right ?? 0;
      }
    } else {
      // For other operators, treat null as 0 where applicable
      if ([
        '-',
        '/',
        '*',
        '%',
        '|',
        '&',
        '^',
        '<<',
        '>>',
        '>>>',
        '<',
        '<=',
        '>',
        '>='
      ].contains(node.operator)) {
        left = left ?? 0;
        right = right ?? 0;
      }
    }
    bool done = true;
    switch (node.operator) {
      case '==':
        rtn = left == right;
        break;
      case '===':
        rtn = left == right;
        break;
      case '!=':
        rtn = left != right;
        break;
      case '!==':
        rtn = left != right;
        break;
      case '<':
        rtn = left < right;
        break;
      case '<=':
        rtn = left <= right;
        break;
      case '>':
        rtn = left > right;
        break;
      case '>=':
        rtn = left >= right;
        break;
      case '-':
        rtn = left - right;
        break;
      case '+':
        rtn = left + right;
        break;
      case '/':
        rtn = left / right;
        break;
      case '*':
        rtn = left * right;
        break;
      case '%':
        rtn = left % right;
        break;
      case '|':
        rtn = left | right;
        break;
      case '^':
        rtn = left ^ right;
        break;
      case '<<':
        rtn = left << right;
        break;
      case '>>':
        rtn = left >> right;
        break;
      case '&':
        rtn = left & right;
        break;
      default:
        done = false;
        break;
    }
    if (!done) {
      throw JSException(
          node.line ?? -1, node.operator! + ' is not yet supported',
          detailedError: 'Code: ${getCode(node)}');
    }
    return rtn;
  } on JSException catch (e) {
    rethrow;
  } on InvalidPropertyException catch (e) {
    throw JSException(node.line ?? 1, '${e.message}. Code: ${getCode(node)}');
  }
}