code: func (v *evalVisitor) VisitBlock(node *ast.BlockStatement) interface{} {
  	v.at(node)
  
  	v.pushBlock(node)
  
  	var result interface{}
  
  	// evaluate expression
  	expr := node.Expression.Accept(v)
  
  	if v.isHelperCall(node.Expression) || v.wasFuncCall(node.Expression) {
  		// it is the responsibility of the helper/function to evaluate block
  		result = expr
  	} else {
  		val := reflect.ValueOf(expr)
  
  		truth, _ := isTrueValue(val)
  		if truth {
  			if node.Program != nil {
  				switch val.Kind() {
  				case reflect.Array, reflect.Slice:
  					concat := ""
  
  					// Array context
  					for i := 0; i < val.Len(); i++ {
  						// Computes new private data frame
  						frame := v.dataFrame.newIterDataFrame(val.Len(), i, nil)
  
  						// Evaluate program
  						concat += v.evalProgram(node.Program, val.Index(i).Interface(), frame, i)
  					}
  
  					result = concat
  				default:
  					// NOT array
  					result = v.evalProgram(node.Program, expr, nil, nil)
  				}
  			}
  		} else if node.Inverse != nil {
  			result, _ = node.Inverse.Accept(v).(string)
  		}
  	}
  
  	v.popBlock()
  
  	return result
  }
docs: // VisitBlock implements corresponding Visitor interface method