runtimeMode()

in src/resolver/client.js [242:397]


  runtimeMode(func, ast, body) {
    var val = new GrammerValue('array', []);
    this.renderGrammerValue(val, ast.runtimeBody);
    if (ast.runtimeBody.tokenRange) {
      this.resolveAnnotations(this.getFrontComments(ast.runtimeBody.tokenRange[1])).forEach(c => {
        val.value.push(c);
      });
    }

    // _runtime = {}
    func.addBodyNode(new GrammerExpr(
      new GrammerVar(this.config.runtime, runtimeType), Symbol.assign(), val
    ));

    // _lastRequest = null;
    func.addBodyNode(new GrammerExpr(
      new GrammerVar('_lastRequest', requestType, 'var'),
      Symbol.assign(),
      new GrammerValue('null', null, nullType)
    ));

    // _lastException = null;
    func.addBodyNode(new GrammerExpr(
      new GrammerVar('_lastException', exceptionType, 'var'),
      Symbol.assign(),
      new GrammerValue('null', null, nullType)
    ));

    // _now = Date.now();
    func.addBodyNode(new GrammerExpr(
      new GrammerVar('_now', int16),
      Symbol.assign(),
      new GrammerValue('behavior', new BehaviorTimeNow(), int16)
    ));

    // let _retryTimes = 0;
    func.addBodyNode(new GrammerExpr(
      new GrammerVar('_retryTimes', int16, 'var'),
      Symbol.assign(),
      new GrammerValue('number', 0, int16)
    ));

    let whileOperation = new GrammerCondition('while');
    whileOperation.addCondition(
      new GrammerCall('method', [
        { type: 'object_static', name: '$Core' },
        { type: 'call_static', name: this.config.tea.core.allowRetry }
      ], [
        new GrammerValue('call', new GrammerCall('key', [
          { type: 'object', name: this.config.runtime },
          { type: 'map', name: 'retry' }
        ], [], genericType)),
        new GrammerValue('param', '_retryTimes', int16),
        new GrammerValue('param', '_now', int16),
      ], new TypeBool())
    );

    let retryTimesIf = new GrammerCondition('if');
    retryTimesIf.addCondition(
      new GrammerExpr(
        new GrammerVar('_retryTimes', int16),
        Symbol.greater(),
        new GrammerValue('number', 0, int16)
      )
    );
    retryTimesIf.addBodyNode(
      new GrammerExpr(
        new GrammerVar('_backoffTime', int16),
        Symbol.assign(),
        new GrammerCall('method', [
          { type: 'object_static', name: '$Core' },
          { type: 'call_static', name: this.config.tea.core.getBackoffTime }
        ], [
          new GrammerValue('call', new GrammerCall('key', [
            { type: 'object', name: this.config.runtime },
            { type: 'map', name: 'backoff' }
          ]), genericType),
          new GrammerValue('param', '_retryTimes', int16),
        ], int16)
      )
    );

    let backoffTimeIf = new GrammerCondition('if');
    let backoffTimeValue = new GrammerValue('number', 0, int16);
    backoffTimeValue.dataType = int16;
    backoffTimeIf.addCondition(
      new GrammerExpr(
        new GrammerVar('_backoffTime', int16),
        Symbol.greater(),
        backoffTimeValue
      )
    );
    backoffTimeIf.addBodyNode(
      new GrammerCall('method', [
        { type: 'object_static', name: '$Core' },
        { type: 'call_static', name: this.config.tea.core.sleep }
      ], [
        new GrammerValue('param', '_backoffTime', int16),
      ])
    );

    retryTimesIf.addBodyNode(backoffTimeIf);
    whileOperation.addBodyNode(retryTimesIf);

    let retryTimesValue = new GrammerValue('number', 1, int16);
    retryTimesValue.dataType = int16;
    whileOperation.addBodyNode(new GrammerExpr(
      new GrammerVar('_retryTimes', int16),
      Symbol.assign(),
      new GrammerExpr(
        new GrammerVar('_retryTimes', int16),
        Symbol.plus(),
        retryTimesValue
      )
    ));

    let requestTryCatch = new GrammerTryCatch();
    let exceptionVar = new GrammerVar('e', exceptionType);
    let exceptionParam = new GrammerValue('var', exceptionVar, exceptionType);
    let catchException = new GrammerException(exceptionType, exceptionVar);

    let tryCatch = new GrammerCatch([
      new GrammerCondition('if', [
        new GrammerCall('method', [
          { type: 'object_static', name: '$Core' },
          { type: 'call_static', name: this.config.tea.core.isRetryable }
        ], [exceptionVar])
      ], [
        new GrammerExpr(
          new GrammerVar('_lastException', exceptionType, 'var'),
          Symbol.assign(),
          exceptionVar
        ),
        new GrammerContinue(whileOperation.index)
      ]),
      new GrammerThrows(null, [exceptionParam])
    ], catchException);
    this.currThrows['$Error'] = errorType;
    this.currThrows['$Exception'] = exceptionType;
    this.requestBody(ast, body, requestTryCatch);
    requestTryCatch.addCatch(tryCatch);

    whileOperation.addBodyNode(requestTryCatch);

    func.addBodyNode(whileOperation);

    func.addBodyNode(
      new GrammerThrows(
        unretryableType, [
          new GrammerValue('var', new GrammerVar('_lastRequest', requestType), requestType),
          new GrammerValue('var', new GrammerVar('_lastException', exceptionType), exceptionType)
        ]
      )
    );
    this.currThrows['$ExceptionUnretryable'] = unretryableType;
  }