Adicionar parênteses

Os blocos implicam parênteses. Por exemplo, quando você vê os blocos a seguir, supõe que significa -(5 + 2), não -5 + 2, porque o 5 e o 2 fazem parte de um bloco, e o - faz parte de outro bloco.

blocos que representam -(5 + 2)

No entanto, se você colocar parênteses em cada bloco, o código ficará muito menos legível. Compare (((5) * (2)) + (3)) com 5 * 2 + 3. Ambas as expressões são avaliadas como a mesma coisa (13), mas a segunda é muito mais fácil de ler.

As regras de precedência de operadores do Blockly ajudam a gerar código com o número mínimo de parênteses, para máxima legibilidade.

Gerar saída "correta"

Se você não precisa que o código gerado seja legível por humanos, não é necessário minimizar os parênteses. O agrupamento de todos os blocos é uma boa abordagem e garante que o código gerado seja sempre avaliado corretamente.

Para garantir a correção, sempre transmita Order.ATOMIC para chamadas valueToCode e sempre retorne Order.NONE do gerador de código de bloco.

Gerar parênteses ideais

Os parênteses só precisam ser inseridos se o código gerado estiver incorreto sem eles. Isso acontece quando a precedência de um operador no bloco externo é mais forte do que a precedência de um operador no bloco interno.

Por exemplo, nos blocos a seguir, há um operador de negação unária e um operador de adição. A negação unária tem uma precedência maior do que o operador de adição.

negate-and-addition

Portanto, se você não adicionar parênteses, vai receber -5 + 2, e o - será avaliado antes do +, que não corresponde aos blocos.

É possível informar ao gerador quando inserir parênteses informando a força dos operadores diferentes. Se ele detectar que o operador externo é mais forte do que o interno, ele vai inserir parênteses para proteger o operador interno.

valueToCode recebe a precedência do operador externo, e a tupla de retorno especifica a precedência do operador interno.

Confira um exemplo de bloco que inclui dois operadores:

Um bloco com um operador de negação unária, um operador de adição e um bloco
filho.

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

javascriptGenerator.forBlock['negate_plus_two'] = function(block, generator) {
  // valueToCode takes in the precedence of the outer operator.
  const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
  const code = `-${innerCode} + 2`;
  // The return tuple specifies the precedence of the inner operator.
  return [code, Order.ADDITION];
}

precedência de valueToCode

Quando você chama valueToCode para gerar o código de um bloco interno, ele transmite a precedência do operador mais forte atuando no código do bloco interno. Esse é o operador contra o qual o código do bloco interno precisa ser protegido.

Por exemplo, nos blocos a seguir, o operador de negação unária e o operador de adição estão atuando no código do bloco interno. A negação unária é mais forte, então essa é a precedência que você precisa transmitir para valueToCode.

Um bloco com um operador de negação unária, um operador de adição e um bloco
filho.

// The - is the strongest operator acting on the inner code.
const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
const code = `-${innerCode} + 2`;

Precedência da devolução

Ao retornar uma precedência do gerador de código de bloco, retorne a precedência do operador mais fraco no código do bloco. Esse é o operador que precisa de proteção.

Por exemplo, o bloco a seguir contém um operador de negação unária e um operador de adição. A adição é mais fraca, então essa é a precedência que você precisa retornar do gerador de código de bloco.

Um bloco com um operador de negação unário, um operador de adição e nenhum bloco
filho

const code = `-${innerCode} + 2`;
// The + is the weakest operator in the block.
return [code, Order.ADDITION];

Enum de ordenação

Cada módulo do gerador de idioma define um tipo enumerado Order que inclui todas as precedências desse idioma.

As precedências mais fortes têm valores de suporte mais baixos, e as mais fracas têm valores de suporte mais altos. Você pode pensar em precedências fortes como "classificadas como mais fortes" e em precedências fracas como "classificadas como mais fracas", como se fossem lutadores competitivos.

Confira os tipos enumerados Order para todos os idiomas integrados:

Precedências especiais

A maioria das precedências nos tipos enumerados Order dos geradores corresponde às precedências definidas pelos respectivos idiomas baseados em texto. No entanto, há duas precedências especiais, Order.ATOMIC e Order.NONE.

Order.ATOMIC tem a precedência mais forte. Ele é usado quando:

Order.NONE é a precedência mais fraca. Ele é usado quando: