---
title: Block-code generators
description: How to generate code for a block.
image: images/blockly_banner.png
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Block-code generators

A block-code generator is a function that generates the code for a block and
returns it as a string. What code a block generates depend on its type:

- Value blocks have an output connection. These blocks act like expressions in
  a text-based language and generate strings that contain expressions.
- Statement blocks are blocks without an output connection. These blocks act
  like statements in a text-based language and generate strings that contain
  statements.

## How to write a block-code generator

For each custom block you create, you need to write a block-code generator for
each language you want to support. Note that all block-code generators are
written in JavaScript, even if they generate code in another language.

All block-code generators perform the following steps:

1.  Import a language code generator.
1.  Get the value of each field and transform it into a code string.
1.  Get the code strings generated by inner blocks, which are blocks attached to
    value and statement inputs.
1.  Build and return the block's code string.

## Example blocks

As examples, we will write JavaScript code generators for the following blocks.

- `custom_compare` is a value block that has a value input named `LEFT`, a
  dropdown field named `OPERATOR`, and a numeric field named `RIGHT`. It
  generates an expression string of the form `'0 = 0'`.

  ![Custom value block for
comparisons.](/images/code-generation/custom-compare.png)

- `custom_if` is a statement block that has a checkbox field named `NOT`, a
  value input named `CONDITION`, and a statement input named `THEN`. It
  generates a statement string of the form `'if (...) {\n...\n};\n'`.

  ![Custom statement block for an if statement. Users can use a checkbox to
negate the if condition.](/images/code-generation/custom-if.png)

This document builds the generators step by step. You can find the completed
generators at the [end of this document](#complete-code-generators).

Note that these blocks are intended only to illustrate code generation. In a
real application, use the built-in `logic_compare` and `controls_if` blocks.

## Import a language code generator

You can import a language code generator using one of the following methods. Use
the imported generator to store block-code generators in the `forBlock` object.

<Tabs groupId="custom_compare-custom_if">
<TabItem value="modules" label="Modules" default>
```js
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) {/* ... */};

````
</TabItem>
<TabItem value="unpkg" label="Unpkg">
You must include the generator after you include Blockly.

```html
<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>
````

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

</TabItem>
<TabItem value="local_scripts" label="Local scripts">
You must include the generator after you include Blockly.

```html
<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>
```

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

</TabItem>
</Tabs>

## Get field values

Fields allow users to enter values like strings, numbers, and colours. To get a
field's value, call `getFieldValue`. What is returned is different from field to
field. For example, text fields return the exact text entered by the user, but
dropdown fields return a language-neutral string associated with the item the
user selected. For more information, see the [documentation for built-in
fields](/guides/create-custom-blocks/fields/built-in-fields/overview).

Depending on the field, you may need to transform the returned value before
using it in code.

<Tabs groupId="custom_compare-custom_if">
<TabItem value="custom_compare" label="custom_compare" default>
```js
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');
  ...
}
```
</TabItem>
<TabItem value="custom_if" label="custom_if">
```js
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' ? '!' : '';
  ...
}
```
</TabItem>
</Tabs>

For more information, see [Transform field
values](/guides/create-custom-blocks/code-generation/fields).

## Get code from inner blocks

Inner blocks are the blocks attached to a block's value and statement inputs.
For example, the `custom_if` block has a value inner block for the if condition,
and statement inner blocks for the code that is executed if the condition is
true.

Unlike field values, the code you get from inner blocks is ready to go and does
not need to be transformed.

:::note
A block attached to a next connection is not an inner block and your
block-code generator should ignore it. The language code generator gets the code
for next blocks.
:::

### Inner value blocks

To get code from an inner block attached to a value input, call `valueToCode`.
This method calls the inner block's code generator.

<Tabs groupId="custom_compare-custom_if">
<TabItem value="custom_compare" label="custom_compare" default>
```js
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);
...
}

````
</TabItem>
<TabItem value="custom_if" label="custom_if">
```js
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';
  ...
}
````

</TabItem>
</Tabs>

When you call `valueToCode`, you need to tell it about the strongest operator in
your code that will apply to the inner block's code. This allows `valueToCode`
to determine whether it needs to wrap the inner block's code in parentheses.

For example, checking the `NOT` box in `custom_if` applies a logical not
operator (`!`) to the condition. In this case, you pass the not operator's
precedence (`Order.LOGICAL_NOT`) to `valueToCode` and `valueToCode` compares
this to the precedence of the weakest operator in the inner block. It then wraps
the inner block's code as needed:

- If `CONDITION` is a variable block, `valueToCode` doesn't add parentheses
  because the not operator can be applied directly to a variable
  (`!myBoolean`).
- If `CONDITION` is a comparison block, `valueToCode` adds parentheses so the
  not operator applies to the entire comparison (`!(a < b)`) instead of the
  left-hand value (`!a < b`).

You don't actually need to know whether `valueToCode` added parentheses. All you
need to do is pass the precedence to `valueToCode` and add the returned code to
your code string. For more information, see [valueToCode
precedence](/guides/create-custom-blocks/code-generation/operator-precedence#valuetocode-precedence).

### Inner statement blocks

To get code from an inner block attached to a statement input, call
`statementToCode`. This method calls the inner block's code generator and
handles indenting code.

<Tabs groupId="custom_compare-custom_if">
<TabItem value="custom_compare" label="custom_compare">
The `custom_compare` block does not have any statement inputs.
</TabItem>
<TabItem value="custom_if" label="custom_if" default>
```js
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  ...
  const statements = generator.statementToCode(block, 'THEN');
  ...
}
```
</TabItem>
</Tabs>

You only need to call `statementToCode` for the inner block directly connected
to a statement input. `statementToCode` handles any additional blocks attached
to the first block.

## Build and return your code string

After you have gotten the code for the fields and inner blocks, build and return
the code string for your block. Exactly what you return depends on your block
type:

- **Value blocks:** Return an array containing the code string and the
  precedence of the weakest operator in your code. `valueToCode` uses this to
  decide if your code needs to be wrapped in parentheses when your block is
  used as an inner block. For more information, see [Return
  precedence](/guides/create-custom-blocks/code-generation/operator-precedence#return-precedence).

- **Statement blocks:** Return the code string.

<Tabs groupId="custom_compare-custom_if">
<TabItem value="custom_compare" label="custom_compare">
```js
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];
}

````
</TabItem>
<TabItem value="custom_if" label="custom_if" default>
```js
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
  ...
  const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
  return code;
}
````

</TabItem>
</Tabs>

If you use the code of an inner value block multiple times in your code string,
you should [cache the code from that
block](/guides/create-custom-blocks/code-generation/caching-arguments)
to avoid subtle bugs and unwanted side-effects.

## Complete code generators

For reference, here are the complete code generators for each block:

<Tabs groupId="custom_compare-custom_if">
<TabItem value="custom_compare" label="custom_compare">
```js
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];
}

````
</TabItem>
<TabItem value="custom_if" label="custom_if" default>
```js
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;
}
````

</TabItem>
</Tabs>
