// TODO handle the overflow
// ES6 support?

// define math operators
const OPERATOR = {
  '+': function add (o1, o2) {
    return o1 + o2
  },
  '-': function substract (o1, o2) {
    return o1 - o2
  },
  '*': function multiply (o1, o2) {
    return o1 * o2
  },
  '/': function divide (o1, o2) {
    return o1 / o2
  },
  '%': function modulo (o1, o2) {
    return o1 % o2
  }
}

// define math common constants, and functions
const MATH = Math

const EXTEND = {
  '(': function math (exp) {
    var i = exp.indexOf('[')
    if (i === -1) i = exp.indexOf('(')
    if (i === -1) return null
    var func = exp.substring(0, i)
    var args = exp.substring(i + 1, exp.length - 1)
    args = args.split(',')
    args.map(function (val) {
      return Number(val)
    })
    args.unshift(func)
    return exports.apply(null, args)
  },
  '^': function pow (exp) {
    var i = exp.indexOf('^')
    if (i === -1) return null
    var o1 = Number(exp.substring(0, i))
    var o2 = Number(exp.substring(i + 1, exp.length))
    return Math.pow(o1, o2)
  },
  '|': function abs (exp) {
    var i = exp.indexOf('|')
    if (i === -1) return null
    return Math.abs(Number(exp.substring(1, exp.length - 1)))
  }
}

function isOperator (token) {
  return OPERATOR.hasOwnProperty(token)
}

function isNumber (num) {
  return !isNaN(num)
}

function isConst (token) {
  return MATH.hasOwnProperty(token) && isNumber(MATH[token])
}

exports = module.exports = function calc (cmd) {
  var argv = arguments
  var length = argv.length

  if (length === 1) return MATH[cmd]

  if (argv.length === 3 && isOperator(cmd)) {
    return OPERATOR[cmd](argv[1], argv[2])
  }

  return MATH[cmd].apply(null, Array.prototype.slice.call(argv, 1))
}

exports.OPERATOR = OPERATOR
exports.MATH = MATH
exports.EXTEND = EXTEND
exports.isOperator = isOperator
exports.isNumber = isNumber
exports.isConst = isConst

@@ -704,70 +704,8 @@
 ,')%0A
-    args.map(function (val) %7B%0A      return Number(val)%0A    %7D)%0A
     
@@ -723,16 +723,16 @@
 t(func)%0A
+
     retu
@@ -865,23 +865,16 @@
 ar o1 = 
-Number(
 exp.subs
@@ -884,17 +884,16 @@
 ng(0, i)
-)
 %0A    var
@@ -898,23 +898,16 @@
 ar o2 = 
-Number(
 exp.subs
@@ -930,17 +930,16 @@
 .length)
-)
 %0A    ret
@@ -1071,23 +1071,16 @@
 ath.abs(
-Number(
 exp.subs
@@ -1104,17 +1104,16 @@
 th - 1))
-)
 %0A  %7D%0A%7D%0A%0A

dont need convert string to number before using math function