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

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

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

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

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

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

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

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

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

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

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

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

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

इस दस्तावेज़ में, जनरेटर को चरण दर चरण बनाया गया है. इस दस्तावेज़ के आखिर में, आपको पूरे जनरेटर दिखेंगे.

ध्यान दें कि इन ब्लॉक का इस्तेमाल, सिर्फ़ कोड जनरेट करने की प्रोसेस को दिखाने के लिए किया गया है. किसी असली ऐप्लिकेशन में, पहले से मौजूद 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 को नॉट ऑपरेटर की प्राथमिकता (Order.LOGICAL_NOT) पास करें. इसके बाद, valueToCode इसकी तुलना, इनर ब्लॉक में सबसे कम प्राथमिकता वाले ऑपरेटर की प्राथमिकता से करता है. इसके बाद, यह ज़रूरत के हिसाब से इनर ब्लॉक के कोड को रैप करता है:

  • अगर CONDITION कोई वैरिएबल ब्लॉक है, तो valueToCode ब्रैकेट नहीं जोड़ता. ऐसा इसलिए, क्योंकि नॉट ऑपरेटर को सीधे किसी वैरिएबल (!myBoolean) पर लागू किया जा सकता है.
  • अगर CONDITION कोई तुलना ब्लॉक है, तो valueToCode ब्रैकेट जोड़ता है. इससे नॉट ऑपरेटर, लेफ्ट-हैंड वैल्यू (!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;
}