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:
- Dil kodu oluşturucu 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 bağlı bloklar olan iç bloklar tarafından oluşturulan kod dizelerini alın.
- 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ı veRIGHT
adlı bir sayısal alana sahip bir değer bloğudur.'0 = 0'
biçiminde bir ifade dizesi oluşturur.custom_if
,NOT
adlı bir onay kutusu alanı,CONDITION
adlı bir değer girişi veTHEN
adlı bir ifade girişi içeren bir ifade bloğudur.'if (...) {\n...\n};\n'
biçiminde bir ifade dizesi oluşturur.
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ğuysavalueToCode
, değil operatörü doğrudan bir değişkene (!myBoolean
) uygulanabildiği için parantez eklemez.CONDITION
bir karşılaştırma bloğuysavalueToCode
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;
}