var bind = {
  max_args: 32,

  get_bind_arg_name: function(index)
  {
    return String.fromCharCode(96 + index);
  },

  get_bind_arg: function(arg)
  {
    for (var i = 0; i < this.max_args; i++)
      if (arg == eval("this.$" + i))
	return this.get_bind_arg_name(i);

    return null;
  },

  bind: function()
  {
    var fn = arguments[0];
    var args = arguments;

    var outer_args_text = new Array();
    var outer_arg_count = 1;
    var inner_args_text = new Array();

    for (var i = 1; i < arguments.length; i++) {
      var bind_arg = this.get_bind_arg(arguments[i]);
      if (bind_arg) {
	outer_args_text.push(this.get_bind_arg_name(outer_arg_count++));
	inner_args_text.push(bind_arg);
      } else {	
	inner_args_text.push("args[" + i + "]");
      }
    }

    var func_text = "function(" + outer_args_text.join(",") + ") {\n";
    func_text += "\tfn(" + inner_args_text.join(",") + ")\n";
    func_text += "};"

    return eval("function x() { return " + func_text + "}; x();");
  }
}

for (var i = 0; i < bind.max_args; i++)
  eval("bind.$" + i + " = new Object();");
