Skip to content

Commit

Permalink
refactor(generators)!: Pass this CodeGenerator to individual generato…
Browse files Browse the repository at this point in the history
…r functions (#7168)

* feat(generators): Pass this CodeGenerator to generator functions

  This implements option 1A of proposal 1 of #7086.

  This commit is not by itself a breaking change, except in the unlikely event that
  developers' custom generator functions take an (optional) second argument of a
  dfferent type.

* feat(generators): Accept generator argument in block functions

  Accept a CodeGenerator instance as parameter two of every
  per-block-type generator function.

* fix(generators): Pass generator when calling other generator functions

  Make sure to pass generator to any other block functions that are
  called recursively.

* refactor(generators)!: Use generator argument in generator functions

  Refactor per-block-type generator functions to use the provided
  generator argument to make recursive calls, rather than depending
  on the closed-over <lang>Generator instance.

  This allows generator functions to be moved between CodeGenerator
  instances (of the same language, at least).

  This commit was created by search-and-replace and addresses most
  but not all recursive references; remaining uses will require
  manual attention and will be dealt with in a following commit.

  BREAKING CHANGE: This commit makes the generator functions we provide
  dependent on the new generator parameter.  Although
  CodeGenerator.prototype.blockToCode has been modified to supply this,
  so this change will not affect most developers, this change will be a
  breaking change where developers make direct calls to these generator
  functions without supplying the generator parameter.  See previous
  commit for an example of the update required.

* refactor(generators): Manual fix for remaining uses of langGenerator

  Manually replace remaining uses of <lang>Generator in block
  generator functions.

* fix(generators): Delete duplicate procedures_callnoreturn generator

  For some reason the generator function for procedures_callnoreturn
  appears twice in generators/javascript/procedures.js.  Delete the
  first copy (since the second one overwrote it anyway).

* chore(generators): Format
  • Loading branch information
cpcallen authored Jun 14, 2023
1 parent 12b91ae commit a345887
Show file tree
Hide file tree
Showing 44 changed files with 1,474 additions and 1,477 deletions.
8 changes: 6 additions & 2 deletions core/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ import {warn} from './utils/deprecation.js';
*
* @see {@link https://developers.google.com/blockly/guides/create-custom-blocks/generating-code}
* @param block The Block instance to generate code for.
* @param genearator The CodeGenerator calling the function.
* @returns A string containing the generated code (for statement blocks),
* or a [code, precedence] tuple (for value/expression blocks), or
* null if no code should be emitted for block.
*/
export type BlockGenerator = (block: Block) => [string, number] | string | null;
export type BlockGenerator = (
block: Block,
generator: CodeGenerator
) => [string, number] | string | null;

/**
* Class for a code generator that translates the blocks into a language.
Expand Down Expand Up @@ -258,7 +262,7 @@ export class CodeGenerator {
// The current preferred method of accessing the block is through the second
// argument to func.call, which becomes the first parameter to the
// generator.
let code = func.call(block, block);
let code = func.call(block, block, this);
if (Array.isArray(code)) {
// Value blocks return tuples of code and operator order.
if (!block.outputConnection) {
Expand Down
40 changes: 20 additions & 20 deletions generators/dart/colour.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import {dartGenerator, Order} from '../dart.js';

dartGenerator.addReservedWords('Math');

dartGenerator.forBlock['colour_picker'] = function(block) {
dartGenerator.forBlock['colour_picker'] = function(block, generator) {
// Colour picker.
const code = dartGenerator.quote_(block.getFieldValue('COLOUR'));
const code = generator.quote_(block.getFieldValue('COLOUR'));
return [code, Order.ATOMIC];
};

dartGenerator.forBlock['colour_random'] = function(block) {
dartGenerator.forBlock['colour_random'] = function(block, generator) {
// Generate a random colour.
dartGenerator.definitions_['import_dart_math'] =
generator.definitions_['import_dart_math'] =
"import 'dart:math' as Math;";
const functionName = dartGenerator.provideFunction_('colour_random', `
String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}() {
const functionName = generator.provideFunction_('colour_random', `
String ${generator.FUNCTION_NAME_PLACEHOLDER_}() {
String hex = '0123456789abcdef';
var rnd = new Math.Random();
return '#\${hex[rnd.nextInt(16)]}\${hex[rnd.nextInt(16)]}'
Expand All @@ -39,16 +39,16 @@ String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}() {
return [code, Order.UNARY_POSTFIX];
};

dartGenerator.forBlock['colour_rgb'] = function(block) {
dartGenerator.forBlock['colour_rgb'] = function(block, generator) {
// Compose a colour from RGB components expressed as percentages.
const red = dartGenerator.valueToCode(block, 'RED', Order.NONE) || 0;
const green = dartGenerator.valueToCode(block, 'GREEN', Order.NONE) || 0;
const blue = dartGenerator.valueToCode(block, 'BLUE', Order.NONE) || 0;
const red = generator.valueToCode(block, 'RED', Order.NONE) || 0;
const green = generator.valueToCode(block, 'GREEN', Order.NONE) || 0;
const blue = generator.valueToCode(block, 'BLUE', Order.NONE) || 0;

dartGenerator.definitions_['import_dart_math'] =
generator.definitions_['import_dart_math'] =
"import 'dart:math' as Math;";
const functionName = dartGenerator.provideFunction_('colour_rgb', `
String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) {
const functionName = generator.provideFunction_('colour_rgb', `
String ${generator.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) {
num rn = (Math.max(Math.min(r, 100), 0) * 2.55).round();
String rs = rn.toInt().toRadixString(16);
rs = '0$rs';
Expand All @@ -68,19 +68,19 @@ String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) {
return [code, Order.UNARY_POSTFIX];
};

dartGenerator.forBlock['colour_blend'] = function(block) {
dartGenerator.forBlock['colour_blend'] = function(block, generator) {
// Blend two colours together.
const c1 =
dartGenerator.valueToCode(block, 'COLOUR1', Order.NONE) || "'#000000'";
generator.valueToCode(block, 'COLOUR1', Order.NONE) || "'#000000'";
const c2 =
dartGenerator.valueToCode(block, 'COLOUR2', Order.NONE) || "'#000000'";
generator.valueToCode(block, 'COLOUR2', Order.NONE) || "'#000000'";
const ratio =
dartGenerator.valueToCode(block, 'RATIO', Order.NONE) || 0.5;
generator.valueToCode(block, 'RATIO', Order.NONE) || 0.5;

dartGenerator.definitions_['import_dart_math'] =
generator.definitions_['import_dart_math'] =
"import 'dart:math' as Math;";
const functionName = dartGenerator.provideFunction_('colour_blend', `
String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String c1, String c2, num ratio) {
const functionName = generator.provideFunction_('colour_blend', `
String ${generator.FUNCTION_NAME_PLACEHOLDER_}(String c1, String c2, num ratio) {
ratio = Math.max(Math.min(ratio, 1), 0);
int r1 = int.parse('0x\${c1.substring(1, 3)}');
int g1 = int.parse('0x\${c1.substring(3, 5)}');
Expand Down
Loading

0 comments on commit a345887

Please sign in to comment.