ब्लॉक-कोड जनरेटर

ब्लॉक-कोड जनरेटर एक ऐसा फ़ंक्शन है जो किसी ब्लॉक के लिए कोड जनरेट करता है और उसे स्ट्रिंग के तौर पर दिखाता है. ब्लॉक किस तरह का है, इसके आधार पर यह तय होता है कि वह कौनसा कोड जनरेट करेगा:

  • वैल्यू ब्लॉक में आउटपुट कनेक्शन होता है. ये ब्लॉक, टेक्स्ट पर आधारित भाषा में एक्सप्रेशन की तरह काम करते हैं और एक्सप्रेशन वाली स्ट्रिंग जनरेट करते हैं.
  • स्टेटमेंट ब्लॉक, ऐसे ब्लॉक होते हैं जिनमें आउटपुट कनेक्शन नहीं होता. ये ब्लॉक, टेक्स्ट पर आधारित भाषा में स्टेटमेंट की तरह काम करते हैं और ऐसी स्ट्रिंग जनरेट करते हैं जिनमें स्टेटमेंट शामिल होते हैं.

ब्लॉक-कोड जनरेटर लिखने का तरीका

अपने बनाए गए हर कस्टम ब्लॉक के लिए, आपको हर उस भाषा के लिए ब्लॉक-कोड जनरेटर लिखना होगा जिसे आपको इस्तेमाल करना है. ध्यान दें कि सभी ब्लॉक-कोड जनरेटर, JavaScript में लिखे जाते हैं. भले ही, वे किसी दूसरी भाषा में कोड जनरेट करते हों.

सभी ब्लॉक-कोड जनरेटर, ये चरण पूरे करते हैं:

  1. भाषा कोड जनरेटर इंपोर्ट करें.
  2. हर फ़ील्ड की वैल्यू पाएं और उसे कोड स्ट्रिंग में बदलें.
  3. इनर ब्लॉक से जनरेट की गई कोड स्ट्रिंग पाएं. ये ऐसे ब्लॉक होते हैं जो वैल्यू और स्टेटमेंट इनपुट से जुड़े होते हैं.
  4. ब्लॉक की कोड स्ट्रिंग बनाएं और उसे दिखाएं.

ब्लॉक के उदाहरण

उदाहरण के तौर पर, हम नीचे दिए गए ब्लॉक के लिए JavaScript कोड जनरेटर लिखेंगे.

  • custom_compare एक वैल्यू ब्लॉक है, जिसमें LEFT नाम का वैल्यू इनपुट, OPERATOR नाम का ड्रॉपडाउन फ़ील्ड, और RIGHT नाम का अंकों वाला फ़ील्ड है. यह '0 = 0' फ़ॉर्मैट की एक्सप्रेशन स्ट्रिंग जनरेट करता है.

    तुलना करने के लिए कस्टम वैल्यू ब्लॉक.

  • custom_if एक स्टेटमेंट ब्लॉक है, जिसमें NOT नाम का चेकबॉक्स फ़ील्ड, CONDITION नाम का वैल्यू इनपुट, और THEN नाम का स्टेटमेंट इनपुट है. यह 'if (...) {\n...\n};\n' फ़ॉर्मैट की स्टेटमेंट स्ट्रिंग जनरेट करता है.

    अगर स्टेटमेंट के लिए कस्टम स्टेटमेंट ब्लॉक. उपयोगकर्ता, अगर शर्त को अस्वीकार करने के लिए चेकबॉक्स का इस्तेमाल कर सकते हैं.

इस दस्तावेज़ में, जनरेटर को सिलसिलेवार तरीके से बनाने का तरीका बताया गया है. जनरेटर के लिए तैयार किए गए कोड, इस दस्तावेज़ के आखिर में देखे जा सकते हैं.

ध्यान दें कि इन ब्लॉक का मकसद सिर्फ़ कोड जनरेशन को दिखाना है. किसी असली ऐप्लिकेशन में, पहले से मौजूद logic_compare और controls_if ब्लॉक का इस्तेमाल करें.

भाषा कोड जनरेटर इंपोर्ट करना

भाषा कोड जनरेटर को इंपोर्ट करने के लिए, इनमें से किसी एक तरीके का इस्तेमाल करें. forBlock ऑब्जेक्ट में ब्लॉक-कोड जनरेटर सेव करने के लिए, इंपोर्ट किए गए जनरेटर का इस्तेमाल करें.

मॉड्यूल

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 शामिल करने के बाद, आपको जनरेटर शामिल करना होगा.

<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) { /* ... */ };

लोकल स्क्रिप्ट

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) { /* ... */ };

फ़ील्ड की वैल्यू पाना

फ़ील्ड की मदद से, उपयोगकर्ता स्ट्रिंग, संख्याएं, और रंग जैसी वैल्यू डाल सकते हैं. किसी फ़ील्ड की वैल्यू पाने के लिए, getFieldValue को कॉल करें. हर फ़ील्ड के लिए, नतीजा अलग-अलग होता है. उदाहरण के लिए, टेक्स्ट फ़ील्ड में उपयोगकर्ता के डाले गए टेक्स्ट को दिखाया जाता है. हालांकि, ड्रॉपडाउन फ़ील्ड में उपयोगकर्ता के चुने गए आइटम से जुड़ी स्ट्रिंग दिखती है. यह स्ट्रिंग किसी भी भाषा में हो सकती है. ज़्यादा जानकारी के लिए, पहले से मौजूद फ़ील्ड के लिए दस्तावेज़ देखें.

फ़ील्ड के आधार पर, आपको कोड में इस्तेमाल करने से पहले, रिटर्न की गई वैल्यू में बदलाव करना पड़ सकता है.

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' ? '!' : '';
  ...
}

ज़्यादा जानकारी के लिए, फ़ील्ड की वैल्यू बदलना लेख पढ़ें.

इनर ब्लॉक से कोड पाना

इनर ब्लॉक, ब्लॉक की वैल्यू और स्टेटमेंट इनपुट से जुड़े ब्लॉक होते हैं. उदाहरण के लिए, custom_if ब्लॉक में, if कंडीशन के लिए वैल्यू इनर ब्लॉक और कंडीशन के सही होने पर चलने वाले कोड के लिए स्टेटमेंट इनर ब्लॉक होता है.

फ़ील्ड वैल्यू के उलट, इनर ब्लॉक से मिलने वाला कोड इस्तेमाल के लिए तैयार होता है और उसे बदलने की ज़रूरत नहीं होती.

इनर वैल्यू ब्लॉक

वैल्यू इनपुट से जुड़े इनर ब्लॉक से कोड पाने के लिए, valueToCode को कॉल करें. यह तरीका, इनर ब्लॉक के कोड जनरेटर को कॉल करता है.

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 को कॉल करते समय, आपको अपने कोड में सबसे ज़्यादा असरदार ऑपरेटर के बारे में बताना होगा. यह ऑपरेटर, इनर ब्लॉक के कोड पर लागू होगा. इससे valueToCode को यह तय करने में मदद मिलती है कि उसे अंदरूनी ब्लॉक के कोड को ब्रैकेट में लपेटना है या नहीं.

उदाहरण के लिए, custom_if में NOT बॉक्स पर सही का निशान लगाने से, शर्त पर लॉजिकल नॉट ऑपरेटर (!) लागू होता है. इस मामले में, valueToCode को not ऑपरेटर की प्राथमिकता (Order.LOGICAL_NOT) दी जाती है. इसके बाद, valueToCode इसकी तुलना इनर ब्लॉक में सबसे कम प्राथमिकता वाले ऑपरेटर से करता है. इसके बाद, यह ज़रूरत के हिसाब से अंदरूनी ब्लॉक के कोड को रैप करता है:

  • अगर CONDITION कोई वैरिएबल ब्लॉक है, तो valueToCode ब्रैकेट नहीं जोड़ता, क्योंकि नॉट ऑपरेटर को सीधे वैरिएबल (!myBoolean) पर लागू किया जा सकता है.
  • अगर CONDITION तुलना वाला ब्लॉक है, तो valueToCode ब्रैकेट जोड़ता है, ताकि !a < b के बजाय, बाईं ओर की वैल्यू (!(a < b)) के बजाय, पूरी तुलना (!(a < b)) पर नॉट ऑपरेटर लागू हो.

आपको यह जानने की ज़रूरत नहीं है कि valueToCode ने ब्रैकेट जोड़े हैं या नहीं. आपको बस valueToCode को प्राथमिकता पास करनी होगी और कोड स्ट्रिंग में, दिखाया गया कोड जोड़ना होगा. ज़्यादा जानकारी के लिए, valueToCode के इस्तेमाल की प्राथमिकता देखें.

इनर स्टेटमेंट ब्लॉक

स्टेटमेंट इनपुट से जुड़े इनर ब्लॉक से कोड पाने के लिए, statementToCode को कॉल करें. यह तरीका, इनर ब्लॉक के कोड जनरेटर को कॉल करता है और इंडेंट किए गए कोड को मैनेज करता है.

custom_compare

custom_compare ब्लॉक में कोई स्टेटमेंट इनपुट नहीं है.

custom_if

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

आपको सिर्फ़ उस इनर ब्लॉक के लिए statementToCode को कॉल करना होगा जो सीधे तौर पर किसी स्टेटमेंट इनपुट से जुड़ा हो. statementToCode, पहले ब्लॉक से जुड़े किसी भी अतिरिक्त ब्लॉक को मैनेज करता है.

कोड स्ट्रिंग बनाना और उसे दिखाना

फ़ील्ड और इनर ब्लॉक का कोड मिलने के बाद, अपने ब्लॉक के लिए कोड स्ट्रिंग बनाएं और उसे दिखाएं. आपके ब्लॉक का टाइप तय करता है कि आपको क्या लौटाना है:

  • वैल्यू ब्लॉक: यह एक ऐरे दिखाता है, जिसमें कोड स्ट्रिंग और आपके कोड में सबसे कम प्राथमिकता वाले ऑपरेटर की प्राथमिकता शामिल होती है. valueToCode इसका इस्तेमाल यह तय करने के लिए करता है कि आपके ब्लॉक को अंदरूनी ब्लॉक के तौर पर इस्तेमाल करने पर, आपके कोड को ब्रैकेट में लपेटना ज़रूरी है या नहीं. ज़्यादा जानकारी के लिए, नतीजों के क्रम देखें.

  • स्टेटमेंट ब्लॉक: कोड स्ट्रिंग दिखाएं.

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;
}

अगर कोड स्ट्रिंग में किसी इनर वैल्यू ब्लॉक का कोड कई बार इस्तेमाल किया जाता है, तो आपको उस ब्लॉक के कोड को कैश मेमोरी में सेव करना चाहिए. इससे, गड़बड़ियों और अनचाहे असर से बचा जा सकता है.

कोड जनरेटर

रेफ़रंस के लिए, यहां हर ब्लॉक के लिए पूरे कोड जनरेटर दिए गए हैं:

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;
}