How to modify the code generator of Blockly build-in arithmetic blocks?

202 views
Skip to first unread message

John K

unread,
Jun 20, 2022, 2:15:11 AM6/20/22
to Blockly

   There are some Blockly builder math blocks: +-/*, etc.
They work fine but have two problems:
A. It can be passed any data into these blocks while the block-generated code executes.
For example,
QQ图片20220620134908.png
Screenshot 2022-06-20 135437.png

B. The expression can be an available divided by 0 and will lead to a result of infinite and have a chance to mess the entire program around and hard to find the problem by users.
Screenshot 2022-06-20 135145.png
Screenshot 2022-06-20 135510.png

To resolve the problems, I think an idea is to check the type of arithmetic block parameters in runtime when block-generated code runs.  prevent code runs and shows a tip message to users if the parameter is not a valid number or is divided by zero.

I wish the new generator code could have the following abilities:
1. Throw an error when a parameter is not a number passed to arithmetic block when code executes. 
2. Throw an error when the dividend is zero when code executes. 

 How to change the code generator of Blockly build-in arithmetic block?

 

 
  

Neil Fraser

unread,
Jun 20, 2022, 4:03:45 AM6/20/22
to blo...@googlegroups.com
With so much functionality you'll want to create a helper function.  Something like:

JavaScript['math_arithmetic'] = function(block) {
  // Basic arithmetic operators, and power.
  const functionName = JavaScript.provideFunction_('mathArithmetic', `
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(a, b, op) {
  if (typeof a !== 'number' || typeof b !== 'number') {
    throw Error('Math operator requires numbers');
  }
  switch (op) {
    case 'ADD':
      return a + b;
    case 'MINUS':
      return a - b;
    case 'MULTIPLY':
      return a * b;
    case 'DIVIDE':
      if (!b) {
        throw Error('Division by zero');
      }
      return a / b;
    case 'POWER':
      return Math.pow(a, b);
  }
  throw Error('Unknown math operation');
}
`);
  const argument0 = JavaScript.valueToCode(block, 'A', order) || '0';
  const argument1 = JavaScript.valueToCode(block, 'B', order) || '0';
  const code = functionName + '(' + argument0 + ', ' + argument1 + ', "' + block.getFieldValue('OP') + '")';
  return [code, JavaScript.ORDER_FUNCTION_CALL];
};

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/9e2c1aee-0560-4109-b620-68abdb2de715n%40googlegroups.com.


--

John K

unread,
Jun 20, 2022, 5:33:39 AM6/20/22
to Blockly
Thank you  Neil Fraser. Your code works well and inspires me a lot.

feni...@google.com

unread,
Jun 21, 2022, 9:30:44 AM6/21/22
to Blockly
For large changes like this it's better to make your own block (something like 'math_arithmetic_runtime_checks') and use that in your app that you were previously using the `math_arithmetic` block.
Reply all
Reply to author
Forward
0 new messages