From c64efe70910271fc82ff4abcd9ac8f65559057d4 Mon Sep 17 00:00:00 2001 From: triton Date: Wed, 30 Jan 2013 15:42:17 +0000 Subject: [PATCH] Added a pass to convert functions to instance methods. --- .../Passes/FunctionToInstanceMethodPass.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/Generator/Passes/FunctionToInstanceMethodPass.cs diff --git a/src/Generator/Passes/FunctionToInstanceMethodPass.cs b/src/Generator/Passes/FunctionToInstanceMethodPass.cs new file mode 100644 index 00000000..e1456082 --- /dev/null +++ b/src/Generator/Passes/FunctionToInstanceMethodPass.cs @@ -0,0 +1,87 @@ +using System; + +namespace Cxxi.Passes +{ + /// + /// This pass will try to hoist functions into classes so they + /// work just like instance methods. + /// + public class FunctionToInstanceMethodPass : TranslationUnitPass + { + /// + /// Processes a function declaration. + /// + public override bool ProcessFunction(Function function) + { + if (function.Ignore) + return false; + + // Check if this function can be converted. + if (function.Parameters.Count == 0) + return false; + + var classParam = function.Parameters[0]; + + Class @class; + if (!GetClassParameter(classParam, out @class)) + return false; + + // If we reach here, it means the first parameter is of class type. + // This means we can change the function to be an instance method. + + // Clean up the name of the function now that it will be an instance method. + if (!function.Name.StartsWith(@class.Name)) + return false; + + function.Name = function.Name.Substring(@class.Name.Length); + function.ExplicityIgnored = true; + + // Create a new fake method so it acts as an instance method. + var method = new Method() + { + Namespace = @class.Namespace, + Name = function.Name, + OriginalName = function.OriginalName, + Access = AccessSpecifier.Public, + Kind = CXXMethodKind.Normal, + ReturnType = function.ReturnType, + Parameters = function.Parameters, + CallingConvention = function.CallingConvention, + IsVariadic = function.IsVariadic, + IsInline = function.IsInline, + Conversion = MethodConversionKind.FunctionToInstanceMethod + }; + + @class.Methods.Add(method); + + Console.WriteLine("Instance method: {0}::{1}", @class.Name, + function.Name); + + return true; + } + + private static bool GetClassParameter(Parameter classParam, out Class @class) + { + TagType tag; + if (classParam.Type.IsPointerTo(out tag)) + { + @class = tag.Declaration as Class; + return true; + } + + if (classParam.Type.IsTagDecl(out @class)) + return true; + + return false; + } + } + + public static class FunctionToInstanceMethodExtensions + { + public static void FunctionToInstanceMethod(this PassBuilder builder) + { + var pass = new FunctionToInstanceMethodPass(); + builder.AddPass(pass); + } + } +}