Moved more transformations into the *Processor classes.

An EnumProcessor or FuncProcessor instance is now required in order to
call their Translate*() methods. A number of transformations that
relied on calling the static methods have now been moved inside the
processor classes.
This commit is contained in:
Stefanos A. 2013-10-27 01:30:45 +02:00
parent 5e06c14607
commit 51f52d7fc4
9 changed files with 79 additions and 138 deletions

View file

@ -58,7 +58,7 @@ namespace Bind
return enums; return enums;
} }
static EnumCollection ProcessNames(EnumCollection enums, XPathNavigator nav) EnumCollection ProcessNames(EnumCollection enums, XPathNavigator nav)
{ {
EnumCollection processed_enums = new EnumCollection(); EnumCollection processed_enums = new EnumCollection();
foreach (var e in enums.Values) foreach (var e in enums.Values)
@ -89,8 +89,11 @@ namespace Bind
return name; return name;
} }
public static string TranslateEnumName(string name) public string TranslateEnumName(string name)
{ {
if (String.IsNullOrEmpty(name))
return name;
if (Utilities.Keywords.Contains(name)) if (Utilities.Keywords.Contains(name))
return name; return name;
@ -99,7 +102,7 @@ namespace Bind
StringBuilder translator = new StringBuilder(name); StringBuilder translator = new StringBuilder(name);
// Split on IHV names, to ensure that characters appearing after these name are uppercase. // Split on IHV names and acronyms, to ensure that characters appearing after these name are uppercase.
var match = Utilities.Acronyms.Match(name); var match = Utilities.Acronyms.Match(name);
int offset = 0; // Everytime we insert a match, we must increase offset to compensate. int offset = 0; // Everytime we insert a match, we must increase offset to compensate.
while (match.Success) while (match.Success)
@ -162,7 +165,7 @@ namespace Bind
return name; return name;
} }
static EnumCollection ProcessConstants(EnumCollection enums, XPathNavigator nav) EnumCollection ProcessConstants(EnumCollection enums, XPathNavigator nav)
{ {
foreach (var e in enums.Values) foreach (var e in enums.Values)
{ {
@ -171,6 +174,7 @@ namespace Bind
{ {
c.Name = TranslateConstantName(c.Name, false); c.Name = TranslateConstantName(c.Name, false);
c.Value = TranslateConstantValue(c.Value); c.Value = TranslateConstantValue(c.Value);
c.Reference = TranslateEnumName(c.Reference);
if (!processed_constants.ContainsKey(c.Name)) if (!processed_constants.ContainsKey(c.Name))
processed_constants.Add(c.Name, c); processed_constants.Add(c.Name, c);
} }
@ -215,6 +219,9 @@ namespace Bind
public static string TranslateConstantName(string s, bool isValue) public static string TranslateConstantName(string s, bool isValue)
{ {
if (String.IsNullOrEmpty(s))
return s;
StringBuilder translator = new StringBuilder(s.Length); StringBuilder translator = new StringBuilder(s.Length);
if (isValue) if (isValue)
@ -319,7 +326,7 @@ namespace Bind
// Note that we have the removal must be a separate step, since // Note that we have the removal must be a separate step, since
// we cannot modify a collection while iterating with foreach. // we cannot modify a collection while iterating with foreach.
var broken_references = e.ConstantCollection.Values var broken_references = e.ConstantCollection.Values
.Where(c => !Constant.TranslateConstantWithReference(c, enums, null)) .Where(c => !Constant.TranslateConstantWithReference(c, enums))
.Select(c => c).ToList(); .Select(c => c).ToList();
foreach (var c in broken_references) foreach (var c in broken_references)
{ {

View file

@ -56,14 +56,15 @@ namespace Bind
Overrides = overrides; Overrides = overrides;
} }
public FunctionCollection Process(DelegateCollection delegates, EnumCollection enums) public FunctionCollection Process(EnumProcessor enum_processor, DelegateCollection delegates, EnumCollection enums)
{ {
Console.WriteLine("Processing delegates."); Console.WriteLine("Processing delegates.");
var nav = new XPathDocument(Overrides).CreateNavigator(); var nav = new XPathDocument(Overrides).CreateNavigator();
foreach (var d in delegates.Values) foreach (var d in delegates.Values)
{ {
TranslateReturnType(nav, d, enums); TranslateExtension(d);
TranslateParameters(nav, d, enums); TranslateReturnType(enum_processor, nav, d, enums);
TranslateParameters(enum_processor, nav, d, enums);
TranslateAttributes(nav, d, enums); TranslateAttributes(nav, d, enums);
} }
@ -76,11 +77,33 @@ namespace Bind
return MarkCLSCompliance(wrappers); return MarkCLSCompliance(wrappers);
} }
// Trims unecessary suffices from the specified OpenGL function name. void TranslateExtension(Delegate d)
public static string TrimName(string name, bool keep_extension)
{ {
string trimmed_name = Utilities.StripGL2Extension(name); var extension = d.Extension.ToUpper();
string extension = Utilities.GetGL2Extension(name); if (extension.Length > 2)
{
extension = extension[0] + extension.Substring(1).ToLower();
}
d.Extension = extension;
}
static string GetTrimmedExtension(string name, string extension)
{
// Extensions are always uppercase
int index = name.LastIndexOf(extension.ToUpper());
if (index >= 0)
{
name = name.Remove(index);
}
return name;
}
// Trims unecessary suffices from the specified OpenGL function name.
static string GetTrimmedName(Delegate d)
{
string name = d.Name;
string extension = d.Extension;
string trimmed_name = GetTrimmedExtension(name, extension);
// Note: some endings should not be trimmed, for example: 'b' from Attrib. // Note: some endings should not be trimmed, for example: 'b' from Attrib.
// Check the endingsNotToTrim regex for details. // Check the endingsNotToTrim regex for details.
@ -117,16 +140,20 @@ namespace Bind
static XPathNavigator GetFuncOverride(XPathNavigator nav, Delegate d) static XPathNavigator GetFuncOverride(XPathNavigator nav, Delegate d)
{ {
string name = TrimName(d.Name, false); string trimmed_name = GetTrimmedName(d);
string ext = d.Extension; string ext = d.Extension;
var function_override = var function_override =
nav.SelectSingleNode(String.Format(Path, d.Name, ext)) ?? nav.SelectSingleNode(String.Format(Path, d.Name, ext)) ??
nav.SelectSingleNode(String.Format(Path, Utilities.StripGL2Extension(d.Name), ext)) ?? nav.SelectSingleNode(String.Format(Path, trimmed_name, ext));
nav.SelectSingleNode(String.Format(Path, name, ext));
return function_override; return function_override;
} }
void TrimName(Function f)
{
f.TrimmedName = GetTrimmedName(f);
}
// Translates the opengl return type to the equivalent C# type. // Translates the opengl return type to the equivalent C# type.
// //
// First, we use the official typemap (gl.tm) to get the correct type. // First, we use the official typemap (gl.tm) to get the correct type.
@ -136,7 +163,7 @@ namespace Bind
// 3) A generic object or void* (translates to IntPtr) // 3) A generic object or void* (translates to IntPtr)
// 4) A GLenum (translates to int on Legacy.Tao or GL.Enums.GLenum otherwise). // 4) A GLenum (translates to int on Legacy.Tao or GL.Enums.GLenum otherwise).
// Return types must always be CLS-compliant, because .Net does not support overloading on return types. // Return types must always be CLS-compliant, because .Net does not support overloading on return types.
static void TranslateReturnType(XPathNavigator nav, Delegate d, EnumCollection enums) void TranslateReturnType(EnumProcessor enum_processor, XPathNavigator nav, Delegate d, EnumCollection enums)
{ {
var function_override = GetFuncOverride(nav, d); var function_override = GetFuncOverride(nav, d);
@ -149,7 +176,7 @@ namespace Bind
} }
} }
d.ReturnType.Translate(nav, d.Category, enums); d.ReturnType.Translate(enum_processor, nav, d.Category, enums);
if (d.ReturnType.CurrentType.ToLower().Contains("void") && d.ReturnType.Pointer != 0) if (d.ReturnType.CurrentType.ToLower().Contains("void") && d.ReturnType.Pointer != 0)
{ {
@ -181,7 +208,7 @@ namespace Bind
d.ReturnType.CurrentType = d.ReturnType.GetCLSCompliantType(); d.ReturnType.CurrentType = d.ReturnType.GetCLSCompliantType();
} }
static void TranslateParameters(XPathNavigator nav, Delegate d, EnumCollection enums) void TranslateParameters(EnumProcessor enum_processor, XPathNavigator nav, Delegate d, EnumCollection enums)
{ {
var function_override = GetFuncOverride(nav, d); var function_override = GetFuncOverride(nav, d);
@ -216,7 +243,7 @@ namespace Bind
} }
} }
d.Parameters[i].Translate(nav, d.Category, enums); d.Parameters[i].Translate(enum_processor, nav, d.Category, enums);
if (d.Parameters[i].CurrentType == "UInt16" && d.Name.Contains("LineStipple")) if (d.Parameters[i].CurrentType == "UInt16" && d.Name.Contains("LineStipple"))
d.Parameters[i].WrapperType = WrapperTypes.UncheckedParameter; d.Parameters[i].WrapperType = WrapperTypes.UncheckedParameter;
} }
@ -242,7 +269,7 @@ namespace Bind
} }
} }
static FunctionCollection CreateWrappers(DelegateCollection delegates, EnumCollection enums) FunctionCollection CreateWrappers(DelegateCollection delegates, EnumCollection enums)
{ {
var wrappers = new FunctionCollection(); var wrappers = new FunctionCollection();
foreach (var d in delegates.Values) foreach (var d in delegates.Values)
@ -347,9 +374,11 @@ namespace Bind
return collection; return collection;
} }
static IEnumerable<Function> CreateNormalWrappers(Delegate d, EnumCollection enums) IEnumerable<Function> CreateNormalWrappers(Delegate d, EnumCollection enums)
{ {
Function f = new Function(d); Function f = new Function(d);
TrimName(f);
WrapReturnType(f); WrapReturnType(f);
foreach (var wrapper in WrapParameters(f, enums)) foreach (var wrapper in WrapParameters(f, enums))
{ {

View file

@ -82,8 +82,11 @@ namespace Bind.GL2
SpecReader.ReadDelegates(Path.Combine(Settings.InputPath, glSpec), Delegates); SpecReader.ReadDelegates(Path.Combine(Settings.InputPath, glSpec), Delegates);
SpecReader.ReadDelegates(overrides, Delegates); SpecReader.ReadDelegates(overrides, Delegates);
Enums = new EnumProcessor(overrides).Process(Enums); var enum_processor = new EnumProcessor(overrides);
Wrappers = new FuncProcessor(overrides).Process(Delegates, Enums); var func_processor = new FuncProcessor(overrides);
Enums = enum_processor.Process(Enums);
Wrappers = func_processor.Process(enum_processor, Delegates, Enums);
} }
#endregion #endregion

View file

@ -215,9 +215,6 @@ namespace Bind
valid = true; valid = true;
var sb = new StringBuilder(); var sb = new StringBuilder();
if (f.TrimmedName == "ExtGetBufferPointer")
;// Debugger.Break();
if (f.Parameters.Count > 0) if (f.Parameters.Count > 0)
{ {
foreach (var p in f.Parameters) foreach (var p in f.Parameters)

View file

@ -98,9 +98,7 @@ namespace Bind.Structures
get { return _reference; } get { return _reference; }
set set
{ {
if (!String.IsNullOrEmpty(value)) _reference = value;
_reference = EnumProcessor.TranslateEnumName(value.Trim());
else _reference = value;
} }
} }
@ -145,51 +143,6 @@ namespace Bind.Structures
#endregion #endregion
#region Translate
[Obsolete]
public static string Translate(string s, bool isValue)
{
translator.Remove(0, translator.Length);
// Translate the constant's name to match .Net naming conventions
bool name_is_all_caps = s.AsEnumerable().All(c => Char.IsLetter(c) ? Char.IsUpper(c) : true);
bool name_contains_underscore = s.Contains("_");
if ((Settings.Compatibility & Settings.Legacy.NoAdvancedEnumProcessing) == Settings.Legacy.None &&
(name_is_all_caps || name_contains_underscore))
{
bool next_char_uppercase = true;
bool is_after_digit = false;
if (!isValue && Char.IsDigit(s[0]))
translator.Insert(0, Settings.ConstantPrefix);
foreach (char c in s)
{
if (c == '_')
next_char_uppercase = true;
else if (Char.IsDigit(c))
{
is_after_digit = true;
translator.Append(c);
}
else
{
translator.Append(next_char_uppercase || (is_after_digit && c == 'd') ? Char.ToUpper(c) : Char.ToLower(c));
is_after_digit = next_char_uppercase = false;
}
}
translator[0] = Char.ToUpper(translator[0]);
}
else
translator.Append(s);
return translator.ToString();
}
#endregion
/// <summary> /// <summary>
/// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair. /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair.
/// </summary> /// </summary>
@ -197,7 +150,7 @@ namespace Bind.Structures
/// <param name="enums">The list of enums to check.</param> /// <param name="enums">The list of enums to check.</param>
/// <param name="auxEnums">The list of auxilliary enums to check.</param> /// <param name="auxEnums">The list of auxilliary enums to check.</param>
/// <returns>True if the reference was found; false otherwise.</returns> /// <returns>True if the reference was found; false otherwise.</returns>
public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums) public static bool TranslateConstantWithReference(Constant c, EnumCollection enums)
{ {
if (c == null) if (c == null)
throw new ArgumentNullException("c"); throw new ArgumentNullException("c");
@ -218,16 +171,9 @@ namespace Bind.Structures
// Transitively translate the referenced token // Transitively translate the referenced token
// Todo: this may cause loops if two tokens reference each other. // Todo: this may cause loops if two tokens reference each other.
// Add a max reference depth and bail out? // Add a max reference depth and bail out?
TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value], enums, auxEnums); TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value], enums);
referenced_constant = (enums[c.Reference].ConstantCollection[c.Value]); referenced_constant = (enums[c.Reference].ConstantCollection[c.Value]);
} }
else if (auxEnums != null && auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value))
{
// Legacy from previous generator incarnation.
// Todo: merge everything into enums and get rid of auxEnums.
TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value], enums, auxEnums);
referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value]);
}
else if (enums.ContainsKey(Settings.CompleteEnumName) && else if (enums.ContainsKey(Settings.CompleteEnumName) &&
enums[Settings.CompleteEnumName].ConstantCollection.ContainsKey(c.Value)) enums[Settings.CompleteEnumName].ConstantCollection.ContainsKey(c.Value))
{ {

View file

@ -43,6 +43,7 @@ namespace Bind.Structures
public Delegate(Delegate d) public Delegate(Delegate d)
{ {
Category = d.Category; Category = d.Category;
Extension = d.Extension;
Name = d.Name; Name = d.Name;
Parameters = new ParameterCollection(d.Parameters); Parameters = new ParameterCollection(d.Parameters);
ReturnType = new Type(d.ReturnType); ReturnType = new Type(d.ReturnType);
@ -226,22 +227,10 @@ namespace Bind.Structures
#region public bool Extension #region public bool Extension
string _extension;
public string Extension public string Extension
{ {
get get;
{ set;
if (!String.IsNullOrEmpty(Name))
{
_extension = Utilities.GetGL2Extension(Name);
return String.IsNullOrEmpty(_extension) ? "Core" : _extension;
}
else
{
return null;
}
}
} }
#endregion #endregion

View file

@ -24,7 +24,7 @@ namespace Bind.Structures
public Function(Delegate d) public Function(Delegate d)
: base(d) : base(d)
{ {
Name = d.Name; TrimmedName = Name = d.Name;
Body = new FunctionBody(); Body = new FunctionBody();
WrappedDelegate = d; WrappedDelegate = d;
} }
@ -34,6 +34,7 @@ namespace Bind.Structures
{ {
Parameters = new ParameterCollection(f.Parameters); Parameters = new ParameterCollection(f.Parameters);
ReturnType = new Type(f.ReturnType); ReturnType = new Type(f.ReturnType);
TrimmedName = f.TrimmedName;
Body.AddRange(f.Body); Body.AddRange(f.Body);
} }
@ -94,38 +95,7 @@ namespace Bind.Structures
#region public string TrimmedName #region public string TrimmedName
public string TrimmedName; public string TrimmedName { get; set; }
#endregion
#region public override string Name
/// <summary>
/// Gets or sets the name of the opengl function.
/// If no Tao compatibility is set, set TrimmedName to Name, after removing
/// [u][bsifd][v].
/// </summary>
public override string Name
{
get { return base.Name; }
set
{
base.Name = value;
if ((Settings.Compatibility & Settings.Legacy.NoTrimFunctionEnding) != Settings.Legacy.None)
{
// If we don't need compatibility with Tao,
// remove the Extension and the overload information from the name
// (Extension == "ARB", "EXT", etc, overload == [u][bsidf][v])
// TODO: Use some regex's here, to reduce clutter.
TrimmedName = value;
}
else
{
TrimmedName = FuncProcessor.TrimName(Name, false);
}
}
}
#endregion #endregion

View file

@ -15,7 +15,7 @@ namespace Bind.Structures
/// <summary> /// <summary>
/// Represents a single parameter of an opengl function. /// Represents a single parameter of an opengl function.
/// </summary> /// </summary>
public class Parameter : Type, IComparable<Parameter> class Parameter : Type, IComparable<Parameter>
{ {
string cache; string cache;
bool rebuild; bool rebuild;
@ -302,9 +302,9 @@ namespace Bind.Structures
#region Translate() #region Translate()
override public void Translate(XPathNavigator overrides, string category, EnumCollection enums) override public void Translate(EnumProcessor enum_processor, XPathNavigator overrides, string category, EnumCollection enums)
{ {
base.Translate(overrides, category, enums); base.Translate(enum_processor, overrides, category, enums);
if (Pointer >= 3) if (Pointer >= 3)
{ {
@ -392,7 +392,7 @@ namespace Bind.Structures
/// <summary> /// <summary>
/// Holds the parameter list of an opengl function. /// Holds the parameter list of an opengl function.
/// </summary> /// </summary>
public class ParameterCollection : List<Parameter>, IComparable<ParameterCollection> class ParameterCollection : List<Parameter>, IComparable<ParameterCollection>
{ {
string cache = String.Empty; string cache = String.Empty;
string callStringCache = String.Empty; string callStringCache = String.Empty;

View file

@ -11,7 +11,7 @@ using System.Xml.XPath;
namespace Bind.Structures namespace Bind.Structures
{ {
public class Type : IComparable<Type> class Type : IComparable<Type>
{ {
internal static Dictionary<string, string> GLTypes; internal static Dictionary<string, string> GLTypes;
internal static Dictionary<string, string> CSTypes; internal static Dictionary<string, string> CSTypes;
@ -324,12 +324,12 @@ namespace Bind.Structures
#region public virtual void Translate(XPathNavigator overrides, string category) #region public virtual void Translate(XPathNavigator overrides, string category)
public virtual void Translate(XPathNavigator overrides, string category, EnumCollection enums) public virtual void Translate(EnumProcessor enum_processor, XPathNavigator overrides, string category, EnumCollection enums)
{ {
Enum @enum; Enum @enum;
string s; string s;
category = EnumProcessor.TranslateEnumName(category); category = enum_processor.TranslateEnumName(category);
// Try to find out if it is an enum. If the type exists in the normal GLEnums list, use this. // Try to find out if it is an enum. If the type exists in the normal GLEnums list, use this.
// Otherwise, try to find it in the aux enums list. If it exists in neither, it is not an enum. // Otherwise, try to find it in the aux enums list. If it exists in neither, it is not an enum.
@ -368,7 +368,7 @@ namespace Bind.Structures
if (enums.ContainsKey(category)) if (enums.ContainsKey(category))
{ {
QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput, QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput,
Settings.NamespaceSeparator, EnumProcessor.TranslateEnumName(category)); Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category));
} }
else else
{ {