Search code examples
javascriptblocklygoogle-blockly

Adding API call to JS-interpreter for use with custom blockly block


I want to preface this by saying I'm new to JavaScript, blockly and most certainly the use of Neil Fraser JS-interpreter.

I've made some custom blocks that simply create JavaScript that when eval() put an object of its block type and user inputs into an array.

The function they use to do this is called pushInstruction(blockName, inputs); where inputs is an array of the blocks user inputs, and blockName is the name of the block.

Now I am trying to use the JS-interpreter, but the problem is with how I go about using these blocks with it.

I'm desperate for help, and for the life of me can't find any resources to help me. It may be something silly.

Custom block code

Blockly.Blocks['select_hand_position'] = {
  init: function() {
    this.appendDummyInput()
        .appendField("Move");
    this.appendDummyInput()
        .appendField(new Blockly.FieldDropdown([["left hand","Left hand"], ["right hand","Right hand"]]), "handSelect")
        .appendField("to index")
        .appendField(new Blockly.FieldNumber(0), "indexSelect");
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(290);
 this.setTooltip("");
 this.setHelpUrl("");
  }
};
Blockly.JavaScript['select_hand_position'] = function(block) {
  var dropdown_handselect = block.getFieldValue('handSelect');
  var number_indexselect = block.getFieldValue('indexSelect'); 
  var input = '["'+dropdown_handselect+'",'+number_indexselect+']';
  var code = 'pushInstruction("select_hand_position",'+input+');'               
  return code;
};

I have a global array to hold the objects

instructionStructure = new Array();

which is then used in this function, of which is the one that the blocks generate code to use.

function pushInstruction(blockName,inputs) {  
  var instruction = null;
  switch(blockName) {
    case "place_book":
    case "grab_book":
    case "select_hand_position":
      instruction = {
        blockName: blockName,
        hand: inputs[0],
        index: inputs[1].toString()
      };
      instructionStructure.push(instruction);
      break;

    default:
      throw 'attempted to push unknown instruction block';
  }       
} 

Step Code

here is the code that is run upon button press of the step button

function stepCode() {
  Blockly.JavaScript.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
  Blockly.JavaScript.addReservedWords('highlightBlock');
  var code = Blockly.JavaScript.workspaceToCode(workspace);
  var myInterpreter = new Interpreter(code, initApi);
  function nextStep() {
    if (myInterpreter.step()) {
      window.setTimeout(nextStep, 1000);
    }
  }
  nextStep();
  alert(instructionStructure);
}

initAPI function

this is where i keep getting a

Uncaught TypeError: Interpreter.setProperty is not a function

on the line

Interpreter.setProperty(scope, 'pushInstruction', interpreter.createNativeFunction(wrapper));

function initApi(interpreter, scope) {

  var wrapper = function(id) {
    id = id ? id.toString() : '';
    return interpreter.createPrimitive(highlightBlock(id));
  };
  interpreter.setProperty(scope, 'highlightBlock',
      interpreter.createNativeFunction(wrapper));


  wrapper = function(blockName, inputs) {
    return pushInstruction(blockName,inputs);
  };
  Interpreter.setProperty(scope, 'pushInstruction',
      interpreter.createNativeFunction(wrapper));  
}

Thank you for spending the time to read over this, I greatly appreciate it!


Solution

  • You have a typo here:

    Interpreter.setProperty(scope, 'pushInstruction',
      interpreter.createNativeFunction(wrapper));  
    

    =>

    interpreter.setProperty(scope, 'pushInstruction',
      interpreter.createNativeFunction(wrapper));  
    

    That's for the Uncaught TypeError. Is it the only problem here? Because I don't really got the

    but the problem is with how I go about using these blocks with it.