]> granicus.if.org Git - icinga2/commitdiff
Implement the DateTime class
authorGunnar Beutner <gunnar@beutner.name>
Tue, 29 Mar 2016 10:45:22 +0000 (12:45 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 29 Mar 2016 11:27:20 +0000 (13:27 +0200)
fixes #9839

17 files changed:
lib/base/CMakeLists.txt
lib/base/convert.cpp
lib/base/convert.hpp
lib/base/datetime-script.cpp [new file with mode: 0644]
lib/base/datetime.cpp [new file with mode: 0644]
lib/base/datetime.hpp [new file with mode: 0644]
lib/base/datetime.ti [new file with mode: 0644]
lib/base/object.hpp
lib/base/primitivetype.hpp
lib/base/type.cpp
lib/base/type.hpp
lib/base/value-operators.cpp
lib/config/expression.cpp
lib/config/vmops.hpp
tools/mkclass/class_lexer.ll
tools/mkclass/classcompiler.cpp
tools/mkclass/classcompiler.hpp

index 1ccc4d1c8ef2451a92b23b9e63e5b3270ab45e55..9c179b2bd56d49433c17cd432764b5b9a2ea7020 100644 (file)
@@ -17,6 +17,7 @@
 
 mkclass_target(application.ti application.tcpp application.thpp)
 mkclass_target(configobject.ti configobject.tcpp configobject.thpp)
+mkclass_target(datetime.ti datetime.tcpp datetime.thpp)
 mkclass_target(filelogger.ti filelogger.tcpp filelogger.thpp)
 mkclass_target(logger.ti logger.tcpp logger.thpp)
 mkclass_target(streamlogger.ti streamlogger.tcpp streamlogger.thpp)
@@ -25,7 +26,7 @@ mkclass_target(sysloglogger.ti sysloglogger.tcpp sysloglogger.thpp)
 set(base_SOURCES
   application.cpp application.thpp application-version.cpp array.cpp
   array-script.cpp boolean.cpp boolean-script.cpp console.cpp context.cpp
-  convert.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
+  convert.cpp datetime.cpp datetime.thpp datetime-script.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
   configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp configwriter.cpp dependencygraph.cpp
   exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
   json-script.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
index 23da66b259c9c2e94f04c72bdbffffb0bfc40895..3495fdd056f14b7c48d20640da43bf83ccee7fdf 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "base/convert.hpp"
+#include "base/datetime.hpp"
 #include <boost/lexical_cast.hpp>
 
 using namespace icinga;
@@ -31,3 +32,18 @@ String Convert::ToString(const Value& val)
 {
        return val;
 }
+
+double Convert::ToDateTimeValue(double val)
+{
+       return val;
+}
+
+double Convert::ToDateTimeValue(const Value& val)
+{
+       if (val.IsNumber())
+               return val;
+       else if (val.IsObjectType<DateTime>())
+               return static_cast<DateTime::Ptr>(val)->GetValue();
+       else
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Not a DateTime value."));
+}
index f14be8455b5c87ac3a7834c1fa8ff9625a30dca8..fd2daa3a60cbea1fbcecc38ab62a6999a8d12df5 100644 (file)
@@ -83,6 +83,9 @@ public:
        static String ToString(const String& val);
        static String ToString(const Value& val);
 
+       static double ToDateTimeValue(double val);
+       static double ToDateTimeValue(const Value& val);
+
 private:
        Convert(void);
 };
diff --git a/lib/base/datetime-script.cpp b/lib/base/datetime-script.cpp
new file mode 100644 (file)
index 0000000..e0210a9
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/)  *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "base/datetime.hpp"
+#include "base/function.hpp"
+#include "base/functionwrapper.hpp"
+#include "base/scriptframe.hpp"
+#include "base/objectlock.hpp"
+
+using namespace icinga;
+
+static String DateTimeFormat(const String& format)
+{
+       ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
+       DateTime::Ptr self = static_cast<DateTime::Ptr>(vframe->Self);
+
+       return self->Format(format);
+}
+
+Object::Ptr DateTime::GetPrototype(void)
+{
+       static Dictionary::Ptr prototype;
+
+       if (!prototype) {
+               prototype = new Dictionary();
+               prototype->Set("format", new Function(WrapFunction(DateTimeFormat)));
+       }
+
+       return prototype;
+}
+
diff --git a/lib/base/datetime.cpp b/lib/base/datetime.cpp
new file mode 100644 (file)
index 0000000..a765fd5
--- /dev/null
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/)  *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "base/datetime.hpp"
+#include "base/datetime.tcpp"
+#include "base/utility.hpp"
+#include "base/primitivetype.hpp"
+
+using namespace icinga;
+
+REGISTER_TYPE_WITH_PROTOTYPE(DateTime, DateTime::GetPrototype());
+
+DateTime::DateTime(double value)
+       : m_Value(value)
+{ }
+
+DateTime::DateTime(const std::vector<Value>& args)
+{
+       if (args.empty())
+               m_Value = Utility::GetTime();
+       else if (args.size() == 3 || args.size() == 6) {
+               struct tm tms;
+               tms.tm_year = args[0] - 1900;
+               tms.tm_mon = args[1] - 1;
+               tms.tm_mday = args[2];
+
+               if (args.size() == 6) {
+                       tms.tm_hour = args[3];
+                       tms.tm_min = args[4];
+                       tms.tm_sec = args[5];
+               } else {
+                       tms.tm_hour = 0;
+                       tms.tm_min = 0;
+                       tms.tm_sec = 0;
+               }
+
+               tms.tm_isdst = -1;
+
+               m_Value = mktime(&tms);
+       } else if (args.size() == 1)
+               m_Value = args[0];
+       else
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid number of arguments for the DateTime constructor."));
+}
+
+double DateTime::GetValue(void) const
+{
+       return m_Value;
+}
+
+String DateTime::Format(const String& format) const
+{
+       return Utility::FormatDateTime(format.CStr(), m_Value);
+}
+
+String DateTime::ToString(void) const
+{
+       return Format("%Y-%m-%d %H:%M:%S %z");
+}
diff --git a/lib/base/datetime.hpp b/lib/base/datetime.hpp
new file mode 100644 (file)
index 0000000..ef3eb8e
--- /dev/null
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/)  *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef DATETIME_H
+#define DATETIME_H
+
+#include "base/i2-base.hpp"
+#include "base/datetime.thpp"
+#include "base/value.hpp"
+#include <vector>
+
+namespace icinga
+{
+
+/**
+ * A date/time value.
+ *
+ * @ingroup base
+ */
+class I2_BASE_API DateTime : public ObjectImpl<DateTime>
+{
+public:
+       DECLARE_OBJECT(DateTime);
+
+       DateTime(double value);
+       DateTime(const std::vector<Value>& args);
+
+       String Format(const String& format) const;
+
+       virtual double GetValue(void) const override;
+       virtual String ToString(void) const override;
+
+       static Object::Ptr GetPrototype(void);
+
+private:
+       double m_Value;
+};
+
+}
+
+#endif /* DATETIME_H */
diff --git a/lib/base/datetime.ti b/lib/base/datetime.ti
new file mode 100644 (file)
index 0000000..2b6d178
--- /dev/null
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/)  *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+library base;
+
+namespace icinga
+{
+
+vararg_constructor class DateTime
+{
+       [state, no_storage] double value {
+               get;
+       };
+};
+
+}
index c68f22fe5bb8425a452f3016f470b48a1a004a82..2cb77263df1f2bd4cd5b449d8145e9f2eb6fdfc0 100644 (file)
@@ -25,6 +25,7 @@
 #include <boost/thread/recursive_mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
 #include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <vector>
 
 using boost::intrusive_ptr;
 using boost::dynamic_pointer_cast;
@@ -61,15 +62,29 @@ extern I2_BASE_API Value Empty;
        IMPL_TYPE_LOOKUP();
 
 template<typename T>
-intrusive_ptr<Object> DefaultObjectFactory(void)
+intrusive_ptr<Object> DefaultObjectFactory(const std::vector<Value>& args)
 {
+       if (!args.empty())
+               BOOST_THROW_EXCEPTION(std::invalid_argument("Constructor does not take any arguments."));
+
        return new T();
 }
 
-typedef intrusive_ptr<Object> (*ObjectFactory)(void);
-
 template<typename T>
+intrusive_ptr<Object> DefaultObjectFactoryVA(const std::vector<Value>& args)
+{
+       return new T(args);
+}
+
+typedef intrusive_ptr<Object> (*ObjectFactory)(const std::vector<Value>&);
+
+template<typename T, bool VA>
 struct TypeHelper
+{
+};
+
+template<typename T>
+struct TypeHelper<T, false>
 {
        static ObjectFactory GetFactory(void)
        {
@@ -77,6 +92,15 @@ struct TypeHelper
        }
 };
 
+template<typename T>
+struct TypeHelper<T, true>
+{
+       static ObjectFactory GetFactory(void)
+       {
+               return DefaultObjectFactoryVA<T>;
+       }
+};
+
 /**
  * Base class for all heap-allocated objects. At least one of its methods
  * has to be virtual for RTTI to work.
index 50f37b3de1fa1d32bb7acf6255b2b30decc7180d..1d80b0e1e277cb9cdfe61ccbf52adee56e7ed37b 100644 (file)
@@ -75,6 +75,9 @@ private:
 #define REGISTER_PRIMITIVE_TYPE(type, base, prototype)                         \
        REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, DefaultObjectFactory<type>)
 
+#define REGISTER_PRIMITIVE_TYPE_VA(type, base, prototype)                              \
+       REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, DefaultObjectFactoryVA<type>)
+
 #define REGISTER_PRIMITIVE_TYPE_NOINST(type, base, prototype)                  \
        REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, NULL)
 
index c4be806be1bf1597f5fd6cdc36e01f54bf8089d5..211eaa13d48d5500b20ec029244100c2e3827a11 100644 (file)
@@ -67,14 +67,14 @@ String Type::GetPluralName(void) const
                return name + "s";
 }
 
-Object::Ptr Type::Instantiate(void) const
+Object::Ptr Type::Instantiate(const std::vector<Value>& args) const
 {
        ObjectFactory factory = GetFactory();
 
        if (!factory)
                BOOST_THROW_EXCEPTION(std::runtime_error("Type does not have a factory function."));
 
-       return factory();
+       return factory(args);
 }
 
 bool Type::IsAbstract(void) const
index 000ef9e4355cca9925be53421b74b4299113188d..20aba26317356aaaa2ac4c97a015844cf8be0f4e 100644 (file)
@@ -86,7 +86,7 @@ public:
 
        String GetPluralName(void) const;
 
-       Object::Ptr Instantiate(void) const;
+       Object::Ptr Instantiate(const std::vector<Value>& args = std::vector<Value>()) const;
 
        bool IsAssignableFrom(const Type::Ptr& other) const;
 
index 9c18f7faa8c074d0214bc288f50200017c2b2b18..ad2691a5951b6fb06a9d9e4cabab9a69cfc71f97 100644 (file)
@@ -20,6 +20,8 @@
 #include "base/value.hpp"
 #include "base/array.hpp"
 #include "base/dictionary.hpp"
+#include "base/datetime.hpp"
+#include "base/convert.hpp"
 #include "base/utility.hpp"
 #include "base/objectlock.hpp"
 #include <boost/foreach.hpp>
@@ -177,6 +179,13 @@ bool Value::operator==(const Value& rhs) const
                return false;
 
        if (IsObject()) {
+               if (IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>()) {
+                       DateTime::Ptr dt1 = *this;
+                       DateTime::Ptr dt2 = rhs;
+
+                       return dt1->GetValue() == dt2->GetValue();
+               }
+
                if (IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
                        Array::Ptr arr1 = *this;
                        Array::Ptr arr2 = rhs;
@@ -234,6 +243,8 @@ Value icinga::operator+(const Value& lhs, const Value& rhs)
                return static_cast<String>(lhs) + static_cast<String>(rhs);
        else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) + static_cast<double>(rhs);
+       else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
+               return new DateTime(Convert::ToDateTimeValue(lhs) + rhs);
        else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
                Array::Ptr result = new Array();
                if (!lhs.IsEmpty())
@@ -277,6 +288,12 @@ Value icinga::operator-(const Value& lhs, const Value& rhs)
 {
        if ((lhs.IsNumber() || lhs.IsEmpty()) && !lhs.IsString() && (rhs.IsNumber() || rhs.IsEmpty()) && !rhs.IsString() && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) - static_cast<double>(rhs);
+       else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
+               return new DateTime(Convert::ToDateTimeValue(lhs) - rhs);
+       else if (lhs.IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>())
+               return Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs);
+       else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+               return new DateTime(Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs));
        else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
                if (lhs.IsEmpty())
                        return new Array();
@@ -567,6 +584,8 @@ bool icinga::operator<(const Value& lhs, const Value& rhs)
                return static_cast<String>(lhs) < static_cast<String>(rhs);
        else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) < static_cast<double>(rhs);
+       else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+               return Convert::ToDateTimeValue(lhs) < Convert::ToDateTimeValue(rhs);
        else
                BOOST_THROW_EXCEPTION(std::invalid_argument("Operator < cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
 }
@@ -597,6 +616,8 @@ bool icinga::operator>(const Value& lhs, const Value& rhs)
                return static_cast<String>(lhs) > static_cast<String>(rhs);
        else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) > static_cast<double>(rhs);
+       else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+               return Convert::ToDateTimeValue(lhs) > Convert::ToDateTimeValue(rhs);
        else
                BOOST_THROW_EXCEPTION(std::invalid_argument("Operator > cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
 }
@@ -627,6 +648,8 @@ bool icinga::operator<=(const Value& lhs, const Value& rhs)
                return static_cast<String>(lhs) <= static_cast<String>(rhs);
        else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) <= static_cast<double>(rhs);
+       else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+               return Convert::ToDateTimeValue(lhs) <= Convert::ToDateTimeValue(rhs);
        else
                BOOST_THROW_EXCEPTION(std::invalid_argument("Operator <= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
 }
@@ -657,6 +680,8 @@ bool icinga::operator>=(const Value& lhs, const Value& rhs)
                return static_cast<String>(lhs) >= static_cast<String>(rhs);
        else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
                return static_cast<double>(lhs) >= static_cast<double>(rhs);
+       else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+               return Convert::ToDateTimeValue(lhs) >= Convert::ToDateTimeValue(rhs);
        else
                BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
 }
index c87e6d1d8434775e6fbae6d71117e4c3edc64e4b..f2ef686f538b0b1570ac4d8678ad27cb10c060d1 100644 (file)
@@ -424,15 +424,15 @@ ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHin
        }
 
        if (vfunc.IsObjectType<Type>()) {
-               if (m_Args.empty())
-                       return VMOps::ConstructorCall(vfunc, m_DebugInfo);
-               else if (m_Args.size() == 1) {
-                       ExpressionResult argres = m_Args[0]->Evaluate(frame);
+               std::vector<Value> arguments;
+               BOOST_FOREACH(Expression *arg, m_Args) {
+                       ExpressionResult argres = arg->Evaluate(frame);
                        CHECK_RESULT(argres);
 
-                       return VMOps::CopyConstructorCall(vfunc, argres.GetValue(), m_DebugInfo);
-               } else
-                       BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor.", m_DebugInfo));
+                       arguments.push_back(argres.GetValue());
+               }
+
+               return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
        }
 
        if (!vfunc.IsObjectType<Function>())
index 174cc76ff74ca6d4c6ee2eeff81a4ff0983dfa91..d0c0f9b6d3752f11e8203bc080ad56d7b2c66416 100644 (file)
@@ -55,36 +55,33 @@ public:
                        return ScriptGlobal::Get(name);
        }
 
-       static inline Value CopyConstructorCall(const Type::Ptr& type, const Value& value, const DebugInfo& debugInfo = DebugInfo())
+       static inline Value ConstructorCall(const Type::Ptr& type, const std::vector<Value>& args, const DebugInfo& debugInfo = DebugInfo())
        {
-               if (type->GetName() == "String")
-                       return Convert::ToString(value);
-               else if (type->GetName() == "Number")
-                       return Convert::ToDouble(value);
-               else if (type->GetName() == "Boolean")
-                       return Convert::ToBool(value);
-               else if (!value.IsEmpty() && !type->IsAssignableFrom(value.GetReflectionType()))
-                       BOOST_THROW_EXCEPTION(ScriptError("Invalid cast: Tried to cast object of type '" + value.GetReflectionType()->GetName() + "' to type '" + type->GetName() + "'", debugInfo));
+               if (type->GetName() == "String") {
+                       if (args.empty())
+                               return "";
+                       else if (args.size() == 1)
+                               return Convert::ToString(args[0]);
+                       else
+                               BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+               } else if (type->GetName() == "Number") {
+                       if (args.empty())
+                               return 0;
+                       else if (args.size() == 1)
+                               return Convert::ToDouble(args[0]);
+                       else
+                               BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+               } else if (type->GetName() == "Boolean") {
+                       if (args.empty())
+                               return 0;
+                       else if (args.size() == 1)
+                               return Convert::ToBool(args[0]);
+                       else
+                               BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+               } else if (args.size() == 1 && type->IsAssignableFrom(args[0].GetReflectionType()))
+                       return args[0];
                else
-                       return value;
-       }
-
-       static inline Value ConstructorCall(const Type::Ptr& type, const DebugInfo& debugInfo = DebugInfo())
-       {
-               if (type->GetName() == "String")
-                       return "";
-               else if (type->GetName() == "Number")
-                       return 0;
-               else if (type->GetName() == "Boolean")
-                       return false;
-               else {
-                       Object::Ptr object = type->Instantiate();
-
-                       if (!object)
-                               BOOST_THROW_EXCEPTION(ScriptError("Failed to instantiate object of type '" + type->GetName() + "'", debugInfo));
-
-                       return object;
-               }
+                       return type->Instantiate(args);
        }
 
        static inline Value FunctionCall(ScriptFrame& frame, const Value& self, const Function::Ptr& func, const std::vector<Value>& arguments)
index 0afb227298b67da5849b221f029c5d3893a867dc..128424d69d0c309fbd80d9450dbe8c79decbe3d4 100644 (file)
@@ -137,6 +137,7 @@ code                                { return T_CODE; }
 load_after                     { return T_LOAD_AFTER; }
 library                                { return T_LIBRARY; }
 abstract                       { yylval->num = TAAbstract; return T_CLASS_ATTRIBUTE; }
+vararg_constructor             { yylval->num = TAVarArgConstructor; return T_CLASS_ATTRIBUTE; }
 config                         { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; }
 state                          { yylval->num = FAState; return T_FIELD_ATTRIBUTE; }
 enum                           { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; }
index d0aab97a9717128b5649642350aeffa553664539..98071ae164c5feb1a31c56d06037b79aa9710ce6 100644 (file)
@@ -222,7 +222,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
        /* TypeHelper */
        if (klass.Attributes & TAAbstract) {
                m_Header << "template<>" << std::endl
-                        << "struct TypeHelper<" << klass.Name << ">" << std::endl
+                        << "struct TypeHelper<" << klass.Name << ", " << ((klass.Attributes & TAVarArgConstructor) ? "true" : "false") << ">" << std::endl
                         << "{" << std::endl
                         << "\t" << "static ObjectFactory GetFactory(void)" << std::endl
                         << "\t" << "{" << std::endl
@@ -412,7 +412,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
        m_Impl << "ObjectFactory TypeImpl<" << klass.Name << ">::GetFactory(void) const" << std::endl
               << "{" << std::endl
-              << "\t" << "return TypeHelper<" << klass.Name << ">::GetFactory();" << std::endl
+              << "\t" << "return TypeHelper<" << klass.Name << ", " << ((klass.Attributes & TAVarArgConstructor) ? "true" : "false") << ">::GetFactory();" << std::endl
               << "}" << std::endl << std::endl;
 
        /* GetLoadDependencies */
index 2369253bc9d34bec14e164c78db571f7ac31c94b..05e0b1a44d382dc3cb16e05d6270db498ee69831 100644 (file)
@@ -159,7 +159,8 @@ struct Field
 
 enum TypeAttribute
 {
-       TAAbstract = 1
+       TAAbstract = 1,
+       TAVarArgConstructor = 2
 };
 
 struct Klass