Almacenamiento en caché de argumentos de bloque de valores

A veces, el generador de código de bloque necesita hacer referencia al código de su varias veces.

Por ejemplo, si tienes un bloque que obtiene el último elemento de una lista, necesitas para acceder al código de lista varias veces:

// Incorrect block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);

  // listCode gets referenced twice.
  const code = `${listCode}[${listCode}.length - 1]`;

  return [code, Order.MEMBER];
}

Pero esto puede causar problemas si el valor resultante del código del bloque interno es incoherentes o tienen efectos secundarios. Por ejemplo, si el código interno una llamada a función, este código específico puede terminar con una condición fuera de rango:

randomList()[randomList().length - 1]

El uso de funciones de utilidad te permite asegurarte de que los bloques internos el código solo es se evalúe una vez.

Funciones de utilidad

Una función de utilidad es una función definida por el desarrollador incluida como parte del cadena de código generada. Puedes usarlos para asegurarte de que el código solo se evalúa una vez y, luego, se puede hacer referencia al valor varias veces.

import {javascriptGenerator, Order} from 'blockly/javascript';

// Correct block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
  const listCode = generator.valueToCode(block, 'LIST', Order.NONE);
  const functionName = generator.provideFunction_(
      'list_lastElement',
      [
        `function ${generator.FUNCTION_NAME_PLACEHOLDER_}(list) {`,
        `  return list[list.length - 1];`,
        `}`
      ]
  );

  // listCode only gets evaluated once.
  const code = `${functionName}(${listCode})`;
  return [code, Order.FUNCTION_CALL];
}

Proporciona la función

Puedes definir funciones de utilidad dentro de generadores de código de bloque con provideFunction_ Toma el nombre que deseas para tu función de utilidad y un array de cadenas de código que define lo que hace la función. Devuelve el nombre resultante de tu función de utilidad, después (posiblemente) de modificarla para que no entran en conflicto con las funciones definidas por el usuario.

provideFunction_ también anula los duplicados de las definiciones de funciones de utilidad, de modo que cada función de utilidad solo existe una vez, incluso si el tipo de bloque que la define existe varias veces.

Actualizar prioridades

Cuando defines una función de utilidad, también debes actualizar las precedencias (que definen cómo se insertan los paréntesis) incluidos en la de código de bloque.

La prioridad siempre se basa en la cadena de código que muestra el código de bloque. generador. No le interesan los operadores dentro de las funciones de utilidad. En la ejemplo anterior, la llamada valueToCode se cambió a Order.NONE y el se cambió la tupla de retorno a Order.FUNCTION_CALL.