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:
- Dil kod üreten model içe aktarın.
- Her alanın değerini alın ve bunu bir kod dizesine dönüştürün.
- Değer ve ifade girişlerine eklenen bloklar olan iç bloklar tarafından oluşturulan kod dizelerini alın.
- 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,LEFTadlı bir değer girişi,OPERATORadlı bir açılır liste alanı veRIGHTadlı bir sayısal alan içeren bir değer bloğudur.'0 = 0'biçiminde bir ifade dizesi oluşturur.
custom_if,NOTadlı bir onay kutusu alanı,CONDITIONadlı bir değer girişi veTHENadlı bir ifade girişi içeren bir ifade bloğudur.'if (...) {\n...\n};\n'biçiminde bir ifade dizesi oluşturur.
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:
CONDITIONbir değişken bloksavalueToCodeparantez eklemez. Çünkü not operatörü doğrudan bir değişkene uygulanabilir (!myBoolean).CONDITIONbir karşılaştırma bloğuysavalueToCode, 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;
}