static bool IsScriptable(Symbol s) { if (s.argList.Contains("[")) return false; if (IsBadType(s.type)) return false; foreach (Parameter p in s.parameters) if (IsBadType(p.type) || IsBadType(p.BasicType())) return false; foreach (string str in s.Comments()) if (str.Contains("[noscript]")) return false; if (s.returnComment != null && s.returnComment.Contains("[noscript]")) return false; return true; }
/* static void GenerateScriptClass(Symbol Class, TextWriter tw) { tw.WriteLine("class " + Class.name + "_scriptclass : public QScriptClass"); tw.WriteLine("{"); tw.WriteLine("public:"); tw.WriteLine(Indent(1) + "QScriptValue objectPrototype;"); tw.WriteLine(Indent(1) + Class.name + "_scriptclass(QScriptEngine *engine):QScriptClass(engine){}"); tw.WriteLine(Indent(1) + "QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id)"); tw.WriteLine(Indent(1) + "{"); tw.WriteLine(Indent(2) + Class.name + " *This = TypeFromQScriptValue<" + Class.name + "*>(object);"); tw.WriteLine(Indent(2) + "if (!This) { printf(\"Error! Cannot convert QScriptValue to type " + Class.name + " in file %s, line %d!\\nTry using " + Class.name + ".get%s() and " + Class.name + ".set%s() to query the member variable '%s'!\\n\", __FILE__, __LINE__, Capitalize((QString)name).c_str(), Capitalize((QString)name).c_str(), ((QString)name).toStdString().c_str()); return QScriptValue(); }"); tw.WriteLine(Indent(2) + "QString name_ = (QString)name;"); foreach (Symbol v in Class.children) if (v.kind == "variable" && IsScriptable(v) && v.visibilityLevel == VisibilityLevel.Public) { // tw.Write(Indent(2) + "if ((QString)name == (QString)\"" + v.name + "\")"); // Experimental: Access members directly using 'foo.x_' and 'foo.x_ptr'. if (v.isStatic) { //tw.Write(Indent(2) + "if (name_ == \"" + v.name + "\")"); //tw.WriteLine(" return TypeToQScriptValue(engine(), This->" + v.name + ");"); } else { tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_\")"); tw.WriteLine(" return TypeToQScriptValue(engine(), This->" + v.name + ");"); if (!Symbol.IsPODType(v.type)) { tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_ptr\")"); tw.WriteLine(" return TypeToQScriptValue(engine(), &This->" + v.name + ");"); } } } tw.WriteLine(Indent(2) + "return QScriptValue();"); tw.WriteLine(Indent(1) + "}"); tw.WriteLine(Indent(1) + "void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value)"); tw.WriteLine(Indent(1) + "{"); tw.WriteLine(Indent(2) + Class.name + " *This = TypeFromQScriptValue<" + Class.name + "*>(object);"); tw.WriteLine(Indent(2) + "if (!This) { printf(\"Error! Cannot convert QScriptValue to type " + Class.name + " in file %s, line %d!\\nTry using " + Class.name + ".get%s() and " + Class.name + ".set%s() to query the member variable '%s'!\\n\", __FILE__, __LINE__, Capitalize((QString)name).c_str(), Capitalize((QString)name).c_str(), ((QString)name).toStdString().c_str()); return; }"); tw.WriteLine(Indent(2) + "QString name_ = (QString)name;"); foreach (Symbol v in Class.children) if (v.kind == "variable" && IsScriptable(v) && !v.IsConst() && v.visibilityLevel == VisibilityLevel.Public) { // tw.Write(Indent(2) + "if (name_ == (QString)\"" + v.name + "\")"); // tw.WriteLine(" This->" + v.name + " = TypeFromQScriptValue<" + v.type + ">(value);"); // Experimental: Access members directly using 'foo.x_' and 'foo.x_ptr'. if (v.isStatic) { //tw.Write(Indent(2) + "if (name_ == \"" + v.name + "\")"); // tw.WriteLine(" This->" + v.name + " = TypeFromQScriptValue<" + v.type + ">(value);"); } else { tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_\")"); tw.WriteLine(" This->" + v.name + " = TypeFromQScriptValue<" + v.type + ">(value);"); if (!Symbol.IsPODType(v.type)) { tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_ptr\")"); tw.WriteLine(" This->" + v.name + " = *TypeFromQScriptValue<" + v.type + "*>(value);"); } } } tw.WriteLine(Indent(1) + "}"); tw.WriteLine(Indent(1) + "QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)"); tw.WriteLine(Indent(1) + "{"); tw.WriteLine(Indent(2) + "QString name_ = (QString)name;"); foreach (Symbol v in Class.children) if (v.kind == "variable" && IsScriptable(v) && v.visibilityLevel == VisibilityLevel.Public) { if (v.isStatic) { //tw.Write(Indent(2) + "if (name_ == \"" + v.name + "\")"); } else { // tw.Write(Indent(2) + "if (name_ == \"" + v.name + "\")"); if (Symbol.IsPODType(v.type)) tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_\")"); else tw.Write(Indent(2) + "if (name_ == \"" + v.name + "_\" || name_ == \"" + v.name + "_ptr\")"); tw.WriteLine(" return flags;"); } // tw.WriteLine(" return flags;"); } tw.WriteLine(Indent(2) + "return 0;"); tw.WriteLine(Indent(1) + "}"); tw.WriteLine(Indent(1) + "QScriptValue prototype() const { return objectPrototype; }"); tw.WriteLine("};"); } */ static void GenerateClassFunction(Symbol function, TextWriter tw) { Symbol Class = function.parent; tw.WriteLine("static QScriptValue " + GetScriptFunctionName(function) + "(QScriptContext *context, QScriptEngine *engine)"); tw.WriteLine("{"); int argIdx = 0; bool isClassCtor = (function.name == Class.name); if (function.name != "toString") // Qt oddities: It seems sometimes the hardcoded toString is called with this as the first argument and not as 'this'. tw.WriteLine(Indent(1) + "if (context->argumentCount() != " + function.parameters.Count + ") { printf(\"Error! Invalid number of arguments passed to function " + GetScriptFunctionName(function) + " in file %s, line %d!\\nExpected " + function.parameters.Count + ", but got %d!\\n\", __FILE__, __LINE__, context->argumentCount()); PrintCallStack(context->backtrace()); return QScriptValue(); }"); // Test that we have a valid this. if (!function.isStatic && !isClassCtor) { // tw.WriteLine(Indent(1) + Class.name + " *This = " + "TypeFromQScriptValue<" + Class.name + "*>(context->thisObject());"); // tw.WriteLine(Indent(1) + Class.name + " *This = " + "qscriptvalue_cast<" + Class.name + "*>(context->thisObject());"); if (function.name == "toString") // Qt oddities: It seems sometimes the hardcoded toString is called with this as the first argument and not as 'this'. { tw.WriteLine(Indent(1) + Class.name + " This;"); tw.WriteLine(Indent(1) + "if (context->argumentCount() > 0) This = qscriptvalue_cast<" + Class.name + ">(context->argument(0)); // Qt oddity (bug?): Sometimes the built-in toString() function doesn't give us this from thisObject, but as the first argument."); tw.WriteLine(Indent(1) + "else This = qscriptvalue_cast<" + Class.name + ">(context->thisObject());"); } else tw.WriteLine(Indent(1) + Class.name + " This = " + "qscriptvalue_cast<" + Class.name + ">(context->thisObject());"); // tw.WriteLine(Indent(1) + "if (!This && context->argumentCount() > 0) This = TypeFromQScriptValue<" + Class.name + "*>(context->argument(0)); // Qt oddity (bug?): Sometimes the built-in toString() function doesn't give us this from thisObject, but as the first argument."); // tw.WriteLine(Indent(1) + "if (!This) { printf(\"Error! Invalid context->thisObject in function " + GetScriptFunctionName(function) + " in file %s, line %d\\n!\", __FILE__, __LINE__); return QScriptValue(); }"); } // Unmarshall all parameters to the function. foreach (Parameter p in function.parameters) tw.WriteLine(Indent(1) + p.BasicType() + " " + p.name + " = qscriptvalue_cast<" + p.BasicType() + ">(context->argument(" + (argIdx++) + "));"); // tw.WriteLine(Indent(1) + p.BasicType() + " " + p.name + " = TypeFromQScriptValue<" + p.BasicType() + ">(context->argument(" + (argIdx++) + "));"); if (isClassCtor) // Is this function a ctor of this class. { if (function.parameters.Count == 0) { bool needInitMemory = false; string initSymbol = ""; // Check if default constructor does not initialize the member variables foreach (string str in function.Comments()) if (str.Contains("default constructor does not initialize") || str.Contains("default ctor does not initialize") || str.Contains("with uninitialized member values")) { needInitMemory = true; break; } foreach (string str in function.notes) if (str.Contains("default constructor does not initialize") || str.Contains("default ctor does not initialize") || str.Contains("with uninitialized member values")) { needInitMemory = true; break; } if (needInitMemory) { // Prefer "identity" initializer if exists (Quat & matrices), otherwise "zero" foreach (Symbol child in Class.children) { if (child.name == "identity" && child.isStatic) { initSymbol = child.name; break; } } if (initSymbol.Length == 0) { foreach (Symbol child in Class.children) { if (child.name == "zero" && child.isStatic) { initSymbol = child.name; break; } } } } if (initSymbol.Length > 0) tw.WriteLine(Indent(1) + Class.name + " ret(" + Class.name + "::" + initSymbol + ");"); else { tw.WriteLine(Indent(1) + Class.name + " ret;"); // Create a new instance of this class, no parameters. if (needInitMemory) tw.WriteLine(Indent(1) + "memset(&ret, 0, sizeof ret);"); } } else tw.Write(Indent(1) + Class.name + " ret("); // Create a new instance of this class, one or more parameters. } else { string instanceName = (function.isStatic ? (Class.name + "::") : "This."); // string instanceName = (function.isStatic ? (Class.name + "::") : "This->"); if (function.type != "void") tw.Write(Indent(1) + function.type + " ret = " + instanceName + function.name + "("); // Make the function call. else tw.Write(Indent(1) + instanceName + function.name + "("); // Make the function call. } for (int i = 0; i < function.parameters.Count; ++i) tw.Write(function.parameters[i].name + (i + 1 < function.parameters.Count ? ", " : "")); if (!isClassCtor || function.parameters.Count > 0) tw.WriteLine(");"); // If the function is non-const, regenerate the proper QScriptValue as the result. if (!function.IsConst() && !function.isStatic && function.name != Class.name) tw.WriteLine(Indent(1) + "ToExistingScriptValue_" + Class.name + "(engine, This, context->thisObject());"); // Return the return value as QScriptValue. if (!isClassCtor) { if (function.type != "void") // tw.WriteLine(Indent(1) + "return TypeToQScriptValue(engine, ret);"); tw.WriteLine(Indent(1) + "return qScriptValueFromValue(engine, ret);"); else tw.WriteLine(Indent(1) + "return QScriptValue();"); } else { // tw.WriteLine(Indent(1) + "return TypeToQScriptValue(engine, ret);"); tw.WriteLine(Indent(1) + "return qScriptValueFromValue(engine, ret);"); } tw.WriteLine("}"); tw.WriteLine(""); }