Mise en cache des arguments du bloc de valeurs

Parfois, votre générateur de code de bloc doit référencer le code de son propre de bloquer plusieurs fois.

Par exemple, si vous disposez d'un bloc qui récupère le dernier élément d'une liste, vous devez pour accéder plusieurs fois au code de la liste:

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

Mais cela peut poser des problèmes si la valeur résultante du code du bloc interne est incohérente ou elle a des effets secondaires. Par exemple, si le code interne est en fait un appel de fonction, ce code particulier peut se retrouver avec une condition hors plage:

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

L'utilisation de fonctions utilitaires vous permet de vous assurer que les blocs internes est uniquement évaluée une seule fois.

Fonctions utilitaires

Une fonction utilitaire est une fonction définie par le développeur, incluse dans le la chaîne de code générée. Vous pouvez les utiliser pour vous assurer que le code du bloc interne est évaluée une seule fois, la valeur peut être référencée plusieurs fois.

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

Fournir la fonction

Vous pouvez définir des fonctions utilitaires dans les générateurs de code de bloc à l'aide de provideFunction_ Il prend le nom que vous souhaitez pour votre fonction utilitaire, et un tableau de chaînes de code définissant ce que fait la fonction. Elle renvoie nom de votre fonction utilitaire, après l'avoir (éventuellement) modifié pour ne pas entrent en conflit avec les fonctions définies par l'utilisateur.

provideFunction_ déduplique également les définitions de fonctions utilitaires, de sorte que chaque La fonction utilitaire n'existe qu'une seule fois, même si le type de bloc qui la définit existe plusieurs fois.

Priorités de mise à jour

Lorsque vous définissez une fonction utilitaire, vous devez également mettre à jour les niveaux de priorité (qui définissent la façon dont les parenthèses sont insérées) incluses dans le un générateur de code de bloc.

La priorité est toujours basée sur la chaîne de code renvoyée par le bloc générateur. Il ne se soucie pas des opérateurs dans les fonctions utilitaires. Dans la section exemple précédent, l'appel valueToCode a été remplacé par Order.NONE, et Le tuple de retour a été remplacé par Order.FUNCTION_CALL.