/// <summary> /// Visits the Class Definition node. /// </summary> /// <param name="node">The node to visit.</param> public override bool VisitClassDefinition(ClassDefinitionNode node) { if (node.ClassInstanceVariableNames == null) return false; if (node.ClassName == null) return false; if (node.ClassVariableNames == null) return false; if (node.IndexedInstanceVariables == null) return false; if (node.InstanceVariableNames == null) return false; if (node.SharedPools == null) return false; if (node.SuperclassName == null) return false; return true; }
public virtual Value evaluate(Context cx, BinaryProgramNode node) { output("<BinaryProgramNode position=\"" + node.pos() + "\">"); indent_Renamed_Field++; if (node.pkgdefs != null) { // for (PackageDefinitionNode n : node.pkgdefs) for (int i = 0, size = node.pkgdefs.size(); i < size; i++) { PackageDefinitionNode n = (PackageDefinitionNode)node.pkgdefs.get_Renamed(i); n.evaluate(cx, this); } } if (node.statements != null) { node.statements.evaluate(cx, this); } if (node.fexprs != null) { // for (FunctionCommonNode n : node.fexprs) for (int i = 0, size = node.fexprs.size(); i < size; i++) { FunctionCommonNode n = (FunctionCommonNode)node.fexprs.get_Renamed(i); n.evaluate(cx, this); } } if (node.clsdefs != null) { // for (FunctionCommonNode n : node.clsdefs) for (int i = 0, size = node.clsdefs.size(); i < size; i++) { ClassDefinitionNode n = (ClassDefinitionNode)node.clsdefs.get_Renamed(i); n.evaluate(cx, this); } } indent_Renamed_Field--; output("</BinaryProgramNode>"); return(null); }
protected override List <AssemblyElement> VisitClassDefinition(ClassDefinitionNode node) { return(new List <AssemblyElement>()); }
protected virtual ClassDefinitionNode ParseClassDefinition() { // TODO : Move constants out of code into a the InterchangeFormatConstants class // TODO : Move error messages out of code into a the InterchangeFormatErrors class // PARSE: <classDefinition> ::= ’Class’ ’named:’ <classNameString> // ’superclass:’ <superclassNameString> // ’indexedInstanceVariables:’ <indexableInstVarType> // ’instanceVariableNames:’ <instanceVariableNames> // ’classVariableNames:’ <classVariableList> // ’sharedPools:’ <poolList> // ’classInstanceVariableNames:’<classInstVariableList> // <elementSeparator> ClassDefinitionNode result = this.CreateClassDefinitionNode(); Token token = this.GetNextTokenxx(); StringToken str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing class name.", token); } str = this.VerifyIdentifierString(str, "Class name not an identifier."); result.ClassName = str; // ’superclass:’ <superclassNameString> token = this.GetNextTokenxx(); KeywordToken cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "superclass:")) { this.ReportParserError("Missing class definition #superclass: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing superclass name.", token); } else if (str.Value.Length != 0) // It's OK to have empry superclass .... Object does { str = this.VerifyIdentifierString(str, "Superclass name not an identifier"); } result.SuperclassName = str; // ’indexedInstanceVariables:’ <indexableInstVarType> token = this.GetNextTokenxx(); cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "indexedInstanceVariables:")) { this.ReportParserError("Missing class definition #indexedInstanceVariables: keyword.", token); } token = this.GetNextTokenxx(); HashedStringToken hstr = token as HashedStringToken; if (hstr == null) { this.ReportParserError(result, "Missing indexed instance variables type.", token); } result.IndexedInstanceVariables = hstr; // ’instanceVariableNames:’ <instanceVariableNames> token = this.GetNextTokenxx(); cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "instanceVariableNames:")) { this.ReportParserError("Missing class definition #instanceVariableNames: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing instance variable names.", token); } str = this.VerifyIdentifierList(str, "Instance variable names list contains non-identifiers."); result.InstanceVariableNames = str; // ’classVariableNames:’ <classVariableList> token = this.GetNextTokenxx(); cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "classVariableNames:")) { this.ReportParserError("Missing class definition #classVariableNames: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing class variable names.", token); } str = this.VerifyIdentifierList(str, "Class variable names list contains non-identifiers."); result.ClassVariableNames = str; // ’sharedPools:’ <poolList> token = this.GetNextTokenxx(); cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "sharedPools:")) { this.ReportParserError("Missing class definition #sharedPools: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing shared pool names.", token); } str = this.VerifyIdentifierList(str, "Shared pool names list contains non-identifiers."); result.SharedPools = str; // ’classInstanceVariableNames:’<classInstVariableList> token = this.GetNextTokenxx(); cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "classInstanceVariableNames:")) { this.ReportParserError("Missing class definition #classInstanceVariableNames: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing class instance variable names.", token); } str = this.VerifyIdentifierList(str, "Class instance variable names list contains non-identifiers."); result.ClassInstanceVariableNames = str; token = this.GetNextTokenxx(); if (!(token is EofToken)) { this.ReportParserError(result, "Unexpected code found after class definition.", token); } return(result); }
private Value evaluate(ClassDefinitionNode node, Context cx, System.String name) { if ((node.name != null) && (node.name.name != null)) { output("<" + name + " name=\"" + node.name.name + "\">"); } else if ((node.cframe != null) && (node.cframe.builder != null)) { output("<" + name + " name=\"" + node.cframe.builder.classname + "\">"); } indent_Renamed_Field++; if (node.attrs != null) { node.attrs.evaluate(cx, this); } if (node.name != null) { node.name.evaluate(cx, this); } if (node.baseclass != null) { node.baseclass.evaluate(cx, this); } if (node.interfaces != null) { node.interfaces.evaluate(cx, this); } if (node.fexprs != null) { for (int i = 0, size = node.fexprs.size(); i < size; i++) { Node fexpr = (Node) node.fexprs.get_Renamed(i); fexpr.evaluate(cx, this); } } if (node.staticfexprs != null) { for (int i = 0, size = node.staticfexprs.size(); i < size; i++) { Node staticfexpr = (Node) node.staticfexprs.get_Renamed(i); staticfexpr.evaluate(cx, this); } } if (node.instanceinits != null) { for (int i = 0, size = node.instanceinits.size(); i < size; i++) { Node instanceinit = (Node) node.instanceinits.get_Renamed(i); instanceinit.evaluate(cx, this); } } if (node.statements != null) { node.statements.evaluate(cx, this); } indent_Renamed_Field--; output("</" + name + ">"); return null; }
public virtual Value evaluate(Context cx, ClassDefinitionNode node) { return evaluate(node, cx, "ClassDefinitionNode"); }
private Value evaluate(ClassDefinitionNode node, Context cx, System.String name) { if ((node.name != null) && (node.name.name != null)) { output("<" + name + " name=\"" + node.name.name + "\">"); } else if ((node.cframe != null) && (node.cframe.builder != null)) { output("<" + name + " name=\"" + node.cframe.builder.classname + "\">"); } indent_Renamed_Field++; if (node.attrs != null) { node.attrs.evaluate(cx, this); } if (node.name != null) { node.name.evaluate(cx, this); } if (node.baseclass != null) { node.baseclass.evaluate(cx, this); } if (node.interfaces != null) { node.interfaces.evaluate(cx, this); } if (node.fexprs != null) { for (int i = 0, size = node.fexprs.size(); i < size; i++) { Node fexpr = (Node)node.fexprs.get_Renamed(i); fexpr.evaluate(cx, this); } } if (node.staticfexprs != null) { for (int i = 0, size = node.staticfexprs.size(); i < size; i++) { Node staticfexpr = (Node)node.staticfexprs.get_Renamed(i); staticfexpr.evaluate(cx, this); } } if (node.instanceinits != null) { for (int i = 0, size = node.instanceinits.size(); i < size; i++) { Node instanceinit = (Node)node.instanceinits.get_Renamed(i); instanceinit.evaluate(cx, this); } } if (node.statements != null) { node.statements.evaluate(cx, this); } indent_Renamed_Field--; output("</" + name + ">"); return(null); }
public virtual Value evaluate(Context cx, ClassDefinitionNode node) { return(evaluate(node, cx, "ClassDefinitionNode")); }
public override void WriteCodeFile(List <Node> nodes) { this.ValidityCheck(nodes); this.WriteCodeLine(@"/* * This file was automatically generated by AutoBind. * Any changes made to this file will be lost when it * is next regenerated. */"); this.WriteCodeLine(); // Get the class node. ClassDefinitionNode cls = (ClassDefinitionNode)(this.GetNodesOfType(nodes, typeof(ClassDefinitionNode))[0]); this.WriteCodeLine("#include \"autobind/types.h\""); this.WriteCodeLine("#include \"autobind/binding/lua.h\""); this.WriteCodeLine("#include \"Object.h\""); this.WriteCodeLine("#include \"" + ClassName.ResolveToHeaderFilename(cls.Class) + "\""); List <Node> imports = this.GetNodesOfType(nodes, typeof(ImportNode)); foreach (Node n in imports) { if (n.Content != cls.Inheritance) { this.WriteCodeLine("#include \"" + ClassName.ResolveToHeaderFilename(n.Content.Trim()) + "\""); } } foreach (Node n in this.GetNodesOfType(nodes, typeof(IncludeNode))) { this.WriteCodeLine("#include " + n.Content.Trim() + ""); } // Search for all methods with multiple definitions. Dictionary <string, int> tempDefDict = new Dictionary <string, int>(); foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (n.AllKeywords.Contains("bound")) { if (tempDefDict.Keys.Contains(n.Name)) { tempDefDict[n.Name] += 1; } else { tempDefDict.Add(n.Name, 1); } } } List <string> duplicates = new List <string>(); foreach (string k in tempDefDict.Keys) { if (tempDefDict[k] > 1) { duplicates.Add(k); } } // If there are any duplicates, we need to include ArgumentCountMismatchException. if (duplicates.Count > 0) { this.WriteCodeLine("#include \"ArgumentCountMismatchException.h\""); } this.WriteCodeLine(); // All of the import declarations will have been made in the header file, // so they aren't needed here. // All of the using declarations will have been made in the header file, // so they aren't needed here. // Begin defining the class. string[] clscomponents = cls.Class.Split('.'); for (int i = 0; i < clscomponents.Length; i++) { if (i < clscomponents.Length - 2) { this.WriteCode("namespace " + clscomponents[i] + " { "); } else if (i == clscomponents.Length - 2) { this.WriteCode("namespace " + clscomponents[i]); } else { this.WriteCodeLine(); this.WriteCodeLine("{"); } } // Search for all methods used by properties. List <string> propertyMethods = new List <string>(); foreach (ClassPropertyDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassPropertyDeclarationNode))) { if (n.GetIsFunc) { propertyMethods.Add(n.GetVal); } if (n.SetIsFunc) { propertyMethods.Add(n.SetVal); } } // Declare all of the static variables which are assigned within the class. this.WriteCodeLine(" /* Variable assignments */"); foreach (ClassVariableDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassVariableDeclarationNode))) { if (n.CPPKeywords.Contains("static")) { string keys = ""; foreach (string k in n.CPPKeywords) { if (!Keywords.CPPVisibilityKeywords.Contains(k) && !Keywords.CPPStripKeywords.Contains(k)) { keys += k + " "; } } if (n.Assign == "") { this.WriteCodeLine(" " + keys + n.Type + " " + cls.ClassOnly + "::" + n.Name + ";"); } else { this.WriteCodeLine(" " + keys + n.Type + " " + cls.ClassOnly + "::" + n.Name + " = " + n.Assign + ";"); } } } this.WriteCodeLine(); // Declare the methods that are in the class. this.WriteCodeLine(" /* Method and constructor definitions */"); List <string> fdefs = new List <string>(); bool funccontent = false; bool funcbound = false; string functype = ""; string funcname = ""; bool unbound = false; foreach (Node r in nodes) { if (r is ClassFunctionDeclarationNode) { //this.WriteCodeLine("#line " + r.LineNumber + " \"" + r.FileName.Replace("\\", "\\\\") + "\""); ClassFunctionDeclarationNode n = (ClassFunctionDeclarationNode)r; string keys = ""; functype = n.Type; funcname = n.Name; unbound = false; foreach (string k in n.CPPKeywords) { if (!Keywords.CPPVisibilityKeywords.Contains(k) && !Keywords.CPPStripKeywords.Contains(k)) { if (!Keywords.CPPTypeKeywords.Contains(k) && !Keywords.LuaTypeKeywords.Contains(k)) { keys += k + " "; } if (Keywords.CPPTypeKeywords.Contains(k) || Keywords.LuaTypeKeywords.Contains(k)) { if (functype == "") { functype = k; } } } } if (duplicates.Contains(funcname) && (n.AllKeywords.Contains("bound") || n.Name == clscomponents[clscomponents.Length - 1])) { // Change the name to a unique identifier. string args = ""; foreach (string a in n.Arguments) { if (a.Trim().Length > 0 && a.Trim().IndexOf(' ') != -1) { string _a = a.Trim().Substring(0, a.Trim().IndexOf(' ')); args += "_" + _a.Replace(":", "_"); } } funcname = "__" + n.Name + args; // Ensure this function is no longer bounded (as we'll // have an automatically created function which dispatches // to the unique functions based on the arguments passed). if (n.AllKeywords.Contains("bound")) { unbound = true; } // Ensure there is a default type of void, in case this // function is a constructor. if (functype == "") { functype = "void"; } } string def = ""; if ((n.AllKeywords.Contains("bound") && !unbound) || propertyMethods.Contains(n.Name) || duplicates.Contains(n.Name)) { if (funcname == clscomponents[clscomponents.Length - 1]) // Constructor { def = keys + cls.ClassOnly + "::" + funcname + "(lua_State * L, bool byuser)"; } else if (n.Name == clscomponents[clscomponents.Length - 1] && duplicates.Contains(n.Name)) // Dispatched Constructor { def = keys + "void " + cls.ClassOnly + "::" + funcname + "(lua_State * L, bool byuser)"; } else { def = keys + "int " + cls.ClassOnly + "::" + funcname + "(lua_State * L)"; } } else { string args = ""; foreach (string a in n.Arguments) { args += a + ", "; } if (args != "") { args = args.Substring(0, args.Length - 2); } Regex re = new Regex("\\[[^\\]]", RegexOptions.Multiline); args = re.Replace(args, ""); if (funcname == cls.ClassOnly) { if (keys.Trim().Length > 0) { keys = keys.Trim() + " "; } def = keys + cls.ClassOnly + "::" + funcname + "(" + args + ")"; } else { def = keys + functype + " " + cls.ClassOnly + "::" + funcname + "(" + args + ")"; } } if (!fdefs.Contains(def)) { this.WriteCodeLine(" " + def); this.WriteCodeLine(" {"); // Add the argument bindings. if ((n.AllKeywords.Contains("bound") && !unbound) || propertyMethods.Contains(n.Name) || duplicates.Contains(n.Name)) { int ai = 1; if (propertyMethods.Contains(n.Name)) { ai = -1; } foreach (string a in n.Arguments) { Regex ar = new Regex("(?<Type>[a-zA-Z0-9_\\.\\:]+)[ \r\n\t]+(?<Name>[a-zA-Z0-9_\\.]+)([ \r\n\t]+\\[(?<Default>[^\\]]+)\\])?"); Match m = ar.Match(a); if (m.Success) { string type = m.Groups["Type"].Value; string name = m.Groups["Name"].Value; string defv = ""; if (m.Groups["Default"].Success) { defv = ", " + m.Groups["Default"].Value; } if (Keywords.LuaTypeKeywords.Contains(type) || type == "bool") { this.WriteCodeLine(" " + type + " " + name + " = Bindings<" + type + ">::GetArgumentBase(L, " + ai + "" + defv + ");"); } else { this.WriteCodeLine(" " + type + " * " + name + " = Bindings<" + type + ">::GetArgument(L, " + ai + "" + defv + ");"); } if (!propertyMethods.Contains(n.Name)) { ai += 1; } } } if (ai != 1) { this.WriteCodeLine(); } } funcbound = ((n.AllKeywords.Contains("bound") && !unbound) || propertyMethods.Contains(n.Name) || duplicates.Contains(n.Name)); funccontent = true; } fdefs.Add(def); } else if (r is DirectNode && funccontent) { // Search the content for any return statements, and use a Regex to // replace them with the appropriate bindings. if (funcbound) { string res = null; if (functype != "variant") { Regex rr = new Regex("^([ \r\n\t]*)([^\\/][^\\/])([^/\n]*)([ \r\n\t]+)return[ \r\n\t]+(?<Val>[^\\;]+)\\;", RegexOptions.Multiline); res = rr.Replace(r.Content, (match) => { if (match.Groups["Val"].Value.StartsWith("Bindings<")) { return(match.Value); } else { return(String.Format( "{0}{1}{2}{3}return Bindings<" + functype + ">::Result(L, {4});", match.Groups[1].Value, match.Groups[2].Value, match.Groups[3].Value, match.Groups[4].Value, match.Groups["Val"].Value )); } } ); Regex brr = new Regex("([ \r\n\t]*)([^\\/][^\\/])([^/\n]*)([ \r\n\t]+)return[ \r\n\t]*\\;", RegexOptions.Multiline); res = brr.Replace(res, "${1}${2}${3}${4}return Bindings<void*>::EmptyResult;"); } else { res = r.Content; } this.WriteCodeLine(" " + res.TrimStart().TrimEnd('\n')); string cc = res.TrimStart().TrimEnd('\n'); if (cc.LastIndexOf("///") != -1 && !cc.Substring(cc.LastIndexOf("///"), 0).Contains('\n')) { // There's a doc-comment on the last line, so we don't want // to call this.WriteCodeLine() as it will seperate it from // the function definition. } else { this.WriteCodeLine(); } } else { this.WriteCodeLine(" " + r.Content.TrimStart().TrimEnd('\n')); string cc = r.Content.TrimStart().TrimEnd('\n'); if (cc.LastIndexOf("///") != -1 && !cc.Substring(cc.LastIndexOf("///"), 0).Contains('\n')) { // There's a doc-comment on the last line, so we don't want // to call this.WriteCodeLine() as it will seperate it from // the function definition. } else { this.WriteCodeLine(); } } funcbound = false; funccontent = false; } } // Declare any dispatchers for overloaded methods. this.WriteCodeLine(" /* Automatic dispatchers for overloaded methods */"); foreach (string d in duplicates) { if (d == clscomponents[clscomponents.Length - 1]) { this.WriteCodeLine(" " + cls.ClassOnly + "::" + d + "(lua_State * L, bool byuser)"); this.WriteCodeLine(" {"); string elsestmt = ""; foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (n.Name != d) { continue; } // Change the name to a unique identifier. string functname = n.Name; string args = ""; foreach (string a in n.Arguments) { if (a.Trim().Length > 0 && a.Trim().IndexOf(' ') != -1) { string _a = a.Trim().Substring(0, a.Trim().IndexOf(' ')); args += "_" + _a.Replace(":", "_"); } } functname = "__" + n.Name + args; if (n.Arguments.Count == 0 || n.Arguments[0] == "") { this.WriteCodeLine(" " + elsestmt + "if (lua_gettop(L) == 0 || !byuser)"); this.WriteCodeLine(" {"); this.WriteCodeLine(" this->" + functname + "(L, byuser);"); this.WriteCodeLine(" }"); } else { this.WriteCodeLine(" " + elsestmt + "if (lua_gettop(L) == " + n.Arguments.Count + " &&"); int ai = 1; foreach (string a in n.Arguments) { string t = a.Trim().Substring(0, a.Trim().IndexOf(' ')); string andd = " &&"; if (ai == n.Arguments.Count) { andd = ")"; } if (Keywords.LuaTypeKeywords.Contains(t) || t == "bool") { this.WriteCodeLine(" Bindings<" + t + ">::IsArgumentBase(L, " + ai + ")" + andd); } else { this.WriteCodeLine(" Bindings<" + t + ">::IsArgument(L, " + ai + ")" + andd); } ai += 1; } this.WriteCodeLine(" {"); this.WriteCodeLine(" this->" + functname + "(L, byuser);"); this.WriteCodeLine(" }"); } if (elsestmt == "") { elsestmt = "else "; } } this.WriteCodeLine(" else"); this.WriteCodeLine(" throw new Engine::ArgumentCountMismatchException();"); this.WriteCodeLine(" }"); this.WriteCodeLine(); } else { this.WriteCodeLine(" int " + cls.ClassOnly + "::" + d + "(lua_State * L)"); this.WriteCodeLine(" {"); string elsestmt = ""; foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (n.Name != d) { continue; } // Change the name to a unique identifier. string functname = n.Name; string args = ""; foreach (string a in n.Arguments) { if (a.Trim().Length > 0 && a.Trim().IndexOf(' ') != -1) { string _a = a.Trim().Substring(0, a.Trim().IndexOf(' ')); args += "_" + _a.Replace(":", "_"); } } functname = "__" + n.Name + args; if (n.Arguments.Count == 0 || n.Arguments[0] == "") { this.WriteCodeLine(" " + elsestmt + "if (lua_gettop(L) == 0)"); this.WriteCodeLine(" {"); this.WriteCodeLine(" return this->" + functname + "(L);"); this.WriteCodeLine(" }"); } else { this.WriteCodeLine(" " + elsestmt + "if (lua_gettop(L) == " + n.Arguments.Count + " &&"); int ai = 1; foreach (string a in n.Arguments) { string t = a.Trim().Substring(0, a.Trim().IndexOf(' ')); string andd = " &&"; if (ai == n.Arguments.Count) { andd = ")"; } if (Keywords.LuaTypeKeywords.Contains(t) || t == "bool") { this.WriteCodeLine(" Bindings<" + t + ">::IsArgumentBase(L, " + ai + ")" + andd); } else { this.WriteCodeLine(" Bindings<" + t + ">::IsArgument(L, " + ai + ")" + andd); } ai += 1; } this.WriteCodeLine(" {"); this.WriteCodeLine(" return this->" + functname + "(L);"); this.WriteCodeLine(" }"); } if (elsestmt == "") { elsestmt = "else "; } } this.WriteCodeLine(" else"); this.WriteCodeLine(" throw new Engine::ArgumentCountMismatchException();"); this.WriteCodeLine(" }"); this.WriteCodeLine(); } } this.WriteHeaderLine(); // Declare automatically generated methods for setting / getting properties. this.WriteCodeLine(" /* Automatic property getter-setter definitions */"); foreach (ClassPropertyDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassPropertyDeclarationNode))) { if (n.GetVal != null && !n.GetIsFunc) { this.WriteCodeLine(" int " + cls.ClassOnly + "::__autobind_property_get_" + n.Name + "(lua_State * L)"); this.WriteCodeLine(" {"); this.WriteCodeLine(" return Bindings<numeric>::Result(L, " + n.GetVal + ");"); this.WriteCodeLine(" }"); this.WriteCodeLine(); } if (n.SetVal != null && !n.SetIsFunc) { this.WriteCodeLine(" int " + cls.ClassOnly + "::__autobind_property_set_" + n.Name + "(lua_State * L)"); this.WriteCodeLine(" {"); this.WriteCodeLine(" " + n.SetVal + " = Bindings<numeric>::GetArgument(L, -1);"); this.WriteCodeLine(" return Bindings<numeric>::EmptyResult;"); this.WriteCodeLine(" }"); this.WriteCodeLine(); } } // Write the definitions of the Binding variables. this.WriteCodeLine(" /* Binding variables */"); if (cls.Alias != "") { this.WriteCodeLine(" const char* " + cls.ClassOnly + "::ClassName = \"" + cls.Alias + "\";"); } else { this.WriteCodeLine(" const char* " + cls.ClassOnly + "::ClassName = \"" + cls.Class + "\";"); } this.WriteCodeLine(" const char* " + cls.ClassOnly + "::Inherits = \"" + cls.Inheritance + "\";"); this.WriteCodeLine(" const Bindings<" + cls.ClassOnly + ">::FunctionType " + cls.ClassOnly + "::Functions[] ="); this.WriteCodeLine(" {"); foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (n.AllKeywords.Contains("bound") && n.Name != clscomponents[clscomponents.Length - 1]) { this.WriteCodeLine(" {\"" + n.Name + "\", &" + cls.ClassOnly + "::" + n.Name + "},"); } } this.WriteCodeLine(" {0}"); this.WriteCodeLine(" };"); this.WriteCodeLine(" const Bindings<" + cls.ClassOnly + ">::PropertyType " + cls.ClassOnly + "::Properties[] ="); this.WriteCodeLine(" {"); foreach (ClassPropertyDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassPropertyDeclarationNode))) { if (n.AllKeywords.Contains("bound")) { string setfunc = ""; string getfunc = ""; if (n.SetIsFunc) { setfunc = n.SetVal; } else { setfunc = "__autobind_property_set_" + n.Name; } if (n.GetIsFunc) { getfunc = n.GetVal; } else { getfunc = "__autobind_property_get_" + n.Name; } if (setfunc == null) // Check for read-only properties. { this.WriteCodeLine(" {\"" + n.Name + "\", &" + cls.ClassOnly + "::" + getfunc + ", NULL},"); } else { this.WriteCodeLine(" {\"" + n.Name + "\", &" + cls.ClassOnly + "::" + getfunc + ", &" + cls.ClassOnly + "::" + setfunc + "},"); } } } this.WriteCodeLine(" {0}"); this.WriteCodeLine(" };"); this.WriteCodeLine(" int (__cdecl *" + cls.ClassOnly + "::Dispatcher)(lua_State * L) = &(Bindings<" + cls.ClassOnly + ">::FunctionDispatch);"); // End the definition of the class. for (int i = 0; i < clscomponents.Length - 1; i++) { this.WriteCodeLine("} "); } this.WriteCodeLine(); }
public override void WriteHeaderFile(List <Node> nodes) { this.ValidityCheck(nodes); this.WriteHeaderLine(@"/* * This file was automatically generated by AutoBind. * Any changes made to this file will be lost when it * is next regenerated. */"); this.WriteHeaderLine(); // Get the class node. ClassDefinitionNode cls = (ClassDefinitionNode)(this.GetNodesOfType(nodes, typeof(ClassDefinitionNode))[0]); if (cls.Alias == "") { Console.Write(cls.Class); } else { Console.Write(cls.Alias); } this.WriteHeaderLine("#ifndef CLASS_" + cls.Class.Replace('.', '_')); this.WriteHeaderLine("#define CLASS_" + cls.Class.Replace('.', '_')); this.WriteHeaderLine(); // Get all of the import nodes and convert them to // #includes. We also predeclare any of the classes // we are importing since it's not feasable to detect // what classes reference what other classes. List <Node> imports = this.GetNodesOfType(nodes, typeof(ImportNode)); this.WriteHeaderLine("/* Imports */"); this.WriteHeaderLine("class Object;"); foreach (Node n in imports) { string[] components = n.Content.Split('.'); for (int i = 0; i < components.Length; i++) { if (i != components.Length - 1) { this.WriteHeader("namespace " + components[i] + " { "); } else { this.WriteHeader("class " + components[i] + "; "); } } for (int i = 0; i < components.Length - 1; i++) { this.WriteHeader("} "); } this.WriteHeaderLine(); } this.WriteHeaderLine("#include \"Object.h\""); foreach (Node n in imports) { if (n.Content == cls.Inheritance) { this.WriteHeaderLine("#include \"" + ClassName.ResolveToHeaderFilename(n.Content.Trim()) + "\""); } } foreach (Node n in this.GetNodesOfType(nodes, typeof(IncludeNode))) { this.WriteHeaderLine("#include " + n.Content.Trim() + ""); } this.WriteHeaderLine(); // Now add all of the using declarations. this.WriteHeaderLine("/* Using declarations */"); foreach (Node n in this.GetNodesOfType(nodes, typeof(UsingNode))) { this.WriteHeaderLine("using " + n.Content.Replace(".", "::") + ";"); } this.WriteHeaderLine(); // Begin declaring the class. string[] clscomponents = cls.Class.Split('.'); for (int i = 0; i < clscomponents.Length; i++) { if (i < clscomponents.Length - 2) { this.WriteHeader("namespace " + clscomponents[i] + " { "); } else if (i == clscomponents.Length - 2) { this.WriteHeader("namespace " + clscomponents[i]); } else { this.WriteHeaderLine(); this.WriteHeaderLine("{"); this.WriteHeaderLine(" /* Begin class declaration */"); this.WriteHeaderLine(" class " + clscomponents[i] + " : public " + cls.Inheritance.Replace(".", "::")); this.WriteHeaderLine(" {"); } } // Declare all of the variables within the class. this.WriteHeaderLine(" /* Variable declarations */"); foreach (ClassVariableDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassVariableDeclarationNode))) { string keys = ""; string visibility = "private"; foreach (string k in n.CPPKeywords) { if (Keywords.CPPVisibilityKeywords.Contains(k)) { visibility = k; } else { keys += k + " "; } } this.WriteHeaderLine(" " + visibility + ": " + keys + n.Type + " " + n.Name + ";"); } this.WriteHeaderLine(); // Search for all methods used by properties. List <string> propertyMethods = new List <string>(); foreach (ClassPropertyDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassPropertyDeclarationNode))) { if (n.GetIsFunc) { propertyMethods.Add(n.GetVal); } if (n.SetIsFunc) { propertyMethods.Add(n.SetVal); } } // Search for all methods with multiple definitions. Dictionary <string, int> tempDefDict = new Dictionary <string, int>(); foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (n.AllKeywords.Contains("bound")) { if (tempDefDict.Keys.Contains(n.Name)) { tempDefDict[n.Name] += 1; } else { tempDefDict.Add(n.Name, 1); } } } List <string> duplicates = new List <string>(); foreach (string k in tempDefDict.Keys) { if (tempDefDict[k] > 1) { duplicates.Add(k); } } // Declare the methods that are in the class. this.WriteHeaderLine(" /* Method and constructor declarations */"); List <string> fdecls = new List <string>(); foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { string keys = ""; string visibility = "private"; string functype = n.Type; string funcname = n.Name; bool unbound = false; foreach (string k in n.CPPKeywords) { if (!Keywords.CPPTypeKeywords.Contains(k) && !Keywords.LuaTypeKeywords.Contains(k)) { if (Keywords.CPPVisibilityKeywords.Contains(k)) { visibility = k; } else { keys += k + " "; } } else if (!n.AllKeywords.Contains("bound") && functype == "") { functype = k; } } if (duplicates.Contains(funcname) && (n.AllKeywords.Contains("bound") || n.Name == clscomponents[clscomponents.Length - 1])) { // Change the name to a unique identifier. string args = ""; foreach (string a in n.Arguments) { if (a.Trim().Length > 0 && a.Trim().IndexOf(' ') != -1) { string _a = a.Trim().Substring(0, a.Trim().IndexOf(' ')); args += "_" + _a.Replace(":", "_"); } } funcname = "__" + n.Name + args; // Ensure this function is no longer bounded (as we'll // have an automatically created function which dispatches // to the unique functions based on the arguments passed). if (n.AllKeywords.Contains("bound")) { unbound = true; } // Ensure there is a default type of void, in case this // function is a constructor. if (functype == "") { functype = "void"; } } string decl = ""; if ((n.AllKeywords.Contains("bound") && !unbound) || propertyMethods.Contains(n.Name) || duplicates.Contains(n.Name)) { if (funcname == clscomponents[clscomponents.Length - 1]) // Constructor { decl = visibility + ": " + keys + funcname + "(lua_State * L, bool byuser);"; } else if (n.Name == clscomponents[clscomponents.Length - 1] && duplicates.Contains(n.Name)) // Dispatched Constructor { decl = visibility + ": " + keys + "void " + funcname + "(lua_State * L, bool byuser);"; } else if (n.AllKeywords.Contains("bound") || propertyMethods.Contains(n.Name) || duplicates.Contains(n.Name)) { decl = visibility + ": " + keys + "int " + funcname + "(lua_State * L);"; } } else { string args = ""; foreach (string a in n.Arguments) { args += a + ", "; } if (args != "") { args = args.Substring(0, args.Length - 2); } Regex r = new Regex("\\[[^\\]]", RegexOptions.Multiline); args = r.Replace(args, "= $1"); if (funcname == cls.ClassOnly) { if (keys.Trim().Length > 0) { keys = keys.Trim() + " "; } decl = visibility + ": " + keys + funcname + "(" + args + ");"; } else { decl = visibility + ": " + keys + functype + " " + funcname + "(" + args + ");"; } } if (!fdecls.Contains(decl)) { this.WriteHeaderLine(" " + decl); } fdecls.Add(decl); } this.WriteHeaderLine(); // Declare any dispatchers for overloaded methods. this.WriteHeaderLine(" /* Automatic dispatchers for overloaded methods */"); List <string> fddecls = new List <string>(); foreach (ClassFunctionDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassFunctionDeclarationNode))) { if (duplicates.Contains(n.Name) && (n.AllKeywords.Contains("bound") || n.Name == clscomponents[clscomponents.Length - 1])) { string keys = ""; string decl = ""; foreach (string k in n.CPPKeywords) { if (!Keywords.CPPTypeKeywords.Contains(k) && !Keywords.LuaTypeKeywords.Contains(k)) { if (!Keywords.CPPVisibilityKeywords.Contains(k)) { keys += k + " "; } } } if (n.Name == clscomponents[clscomponents.Length - 1]) // Constructor { decl = "public: " + keys + n.Name + "(lua_State * L, bool byuser);"; } else { decl = "public: " + keys + "int " + n.Name + "(lua_State * L);"; } if (!fddecls.Contains(decl)) { this.WriteHeaderLine(" " + decl); } fddecls.Add(decl); } } this.WriteHeaderLine(); // Declare automatically generated methods for setting / getting properties. this.WriteHeaderLine(" /* Automatic property getter-setter declarations */"); foreach (ClassPropertyDeclarationNode n in this.GetNodesOfType(nodes, typeof(ClassPropertyDeclarationNode))) { if (n.GetVal != null && !n.GetIsFunc) { this.WriteHeaderLine(" private: int __autobind_property_get_" + n.Name + "(lua_State * L);"); } if (n.SetVal != null && !n.SetIsFunc) { this.WriteHeaderLine(" private: int __autobind_property_set_" + n.Name + "(lua_State * L);"); } } this.WriteHeaderLine(); // Write the declarations of the Binding variables. this.WriteHeaderLine(" /* Binding variables */"); this.WriteHeaderLine(" public: static const char *ClassName;"); this.WriteHeaderLine(" public: static const char *Inherits;"); this.WriteHeaderLine(" public: static const Bindings<" + cls.ClassOnly + ">::FunctionType Functions[];"); this.WriteHeaderLine(" public: static const Bindings<" + cls.ClassOnly + ">::PropertyType Properties[];"); this.WriteHeaderLine(" public: static int (__cdecl *Dispatcher)(lua_State * L);"); // End the declaration of the class. this.WriteHeaderLine(" };"); for (int i = 0; i < clscomponents.Length - 1; i++) { this.WriteHeaderLine("} "); } this.WriteHeaderLine(); //this.WriteHeaderLine("#pragma message(\"DEFINED " + cls.Class + "...\")"); //this.WriteHeaderLine(); // Add the #endif. this.WriteHeaderLine("#endif"); }
/// <summary> /// Visits the Class Definition node. /// </summary> /// <param name="node">The node to visit.</param> public virtual TResult VisitClassDefinition(ClassDefinitionNode node) { return(default(TResult)); // The default naive implementation }