Browse Source

Generator: begin to support multiple inheritance.

+ Methods/properties from non-primary base classes will be included in subclass wrapper.
+ Add cast operator from subclass to non-primary base class(es).
pull/1/head
Alex Corrado 14 years ago
parent
commit
9ba550bc02
  1. 25
      src/generator/Class.cs
  2. 11
      src/generator/Generator.cs
  3. 61
      src/generator/Method.cs
  4. 7
      src/generator/Node.cs
  5. 14
      src/generator/Property.cs

25
src/generator/Class.cs

@ -173,6 +173,31 @@ class Class @@ -173,6 +173,31 @@ class Class
}
}
// Add all members inherited from non-primary bases
// With the exception of virtual methods that have been overridden, these methods must be called
// thru a cast to the base class that performs a this ptr adjustment
foreach (var baseClass in BaseClasses.Skip (1)) {
foreach (var method in baseClass.Methods) {
if (method.IsConstructor || (method.IsVirtual && Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))))
continue;
if (method.GenWrapperMethod)
decl.Members.Add (method.GenerateInheritedWrapperMethod (g, baseClass));
}
foreach (var prop in baseClass.Properties) {
decl.Members.Add (prop.GenerateInheritedProperty (g, baseClass));
}
// generate implicit cast to base class
// 1. Create field to cache base casts
decl.Members.Add (new CodeMemberField (baseClass.Name, baseClass.Name + "_base"));
// 2. Add op_Implicit
// FIXME: Can't figure out language-neutral way to do this with codedom.. C# only for now
decl.Members.Add (new CodeSnippetTypeMember (string.Format ("public static implicit operator {0}({1} subClass) {{\n\t\t\tif (subClass.{2} == null)\n\t\t\t\tsubClass.{2} = impl.TypeInfo.Cast<{0}>(subClass);\n\t\t\treturn subClass.{2};\n\t\t}}\n\t\t", baseClass.Name, Name, baseClass.Name + "_base")));
}
foreach (Property p in Properties) {
decl.Members.Add (p.GenerateProperty (g));
}

11
src/generator/Generator.cs

@ -224,10 +224,9 @@ public class Generator @@ -224,10 +224,9 @@ public class Generator
continue;
}
if (!n.CheckValue ("access", "public") || (n.HasValue ("overrides") && !dtor))
continue;
if (!n.IsTrue ("extern") && !n.IsTrue ("inline"))
if (!n.CheckValue ("access", "public") || // exclude non-public methods
(!dtor && n.HasValue ("overrides") && klass.BaseClasses [0].Node.CheckValueList ("members", n.Attributes ["overrides"])) || // excl. virtual methods from primary base (except dtor)
(!n.IsTrue ("extern") && !n.IsTrue ("inline")))
continue;
string name = dtor ? "Destruct" : n.Name;
@ -243,7 +242,7 @@ public class Generator @@ -243,7 +242,7 @@ public class Generator
IsDestructor = dtor
};
if (dtor)
if (dtor || method.IsArtificial)
method.GenWrapperMethod = false;
bool skip = false;
@ -477,7 +476,7 @@ public class Generator @@ -477,7 +476,7 @@ public class Generator
Directory.CreateDirectory (OutputDir);
Provider = new CSharpCodeProvider ();
CodeGenOptions = new CodeGeneratorOptions { BlankLinesBetweenMembers = false };
CodeGenOptions = new CodeGeneratorOptions { BlankLinesBetweenMembers = false, IndentString = "\t" };
CodeTypeDeclaration libDecl = null;

61
src/generator/Method.cs

@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
using System.CodeDom;
using System.CodeDom.Compiler;
@ -164,23 +165,22 @@ class Method @@ -164,23 +165,22 @@ class Method
return method;
}
public CodeMemberMethod GenerateWrapperMethod (Generator g) {
public CodeMemberMethod GenerateWrapperDeclaration (Generator g) {
CodeMemberMethod method;
if (IsConstructor)
method = new CodeConstructor () {
Name = GetCSharpMethodName (Name)
};
Name = GetCSharpMethodName (Name)
};
else
method = new CodeMemberMethod () {
Name = GetCSharpMethodName (Name)
};
Name = GetCSharpMethodName (Name)
};
method.Attributes = MemberAttributes.Public;
if (IsStatic)
method.Attributes |= MemberAttributes.Static;
CodeTypeReference rtype = g.CppTypeToCodeDomType (ReturnType);
method.ReturnType = rtype;
method.ReturnType = g.CppTypeToCodeDomType (ReturnType);
foreach (var p in Parameters) {
bool byref;
@ -191,27 +191,58 @@ class Method @@ -191,27 +191,58 @@ class Method
method.Parameters.Add (param);
}
return method;
}
IEnumerable<CodeExpression> GetArgumentExpressions (Generator g) {
for (int i = 0; i < Parameters.Count; ++i) {
bool byref;
g.CppTypeToCodeDomType (Parameters [i].Type, out byref);
CodeExpression arg = new CodeArgumentReferenceExpression (Parameters [i].Name);
if (byref)
arg = new CodeDirectionExpression (FieldDirection.Ref, arg);
yield return arg;
}
yield break;
}
// for methods inherited from non-primary bases
public CodeMemberMethod GenerateInheritedWrapperMethod (Generator g, Class baseClass) {
var method = GenerateWrapperDeclaration (g);
var args = GetArgumentExpressions (g).ToArray ();
var call = new CodeMethodInvokeExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), method.Name, args);
if (method.ReturnType.BaseType == "System.Void")
method.Statements.Add (call);
else
method.Statements.Add (new CodeMethodReturnStatement (call));
return method;
}
public CodeMemberMethod GenerateWrapperMethod (Generator g) {
var method = GenerateWrapperDeclaration (g);
if (IsConstructor) {
//this.native_ptr = impl.Alloc(this);
method.Statements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (null, "native_ptr"), new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Alloc"), new CodeExpression [] { new CodeThisReferenceExpression () })));
}
// Call the iface method
CodeExpression[] args = new CodeExpression [Parameters.Count + (IsStatic ? 0 : 1)];
var args = new CodeExpression [Parameters.Count + (IsStatic ? 0 : 1)];
if (!IsStatic)
args [0] = new CodeFieldReferenceExpression (null, "Native");
for (int i = 0; i < Parameters.Count; ++i) {
bool byref;
g.CppTypeToCodeDomType (Parameters [i].Type, out byref);
CodeExpression arg = new CodeArgumentReferenceExpression (Parameters [i].Name);
if (byref)
arg = new CodeDirectionExpression (FieldDirection.Ref, arg);
var i = 0;
foreach (var arg in GetArgumentExpressions (g)) {
args [i + (IsStatic ? 0 : 1)] = arg;
i++;
}
var call = new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), Name), args);
if (rtype.BaseType == "System.Void" || IsConstructor)
if (method.ReturnType.BaseType == "System.Void" || IsConstructor)
method.Statements.Add (call);
else
method.Statements.Add (new CodeMethodReturnStatement (call));

7
src/generator/Node.cs

@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
@ -85,6 +86,10 @@ class Node { @@ -85,6 +86,10 @@ class Node {
}
public bool CheckValue (string key, string name) {
return Attributes.ContainsKey (key) && Attributes[key] == name;
return Attributes.ContainsKey (key) && Attributes[key].Trim () == name.Trim ();
}
public bool CheckValueList (string key, string name) {
return Attributes.ContainsKey (key) && Attributes[key].Split (' ').Contains (name.Trim ());
}
}

14
src/generator/Property.cs

@ -62,7 +62,19 @@ class Property @@ -62,7 +62,19 @@ class Property
p.GetStatements.Add (new CodeMethodReturnStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), GetMethod.Name), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native") })));
}
if (SetMethod != null) {
p.SetStatements.Add (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), SetMethod.Name), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native"), new CodeArgumentReferenceExpression ("value") }));
p.SetStatements.Add (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), SetMethod.Name), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native"), new CodePropertySetValueReferenceExpression () }));
}
return p;
}
public CodeMemberProperty GenerateInheritedProperty (Generator g, Class baseClass) {
var p = new CodeMemberProperty () { Name = Name, Attributes = MemberAttributes.Public|MemberAttributes.Final };
p.Type = g.CppTypeToCodeDomType (Type);
if (GetMethod != null) {
p.GetStatements.Add (new CodeMethodReturnStatement (new CodePropertyReferenceExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), GetMethod.Name)));
}
if (SetMethod != null) {
p.SetStatements.Add (new CodeAssignStatement (new CodePropertyReferenceExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), SetMethod.Name), new CodePropertySetValueReferenceExpression ()));
}
return p;
}

Loading…
Cancel
Save