Fix generator problems exposed by qt.
This commit is contained in:
Родитель
344debf842
Коммит
f295c467fe
|
@ -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));
|
||||
|
|
Загрузка…
Ссылка в новой задаче