Blok kodu oluşturma araçları

Blok kodu oluşturucu, bir bloğun kodunu oluşturan ve bunu dize olarak döndüren bir işlevdir. Bir bloğun oluşturduğu kod, türüne bağlıdır:

  • Değer bloklarının çıkış bağlantısı vardır. Bu bloklar, metin tabanlı bir dilde ifade gibi davranır ve ifade içeren dizeler oluşturur.
  • İfade blokları, çıkış bağlantısı olmayan bloklardır. Bu bloklar, metin tabanlı bir dilde ifadeler gibi davranır ve ifade içeren dizeler oluşturur.

Blok kodu oluşturucu yazma

Oluşturduğunuz her özel blok için desteklemek istediğiniz her dil için bir blok kodu oluşturucu yazmanız gerekir. Tüm blok kod oluşturucuların, başka bir dilde kod oluştursalar bile JavaScript'te yazıldığını unutmayın.

Tüm blok kodu oluşturucular aşağıdaki adımları gerçekleştirir:

  1. Dil kodu oluşturucu içe aktarın.
  2. Her alanın değerini alın ve bunu bir kod dizesine dönüştürün.
  3. Değer ve ifade girişlerine bağlı bloklar olan iç bloklar tarafından oluşturulan kod dizelerini alın.
  4. Bloğun kod dizesini oluşturup döndürme.

Örnek bloklar

Örnek olarak aşağıdaki bloklar için JavaScript kod oluşturucular yazacağız.

  • custom_compare, LEFT adlı bir değer girişi, OPERATOR adlı bir açılır liste alanı ve RIGHT adlı bir sayısal alana sahip bir değer bloğudur. '0 = 0' biçiminde bir ifade dizesi oluşturur.

    Karşılaştırmalar için özel değer bloğu.

  • custom_if, NOT adlı bir onay kutusu alanı, CONDITION adlı bir değer girişi ve THEN adlı bir ifade girişi içeren bir ifade bloğudur. 'if (...) {\n...\n};\n' biçiminde bir ifade dizesi oluşturur.

    If ifadesi için özel ifade bloğu. Kullanıcılar, "if" koşulunu geçersiz kılmak için onay kutusunu kullanabilir.

Bu dokümanda, jeneratörler adım adım oluşturulmaktadır. Oluşturulan jeneratörleri bu dokümanın sonunda bulabilirsiniz.

Bu blokların yalnızca kod oluşturmayı göstermek için tasarlandığını unutmayın. Gerçek bir uygulamada yerleşik logic_compare ve controls_if bloklarını kullanın.

Dil kodu oluşturucu içe aktarma

Dil kodu oluşturucuyu aşağıdaki yöntemlerden birini kullanarak içe aktarabilirsiniz. Blok kodu oluşturucuları forBlock nesnesinde depolamak için içe aktarılan oluşturucuyu kullanın.

Modüller

import {javascriptGenerator} from 'blockly/javascript';
import {pythonGenerator} from 'blockly/python';
import {phpGenerator} from 'blockly/php';
import {luaGenerator} from 'blockly/lua';
import {dartGenerator} from 'blockly/dart';

// Add block-code generators for the custom_if block.
javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };

Unpkg

Blockly'yi ekledikten sonra jeneratörü eklemeniz gerekir.

<script src="https://unpkg.com/blockly"></script>
<script src="https://unpkg.com/blockly/javascript_compressed"></script>
<script src="https://unpkg.com/blockly/python_compressed"></script>
<script src="https://unpkg.com/blockly/php_compressed"></script>
<script src="https://unpkg.com/blockly/lua_compressed"></script>
<script src="https://unpkg.com/blockly/dart_compressed"></script>
// Add block-code generators for the custom_if block.
javascript.javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
python.pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
php.phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
lua.luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dart.dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };

Yerel komut dosyaları

Blockly'yi ekledikten sonra jeneratörü eklemeniz gerekir.

<script src="blockly_compressed.js"></script>
<script src="javascript_compressed.js"></script>
<script src="python_compressed.js"></script>
<script src="php_compressed.js"></script>
<script src="lua_compressed.js"></script>
<script src="dart_compressed.js"></script>
// Add block-code generators for the custom_if block.
javascript.javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
python.pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
php.phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
lua.luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dart.dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };

Alan değerlerini alma

Alanlar, kullanıcıların dize, sayı ve renk gibi değerler girmesine olanak tanır. Bir alanın değerini almak için getFieldValue işlevini çağırın. Döndürülen değer, alandan alana değişir. Örneğin, metin alanları kullanıcı tarafından girilen metni tam olarak döndürür ancak açılır liste alanları, kullanıcının seçtiği öğeyle ilişkili dilsiz bir dize döndürür. Daha fazla bilgi için yerleşik alanlarla ilgili dokümanları inceleyin.

Alana bağlı olarak, döndürülen değeri kodda kullanmadan önce dönüştürmeniz gerekebilir.

custom_compare

javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
  // Use the value of the OPERATOR dropdown to look up the actual operator.
  const OPERATORS = {
    EQUALS: '==',
    LESS: '<',
    GREATER: '>',
  };
  const operator = OPERATORS[block.getFieldValue('OPERATOR')];
  // The value of the RIGHT field is a number and can be used directly when
  // building the block's code string.
  const right = block.getFieldValue('RIGHT');
  ...
}

custom_if

javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  // Use the value of the NOT field to get the negation operator (if any).
  const checkbox = block.getFieldValue('NOT');
  const negate = checkbox === 'TRUE' ? '!' : '';
  ...
}

Daha fazla bilgi için Alan değerlerini dönüştürme başlıklı makaleyi inceleyin.

İç bloklardan kod alma

İç bloklar, bir bloğun değerine ve ifade girişlerine eklenmiş bloklardır. Örneğin, custom_if bloğunda, if koşulu için bir değer iç bloğu ve koşul doğruysa yürütülen kod için ifade iç blokları bulunur.

Alan değerlerinden farklı olarak, iç bloklardan aldığınız kod kullanıma hazırdır ve dönüştürülmesi gerekmez.

İç değer blokları

Bir değer girişine bağlı iç bloktan kod almak için valueToCode işlevini çağırın. Bu yöntem, iç bloğun kod oluşturucusunu çağırır.

custom_compare

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

javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
  ...
  const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
  const left = generator.valueToCode(block, 'LEFT', order);
  ...
}

custom_if

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

javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  ...
  const order = checkbox === 'TRUE' ? Order.LOGICAL_NOT : Order.NONE;
  const condition = generator.valueToCode(block, 'CONDITION', order) || 'false';
  ...
}

valueToCode işlevini çağırırken, kodunuzdaki ve iç bloğun kodu için geçerli olacak en güçlü operatörden bahsetmeniz gerekir. Bu sayede valueToCode, iç bloğun kodunu parantez içine alması gerekip gerekmediğini belirleyebilir.

Örneğin, custom_if içindeki NOT kutusunu işaretlemek, koşula mantıksal değil operatörü (!) uygular. Bu durumda, değil operatörünün önceliğini (Order.LOGICAL_NOT) valueToCode'a iletirsiniz ve valueToCode bunu iç bloktaki en zayıf operatörün önceliğiyle karşılaştırır. Ardından, iç bloğun kodunu gerektiği gibi sarar:

  • CONDITION bir değişken bloğuysa valueToCode, değil operatörü doğrudan bir değişkene (!myBoolean) uygulanabildiği için parantez eklemez.
  • CONDITION bir karşılaştırma bloğuysa valueToCode parantez ekler. Böylece değil operatörü, soldaki değer (!a < b) yerine karşılaştırmanın tamamı (!(a < b)) için geçerli olur.

valueToCode'ün parantez ekleyip eklemediğini bilmeniz gerekmez. Tek yapmanız gereken önceliği valueToCode'e iletmek ve döndürülen kodu kod dizenize eklemektir. Daha fazla bilgi için valueToCode önceliği konusuna bakın.

İç ifade blokları

Bir ifade girişine bağlı iç bloktan kod almak için statementToCode işlevini çağırın. Bu yöntem, iç bloğun kod oluşturucusunu çağırır ve kod girmeyi işler.

custom_compare

custom_compare bloğunda ifade girişi yoktur.

custom_if

javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  ...
  const statements = generator.statementToCode(block, 'THEN');
  ...
}

Yalnızca doğrudan bir ifade girişine bağlı olan iç blok için statementToCode çağrısını yapmanız gerekir. statementToCode, ilk bloğa eklenmiş ek blokları işler.

Kod dizenizi oluşturup döndürme

Alanların ve iç blokların kodunu aldıktan sonra, bloğunuzun kod dizesini oluşturup döndürün. İade ettiğiniz öğe, blok türünüze bağlıdır:

  • Değer blokları: Kod dizesini ve kodunuzdaki en zayıf operatörün önceliğini içeren bir dizi döndürür. valueToCode, bloğunuz iç blok olarak kullanıldığında kodunuzun paranteze alınması gerekip gerekmediğine karar vermek için bunu kullanır. Daha fazla bilgi için Döndürme önceliği bölümüne bakın.

  • İfade blokları: Kod dizesini döndürür.

custom_compare

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

javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
  ...
  const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
  ...
  const code = left + ' ' + operator + ' ' + right;
  return [code, order];
}

custom_if

javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  ...
  const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
  return code;
}

Kod dizinizde bir iç değer bloğunun kodunu birden fazla kez kullanıyorsanız gizli hataları ve istenmeyen yan etkileri önlemek için bu bloktaki kodu önbelleğe almanız gerekir.

Tam kod oluşturucular

Referans olarak, her blok için kod oluşturucuların tamamını aşağıda bulabilirsiniz:

custom_compare

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

javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
  const OPERATORS = {
    EQUALS: '==',
    LESS: '<',
    GREATER: '>',
  };
  const operator = OPERATORS[block.getFieldValue('OPERATOR')];
  const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
  const left = generator.valueToCode(block, 'LEFT', order);
  const right = block.getFieldValue('RIGHT');
  const code = left + ' ' + operator + ' ' + right;
  return [code, order];
}

custom_if

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

javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  const checkbox = block.getFieldValue('NOT');
  const negate = checkbox === 'TRUE' ? '!' : '';
  const order = checkbox === 'TRUE' ? Order.LOGICAL_NOT : Order.NONE;
  const condition = generator.valueToCode(block, 'CONDITION', order) || 'false';
  const statements = generator.statementToCode(block, 'THEN');
  const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
  return code;
}