Armazenamento em cache de argumentos de bloco de valor

Às vezes, o gerador de código de bloco precisa referenciar o código do próprio bloco várias vezes.

Por exemplo, se você tem um bloco que recebe o último elemento de uma lista, você precisa para acessar o código da lista várias vezes:

// 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];
}

Mas isso pode causar problemas se o valor resultante do código do bloco interno for inconsistentes ou têm efeitos colaterais. Por exemplo, se o código interno for uma chamada de função, esse código específico pode acabar com uma condição fora do intervalo:

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

O uso de funções utilitárias permite que os blocos internos o código é apenas avaliado uma vez.

Funções do utilitário

Uma função utilitária é uma função definida pelo desenvolvedor, incluída como parte do string de código gerada. Você pode usá-los para garantir que o código de bloco interno seja somente avaliado uma vez, e o valor pode ser referenciado várias vezes.

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];
}

Forneça a função

É possível definir funções utilitárias dentro de geradores de código de bloco usando provideFunction_: Ele usa o nome que você quer para sua função utilitária e uma matriz de strings de código que definem o que a função faz. Ela retorna nome resultante da sua função de utilitário, depois de (possivelmente) modificá-la para não em conflito com as funções definidas pelo usuário.

provideFunction_ também elimina as definições de função utilitária, de modo que cada a função utilitária só existe uma vez, mesmo que exista o tipo de bloco que a define. várias vezes.

Atualizar precedências

Ao definir uma função de utilitário, também é preciso atualizar as precedências (que definem como os parênteses são inseridos) incluídos no de código de bloco.

A precedência é sempre baseada na string de código retornada pelo bloco gerador. Ela não se importa com operadores dentro de funções utilitárias. Então, no no exemplo anterior, a chamada valueToCode foi alterada para Order.NONE, e o tupla de retorno alterada para Order.FUNCTION_CALL.