Generator kode blok adalah fungsi yang menghasilkan kode untuk blok dan menampilkannya sebagai string. Kode yang dihasilkan blok bergantung pada jenisnya:
- Blok nilai memiliki koneksi output. Blok ini bertindak seperti ekspresi dalam bahasa berbasis teks dan menghasilkan string yang berisi ekspresi.
- Blok pernyataan adalah blok tanpa koneksi output. Blok ini bertindak seperti pernyataan dalam bahasa berbasis teks dan menghasilkan string yang berisi pernyataan.
Cara menulis generator kode blok
Untuk setiap blok kustom yang Anda buat, Anda harus menulis generator kode blok untuk setiap bahasa yang ingin Anda dukung. Perhatikan bahwa semua generator kode blok ditulis dalam JavaScript, meskipun menghasilkan kode dalam bahasa lain.
Semua generator kode blok melakukan langkah-langkah berikut:
- Mengimpor generator kode bahasa.
- Mendapatkan nilai setiap kolom dan mengubahnya menjadi string kode.
- Mendapatkan string kode yang dihasilkan oleh blok dalam, yang merupakan blok yang dilampirkan ke input nilai dan pernyataan.
- Membuat dan menampilkan string kode blok.
Contoh blok
Sebagai contoh, kita akan menulis generator kode JavaScript untuk blok berikut.
custom_compareadalah blok nilai yang memiliki input nilai bernamaLEFT, kolom dropdown bernamaOPERATOR, dan kolom numerik bernamaRIGHT. Blok ini menghasilkan string ekspresi dalam bentuk'0 = 0'.
custom_ifadalah blok pernyataan yang memiliki kolom kotak centang bernamaNOT, input nilai bernamaCONDITION, dan input pernyataan bernamaTHEN. Blok ini menghasilkan string pernyataan dalam bentuk'if (...) {\n...\n};\n'.
Dokumen ini membuat generator langkah demi langkah. Anda dapat menemukan generator yang telah selesai di akhir dokumen ini.
Perhatikan bahwa blok ini hanya dimaksudkan untuk mengilustrasikan pembuatan kode. Dalam aplikasi sebenarnya, gunakan blok logic_compare dan controls_if bawaan.
Mengimpor generator kode bahasa
Anda dapat mengimpor generator kode bahasa menggunakan salah satu metode berikut. Gunakan generator yang diimpor untuk menyimpan generator kode blok dalam objek forBlock.
Modul
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
Anda harus menyertakan generator setelah menyertakan Blockly.
<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) { /* ... */ };
Skrip lokal
Anda harus menyertakan generator setelah menyertakan Blockly.
<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) { /* ... */ };
Mendapatkan nilai kolom
Kolom memungkinkan pengguna memasukkan nilai seperti string, angka, dan warna. Untuk mendapatkan nilai kolom, panggil getFieldValue. Nilai yang ditampilkan berbeda dari kolom ke kolom. Misalnya, kolom teks menampilkan teks persis yang dimasukkan oleh pengguna, tetapi kolom dropdown menampilkan string netral bahasa yang terkait dengan item yang dipilih pengguna. Untuk mengetahui informasi selengkapnya, lihat dokumentasi untuk kolom bawaan.
Bergantung pada kolom, Anda mungkin perlu mengubah nilai yang ditampilkan sebelum menggunakannya dalam kode.
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' ? '!' : '';
...
}
Untuk mengetahui informasi selengkapnya, lihat Mengubah nilai kolom.
Mendapatkan kode dari blok dalam
Blok dalam adalah blok yang dilampirkan ke input nilai dan pernyataan blok.
Misalnya, blok custom_if memiliki blok dalam nilai untuk kondisi if, dan blok dalam pernyataan untuk kode yang dieksekusi jika kondisinya benar.
Tidak seperti nilai kolom, kode yang Anda dapatkan dari blok dalam siap digunakan dan tidak perlu diubah.
Blok nilai dalam
Untuk mendapatkan kode dari blok dalam yang dilampirkan ke input nilai, panggil valueToCode.
Metode ini memanggil generator kode blok dalam.
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';
...
}
Saat memanggil valueToCode, Anda harus memberi tahu operator terkuat dalam kode yang akan diterapkan ke kode blok dalam. Hal ini memungkinkan valueToCode menentukan apakah kode blok dalam perlu digabungkan dalam tanda kurung.
Misalnya, mencentang kotak NOT di custom_if akan menerapkan operator logis not (!) ke kondisi. Dalam hal ini, Anda meneruskan prioritas operator not (Order.LOGICAL_NOT) ke valueToCode dan valueToCode membandingkannya dengan prioritas operator terlemah di blok dalam. Kemudian, kode blok dalam akan digabungkan sesuai kebutuhan:
- Jika
CONDITIONadalah blok variabel,valueToCodetidak menambahkan tanda kurung karena operator not dapat diterapkan langsung ke variabel (!myBoolean). - Jika
CONDITIONadalah blok perbandingan,valueToCodeakan menambahkan tanda kurung sehingga operator not berlaku untuk seluruh perbandingan (!(a < b)) dan bukan nilai sisi kiri (!a < b).
Anda sebenarnya tidak perlu mengetahui apakah valueToCode menambahkan tanda kurung. Yang perlu Anda lakukan adalah meneruskan prioritas ke valueToCode dan menambahkan kode yang ditampilkan ke string kode Anda. Untuk mengetahui informasi selengkapnya, lihat prioritas valueToCode.
Blok pernyataan dalam
Untuk mendapatkan kode dari blok dalam yang dilampirkan ke input pernyataan, panggil statementToCode. Metode ini memanggil generator kode blok dalam dan menangani kode indentasi.
custom_compare
Blok custom_compare tidak memiliki input pernyataan.
custom_if
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
...
const statements = generator.statementToCode(block, 'THEN');
...
}
Anda hanya perlu memanggil statementToCode untuk blok dalam yang terhubung langsung ke input pernyataan. statementToCode menangani blok tambahan yang dilampirkan ke blok pertama.
Membuat dan menampilkan string kode
Setelah mendapatkan kode untuk kolom dan blok dalam, buat dan tampilkan string kode untuk blok Anda. Apa yang Anda tampilkan bergantung pada jenis blok Anda:
Blok nilai: Menampilkan array yang berisi string kode dan prioritas operator terlemah dalam kode Anda.
valueToCodemenggunakan ini untuk memutuskan apakah kode Anda perlu digabungkan dalam tanda kurung saat blok Anda digunakan sebagai blok dalam. Untuk mengetahui informasi selengkapnya, lihat Prioritas pengembalian.Blok pernyataan: Menampilkan string kode.
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;
}
Jika Anda menggunakan kode blok nilai dalam beberapa kali dalam string kode, Anda harus menyimpan kode dari blok tersebut dalam cache untuk menghindari bug yang tidak terlihat dan efek samping yang tidak diinginkan.
Generator kode lengkap
Sebagai referensi, berikut adalah generator kode lengkap untuk setiap blok:
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;
}