Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 14628)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 14629)
@@ -24,4 +24,9 @@
 using namespace std;
 using namespace v8;
+
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateLocal;
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateSky;
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateMoon;
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDatabase;
 
 
@@ -327,5 +332,11 @@
         return ThrowException(String::New("State name must not contain : or =."));
 
-    if (JsHasState(index) || JsHasState(name))
+    struct Find : State
+    {
+        Find(int idx, const string &n) : State(idx, n) { }
+        bool operator()(const pair<int, string> &p) { return index==p.first || name==p.second; }
+    };
+
+    if (find_if(fStates.begin(), fStates.end(), Find(index, name))!=fStates.end())
     {
         const string what =
@@ -363,4 +374,24 @@
 
     return Boolean::New(JsSetState(index));
+}
+
+Handle<Value> InterpreterV8::FuncGetState(const Arguments& args)
+{
+    if (args.Length()>0)
+        return ThrowException(String::New("getState must not take arguments."));
+
+    const State state = JsGetCurrentState();
+
+    HandleScope handle_scope;
+
+    Handle<Object> rc = Object::New();
+    if (rc.IsEmpty())
+        return Undefined();
+
+    rc->Set(String::New("index"), Integer::New(state.index), ReadOnly);
+    rc->Set(String::New("name"), String::New(state.name.c_str()), ReadOnly);
+    rc->Set(String::New("description"), String::New(state.comment.c_str()), ReadOnly);
+
+    return handle_scope.Close(rc);
 }
 
@@ -517,5 +548,5 @@
         for (vector<mysqlpp::Row>::const_iterator it=res.begin(); it<res.end(); it++)
         {
-            Handle<Array> row = Array::New();
+            Handle<Object> row = Object::New();
             if (row.IsEmpty())
                 return Undefined();
@@ -567,4 +598,5 @@
                     else
                         row->Set(name, Integer::New((int32_t)(*it)[i]), ReadOnly);
+                    continue;
                 }
 
@@ -649,20 +681,25 @@
         fDatabases.push_back(db);
 
-        Handle<ObjectTemplate> tem = ObjectTemplate::New();
-        tem->Set(String::New("user"),     String::New(db->user.c_str()), ReadOnly);
-        tem->Set(String::New("server"),   String::New(db->server.c_str()), ReadOnly);
-        tem->Set(String::New("database"), String::New(db->db.c_str()), ReadOnly);
-        tem->Set(String::New("port"),     db->port==0?Undefined():Integer::NewFromUnsigned(db->port), ReadOnly);
-        tem->Set(String::New("query"),    FunctionTemplate::New(WrapDbQuery), ReadOnly);
-        tem->Set(String::New("close"),    FunctionTemplate::New(WrapDbClose),   ReadOnly);
-        tem->SetInternalFieldCount(1);
-
-        Handle<Object> obj = tem->NewInstance();
-        if (obj.IsEmpty())
+        Handle<Object> This = args.This();
+        if (!args.IsConstructCall())
+        {
+            Handle<ObjectTemplate> T = fTemplateDatabase->PrototypeTemplate();
+            if (T.IsEmpty())
+                return Undefined();
+
+            This = T->NewInstance();
+        }
+        if (This.IsEmpty())
             return Undefined();
 
-        obj->SetInternalField(0, External::New(db));
-
-        return handle_scope.Close(obj);
+        This->Set(String::New("user"),     String::New(db->user.c_str()), ReadOnly);
+        This->Set(String::New("server"),   String::New(db->server.c_str()), ReadOnly);
+        This->Set(String::New("database"), String::New(db->db.c_str()), ReadOnly);
+        This->Set(String::New("port"),     db->port==0?Undefined():Integer::NewFromUnsigned(db->port), ReadOnly);
+        This->Set(String::New("query"),    FunctionTemplate::New(WrapDbQuery)->GetFunction(), ReadOnly);
+        This->Set(String::New("close"),    FunctionTemplate::New(WrapDbClose)->GetFunction(),   ReadOnly);
+        This->SetInternalField(0, External::New(db));
+
+        return handle_scope.Close(This);
     }
     catch (const exception &e)
@@ -1143,57 +1180,4 @@
 }
 
-Handle<Value> InterpreterV8::LocalToString(const Arguments &/*args*/)
-{
-    return String::New("[object Local]");
-    /*
-    HandleScope handle_scope;
-
-    const Handle<Object> This = args.This();
-
-    Handle<String> zd = This->Get(String::New("zd"))->ToString();
-    Handle<String> az = This->Get(String::New("az"))->ToString();
-
-    return String::New("TEST");
-    */
-}
-
-Handle<Value> InterpreterV8::SkyToString(const Arguments &/*args*/)
-{
-    return String::New("[object Sky]");
-}
-
-Handle<Value> InterpreterV8::MoonToString(const Arguments &/*args*/)
-{
-    return String::New("[object Moon]");
-}
-
-Handle<Value> InterpreterV8::ConstructLocal(double zd, double az, Handle<Value> time)
-{
-    Handle<ObjectTemplate> loc = ObjectTemplate::New();
-
-    loc->Set(String::New("zd"),       Number::New(zd), ReadOnly);
-    loc->Set(String::New("az"),       Number::New(az), ReadOnly);
-    loc->Set(String::New("toSky"),    FunctionTemplate::New(LocalToSky), ReadOnly);
-    loc->Set(String::New("toString"), FunctionTemplate::New(LocalToString), ReadOnly);
-    if (!time.IsEmpty())
-        loc->Set(String::New("time"), time);
-
-    return loc->NewInstance();
-}
-
-Handle<Value> InterpreterV8::ConstructSky(double ra, double dec, Handle<Value> time, bool ismoon)
-{
-    Handle<ObjectTemplate> sky = ObjectTemplate::New();
-
-    sky->Set(String::New("ra"),       Number::New(ra),  ReadOnly);
-    sky->Set(String::New("dec"),      Number::New(dec), ReadOnly);
-    sky->Set(String::New("toLocal"),  FunctionTemplate::New(ismoon?MoonToLocal :SkyToLocal),  ReadOnly);
-    sky->Set(String::New("toString"), FunctionTemplate::New(ismoon?MoonToString:SkyToString), ReadOnly);
-    if (!time.IsEmpty())
-        sky->Set(String::New("time"), time);
-
-    return sky->NewInstance();
-}
-
 Handle<Value> InterpreterV8::LocalDist(const Arguments &args)
 {
@@ -1285,5 +1269,10 @@
     ln_get_equ_from_hrz(&hrz, &obs, utc.JD(), &equ);
 
-    return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date));
+    // -----------------------------
+
+    Handle<Value> arg[] = { Number::New(equ.ra/15), Number::New(equ.dec), date };
+    return fTemplateSky->GetFunction()->NewInstance(3, arg);
+
+    //return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date));
 }
 
@@ -1317,5 +1306,6 @@
     ln_get_hrz_from_equ(&equ, &obs, utc.JD(), &hrz);
 
-    return handle_scope.Close(ConstructLocal(90-hrz.alt, hrz.az, date));
+    Handle<Value> arg[] = { Number::New(90-hrz.alt), Number::New(hrz.az), date };
+    return fTemplateLocal->GetFunction()->NewInstance(3, arg);
 }
 
@@ -1334,7 +1324,6 @@
     HandleScope handle_scope;
 
-    const Local<Value> date =
-        args.Length()==0 ? Date::New(Time().JavaDate()) : args.This()->Get(String::New("time"));
-    if (date.IsEmpty())
+    const Local<Value> date = args.This()->Get(String::New("time"));
+    if (date.IsEmpty() || date->IsUndefined() )
         return Undefined();
 
@@ -1349,5 +1338,6 @@
     ln_get_hrz_from_equ(&equ, &obs, utc.JD(), &hrz);
 
-    return handle_scope.Close(ConstructLocal(90-hrz.alt, hrz.az, date));
+    Handle<Value> arg[] = { Number::New(90-hrz.alt), Number::New(hrz.az), date };
+    return fTemplateLocal->GetFunction()->NewInstance(3, arg);
 }
 
@@ -1370,11 +1360,40 @@
     ln_get_lunar_equ_coords_prec(utc.JD(), &equ, 0.01);
 
-    return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date, true));
+    // ----------------------------
+
+    Handle<Object> This = args.This();
+    if (!args.IsConstructCall())
+    {
+        Handle<ObjectTemplate> T = fTemplateMoon->PrototypeTemplate();
+        if (T.IsEmpty())
+            return Undefined();
+
+        This = T->NewInstance();
+    }
+    if (This.IsEmpty())
+        return Undefined();
+
+    Handle<Function> function =
+        FunctionTemplate::New(MoonToLocal)->GetFunction();
+    if (function.IsEmpty())
+        return Undefined();
+
+    This->Set(String::New("ra"),      Number::New(equ.ra/15),  ReadOnly);
+    This->Set(String::New("dec"),     Number::New(equ.dec),    ReadOnly);
+    This->Set(String::New("toLocal"), function,                ReadOnly);
+    This->Set(String::New("time"),    date,                    ReadOnly);
+
+    return This;
+
+    //return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date, true));
 }
 
 Handle<Value> InterpreterV8::ConstructorSky(const Arguments &args)
 {
-    if (args.Length()!=2)
-        return ThrowException(String::New("Sky constructor takes two arguments."));
+    if (args.Length()<2 || args.Length()>3)
+        return ThrowException(String::New("Sky constructor takes two or three arguments."));
+
+    if (args.Length()==3 && !args[2]->IsDate())
+        return ThrowException(String::New("Third argument must be a Date."));
 
     const double ra  = args[0]->NumberValue();
@@ -1384,11 +1403,40 @@
         return ThrowException(String::New("Both arguments to Sky must be valid numbers."));
 
-    return ConstructSky(ra, dec);
+    // ----------------------------
+
+    Handle<Object> This = args.This();
+    if (!args.IsConstructCall())
+    {
+        Handle<ObjectTemplate> T = fTemplateSky->PrototypeTemplate();
+        if (T.IsEmpty())
+            return Undefined();
+
+        This = T->NewInstance();
+    }
+    if (This.IsEmpty())
+        return Undefined();
+
+    Handle<Function> function =
+        FunctionTemplate::New(SkyToLocal)->GetFunction();
+    if (function.IsEmpty())
+        return Undefined();
+
+    This->Set(String::New("ra"),      Number::New(ra),  ReadOnly);
+    This->Set(String::New("dec"),     Number::New(dec), ReadOnly);
+    This->Set(String::New("toLocal"), function,         ReadOnly);
+    if (args.Length()==3)
+        This->Set(String::New("time"), args[2], ReadOnly);
+
+    return This;
 }
 
 Handle<Value> InterpreterV8::ConstructorLocal(const Arguments &args)
 {
-    if (args.Length()!=2)
-        return ThrowException(String::New("Local constructor takes two arguments."));
+    if (args.Length()<2 || args.Length()>3)
+        return ThrowException(String::New("Local constructor takes two or three arguments."));
+
+    if (args.Length()==3 && !args[2]->IsDate())
+        return ThrowException(String::New("Third argument must be a Date."));
+
 
     const double zd = args[0]->NumberValue();
@@ -1398,5 +1446,32 @@
         return ThrowException(String::New("Both arguments to Local must be valid numbers."));
 
-    return ConstructLocal(zd, az);
+    // --------------------
+
+    Handle<Object> This = args.This();
+    if (!args.IsConstructCall())
+    {
+        Handle<ObjectTemplate> T = fTemplateLocal->PrototypeTemplate();
+        if (T.IsEmpty())
+            return Undefined();
+
+        This = T->NewInstance();
+    }
+    if (This.IsEmpty())
+        return Undefined();
+
+    Handle<Function> function =
+        FunctionTemplate::New(LocalToSky)->GetFunction();
+    if (function.IsEmpty())
+        return Undefined();
+
+    This->Set(String::New("zd"),    Number::New(zd), ReadOnly);
+    This->Set(String::New("az"),    Number::New(az), ReadOnly);
+    This->Set(String::New("toSky"), function,        ReadOnly);
+    if (args.Length()==3)
+        This->Set(String::New("time"), args[2], ReadOnly);
+
+    return This;
+
+    // ----------------------
 }
 #endif
@@ -1606,5 +1681,7 @@
         "}"*/;
 
-    Script::New(String::New(code.c_str()), String::New("internal"))->Run();
+    Handle<Script> script = Script::New(String::New(code.c_str()), String::New("internal"));
+    if (!script.IsEmpty())
+        script->Run();
 }
 
@@ -1633,9 +1710,9 @@
     dim->Set(String::New("newState"),  FunctionTemplate::New(WrapNewState),  ReadOnly);
     dim->Set(String::New("setState"),  FunctionTemplate::New(WrapSetState),  ReadOnly);
+    dim->Set(String::New("getState"),  FunctionTemplate::New(WrapGetState),  ReadOnly);
     dim->Set(String::New("sleep"),     FunctionTemplate::New(WrapSleep),     ReadOnly);
     dim->Set(String::New("timeout"),   FunctionTemplate::New(WrapTimeout),   ReadOnly);
     dim->Set(String::New("subscribe"), FunctionTemplate::New(WrapSubscribe), ReadOnly);
-    dim->Set(String::New("database"),  FunctionTemplate::New(WrapDatabase),  ReadOnly);
-    //dim->Set(String::New("file"),      FunctionTemplate::New(WrapFile),      ReadOnly);
+    dim->Set(String::New("file"),      FunctionTemplate::New(WrapFile),      ReadOnly);
 
     Handle<ObjectTemplate> onchange = ObjectTemplate::New();
@@ -1645,19 +1722,33 @@
     Handle<ObjectTemplate> global = ObjectTemplate::New();
     global->Set(String::New("dim"), dim, ReadOnly);
-    global->Set(String::New("include"), FunctionTemplate::New(WrapInclude),                ReadOnly);
-    global->Set(String::New("exit"),    FunctionTemplate::New(WrapExit),                   ReadOnly);
-    global->Set(String::New("version"), FunctionTemplate::New(InterpreterV8::FuncVersion), ReadOnly);
+    global->Set(String::New("include"),  FunctionTemplate::New(WrapInclude),                ReadOnly);
+    global->Set(String::New("exit"),     FunctionTemplate::New(WrapExit),                   ReadOnly);
+    global->Set(String::New("version"),  FunctionTemplate::New(InterpreterV8::FuncVersion), ReadOnly);
+
+    Handle<FunctionTemplate> db = FunctionTemplate::New(WrapDatabase);
+    db->SetClassName(String::New("Database"));
+    db->InstanceTemplate()->SetInternalFieldCount(1);
+    global->Set(String::New("Database"), db, ReadOnly);
+
+    fTemplateDatabase = db;
 
 #ifdef HAVE_NOVA
     Handle<FunctionTemplate> sky = FunctionTemplate::New(ConstructorSky);
+    sky->SetClassName(String::New("Sky"));
     global->Set(String::New("Sky"), sky, ReadOnly);
 
     Handle<FunctionTemplate> loc = FunctionTemplate::New(ConstructorLocal);
-    loc->Set(String::New("dist"), FunctionTemplate::New(LocalDist), ReadOnly);
+    loc->SetClassName(String::New("Local"));
+    loc->Set(String::New("dist"),  FunctionTemplate::New(LocalDist), ReadOnly);
     global->Set(String::New("Local"), loc, ReadOnly);
 
     Handle<FunctionTemplate> moon = FunctionTemplate::New(ConstructorMoon);
+    moon->SetClassName(String::New("Moon"));
     moon->Set(String::New("disk"), FunctionTemplate::New(MoonDisk), ReadOnly);
     global->Set(String::New("Moon"), moon, ReadOnly);
+
+    fTemplateLocal = loc;
+    fTemplateSky   = sky;
+    fTemplateMoon  = moon;
 #endif
 
@@ -1744,4 +1835,8 @@
 #endif
 
+    fStates.clear();
+
+    fGlobalContext.Dispose();
+
     JsEnd(filename);
 
Index: /trunk/FACT++/src/InterpreterV8.h
===================================================================
--- /trunk/FACT++/src/InterpreterV8.h	(revision 14628)
+++ /trunk/FACT++/src/InterpreterV8.h	(revision 14629)
@@ -41,4 +41,12 @@
     std::vector<std::thread> fTimeout;
 
+    // List of all states already set
+    std::vector<std::pair<int, std::string>> fStates;
+
+    static v8::Handle<v8::FunctionTemplate> fTemplateLocal;
+    static v8::Handle<v8::FunctionTemplate> fTemplateSky;
+    static v8::Handle<v8::FunctionTemplate> fTemplateMoon;
+    static v8::Handle<v8::FunctionTemplate> fTemplateDatabase;
+
 #ifdef HAVE_SQL
     std::list<Database*> fDatabases;
@@ -67,4 +75,5 @@
     v8::Handle<v8::Value> FuncState(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncSetState(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncGetState(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncNewState(const v8::Arguments& args);
     //v8::Handle<v8::Value> FuncOpen(const v8::Arguments& args);
@@ -83,6 +92,4 @@
     static v8::Handle<v8::Value> SkyToString(const v8::Arguments &args);
     static v8::Handle<v8::Value> MoonToString(const v8::Arguments &args);
-    static v8::Handle<v8::Value> ConstructLocal(double zd, double az, v8::Handle<v8::Value> time=v8::Handle<v8::Value>());
-    static v8::Handle<v8::Value> ConstructSky(double ra, double dec, v8::Handle<v8::Value> time=v8::Handle<v8::Value>(), bool ismoon=false);
     static v8::Handle<v8::Value> LocalDist(const v8::Arguments &args);
     static v8::Handle<v8::Value> MoonDisk(const v8::Arguments &args);
@@ -108,4 +115,5 @@
     static v8::Handle<v8::Value> WrapNewState(const v8::Arguments &args) { if (This) return This->FuncNewState(args); else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSetState(const v8::Arguments &args) { if (This) return This->FuncSetState(args); else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapGetState(const v8::Arguments &args) { if (This) return This->FuncGetState(args); else return v8::Undefined(); }
     //static v8::Handle<v8::Value> WrapOpen(const v8::Arguments &args)     { if (This) return This->FuncOpen(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSubscribe(const v8::Arguments &args){ if (This) return This->FuncSubscribe(args);else return v8::Undefined(); }
@@ -160,9 +168,10 @@
     virtual bool  JsUnsubscribe(const std::string &) { return false; };
 
-    virtual bool JsNewState(int, const std::string&, const std::string&) { return false; }
-    virtual bool JsSetState(int) { return false; }
-    virtual bool JsHasState(int) const { return false; }
-    virtual bool JsHasState(const std::string &) const { return false; }
-    virtual int  JsGetState(const std::string &) const { return -2; }
+    virtual bool  JsNewState(int, const std::string&, const std::string&) { return false; }
+    virtual bool  JsSetState(int) { return false; }
+    virtual bool  JsHasState(int) const { return false; }
+    virtual bool  JsHasState(const std::string &) const { return false; }
+    virtual int   JsGetState(const std::string &) const { return -2; }
+    virtual State JsGetCurrentState() const { return State(); }
 
     virtual std::vector<Description> JsDescription(const std::string &) { return std::vector<Description>(); };
