<commit_before>/*
 * Copyright 2016 The CodeWorld Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

goog.provide('Blockly.Blocks.cwLists');

goog.require('Blockly.Blocks');

var listsHUE = 260;


Blockly.Blocks['lists_comprehension'] = {
  /**
   * Block for creating a list with any number of elements of any type.
   * @this Blockly.Block
   */
  init: function() {
    this.setColour(listsHUE);
    this.vars_ = ['i','j','k'];
    this.varTypes_ = [Type.generateTypeVar('lc'), Type.generateTypeVar('lc'), Type.generateTypeVar('lc')];
    this.appendValueInput("DO")
        .appendField(new Blockly.FieldLabel("List Comprehension","blocklyTextEmph"))
    this.appendValueInput('VAR0')
          .setAlign(Blockly.ALIGN_RIGHT)
          .appendField(new Blockly.FieldLocalVar(this.vars_[0],this.getArgType(0)))
          .appendField('\u2190');
    this.appendValueInput('VAR1')
          .setAlign(Blockly.ALIGN_RIGHT)
          .appendField(new Blockly.FieldLocalVar(this.vars_[1],this.getArgType(1)))
          .appendField('\u2190');
    this.setOutput(true);
    this.setMutator(new Blockly.Mutator(['lists_comp_var', 'lists_comp_guard']));
    this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);
    this.varCount_ = 2;
    this.guardCount_ = 0;
    this.resetArrows();
    Blockly.TypeInf.defineFunction("<]", Type.fromList([Type.Lit("list", [Type.Var("a")]), Type.Var("a")  ]));
    Blockly.TypeInf.defineFunction("MK", Type.fromList([Type.Var("a"), Type.Lit("list", [Type.Var("a")]) ]));
  },

  getExpr: function(){

    var mainExp = Exp.Var('undef');
    if (this.getInput("DO").connection.isConnected())
      mainExp = this.getInput("DO").connection.targetBlock().getExpr();

    mainExp.tag = this.getInput("DO").connection;
    
    var guardExps = [];
    for(var i = 0; i < this.guardCount_; i++){
      var inp = this.getInput("GUARD" + i);
      if(inp.connection && inp.connection.isConnected()){
        var exp = inp.connection.targetBlocks().getExpr();
        exp.tag = inp.connection;
        guardExps.push(exp);
      }
      else{
        var exp = Exp.Var('undef');
        exp.tag = inp.connection;
        guardExps.push(exp);
      }
    }
    // TODO add guards
 

    var func = (a,b) => Exp.Let(a,b,c);   //Exp.AppFunc([a,b],Exp.Var(":"));
    var result = mainExp;
    for(var i = this.varCount_ - 1; i !== -1; i--){
      var varName = this.vars_[i];
      var inp = this.getInput("VAR" + i);
      if(inp.connection.isConnected()){
        var exp = inp.connection.targetBlock().getExpr();
        exp.tag = inp.connection;
        
        var letExp = Exp.App(Exp.Var("<]"),exp);
        var field = inp.fieldRow[0];
        if(!field.typeExpr)
          throw "Wrong field !";
        letExp.tag = field;

        result = Exp.Let(varName, letExp, result); 
      }
      else{
        result = Exp.Let(varName, Exp.Var('undef') , result); 
      }
    }
   
    result = Exp.App(Exp.Var("MK"), result);
    result.tag = this.outputConnection;
    return result;

  },

  foldr: function (fn, ult, xs) {
    var result = ult;
      for (var i = xs.length - 1; i !== -1; i--) {
        result = fn(xs[i], result);
      }
    return result;
  },

  
  resetArrows: function(){
    this.arrows = null;
    var tps = [];
    this.varTypes_ = [];

    var a = Type.generateTypeVar('a');

    tps.push(a);
    for(var i = 0; i < this.varCount_; i++){
      var varTp = Type.generateTypeVar('lc');
      this.varTypes_.push(varTp);
      var t = Type.Lit("list", [varTp]);
      tps.push(t);
    }
    for(var i = 0; i < this.guardCount_; i++){
      tps.push(Type.Lit("Bool"));
    }

    tps.push(Type.Lit("list",[a]));
    this.arrows = Type.fromList(tps);
    this.initArrows(false);
  },

  assignVars: function(){
    var i = 0;
    var thisBlock = this;
    this.inputList.forEach(function(inp){
      if(inp.name.startsWith('VAR')){
        for(var f = 0; f < inp.fieldRow.length; f++){
          var fieldvar = inp.fieldRow[f];
          if(fieldvar instanceof Blockly.FieldLocalVar){
            var tp = thisBlock.varTypes_[i++];
            fieldvar.typeExpr = tp;
            break;
          }
        }
      };
    });
  },

  getArgType: function(localId){
    return this.varTypes_[localId];
  },

  getVars: function(connection){
    var i = 0;
    var available = [];
    for(i = 0; i < this.varCount_; i++){
      if(this.getInput('DO').connection == connection)
        return this.vars_;

      if(this.getInput('VAR' + i).connection == connection)
        return available;

      available = available.concat(this.vars_[i]);
      
    }
    return [];
  },
  /**
   * Create XML to represent list inputs.
   * @return {Element} XML storage element.
   * @this Blockly.Block
   */
  mutationToDom: function() {
    var container = document.createElement('mutation');
    container.setAttribute('guardcount', this.guardCount_);
    container.setAttribute('varcount', this.varCount_);

    for (var i = 0; i < this.varCount_; i++) {
      var parameter = document.createElement('var');
      parameter.setAttribute('name', this.vars_[i]);
      
      container.appendChild(parameter);
    }

    return container;
  },
  /**
   * Parse XML to restore the list inputs.
   * @param {!Element} xmlElement XML storage element.
   * @this Blockly.Block
   */
  domToMutation: function(xmlElement) {<commit_msg>Add guards in generating expression for list comprehension<commit_after>/*
 * Copyright 2016 The CodeWorld Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

goog.provide('Blockly.Blocks.cwLists');

goog.require('Blockly.Blocks');

var listsHUE = 260;


Blockly.Blocks['lists_comprehension'] = {
  /**
   * Block for creating a list with any number of elements of any type.
   * @this Blockly.Block
   */
  init: function() {
    this.setColour(listsHUE);
    this.vars_ = ['i','j','k'];
    this.varTypes_ = [Type.generateTypeVar('lc'), Type.generateTypeVar('lc'), Type.generateTypeVar('lc')];
    this.appendValueInput("DO")
        .appendField(new Blockly.FieldLabel("List Comprehension","blocklyTextEmph"))
    this.appendValueInput('VAR0')
          .setAlign(Blockly.ALIGN_RIGHT)
          .appendField(new Blockly.FieldLocalVar(this.vars_[0],this.getArgType(0)))
          .appendField('\u2190');
    this.appendValueInput('VAR1')
          .setAlign(Blockly.ALIGN_RIGHT)
          .appendField(new Blockly.FieldLocalVar(this.vars_[1],this.getArgType(1)))
          .appendField('\u2190');
    this.setOutput(true);
    this.setMutator(new Blockly.Mutator(['lists_comp_var', 'lists_comp_guard']));
    this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);
    this.varCount_ = 2;
    this.guardCount_ = 0;
    this.resetArrows();
    Blockly.TypeInf.defineFunction("&&&", Type.fromList([Type.Lit("Bool"),Type.Lit("Bool"),Type.Lit("Bool")]));
    Blockly.TypeInf.defineFunction("filtB", Type.fromList([Type.Var('a'), Type.Lit("Bool"), Type.Var('a')  ]));
    Blockly.TypeInf.defineFunction("<]", Type.fromList([Type.Lit("list", [Type.Var("a")]), Type.Var("a")  ]));
    Blockly.TypeInf.defineFunction("MK", Type.fromList([Type.Var("a"), Type.Lit("list", [Type.Var("a")]) ]));
  },

  foldr1 : function(fn, xs) {
    var result = xs[xs.length - 1];
      for (var i = xs.length - 2; i > -1; i--) {
        result = fn(xs[i], result);
      }
    return result;
  },

  getExpr: function(){

    // Do main exp
    var mainExp = Exp.Var('undef');
    if (this.getInput("DO").connection.isConnected())
      mainExp = this.getInput("DO").connection.targetBlock().getExpr();

    mainExp.tag = this.getInput("DO").connection;
    
    // Do Guards
    var guardExps = [];
    for(var i = 0; i < this.guardCount_; i++){
      var inp = this.getInput("GUARD" + i);
      if(inp.connection && inp.connection.isConnected()){
        var exp = inp.connection.targetBlock().getExpr();
        exp.tag = inp.connection;
        guardExps.push(exp);
      }
      else{
        var exp = Exp.Var('undef');
        exp.tag = inp.connection;
        guardExps.push(exp);
      }
    }

    var boolComb = (a,b) => Exp.AppFunc([a,b],Exp.Var("&&&"));
    var guardExp;
    if(guardExps.length == 0){
      guardExp = Exp.Lit('Bool');
    }
    else if(guardExps.length == 1){
      var inp = this.getInput("GUARD0");
      if(inp.connection.isConnected()){
        guardExp = inp.connection.targetBlock().getExpr();
        guardExp.tag = inp.connection;
      }
      else{
        guardExp = Exp.Lit('Bool');
        guardExp.tag = inp.connection;
      }
    }
    else{
      guardExp = this.foldr1(boolComb,guardExps);
    }
    
    // Do variables
    var func = (a,b) => Exp.Let(a,b,c);   //Exp.AppFunc([a,b],Exp.Var(":"));
    var result = Exp.AppFunc([mainExp, guardExp], Exp.Var('filtB'));
    for(var i = this.varCount_ - 1; i !== -1; i--){
      var varName = this.vars_[i];
      var inp = this.getInput("VAR" + i);
      if(inp.connection.isConnected()){
        var exp = inp.connection.targetBlock().getExpr();
        exp.tag = inp.connection;
        
        var letExp = Exp.App(Exp.Var("<]"),exp);
        var field = inp.fieldRow[0];
        if(!field.typeExpr)
          throw "Wrong field !";
        letExp.tag = field;

        result = Exp.Let(varName, letExp, result); 
      }
      else{
        result = Exp.Let(varName, Exp.Var('undef') , result); 
      }
    }
  
    // Do result
    result = Exp.AppFunc( [result], Exp.Var("MK"));
    result.tag = this.outputConnection;
    return result;

  },

  foldr: function (fn, ult, xs) {
    var result = ult;
      for (var i = xs.length - 1; i !== -1; i--) {
        result = fn(xs[i], result);
      }
    return result;
  },

  
  resetArrows: function(){
    this.arrows = null;
    var tps = [];
    this.varTypes_ = [];

    var a = Type.generateTypeVar('a');

    tps.push(a);
    for(var i = 0; i < this.varCount_; i++){
      var varTp = Type.generateTypeVar('lc');
      this.varTypes_.push(varTp);
      var t = Type.Lit("list", [varTp]);
      tps.push(t);
    }
    for(var i = 0; i < this.guardCount_; i++){
      tps.push(Type.Lit("Bool"));
    }

    tps.push(Type.Lit("list",[a]));
    this.arrows = Type.fromList(tps);
    this.initArrows(false);
  },

  assignVars: function(){
    var i = 0;
    var thisBlock = this;
    this.inputList.forEach(function(inp){
      if(inp.name.startsWith('VAR')){
        for(var f = 0; f < inp.fieldRow.length; f++){
          var fieldvar = inp.fieldRow[f];
          if(fieldvar instanceof Blockly.FieldLocalVar){
            var tp = thisBlock.varTypes_[i++];
            fieldvar.typeExpr = tp;
            break;
          }
        }
      };
    });
  },

  getArgType: function(localId){
    return this.varTypes_[localId];
  },

  getVars: function(connection){
    var i = 0;
    var available = [];
    for(i = 0; i < this.varCount_; i++){
      if(this.getInput('DO').connection == connection)
        return this.vars_;

      if(this.getInput('VAR' + i).connection == connection)
        return available;

      if(this.getInput('GUARD' +i).connection == connection)
        return this.vars_;

      available = available.concat(this.vars_[i]);
      
    }
    return [];
  },
  /**
   * Create XML to represent list inputs.
   * @return {Element} XML storage element.
   * @this Blockly.Block
   */
  mutationToDom: function() {
    var container = document.createElement('mutation');
    container.setAttribute('guardcount', this.guardCount_);
    container.setAttribute('varcount', this.varCount_);

    for (var i = 0; i < this.varCount_; i++) {
      var parameter = document.createElement('var');
      parameter.setAttribute('name', this.vars_[i]);
      
      container.appendChild(parameter);
    }

    return container;
  },
  /**
   * Parse XML to restore the list inputs.
   * @param {!Element} xmlElement XML storage element.
   * @this Blockly.Block
   */
  domToMutation: function(xmlElement) {
{'fraction_non_alphanumeric': 0.16016253929310742, 'fraction_numerical': 0.006746914053515295, 'mean_word_length': 2.6983271902466686, 'pattern_counts': {'":': 2, '<': 19, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '892165', 'n_tokens_mistral': 4340, 'n_tokens_neox': 4237, 'n_words': 908}