<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -22,7 +22,7 @@ import Control.Monad.Error
 import Control.Monad (forM_, replicateM, liftM2, liftM3, liftM4)
 import Control.Applicative ((&lt;$&gt;))
 import Data.Bits (shiftR, (.&amp;.))
-import Data.Char (chr)
+import Data.Char (chr, isAsciiLower, isAscii)
 import Data.Binary (Binary(..), Word8)
 import Data.Binary.Put (
   Put, putWord8, putWord16be, 
@@ -30,6 +30,8 @@ import Data.Binary.Put (
 import Data.Binary.Get (
   Get, getWord8, getWord16be, getWord32be,
   getLazyByteString)
+import Data.List (intercalate)
+import Data.Time (UTCTime(..), diffUTCTime, addUTCTime, Day(..))
 import Data.ByteString.Lazy (ByteString)
 import qualified Data.ByteString.Lazy as B
 import qualified Data.ByteString.Lazy.Char8 as C
@@ -37,6 +39,26 @@ import Data.Map (Map)
 import qualified Data.Map as Map
 import Text.Printf (printf)
 
+-- The 0th-hour as per the BERT spec.
+zeroHour = UTCTime (read &quot;1970-01-01&quot;) 0
+
+decomposeTime :: UTCTime -&gt; (Int, Int, Int)
+decomposeTime t = (mS, s, uS)
+  where
+    d       = diffUTCTime t zeroHour
+    (mS, s) = (floor d) `divMod` 1000000
+    uS      = floor $ 1000000 * (snd $ properFraction d)
+
+composeTime :: (Int, Int, Int) -&gt; UTCTime
+composeTime (mS, s, uS) = addUTCTime seconds zeroHour
+  where
+    mS'     = fromIntegral mS
+    s'      = fromIntegral s
+    uS'     = fromIntegral uS
+    seconds = ((mS' * 1000000) + s' + (uS' / 1000000))
+
+fromAtom (AtomTerm a) = a
+
 -- | A single BERT term.
 data Term
   -- Simple (erlang) terms:
@@ -49,15 +71,55 @@ data Term
   | BinaryTerm     ByteString
   | BigintTerm     Integer
   | BigbigintTerm  Integer
-    -- Complex terms:
+  -- Composite (BERT specific) terms:
   | NilTerm
   | BoolTerm       Bool
   | DictionaryTerm [(Term, Term)]
-    -- TODO: time, regex
-    deriving (Show, Eq, Ord)
+  | TimeTerm       UTCTime
+  | RegexTerm      String [String]
+    deriving (Eq, Ord)
 
--- TODO: show(/read) instances that are like erlang's representation
--- of this.
+instance Show Term where
+  -- Provide an erlang-compatible 'show' for terms. The results of
+  -- this should be parseable as erlang source. 
+  show = showTerm
+
+showTerm (IntTerm x) = show x
+showTerm (FloatTerm x) = printf &quot;%15.15e&quot; x
+showTerm (AtomTerm &quot;&quot;) = &quot;&quot;
+showTerm (AtomTerm a@(x:xs))
+  | isAsciiLower x = a
+  | otherwise      = &quot;'&quot; ++ a ++ &quot;'&quot;
+showTerm (TupleTerm ts) = 
+  &quot;{&quot; ++ intercalate &quot;, &quot; (map showTerm ts) ++ &quot;}&quot;
+showTerm (BytelistTerm bs) = show $ C.unpack bs
+showTerm (ListTerm ts) = 
+  &quot;[&quot; ++ intercalate &quot;, &quot; (map showTerm ts) ++ &quot;]&quot;
+showTerm (BinaryTerm b)
+  | all (isAscii . chr . fromIntegral) (B.unpack b) = 
+      wrap $ &quot;\&quot;&quot; ++ C.unpack b ++ &quot;\&quot;&quot;
+  | otherwise = 
+      wrap $ intercalate &quot;, &quot; $ map show $ B.unpack b
+  where
+    wrap x = &quot;&lt;&lt;&quot; ++ x ++ &quot;&gt;&gt;&quot;
+showTerm (BigintTerm x) = show x
+showTerm (BigbigintTerm x) = show x
+showTerm NilTerm = &quot;[]&quot;
+showTerm (BoolTerm x) = 
+  printf &quot;{bert, %s}&quot; $ b x
+  where
+    b True  = &quot;true&quot;
+    b False = &quot;false&quot;
+showTerm (DictionaryTerm kvs) =
+  printf &quot;{bert, dict, [%s]}&quot; kvs'
+  where 
+    kvs' = intercalate &quot;, &quot;
+         $ map (\(k, v) -&gt; &quot;{&quot; ++ show k ++ &quot;,&quot; ++ show v ++ &quot;}&quot;) kvs
+showTerm (TimeTerm t) =
+  printf &quot;{bert, time, %s}&quot; $ intercalate &quot;, &quot; $ map show [mS, s, uS]
+  where (mS, s, uS) = decomposeTime t
+showTerm (RegexTerm s os) =
+  printf &quot;{bert, regex, \&quot;%s\&quot;, [%s]}&quot; s (intercalate &quot;, &quot; $ map (showTerm . AtomTerm) os)
 
 class BERT a where
   -- | Introduce a 'Term' from a Haskell value.
@@ -193,10 +255,19 @@ putTerm (BoolTerm value) =
   where
     value' = if value then &quot;true&quot; else &quot;false&quot;
 putTerm (DictionaryTerm value) =
-  putTerm $ TupleTerm [ AtomTerm &quot;bert&quot;
-                      , AtomTerm &quot;dict&quot;
-                      , ListTerm $ map (\(k, v) -&gt; TupleTerm [k, v]) value
-                      ]
+  putTerm $ TupleTerm [
+             AtomTerm &quot;bert&quot;, AtomTerm &quot;dict&quot;, 
+             ListTerm $ map (\(k, v) -&gt; TupleTerm [k, v]) value]
+putTerm (TimeTerm t) =
+  putTerm $ TupleTerm [
+             AtomTerm &quot;bert&quot;, AtomTerm &quot;time&quot;, 
+             IntTerm mS, IntTerm s, IntTerm uS]
+  where (mS, s, uS) = decomposeTime t
+putTerm (RegexTerm s os) =
+  putTerm $ TupleTerm [
+             AtomTerm &quot;bert&quot;, AtomTerm &quot;regex&quot;,
+             BytelistTerm (C.pack s), ListTerm $ map AtomTerm os]
+
 -- | Binary decoding of a single term (without header)
 getTerm = do
   tag &lt;- get8i
@@ -222,7 +293,17 @@ getTerm = do
       where
         toTuple (TupleTerm [k, v]) = return $ (k, v)
         toTuple _ = fail &quot;invalid dictionary&quot;
-
+    tupleTerm [AtomTerm &quot;bert&quot;, AtomTerm &quot;time&quot;, 
+               IntTerm mS, IntTerm s, IntTerm uS] = 
+      return $ TimeTerm $ composeTime (mS, s, uS)
+    tupleTerm [AtomTerm &quot;bert&quot;, AtomTerm &quot;regex&quot;,
+               BytelistTerm s, ListTerm os] =
+      options os &gt;&gt;= return . RegexTerm (C.unpack s)
+      where
+        -- TODO: type-check the options values as well
+        options []                = return []
+        options ((AtomTerm o):os) = options os &gt;&gt;= return . (o:)
+        options _                 = fail &quot;regex options must be atoms&quot;
     tupleTerm xs = return $ TupleTerm xs
 
 putBigint putter value = do</diff>
      <filename>Data/BERT/Term.hs</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>09ccd012d6ab8f15064407a354e1782bd7023e33</id>
    </parent>
  </parents>
  <author>
    <name>marius a. eriksen</name>
    <email>marius@monkey.org</email>
  </author>
  <url>http://github.com/mariusaeriksen/bert/commit/8ca25f5aee7a5b24765efc7d3b646f854a20149c</url>
  <id>8ca25f5aee7a5b24765efc7d3b646f854a20149c</id>
  <committed-date>2009-11-01T18:40:55-08:00</committed-date>
  <authored-date>2009-11-01T18:40:55-08:00</authored-date>
  <message>Support for time &amp; regex composite types.</message>
  <tree>014e315609190343eda99505d523076cd4f467d2</tree>
  <committer>
    <name>marius a. eriksen</name>
    <email>marius@monkey.org</email>
  </committer>
</commit>
