<commit_before>hppy = require '../'
fs   = require 'fs'
_    = require 'underscore'

HPPY_CALLBACK_NAME = "hppy_callback"
HPPY_ERROR_NAME = "hppy_error"

NULLARG =
  type: 'Literal'
  value: null
  raw: 'null'
ERRORARG =
  type: 'Identifier'
  name: HPPY_ERROR_NAME
CALLBACKARG =
  type: 'Identifier'
  name: HPPY_CALLBACK_NAME

hppy.define(
  cps: (ast) ->
    # Get the real function from the last argument of CPS
    f = _(ast.arguments).last()
    # Push the callback template parameter to the function arguments
    f.params.push(CALLBACKARG)
    # Return the modified function
    f

  cont: (ast) ->
    console.log("CONT")
    _(ast).inspect()
    # Get the real function from the last argument of CPS
    f = _(ast.arguments).last()
    # Push the callback template parameter to the function arguments
    f.params.unshift(ERRORARG)
    # Return the modified function
    body = f.body.body
    f.body.body = [ {
      type: 'IfStatement'
      test: {
        type: 'BinaryExpression'
        operator: '!='
        left: { type: 'Identifier', name: HPPY_ERROR_NAME }
        right: { type: 'Literal', value: null, raw: 'null' } }
      consequent: {
        type: 'BlockStatement'
        body: [ {
          type: 'ReturnStatement'
          argument: {
            type: 'CallExpression'
            callee: { type: 'Identifier', name: HPPY_CALLBACK_NAME }
            arguments: [ { type: 'Identifier', name: HPPY_ERROR_NAME } ] } } ] }
      alternate: {
        type: 'BlockStatement'
        body: body
      } } ]
    f

  ret: (ast) ->
    # Clone the ret arguments
    args = ast.arguments.slice()
    # Add a NULL template in the begining
    args.unshift(NULLARG)

    # Return new AST node
    type      : 'CallExpression'
    arguments : args
    callee    :
      type    : 'Identifier'
      name    : HPPY_CALLBACK_NAME

  err: (ast) ->
    ast.callee.name = HPPY_CALLBACK_NAME
    console.log("ERR")
    _(ast).inspect())

console.log "================ TEMPLATE  =============="
hppy.inspect(() ->
  myfunc = (fileName, cb) ->
    fs.readFile(fileName, 'utf8', (err, data) ->
      if err?
        cb(err)
      else
        cb(null, data)))

console.log "================ PRODUCT  =============="

eval(hppy(() ->
  myfunc = cps((fileName) ->
    fs.readFile(fileName, 'utf8', cont('myfunc', 'readfile', (data) ->
      if data.length == 0
        err("File empty!")
      else
        ret(data))))

  add = () -> 1 + 1

  add()

  myfunc('testfile', (err, data) ->
    if err?

      # Error management for GUI users
      if _.contains err.id, 'myfunc'
        console.log "Error in myfunc"

      if _.contains err.id, 'readfile'
        console.log "Could not read file"

      else
        console.log "No handler defined for error id #{err.id}"

      # Log output for system administrators
      console.error err
    else
      console.log "No errors"
      console.log data)))<commit_msg>updated example<commit_after>hppy = require '../'
fs   = require 'fs'
_    = require 'underscore'

HPPY_CALLBACK_NAME = "hppy_callback"
HPPY_ERROR_NAME = "hppy_error"

NULLARG =
  type: 'Literal'
  value: null
  raw: 'null'
ERRORARG =
  type: 'Identifier'
  name: HPPY_ERROR_NAME
CALLBACKARG =
  type: 'Identifier'
  name: HPPY_CALLBACK_NAME

hppy.define(
  cps: (ast) ->
    # Get the real function from the last argument of CPS
    f = _(ast.arguments).last()
    # Push the callback template parameter to the function arguments
    f.params.push(CALLBACKARG)
    # Return the modified function
    f

  cont: (ast) ->
    _(ast).inspect()
    # Get the real function from the last argument of CPS
    f = _(ast.arguments).last()
    # Push the callback template parameter to the function arguments
    f.params.unshift(ERRORARG)
    # Return the modified function
    body = f.body.body
    f.body.body = [ {
      type: 'IfStatement'
      test: {
        type: 'BinaryExpression'
        operator: '!='
        left: { type: 'Identifier', name: HPPY_ERROR_NAME }
        right: { type: 'Literal', value: null, raw: 'null' } }
      consequent: {
        type: 'BlockStatement'
        body: [ {
          type: 'ReturnStatement'
          argument: {
            type: 'CallExpression'
            callee: { type: 'Identifier', name: HPPY_CALLBACK_NAME }
            arguments: [ { type: 'Identifier', name: HPPY_ERROR_NAME } ] } } ] }
      alternate: {
        type: 'BlockStatement'
        body: body
      } } ]
    f

  ret: (ast) ->
    # Clone the ret arguments
    args = ast.arguments.slice()
    # Add a NULL template in the begining
    args.unshift(NULLARG)

    # Return new AST node
    type      : 'CallExpression'
    arguments : args
    callee    :
      type    : 'Identifier'
      name    : HPPY_CALLBACK_NAME

  err: (ast) ->
    ast.callee.name = HPPY_CALLBACK_NAME
    ast)

eval(hppy(() ->
  myfunc = cps((fileName) ->
    fs.readFile(fileName, 'utf8', cont('myfunc', 'readfile', (data) ->
      if data.length == 0
        err("File empty!")
      else
        ret(data))))

  myfunc('testfile', (err, data) ->
    if err?
      # Log output for system administrators
      console.error err
    else
      console.log "No errors"
      console.log data)))

{'fraction_non_alphanumeric': 0.13039309683604985, 'fraction_numerical': 0.0013422818791946308, 'mean_word_length': 2.34788189987163, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '1962548', 'n_tokens_mistral': 1689, 'n_tokens_neox': 1658, 'n_words': 455}