Thrift: Added support for double type across all languages

Summary: Just for completeness cause I'm crazy. Let's never use these!

Notes: Also made thrift grammar support # style comments, so you can do this at the top of your files

#!/usr/local/bin/thrift --cpp

/**
 * This is a thrift def file youc an invoke directly and gen code!
 */

blah


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664789 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index b43ee16..56980e4 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -1125,6 +1125,9 @@
       case t_base_type::TYPE_I64:
         out << "readI64(itrans, " << name << ");";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble(itrans, " << name << ");";
+        break;
       default:
         throw "compiler error: no C++ reader for base type " + tbase + name;
       }
@@ -1331,6 +1334,9 @@
       case t_base_type::TYPE_I64:
         out << "writeI64(otrans, " << name << ");";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(otrans, " << name << ");";
+        break;
       default:
         throw "compiler error: no C++ writer for base type " + tbase + name;
       }
@@ -1540,6 +1546,8 @@
     return "int32_t";
   case t_base_type::TYPE_I64:
     return "int64_t";
+  case t_base_type::TYPE_DOUBLE:
+    return "double";
   default:
     throw "compiler error: no C++ base type name for base type " + tbase;
   }
@@ -1576,6 +1584,9 @@
       case t_base_type::TYPE_I64:
         result += " = 0";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = (double)0";
+        break;
       default:
         throw "compiler error: no C++ initializer for base type " + tbase;
       }
@@ -1645,6 +1656,8 @@
       return "facebook::thrift::protocol::T_I32";
     case t_base_type::TYPE_I64:
       return "facebook::thrift::protocol::T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "facebook::thrift::protocol::T_DOUBLE";
     }
   } else if (type->is_enum()) {
     return "facebook::thrift::protocol::T_I32";
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 390c563..6d12dce 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -867,6 +867,9 @@
       case t_base_type::TYPE_I64:
         out << "readI64(_itrans);";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble(_itrans);";
+        break;
       default:
         throw "compiler error: no Java name for base type " + tbase;
       }
@@ -1068,6 +1071,9 @@
       case t_base_type::TYPE_I64:
         out << "writeI64(_otrans, " << name << ");";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(_otrans, " << name << ");";
+        break;
       default:
         throw "compiler error: no Java name for base type " + tbase;
       }
@@ -1256,6 +1262,8 @@
     return (in_container ? "Integer" : "int");
   case t_base_type::TYPE_I64:
     return (in_container ? "Long" : "long");
+  case t_base_type::TYPE_DOUBLE:
+    return (in_container ? "Double" : "double");
   default:
     throw "compiler error: no C++ name for base type " + tbase;
   }
@@ -1292,6 +1300,9 @@
       case t_base_type::TYPE_I64:
         result += " = 0";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = (double)0";
+        break;
     }
 
     } else if (ttype->is_enum()) {
@@ -1372,6 +1383,8 @@
       return "TType.I32";
     case t_base_type::TYPE_I64:
       return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
     }
   } else if (type->is_enum()) {
     return "TType.I32";
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 8b05f70..6ac0b33 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -622,7 +622,7 @@
           "return;" << endl;
       } else {
         f_service_ <<
-          indent() << "throw Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+          indent() << "throw new Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
       }     
     }      
 
@@ -722,6 +722,11 @@
             indent() << "  $" << name << " = $_arr[1]*4294967296 + $_arr[2];" << endl <<
             indent() << "}" << endl;
           break;
+        case t_base_type::TYPE_DOUBLE:
+          out <<
+            indent() << "$_arr = unpack('d', strrev(" << itrans << "->readAll(8)));" << endl <<
+            indent() << "$" << name << " = $_arr[1];" << endl;
+          break;
         default:
           throw "compiler error: no PHP name for base type " + tbase + tfield->get_name();
         }
@@ -764,6 +769,9 @@
         case t_base_type::TYPE_I64:
           out << "readI64($itrans, $" << name << ");";
           break;
+        case t_base_type::TYPE_DOUBLE:
+          out << "readDouble($itrans, $" << name << ");";
+          break;
         default:
           throw "compiler error: no PHP name for base type " + tbase;
         }
@@ -808,9 +816,9 @@
   t_field fvtype(g_program->get_byte_type(), vtype);
   t_field fetype(g_program->get_byte_type(), etype);
 
-  indent(out) <<
-    prefix << " = array();" << endl <<
-    "$" << size << " = 0;" << endl;
+  out <<
+    indent() << "$" << prefix << " = array();" << endl <<
+    indent() << "$" << size << " = 0;" << endl;
   
   // Declare variables, read header
   if (ttype->is_map()) {
@@ -1000,6 +1008,10 @@
           out << 
             indent() << "$_output .= pack('N2', $" << name << " >> 32, $" << name << " & 0xFFFFFFFF);" << endl;
           break;
+        case t_base_type::TYPE_DOUBLE:
+          out << 
+            indent() << "$_output .= strrev(pack('d', $" << name << "));" << endl;
+          break;
         default:
           throw "compiler error: no PHP name for base type " + tbase;
         }
@@ -1037,6 +1049,9 @@
         case t_base_type::TYPE_I64:
           out << "writeI64($otrans, $" << name << ");";
           break;
+        case t_base_type::TYPE_DOUBLE:
+          out << "writeDouble($otrans, $" << name << ");";
+          break;
         default:
           throw "compiler error: no PHP name for base type " + tbase;
         }
@@ -1247,6 +1262,8 @@
     return "Int32";
   case t_base_type::TYPE_I64:
     return "Int64";
+  case t_base_type::TYPE_DOUBLE:
+    return "Double";
   default:
     throw "compiler error: no PHP name for base type " + tbase;
   }
@@ -1281,6 +1298,9 @@
       case t_base_type::TYPE_I64:
         result += " = 0";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = 0.0";
+        break;
       default:
         throw "compiler error: no PHP initializer for base type " + tbase;
       }
@@ -1357,6 +1377,8 @@
       return "TType::I32";
     case t_base_type::TYPE_I64:
       return "TType::I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType::DOUBLE";
     }
   } else if (type->is_enum()) {
     return "TType::I32";
diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc
index 53e5b3b..522ce38 100644
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ b/compiler/cpp/src/generate/t_py_generator.cc
@@ -784,6 +784,9 @@
       case t_base_type::TYPE_I64:
         out << "readI64(itrans);";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble(itrans);";
+        break;
       default:
         throw "compiler error: no PHP name for base type " + tbase;
       }
@@ -988,6 +991,9 @@
       case t_base_type::TYPE_I64:
         out << "writeI64(otrans, " << name << ")";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(otrans, " << name << ")";
+        break;
       default:
         throw "compiler error: no PHP name for base type " + tbase;
       }
@@ -1161,6 +1167,8 @@
     return "Int32";
   case t_base_type::TYPE_I64:
     return "Int64";
+  case t_base_type::TYPE_DOUBLE:
+    return "Double";
   default:
     throw "compiler error: no PHP name for base type " + tbase;
   }
@@ -1195,6 +1203,9 @@
       case t_base_type::TYPE_I64:
         result += " = 0";
         break;
+      case t_base_type::TYPE_DOUBLE:
+        result += " = 0.0";
+        break;
       default:
         throw "compiler error: no PHP initializer for base type " + tbase;
       }
@@ -1275,6 +1286,8 @@
       return "TType.I32";
     case t_base_type::TYPE_I64:
       return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
     }
   } else if (type->is_enum()) {
     return "TType.I32";
diff --git a/compiler/cpp/src/parse/t_base_type.h b/compiler/cpp/src/parse/t_base_type.h
index 1429d1c..0e97207 100644
--- a/compiler/cpp/src/parse/t_base_type.h
+++ b/compiler/cpp/src/parse/t_base_type.h
@@ -10,7 +10,9 @@
  */
 class t_base_type : public t_type {
  public:
-  /** Enumeration of thrift base types */
+  /**
+   * Enumeration of thrift base types
+   */
   enum t_base {
     TYPE_VOID,
     TYPE_STRING,
@@ -18,7 +20,8 @@
     TYPE_BYTE,
     TYPE_I16,
     TYPE_I32,
-    TYPE_I64
+    TYPE_I64,
+    TYPE_DOUBLE
   };
 
   t_base_type(std::string name, t_base base) :
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
index abb368b..9fa4271 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -37,6 +37,7 @@
     type_i16    = new t_base_type("i16",    t_base_type::TYPE_I16);
     type_i32    = new t_base_type("i32",    t_base_type::TYPE_I32);
     type_i64    = new t_base_type("i64",    t_base_type::TYPE_I64);
+    type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
   }
 
   ~t_program() {
@@ -46,6 +47,7 @@
     delete type_i16;
     delete type_i32;
     delete type_i64;
+    delete type_double;
   }
 
   // Name accessor
@@ -69,6 +71,7 @@
   t_type* get_i16_type()    const { return type_i16;    }
   t_type* get_i32_type()    const { return type_i32;    }
   t_type* get_i64_type()    const { return type_i64;    }
+  t_type* get_double_type() const { return type_double; }
 
   // Custom data type lookup
   t_type* get_custom_type(std::string name) {
@@ -130,6 +133,7 @@
   t_type* type_i16;
   t_type* type_i32;
   t_type* type_i64;
+  t_type* type_double;
 };
 
 #endif
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index 1ff7708..484e43b 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -23,6 +23,7 @@
 whitespace   ([ \t\r\n]*)
 multicomm    ("/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/")
 comment      ("//"[^\n]*)
+unixcomment  ("#"[^\n]*)
 symbol       ([\,\{\}\(\)\=<>])
 
 %%
@@ -30,6 +31,7 @@
 {whitespace}  { /* do nothing */ }
 {multicomm}   { /* do nothing */ }
 {comment}     { /* do nothing */ }
+{unixcomment} { /* do nothing */ }
 
 {symbol}      { return yytext[0]; }
 
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index e738180..f2fd790 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -394,6 +394,11 @@
       pdebug("BaseType -> tok_i64");
       $$ = g_program->get_i64_type();
     }
+| tok_double
+    {
+      pdebug("BaseType -> tok_double");
+      $$ = g_program->get_double_type();
+    }
 
 ContainerType:
   MapType
diff --git a/lib/cpp/src/protocol/TBinaryProtocol.cc b/lib/cpp/src/protocol/TBinaryProtocol.cc
index 51c9306..9fb2ec3 100644
--- a/lib/cpp/src/protocol/TBinaryProtocol.cc
+++ b/lib/cpp/src/protocol/TBinaryProtocol.cc
@@ -116,7 +116,24 @@
   out->write((uint8_t*)&net, 8);
   return 8;
 }
+  
+uint32_t TBinaryProtocol::writeDouble(shared_ptr<TTransport> out,
+                                      const double dub) const {
+  uint8_t b[8];
+  uint8_t* d = (uint8_t*)&dub;
+  b[0] = d[7];
+  b[1] = d[6];
+  b[2] = d[5];
+  b[3] = d[4];
+  b[4] = d[3];
+  b[5] = d[2];
+  b[6] = d[1];
+  b[7] = d[0];
+  out->write((uint8_t*)b, 8);
+  return 8;
+}
 
+  
 uint32_t TBinaryProtocol::writeString(shared_ptr<TTransport> out,
                                       const string& str) const {
   uint32_t result = writeI32(out, str.size());
@@ -276,6 +293,23 @@
   return 8;
 }
 
+uint32_t TBinaryProtocol::readDouble(shared_ptr<TTransport> in,
+                                     double& dub) const {
+  uint8_t b[8];
+  uint8_t d[8];
+  in->readAll(b, 8);
+  d[0] = b[7];
+  d[1] = b[6];
+  d[2] = b[5];
+  d[3] = b[4];
+  d[4] = b[3];
+  d[5] = b[2];
+  d[6] = b[1];
+  d[7] = b[0];
+  dub = *(double*)d;
+  return 8;
+}
+
 uint32_t TBinaryProtocol::readString(shared_ptr<TTransport> in,
                                      string& str) const {
   uint32_t result;
diff --git a/lib/cpp/src/protocol/TBinaryProtocol.h b/lib/cpp/src/protocol/TBinaryProtocol.h
index 5bca6dd..7f36a57 100644
--- a/lib/cpp/src/protocol/TBinaryProtocol.h
+++ b/lib/cpp/src/protocol/TBinaryProtocol.h
@@ -80,6 +80,10 @@
   uint32_t writeI64(shared_ptr<TTransport> out,
 		     const int64_t i64) const;
 
+  uint32_t writeDouble(shared_ptr<TTransport> out,
+                       const double dub) const;
+
+
   uint32_t writeString(shared_ptr<TTransport> out,
 			const std::string& str) const;
 
@@ -141,6 +145,9 @@
   uint32_t readI64(shared_ptr<TTransport> in,
 		    int64_t& i64) const;
 
+  uint32_t readDouble(shared_ptr<TTransport> in,
+                      double& dub) const;
+
   uint32_t readString(shared_ptr<TTransport> in,
 		       std::string& str) const;
 };
diff --git a/lib/cpp/src/protocol/TProtocol.h b/lib/cpp/src/protocol/TProtocol.h
index 65d6f3c..89c7f48 100644
--- a/lib/cpp/src/protocol/TProtocol.h
+++ b/lib/cpp/src/protocol/TProtocol.h
@@ -16,7 +16,7 @@
 
 using namespace facebook::thrift::transport;
 
-#define ntohll(x) (((uint64_t)(ntohl((int)((x << 32) >> 32))) << 32) | (uint32_t)ntohl(((int)(x >> 32))))
+#define ntohll(x) (((uint64_t)(ntohl((int)((x & 0x00000000FFFFFFFF)))) << 32) | (uint32_t)ntohl(((int)(x >> 32 & 0x00000000FFFFFFFF))))
 
 #define htonll(x) ntohll(x)
 
@@ -38,6 +38,7 @@
   T_I32        = 8,
   T_U64        = 9,
   T_I64        = 10,
+  T_DOUBLE     = 4,
   T_STRING     = 11,
   T_UTF7       = 11,
   T_STRUCT     = 12,
@@ -133,6 +134,9 @@
   virtual uint32_t writeI64(shared_ptr<TTransport> out,
 			    const int64_t i64) const = 0;
 
+  virtual uint32_t writeDouble(shared_ptr<TTransport> out,
+                               const double dub) const = 0;
+
   virtual uint32_t writeString(shared_ptr<TTransport> out,
 			       const std::string& str) const = 0;
 
@@ -193,6 +197,9 @@
   virtual uint32_t readI64(shared_ptr<TTransport> in,
 			   int64_t& i64) const = 0;
 
+  virtual uint32_t readDouble(shared_ptr<TTransport> in,
+			      double& dub) const = 0;
+
   virtual uint32_t readString(shared_ptr<TTransport> in,
 			      std::string& str) const = 0;
 
@@ -226,6 +233,11 @@
         int64_t i64;
         return readI64(in, i64);
       }
+    case T_DOUBLE:
+      {
+        double dub;
+        return readDouble(in, dub);
+      }
     case T_STRING:
       {
         std::string str;
diff --git a/lib/java/src/protocol/TBinaryProtocol.java b/lib/java/src/protocol/TBinaryProtocol.java
index d90dece..4d6c345 100644
--- a/lib/java/src/protocol/TBinaryProtocol.java
+++ b/lib/java/src/protocol/TBinaryProtocol.java
@@ -95,6 +95,10 @@
     out.write(i64out, 0, 8);
   }
 
+  public void writeDouble(TTransport out, double dub) throws TException {
+    writeI64(out, Double.doubleToLongBits(dub));
+  }
+
   public void writeString(TTransport out, String str) throws TException {
     byte[] dat = str.getBytes();
     writeI32(out, dat.length);
@@ -203,6 +207,10 @@
       ((long)(i64rd[7] & 0xff));
   }
 
+  public double readDouble(TTransport in) throws TException {
+    return Double.longBitsToDouble(readI64(in));
+  }
+
   public String readString(TTransport in)  throws TException {
     int size = readI32(in);
     byte[] buf = new byte[size];
diff --git a/lib/java/src/protocol/TProtocol.java b/lib/java/src/protocol/TProtocol.java
index 69fe885..0831d12 100644
--- a/lib/java/src/protocol/TProtocol.java
+++ b/lib/java/src/protocol/TProtocol.java
@@ -61,6 +61,10 @@
   public void writeI64         (TTransport out,
                                 long       i64)     throws TException;
 
+  public void writeDouble      (TTransport out,
+                                double     dub)     throws TException;
+
+
   public void writeString      (TTransport out,
                                 String     str)     throws TException;
 
@@ -102,6 +106,8 @@
  
   public long     readI64          (TTransport in)  throws TException;
 
+  public double   readDouble       (TTransport in)  throws TException;
+
   public String   readString       (TTransport in)  throws TException;
 
 }
diff --git a/lib/java/src/protocol/TProtocolUtil.java b/lib/java/src/protocol/TProtocolUtil.java
index 5223639..1c88f8a 100644
--- a/lib/java/src/protocol/TProtocolUtil.java
+++ b/lib/java/src/protocol/TProtocolUtil.java
@@ -34,6 +34,10 @@
       {
         prot.readI64(in);
       }
+    case TType.DOUBLE:
+      {
+        prot.readDouble(in);
+      }
     case TType.STRING:
       {
         prot.readString(in);
diff --git a/lib/java/src/protocol/TType.java b/lib/java/src/protocol/TType.java
index 37b53bd..bed9a21 100644
--- a/lib/java/src/protocol/TType.java
+++ b/lib/java/src/protocol/TType.java
@@ -10,6 +10,7 @@
   public static final byte VOID   = 1;
   public static final byte BOOL   = 2;
   public static final byte BYTE   = 3;
+  public static final byte DOUBLE = 4;
   public static final byte I16    = 6;
   public static final byte I32    = 8;
   public static final byte I64    = 10;
diff --git a/lib/php/src/protocol/TBinaryProtocol.php b/lib/php/src/protocol/TBinaryProtocol.php
index 4bb0297..2b1384f 100644
--- a/lib/php/src/protocol/TBinaryProtocol.php
+++ b/lib/php/src/protocol/TBinaryProtocol.php
@@ -136,6 +136,12 @@
     return 8;
   }
 
+  public function writeDouble($out, $value) {
+    $data = pack('d', $value);
+    $out->write(strrev($data), 8);
+    return 8;
+  }
+
   public function writeString($out, $value) {
     $len = strlen($value);
     $result = $this->writeI32($out, $len);
@@ -302,6 +308,13 @@
     return 8;
   }
 
+  public function readDouble($in, &$value) {
+    $data = strrev($in->readAll(8));
+    $arr = unpack('d', $data);
+    $value = $arr[1];
+    return 8;
+  }
+
   public function readString($in, &$value) {
     $result = $this->readI32($in, $len);
     $value = $in->readAll($len);
diff --git a/lib/php/src/protocol/TProtocol.php b/lib/php/src/protocol/TProtocol.php
index 855d588..6101f57 100644
--- a/lib/php/src/protocol/TProtocol.php
+++ b/lib/php/src/protocol/TProtocol.php
@@ -89,6 +89,8 @@
 
   public abstract function writeI64($out, $i64);
 
+  public abstract function writeDouble($out, $dub);
+
   public abstract function writeString($out, $str);
 
 
@@ -139,6 +141,8 @@
 
   public abstract function readI64($in, &$i64);
 
+  public abstract function readDouble($in, &$dub);
+
   public abstract function readString($in, &$str);
 
   /**
@@ -160,6 +164,8 @@
       return $this->readI32($in, $i32);
     case TType::I64:
       return $this->readI64($in, $i64);
+    case TType::DOUBLE:
+      return $this->readDouble($in, $dub);
     case TType::STRING:
       return $this->readString($in, $str);
     case TType::STRUCT:
diff --git a/lib/php/src/protocol/TType.php b/lib/php/src/protocol/TType.php
index 6ef0935..aa930ce 100644
--- a/lib/php/src/protocol/TType.php
+++ b/lib/php/src/protocol/TType.php
@@ -15,7 +15,8 @@
   const VOID   = 1;
   const BOOL   = 2;
   const BYTE   = 3;
-  const I08    = 4;
+  const I08    = 3;
+  const DOUBLE = 4;
   const I16    = 6;
   const I32    = 8;
   const I64    = 10;
diff --git a/lib/py/src/protocol/TBinaryProtocol.py b/lib/py/src/protocol/TBinaryProtocol.py
index 860f461..25f3218 100644
--- a/lib/py/src/protocol/TBinaryProtocol.py
+++ b/lib/py/src/protocol/TBinaryProtocol.py
@@ -73,6 +73,10 @@
     buff = pack("!q", i64)
     otrans.write(buff)
 
+  def writeDouble(self, otrans, dub):
+    buff = pack("!d", dub)
+    otrans.write(buff)
+
   def writeString(self, otrans, str):
     self.writeI32(otrans, len(str))
     otrans.write(str)
@@ -153,6 +157,11 @@
     val, = unpack('!q', buff)
     return val
 
+  def readDouble(self, itrans):
+    buff = itrans.readAll(8)
+    val, = unpack('!d', buff)
+    return val
+
   def readString(self, itrans):
     len = self.readI32(itrans)
     str = itrans.readAll(len)
diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py
index 3105e25..0b480d3 100644
--- a/lib/py/src/protocol/TProtocol.py
+++ b/lib/py/src/protocol/TProtocol.py
@@ -3,7 +3,8 @@
   VOID   = 1
   BOOL   = 2
   BYTE   = 3
-  I08    = 4
+  I08    = 3
+  DOUBLE = 4
   I16    = 6
   I32    = 8
   I64    = 10
@@ -78,6 +79,9 @@
   def writeI64(self, otrans, i64):
     pass
 
+  def writeDouble(self, otrans, dub):
+    pass
+
   def writeString(self, otrans, str):
     pass
 
@@ -132,6 +136,9 @@
   def readI64(self, itrans):
     pass
 
+  def readDouble(self, itrans):
+    pass
+
   def readString(self, itrans):
     pass
 
@@ -148,6 +155,8 @@
       self.readI32(itrans)
     elif type == TType.I64:
       self.readI64(itrans)
+    elif type == TType.DOUBLE:
+      self.readDouble(itrans)
     elif type == TType.STRING:
       self.readString(itrans)
     elif type == TType.STRUCT:
diff --git a/lib/py/src/server/TServer.py b/lib/py/src/server/TServer.py
index 69be260..a5d5621 100644
--- a/lib/py/src/server/TServer.py
+++ b/lib/py/src/server/TServer.py
@@ -1,3 +1,6 @@
+import sys
+import traceback
+
 from thrift.Thrift import TProcessor
 from thrift.transport import TTransport
 
@@ -27,6 +30,6 @@
         while True:
           self.processor.process(client, client)
       except Exception, x:
-        print x
+        print '%s, %s, %s' % (type(x), x, traceback.format_exc())
         print 'Client died.'
       client.close()
diff --git a/lib/py/src/transport/TSocket.py b/lib/py/src/transport/TSocket.py
index 4ef35d9..61f1cff 100644
--- a/lib/py/src/transport/TSocket.py
+++ b/lib/py/src/transport/TSocket.py
@@ -36,7 +36,7 @@
   def read(self, sz):
     buff = self.handle.recv(sz)
     if len(buff) == 0:
-      raise Exception('TScket read 0 bytes')
+      raise Exception('TSocket read 0 bytes')
     return buff
 
   def write(self, buff):
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index 897d707..414dcea 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -56,6 +56,7 @@
   byte         testByte(byte thing = 1),
   i32          testI32(i32 thing = 1),
   i64          testI64(i64 thing = 1),
+  double       testDouble(double thing = 1),
   Xtruct       testStruct(Xtruct thing = 1),
   Xtruct2      testNest(Xtruct2 thing = 1),
   map<i32,i32> testMap(map<i32,i32> thing = 1),
diff --git a/test/cpp/src/TestClient.cc b/test/cpp/src/TestClient.cc
index d340e26..e12b65b 100644
--- a/test/cpp/src/TestClient.cc
+++ b/test/cpp/src/TestClient.cc
@@ -99,6 +99,13 @@
     printf("testI64(-34359738368)");
     int64_t i64 = testClient.testI64(-34359738368LL);
     printf(" = %ld\n", i64);
+
+    /**
+     * DOUBLE TEST
+     */
+    printf("testDouble(-5.2098523)");
+    double dub = testClient.testDouble(-5.2098523);
+    printf(" = %lf\n", dub);
     
     /**
      * STRUCT TEST
diff --git a/test/cpp/src/TestServer.cc b/test/cpp/src/TestServer.cc
index 63a7594..97d3440 100644
--- a/test/cpp/src/TestServer.cc
+++ b/test/cpp/src/TestServer.cc
@@ -47,6 +47,11 @@
     return thing;
   }
 
+  double testDouble(double thing) {
+    printf("testDouble(%lf)\n", thing);
+    return thing;
+  }
+
   Xtruct testStruct(Xtruct thing) {
     printf("testStruct({\"%s\", %d, %d, %ld})\n",
            thing.string_thing.c_str(),
diff --git a/test/java/src/TestClient.java b/test/java/src/TestClient.java
index 686920c..74fbfef 100644
--- a/test/java/src/TestClient.java
+++ b/test/java/src/TestClient.java
@@ -94,6 +94,13 @@
         System.out.print(" = " + i64 + "\n");
 
         /**
+         * DOUBLE TEST
+         */
+        System.out.print("testDouble(5.325098235)");
+        double dub = testClient.testDouble(5.325098235);
+        System.out.print(" = " + dub + "\n");
+
+        /**
          * STRUCT TEST
          */
         System.out.print("testStruct({\"Zero\", 1, -3, -5})");
diff --git a/test/java/src/TestServer.java b/test/java/src/TestServer.java
index 7418cbb..8e3e4ed 100644
--- a/test/java/src/TestServer.java
+++ b/test/java/src/TestServer.java
@@ -45,6 +45,11 @@
       System.out.print("testI64(" + thing + ")\n");
       return thing;
     }
+
+    public double testDouble(double thing) {
+      System.out.print("testDouble(" + thing + ")\n");
+      return thing;
+    }
   
     public Xtruct testStruct(Xtruct thing) {
       System.out.print("testStruct({" +
diff --git a/test/php/TestClient.php b/test/php/TestClient.php
index 6dd40d7..a92adcc 100644
--- a/test/php/TestClient.php
+++ b/test/php/TestClient.php
@@ -85,6 +85,13 @@
 print_r(" = $i64\n");
 
 /**
+ * DOUBLE TEST
+ */
+print_r("testDouble(-852.234234234)");
+$dub = $testClient->testDouble(-852.234234234);
+print_r(" = $dub\n");
+
+/**
  * STRUCT TEST
  */
 print_r("testStruct({\"Zero\", 1, -3, -5})");
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 21d1990..3edff1c 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -32,9 +32,15 @@
 print "testI32(-1)"
 print client.testI32(-1)
 
+print "testI32(0)"
+print client.testI32(0)
+
 print "testI64(-34359738368)"
 print client.testI64(-34359738368)
 
+print "testDouble(-5.235098235)"
+print client.testDouble(-5.235098235)
+
 print "testStruct({Zero, 1, -3, -5})"
 x = Xtruct()
 x.string_thing = "Zero"
diff --git a/test/py/TestServer.py b/test/py/TestServer.py
index 4b571c7..525ffee 100755
--- a/test/py/TestServer.py
+++ b/test/py/TestServer.py
@@ -22,12 +22,33 @@
     print 'testByte(%d)' % byte
     return byte
 
+  def testI16(self, i16):
+    print 'testI16(%d)' % i16
+    return i16
+
+  def testI32(self, i32):
+    print 'testI32(%d)' % i32
+    return i32
+
+  def testI64(self, i64):
+    print 'testI64(%d)' % i64
+    return i64
+
+  def testDouble(self, dub):
+    print 'testDouble(%f)' % dub
+    return dub
+
+  def testStruct(self, thing):
+    print 'testStruct({%s, %d, %d, %d})' % (thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing)
+    return thing
+
   def testException(self, str):
     print 'testException(%s)' % str
-    x = Xception()
-    x.errorCode = 1001
-    x.message = str
-    raise x
+    if str == 'Xception':
+      x = Xception()
+      x.errorCode = 1001
+      x.message = str
+      raise x
 
 transport = TSocket.TServerSocket(9090)
 protocol = TBinaryProtocol.TBinaryProtocol()