Fix generator problems exposed by qt.

This commit is contained in:
Zoltan Varga 2011-02-28 19:54:48 +01:00 коммит произвёл Andreia Gaita
Родитель 344debf842
Коммит f295c467fe
3 изменённых файлов: 153 добавлений и 40 удалений

Просмотреть файл

@ -12,6 +12,7 @@ class Class
{
public Class (Node n) {
Node = n;
BaseClasses = new List<Class> ();
Methods = new List<Method> ();
Fields = new List<Field> ();
}
@ -26,6 +27,10 @@ class Class
}
}
public List<Class> BaseClasses {
get; set;
}
public List<Method> Methods {
get; set;
}
@ -34,11 +39,19 @@ class Class
get; set;
}
public CodeTypeDeclaration GenerateClass (Generator g, CodeTypeDeclaration libDecl) {
public bool Disable {
get; set;
}
public CodeTypeDeclaration GenerateClass (Generator g, CodeTypeDeclaration libDecl, string libFieldName) {
var decl = new CodeTypeDeclaration (Name);
decl.IsPartial = true;
// FIXME: Inheritance
decl.BaseTypes.Add (new CodeTypeReference ("ICppObject"));
if (BaseClasses.Count > 0)
decl.BaseTypes.Add (new CodeTypeReference (BaseClasses [0].Name));
else
decl.BaseTypes.Add (new CodeTypeReference ("ICppObject"));
bool hasBase = BaseClasses.Count > 0;
var layout = new CodeTypeDeclaration ("_" + Name);
layout.IsStruct = true;
@ -63,34 +76,47 @@ class Class
var implField = new CodeMemberField (new CodeTypeReference (iface.Name), "impl");
implField.Attributes = MemberAttributes.Private|MemberAttributes.Static;
var getclass = new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (libDecl.Name), "Test"), "GetClass", new CodeTypeReference [] { new CodeTypeReference (iface.Name), new CodeTypeReference (layout.Name), new CodeTypeReference (decl.Name) });
var getclass = new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (libDecl.Name), libFieldName), "GetClass", new CodeTypeReference [] { new CodeTypeReference (iface.Name), new CodeTypeReference (layout.Name), new CodeTypeReference (decl.Name) });
implField.InitExpression = new CodeMethodInvokeExpression (getclass, new CodeExpression [] { new CodePrimitiveExpression (Name) });
decl.Members.Add (implField);
//private static IClass impl = global::CppTests.Libs.Test.GetClass <IClass, _Class, Class>("Class");
var ptrField = new CodeMemberField (new CodeTypeReference ("CppInstancePtr"), "native_ptr");
ptrField.Attributes = MemberAttributes.Family;
decl.Members.Add (ptrField);
if (!hasBase) {
var ptrField = new CodeMemberField (new CodeTypeReference ("CppInstancePtr"), "native_ptr");
ptrField.Attributes = MemberAttributes.Family;
decl.Members.Add (ptrField);
}
var allocCtor = new CodeConstructor () {
};
allocCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppLibrary"), "dummy"));
allocCtor.Statements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (null, "native_ptr"), new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Alloc"), new CodeExpression [] { new CodeThisReferenceExpression () })));
if (hasBase) {
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo");
allocCtor.BaseConstructorArgs.Add (implTypeInfo);
}
decl.Members.Add (allocCtor);
var subclassCtor = new CodeConstructor () {
Attributes = MemberAttributes.Family
};
subclassCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppTypeInfo"), "subClass"));
subclassCtor.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeArgumentReferenceExpression ("subClass"), "AddBase"), new CodeExpression [] { new CodeFieldReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "TypeInfo") })));
if (hasBase) {
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo");
subclassCtor.BaseConstructorArgs.Add (implTypeInfo);
}
decl.Members.Add (subclassCtor);
var nativeProperty = new CodeMemberProperty () {
Name = "Native",
Type = new CodeTypeReference ("CppInstancePtr"),
Attributes = MemberAttributes.Public|MemberAttributes.Final
};
nativeProperty.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "native_ptr")));
decl.Members.Add (nativeProperty);
if (!hasBase) {
var nativeProperty = new CodeMemberProperty () {
Name = "Native",
Type = new CodeTypeReference ("CppInstancePtr"),
Attributes = MemberAttributes.Public|MemberAttributes.Final
};
nativeProperty.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "native_ptr")));
decl.Members.Add (nativeProperty);
}
var disposeMethod = new CodeMemberMethod () {
Name = "Dispose",
@ -103,7 +129,13 @@ class Class
foreach (Method m in Methods) {
iface.Members.Add (m.GenerateIFaceMethod (g));
decl.Members.Add (m.GenerateWrapperMethod (g));
var cm = m.GenerateWrapperMethod (g);
if (m.IsConstructor && hasBase) {
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo");
(cm as CodeConstructor).BaseConstructorArgs.Add (implTypeInfo);
}
decl.Members.Add (cm);
}
return decl;

Просмотреть файл

@ -171,9 +171,9 @@ public class Generator
// Compute bases
foreach (Class klass in classes) {
foreach (Node bn in klass.Node.Children.Where (o => o.Type == "Base")) {
//Class baseClass = nodeToClass [bn.NodeForAttr ("type")];
throw new NotImplementedException ();
foreach (Node bn in klass.Node.Children.Where (o => o.Type == "Base")) {
Class baseClass = NodeToClass [bn.NodeForAttr ("type")];
klass.BaseClasses.Add (baseClass);
}
}
@ -202,6 +202,9 @@ public class Generator
fieldName = n.Name;
else
fieldName = "field" + fieldCount++;
if (CppTypeToCodeDomType (fieldType) == null)
// FIXME: Assume IntPtr
fieldType = ((CppType)CppTypes.Void).Modify (CppModifiers.Pointer);
klass.Fields.Add (new Field (fieldName, fieldType));
break;
case "Constructor":
@ -222,7 +225,6 @@ public class Generator
if (!n.IsTrue ("extern") && !n.IsTrue ("inline"))
continue;
// FIXME: Casing
string name = dtor ? "Destruct" : n.Name;
var method = new Method (n) {
@ -236,17 +238,22 @@ public class Generator
IsDestructor = dtor
};
bool skip = false;
CppType retType;
if (n.HasValue ("returns"))
retType = GetType (n.NodeForAttr ("returns"));
else
retType = CppTypes.Void;
if (retType.ElementType == CppTypes.Unknown)
throw new NotImplementedException ();
skip = true;
if (CppTypeToCodeDomType (retType) == null) {
Console.WriteLine ("\t\tS: " + retType);
skip = true;
}
method.ReturnType = retType;
bool skip = false;
int c = 0;
List<CppType> argTypes = new List<CppType> ();
foreach (Node arg in n.Children.Where (o => o.Type == "Argument")) {
@ -262,6 +269,11 @@ public class Generator
skip = true;
}
if (CppTypeToCodeDomType (argtype) == null) {
Console.WriteLine ("\t\tS: " + argtype);
skip = true;
}
method.Parameters.Add (new Tuple<string, CppType> (argname, argtype));
argTypes.Add (argtype);
@ -278,6 +290,12 @@ public class Generator
klass.Methods.Add (method);
}
Field f2 = klass.Fields.FirstOrDefault (f => f.Type.ElementType == CppTypes.Unknown);
if (f2 != null) {
Console.WriteLine ("Skipping " + klass.Name + " because field " + f2.Name + " has unknown type.");
klass.Disable = true;
}
}
}
@ -302,10 +320,17 @@ public class Generator
else
throw new NotImplementedException ();
case "Class":
// FIXME: Missing classes
case "Struct":
if (!NodeToClass.ContainsKey (n)) {
if (modifiers.Modifiers.Count () == 1 && modifiers.Modifiers [0] == CppModifiers.Pointer)
// Map these to void*
return modifiers.CopyTypeFrom (CppTypes.Void);
else
return CppTypes.Unknown;
}
return modifiers.CopyTypeFrom (new CppType (CppTypes.Class, NodeToClass [n].Name));
default:
throw new NotImplementedException (n.Type);
return CppTypes.Unknown;
}
}
@ -313,11 +338,32 @@ public class Generator
return Node.IdToNode [n.Attributes ["type"]];
}
public CodeTypeReference CppTypeToCodeDomType (CppType t) {
// Return the CodeDom type reference corresponding to T, or null
public CodeTypeReference CppTypeToCodeDomType (CppType t, out bool byref) {
CodeTypeReference rtype = null;
// FIXME: Modifiers
byref = false;
Type mtype = t.ToManagedType ();
if (mtype != null) {
if (mtype.IsByRef) {
byref = true;
mtype = mtype.GetElementType ();
}
return new CodeTypeReference (mtype);
}
if (t.Modifiers.Count > 0 && t.ElementType != CppTypes.Void && t.ElementType != CppTypes.Class)
return null;
switch (t.ElementType) {
case CppTypes.Void:
if (t.Modifiers.Count > 0) {
if (t.Modifiers.Count == 1 && t.Modifiers [0] == CppModifiers.Pointer)
rtype = new CodeTypeReference (typeof (IntPtr));
else
return null;
} else {
rtype = new CodeTypeReference (typeof (void));
}
break;
case CppTypes.Bool:
rtype = new CodeTypeReference (typeof (bool));
@ -325,16 +371,31 @@ public class Generator
case CppTypes.Int:
rtype = new CodeTypeReference (typeof (int));
break;
case CppTypes.Float:
rtype = new CodeTypeReference (typeof (float));
break;
case CppTypes.Double:
rtype = new CodeTypeReference (typeof (double));
break;
case CppTypes.Char:
rtype = new CodeTypeReference (typeof (char));
break;
case CppTypes.Class:
// FIXME: Full name
rtype = new CodeTypeReference (t.ElementTypeName);
break;
default:
throw new NotImplementedException (t.ToString ());
return null;
}
return rtype;
}
public CodeTypeReference CppTypeToCodeDomType (CppType t) {
bool byref;
return CppTypeToCodeDomType (t, out byref);
}
void GenerateCode () {
Directory.CreateDirectory (OutputDir);
@ -353,9 +414,9 @@ public class Generator
var decl = new CodeTypeDeclaration ("Libs");
var field = new CodeMemberField (new CodeTypeReference ("CppLibrary"), "Test");
var field = new CodeMemberField (new CodeTypeReference ("CppLibrary"), LibBaseName);
field.Attributes = MemberAttributes.Public|MemberAttributes.Static;
field.InitExpression = new CodeObjectCreateExpression (new CodeTypeReference ("CppLibrary"), new CodeExpression [] { new CodePrimitiveExpression ("Test") });
field.InitExpression = new CodeObjectCreateExpression (new CodeTypeReference ("CppLibrary"), new CodeExpression [] { new CodePrimitiveExpression (LibBaseName) });
decl.Members.Add (field);
ns.Types.Add (decl);
@ -370,13 +431,16 @@ public class Generator
// Generate user classes
foreach (Class klass in Classes) {
if (klass.Disable)
continue;
var cu = new CodeCompileUnit ();
var ns = new CodeNamespace (Namespace);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Imports.Add(new CodeNamespaceImport("Mono.VisualC.Interop"));
cu.Namespaces.Add (ns);
ns.Types.Add (klass.GenerateClass (this, libDecl));
ns.Types.Add (klass.GenerateClass (this, libDecl, LibBaseName));
//Provider.GenerateCodeFromCompileUnit(cu, Console.Out, CodeGenOptions);
using (TextWriter w = File.CreateText (Path.Combine (OutputDir, klass.Name + ".cs"))) {

Просмотреть файл

@ -64,6 +64,10 @@ class Method
get; set;
}
string GetCSharpMethodName (string name) {
return "" + Char.ToUpper (name [0]) + name.Substring (1);
}
public CodeMemberMethod GenerateIFaceMethod (Generator g) {
var method = new CodeMemberMethod () {
Name = Name
@ -73,12 +77,15 @@ class Method
method.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppInstancePtr"), "this"));
CodeTypeReference rtype = g.CppTypeToCodeDomType (ReturnType);
if (rtype != null)
method.ReturnType = rtype;
method.ReturnType = rtype;
foreach (var p in Parameters) {
CppType ptype = p.Item2;
var param = new CodeParameterDeclarationExpression (g.CppTypeToCodeDomType (ptype), p.Item1);
bool byref;
var ctype = g.CppTypeToCodeDomType (ptype, out byref);
var param = new CodeParameterDeclarationExpression (ctype, p.Item1);
if (byref)
param.Direction = FieldDirection.Ref;
if (!IsVirtual && !ptype.ToString ().Equals (string.Empty))
param.CustomAttributes.Add (new CodeAttributeDeclaration ("MangleAsAttribute", new CodeAttributeArgument (new CodePrimitiveExpression (ptype.ToString ()))));
// FIXME: Structs too
@ -114,22 +121,25 @@ class Method
if (IsConstructor)
method = new CodeConstructor () {
Name = Name
Name = GetCSharpMethodName (Name)
};
else
method = new CodeMemberMethod () {
Name = Name
Name = GetCSharpMethodName (Name)
};
method.Attributes = MemberAttributes.Public;
if (IsStatic)
method.Attributes |= MemberAttributes.Static;
CodeTypeReference rtype = g.CppTypeToCodeDomType (ReturnType);
if (rtype != null)
method.ReturnType = rtype;
method.ReturnType = rtype;
foreach (var p in Parameters) {
var param = new CodeParameterDeclarationExpression (g.CppTypeToCodeDomType (p.Item2), p.Item1);
bool byref;
var ptype = g.CppTypeToCodeDomType (p.Item2, out byref);
var param = new CodeParameterDeclarationExpression (ptype, p.Item1);
if (byref)
param.Direction = FieldDirection.Ref;
method.Parameters.Add (param);
}
@ -142,11 +152,18 @@ class Method
CodeExpression[] args = new CodeExpression [Parameters.Count + (IsStatic ? 0 : 1)];
if (!IsStatic)
args [0] = new CodeFieldReferenceExpression (null, "Native");
for (int i = 0; i < Parameters.Count; ++i)
args [i + (IsStatic ? 0 : 1)] = new CodeArgumentReferenceExpression (Parameters [i].Item1);
for (int i = 0; i < Parameters.Count; ++i) {
bool byref;
g.CppTypeToCodeDomType (Parameters [i].Item2, out byref);
CodeExpression arg = new CodeArgumentReferenceExpression (Parameters [i].Item1);
if (byref)
arg = new CodeDirectionExpression (FieldDirection.Ref, arg);
args [i + (IsStatic ? 0 : 1)] = arg;
}
var call = new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), Name), args);
if (rtype == null || IsConstructor)
if (rtype.BaseType == "System.Void" || IsConstructor)
method.Statements.Add (call);
else
method.Statements.Add (new CodeMethodReturnStatement (call));