Blok kodu oluşturma araçları

Blok kodu oluşturucu, bir blok için kod 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 dildeki ifadeler gibi davranır ve ifadeler içeren dizeler oluşturur.
  • İfade blokları, çıkış bağlantısı olmayan bloklardır. Bu bloklar, metin tabanlı bir dildeki ifadeler gibi davranır ve ifadeler 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. Başka bir dilde kod oluştursalar bile tüm blok kodu oluşturucuların JavaScript ile yazıldığını unutmayın.

Tüm blok kodu oluşturucular aşağıdaki adımları uygular:

  1. Dil kod üreten model 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 eklenen bloklar olan iç bloklar tarafından oluşturulan kod dizelerini alın.
  4. Bloğun kod dizesini oluşturur ve döndürür.

Örnek bloklar

Örnek olarak, aşağıdaki bloklar için JavaScript kodu 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 alan içeren 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.

    Bir if ifadesi için özel ifade bloğu. Kullanıcılar, koşulun olumsuzlanması için onay kutusunu kullanabilir.

Bu belgede, oluşturucular adım adım oluşturulur. Tamamlanmış jeneratörleri bu belgenin sonunda bulabilirsiniz.

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

Dil kod üreten model içe aktarma

Aşağıdaki yöntemlerden birini kullanarak dil kodu üreten model içe aktarabilirsiniz. İçe aktarılan oluşturucuyu kullanarak blok kodu oluşturucuları forBlock nesnesinde saklayı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 oluşturma aracını 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 oluşturma aracını 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 dizeler, sayılar ve renkler 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ğerler alandan alana farklılık gösterir. Örneğin, metin alanları kullanıcı tarafından girilen metni tam olarak döndürürken açılır liste alanları, kullanıcının seçtiği öğeyle ilişkili dilden bağımsız bir dize döndürür. Daha fazla bilgi için yerleşik alanlarla ilgili dokümanlara bakın.

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 eklenen 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ğerlerinin aksine, 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 eklenmiş bir iç bloktan kod almak için valueToCode işlevini çağırın. Bu yöntem, iç blokun kod üreten modelini ç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'ı aradığınızda, iç blok koduna uygulanacak kodunuzdaki en güçlü operatör hakkında bilgi vermeniz gerekir. Bu, valueToCode'nın iç blok kodunu parantez içine alması gerekip gerekmediğini belirlemesine olanak tanır.

Örneğin, custom_if bölümünde NOT kutusunu işaretlemek koşula mantıksal değil operatörü (!) uygular. Bu durumda, not operatörünün önceliğini (Order.LOGICAL_NOT) valueToCode'ye aktarırsınız ve valueToCode bunu iç bloktaki en zayıf operatörün önceliğiyle karşılaştırır. Ardından, gerektiğinde iç bloğun kodunu sarar:

  • CONDITION bir değişken bloksa valueToCode parantez eklemez. Çünkü not operatörü doğrudan bir değişkene uygulanabilir (!myBoolean).
  • CONDITION bir karşılaştırma bloğuysa valueToCode, parantez ekler. Böylece not operatörü, soldaki değer (!a < b) yerine karşılaştırmanın tamamına (!(a < b)) uygulanır.

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

İç ifade blokları

Bir ifade girişine eklenmiş bir iç bloktan kod almak için statementToCode işlevini çağırın. Bu yöntem, iç bloktaki kod üreten modelini çağırır ve kodun girintilenmesini sağlar.

custom_compare

custom_compare bloğunda herhangi bir ifade girişi yok.

custom_if

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

Yalnızca bir ifade girişine doğrudan bağlı olan iç blok için statementToCode işlevini çağırmanız gerekir. statementToCode, ilk bloğa eklenen diğer tüm 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. Tam olarak neyi döndüreceğiniz, 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 parantez içine alınması gerekip gerekmediğine karar vermek için bunu kullanır. Daha fazla bilgi için Dönüş önceliği başlıklı makaleyi inceleyin.

  • İ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 dizenizde bir iç değer bloğunun kodunu birden çok kez kullanıyorsanız ince hataları ve istenmeyen yan etkileri önlemek için bu bloktaki kodu önbelleğe almanız gerekir.

Kod tamamlama araçları

Referans olması için her blokla ilgili 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;
}