Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Applied patch from Nathan Stott, adding MethodSubstitutionBaseClassCo…

…mpilerStep and refactoring AnonymousBaseClassCompilerStep to a class hierarchy.

Breaking change: Renamed AnonymousBaseClassCompilerStep to ImplicitBaseClassCompilerStep - feedback showed that this is a better name.
Making _sure_ we wouldn't break if the asm.info is locked by VS.
Modifying Binsor to match new version of Rhino DSL.

git-svn-id: https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk@1470 079b0acf-d9fa-0310-9935-e5ade295c882
  • Loading branch information...
commit 33b1e5f9cf2b8006b59469c0f1f53a97b59a348a 1 parent 368eae5
ayenderahien authored
View
26 Rhino.DSL-vs2008.sln
@@ -23,29 +23,3 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
-?
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhino.DSL-vs2008", "Rhino.DSL\Rhino.DSL-vs2008.csproj", "{B788F27C-E00A-434A-81AA-1D592E030934}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhino.DSL.Tests-v2008", "Rhino.DSL.Tests\Rhino.DSL.Tests-v2008.csproj", "{9BCD2185-4653-45D7-99B2-3043E55A6746}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B788F27C-E00A-434A-81AA-1D592E030934}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B788F27C-E00A-434A-81AA-1D592E030934}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B788F27C-E00A-434A-81AA-1D592E030934}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B788F27C-E00A-434A-81AA-1D592E030934}.Release|Any CPU.Build.0 = Release|Any CPU
- {9BCD2185-4653-45D7-99B2-3043E55A6746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9BCD2185-4653-45D7-99B2-3043E55A6746}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9BCD2185-4653-45D7-99B2-3043E55A6746}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9BCD2185-4653-45D7-99B2-3043E55A6746}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
View
4 Rhino.DSL.Tests/AnonymousBaseClassTestFixture.cs
@@ -45,7 +45,7 @@ public void CanExecuteNewTypeAndGetCodeFromFile()
protected override void AddCompilerSteps(BooCompiler compiler, string filename, CompilerPipeline pipeline)
{
compiler.Parameters.Pipeline.Insert(1,
- new AnonymousBaseClassCompilerStep(typeof (MyAnonymousBaseClass), "Run"));
+ new ImplicitBaseClassCompilerStep(typeof (MyAnonymousBaseClass), "Run"));
}
}
@@ -53,4 +53,4 @@ public abstract class MyAnonymousBaseClass
{
public abstract void Run();
}
-}
+}
View
2  Rhino.DSL.Tests/DslFactoryFixture/DslEngineFixture.cs
@@ -67,7 +67,7 @@ protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline
new ParameterDeclaration("input", new SimpleTypeReference("System.String"));
parameters.Add(newParameterDeclaration);
- pipeline.Insert(1, new AnonymousBaseClassCompilerStep(typeof(MyClassWithParams),
+ pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof(MyClassWithParams),
"Hello",
parameters,
"System"));
View
4 Rhino.DSL.Tests/DslFactoryFixture/DslFixtureIntegrationFixture.cs
@@ -53,7 +53,7 @@ public class DemoDslEngine : DslEngine
{
protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline pipeline, string[] urls)
{
- pipeline.Insert(1, new AnonymousBaseClassCompilerStep(typeof (DemoDslBase), "Execute"));
+ pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (DemoDslBase), "Execute"));
}
}
-}
+}
View
4 Rhino.DSL.Tests/FeaturesDSL/WithActionsDSLFixture.cs
@@ -51,7 +51,7 @@ public class WithActionsDslEngine : DslEngine
protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline pipeline, string[] urls)
{
pipeline.Insert(1,
- new AnonymousBaseClassCompilerStep(typeof(WithAction), "Execute",
+ new ImplicitBaseClassCompilerStep(typeof(WithAction), "Execute",
//default namespaces
"Rhino.DSL.Tests.FeaturesDSL"));
pipeline.Insert(2, new UseSymbolsStep());
@@ -83,4 +83,4 @@ public ActionMacro() : base("Action")
}
}
-}
+}
View
5 Rhino.DSL.Tests/MethodSubstitutionBaseClass.boo
@@ -0,0 +1,5 @@
+SomeAbstractMethod:
+ System.Console.WriteLine("abstract")
+
+SomeVirtualMethod:
+ System.Console.WriteLine("virtual")
View
65 Rhino.DSL.Tests/MethodSubstitutionBaseClassTestFixture.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using Boo.Lang.Compiler;
+using MbUnit.Framework;
+
+namespace Rhino.DSL.Tests
+{
+ [TestFixture]
+ public class MethodSubstitutionBaseClassTestFixture : BaseCompilerTestFixture
+ {
+ private Assembly assembly;
+
+ [SetUp]
+ public override void SetUp()
+ {
+ base.SetUp();
+ assembly = Compile(@"MethodSubstitutionBaseClass.boo");
+ }
+
+ [Test]
+ public void CanCreateAnonymousBaseClass()
+ {
+ Assert.IsNotNull(assembly);
+ }
+
+ [Test]
+ public void WillCreateTypeWithSameNameAsFile()
+ {
+ Assert.IsNotNull(
+ assembly.GetType("MethodSubstitutionBaseClass")
+ );
+ }
+
+ [Test]
+ public void CanExecuteNewTypeAndGetCodeFromFile()
+ {
+ MyMethodSubstitutionBaseClass instance = (MyMethodSubstitutionBaseClass)assembly.CreateInstance("MethodSubstitutionBaseClass");
+ instance.SomeAbstractMethod();
+ instance.SomeVirtualMethod();
+ Assert.AreEqual("abstract" + Environment.NewLine +
+ "virtual" + Environment.NewLine,
+ consoleOutput.GetStringBuilder().ToString());
+ }
+
+ protected override void AddCompilerSteps(BooCompiler compiler, string filename, CompilerPipeline pipeline)
+ {
+ compiler.Parameters.AddAssembly(typeof(Boo.Lang.Compiler.Ast.DepthFirstTransformer).Assembly);
+ compiler.Parameters.Pipeline.Insert(1,
+ new MethodSubstitutionBaseClassCompilerStep(typeof(MyMethodSubstitutionBaseClass),
+ "System",
+ "Boo.Lang.Compiler.Ast.DepthFirstTransformer"));
+ }
+ }
+
+ public abstract class MyMethodSubstitutionBaseClass
+ {
+ public abstract void SomeAbstractMethod();
+ public virtual void SomeVirtualMethod()
+ {
+
+ }
+ }
+}
View
4 Rhino.DSL.Tests/OrderDSL/OrderActionsDslEngine.cs
@@ -10,11 +10,11 @@ public class OrderActionsDslEngine : DslEngine
protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline pipeline, string[] urls)
{
pipeline.Insert(1,
- new AnonymousBaseClassCompilerStep(typeof (BaseOrderActionsDSL), "Prepare",
+ new ImplicitBaseClassCompilerStep(typeof (BaseOrderActionsDSL), "Prepare",
//default namespaces
"Rhino.DSL.Tests.SchedulingDSL"));
pipeline.InsertBefore(typeof (ProcessMethodBodiesWithDuckTyping),
new UnderscorNamingConventionsToPascalCaseCompilerStep());
}
}
-}
+}
View
6 Rhino.DSL.Tests/Rhino.DSL.Tests-v2008.csproj
@@ -71,6 +71,7 @@
<Compile Include="ExternalDSL\ExternalDSLDemo.cs" />
<Compile Include="ExternalDSL\Parser.cs" />
<Compile Include="FeaturesDSL\WithActionsDSLFixture.cs" />
+ <Compile Include="MethodSubstitutionBaseClassTestFixture.cs" />
<Compile Include="OrderDSL\BaseOrderActionsDSL.cs" />
<Compile Include="OrderDSL\Order.cs" />
<Compile Include="OrderDSL\OrderActionsDslEngine.cs" />
@@ -108,6 +109,9 @@
<None Include="FeaturesDSL\HasAction.boo">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
+ <None Include="MethodSubstitutionBaseClass.boo">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
<None Include="namespacesImports.boo">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@@ -138,4 +142,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
View
5 Rhino.DSL.Tests/SchedulingDSL/SchedulingDslEngine.cs
@@ -1,14 +1,13 @@
namespace Rhino.DSL.Tests.SchedulingDSL
{
- using System;
using Boo.Lang.Compiler;
public class SchedulingDslEngine : DslEngine
{
protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline pipeline, string[] urls)
{
- pipeline.Insert(1, new AnonymousBaseClassCompilerStep(typeof (BaseScheduler), "Prepare",
+ pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (BaseScheduler), "Prepare",
"Rhino.DSL.Tests.SchedulingDSL"));
}
}
-}
+}
View
118 Rhino.DSL/AnonymousBaseClassCompilerStep.cs
@@ -1,118 +0,0 @@
-namespace Rhino.DSL
-{
- using System;
- using System.Reflection;
- using Boo.Lang.Compiler.Ast;
- using Boo.Lang.Compiler.Steps;
- using Boo.Lang.Compiler.Util;
- using Module=Boo.Lang.Compiler.Ast.Module;
-
- /// <summary>
- /// Takes all the code that exists in a module's global section and put it in a specificied
- /// method of a class. Allow easy handling of the Anonymous Base Class pattern
- /// </summary>
- public class AnonymousBaseClassCompilerStep : AbstractCompilerStep
- {
- private readonly Type baseClass;
- private readonly string methodName;
- private readonly string[] namespaces;
- private readonly ParameterDeclarationCollection parameters;
-
- /// <summary>
- /// Create new instance of <seealso cref="AnonymousBaseClassCompilerStep"/>
- /// </summary>
- /// <param name="baseClass">The base class that will be used</param>
- /// <param name="methodName">The name of the method that will get all the code from globals moved to it.</param>
- /// <param name="namespaces">Namespaces that would be automatically imported into all modules</param>
- public AnonymousBaseClassCompilerStep(Type baseClass, string methodName, params string[] namespaces)
- : this(baseClass, methodName, null, namespaces)
- {
- }
-
- /// <summary>
- /// Create new instance of <seealso cref="AnonymousBaseClassCompilerStep"/>
- /// </summary>
- /// <param name="baseClass">The base class that will be used</param>
- /// <param name="methodName">The name of the method that will get all the code from globals moved to it.</param>
- /// <param name="parameters">The parameters of this method</param>
- /// <param name="namespaces">Namespaces that would be automatically imported into all modules</param>
- public AnonymousBaseClassCompilerStep(Type baseClass, string methodName, ParameterDeclarationCollection parameters, params string[] namespaces)
- {
- this.namespaces = namespaces;
- this.baseClass = baseClass;
- this.methodName = methodName;
- this.parameters = parameters;
- }
-
- ///<summary>
- /// Run this compiler step
- ///</summary>
- public override void Run()
- {
- if (Context.References.Contains(baseClass.Assembly) == false)
- Context.Parameters.References.Add(baseClass.Assembly);
-
- foreach (Module module in CompileUnit.Modules)
- {
- foreach (string ns in namespaces)
- {
- module.Imports.Add(new Import(module.LexicalInfo, ns));
- }
-
- ClassDefinition definition = new ClassDefinition();
- definition.Name = module.FullName;
- definition.BaseTypes.Add(new SimpleTypeReference(baseClass.FullName));
- Method method = new Method(methodName);
-
-
- if (parameters != null)
- {
- foreach (ParameterDeclaration parameter in parameters)
- {
- method.Parameters.Add(parameter);
- }
- }
-
- method.Body = module.Globals;
- module.Globals = new Block();
- definition.Members.Add(method);
- module.Members.Add(definition);
-
- GenerateConstructors(definition);
-
- ExtendBaseClass(definition);
- }
- }
-
- private void GenerateConstructors(TypeDefinition definition)
- {
- ConstructorInfo[] ctors =
- baseClass.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- foreach (ConstructorInfo ctor in ctors)
- {
- if (ctor.IsPrivate)
- continue;
- Constructor constructor = new Constructor(definition.LexicalInfo);
- definition.Members.Add(constructor);
- MethodInvocationExpression super = new MethodInvocationExpression(new SuperLiteralExpression());
- constructor.Body.Add(super);
- foreach (ParameterInfo info in ctor.GetParameters())
- {
- SimpleTypeReference typeReference =
- new SimpleTypeReference(TypeUtilities.GetFullName(info.ParameterType));
- constructor.Parameters.Add(new ParameterDeclaration(info.Name,
- typeReference)
- );
- super.Arguments.Add(new ReferenceExpression(info.Name));
- }
- }
- }
-
- /// <summary>
- /// Allow a derived class to perform additional operations on the newly created type definition.
- /// </summary>
- protected virtual void ExtendBaseClass(TypeDefinition definition)
- {
- }
- }
-}
View
102 Rhino.DSL/BaseClassCompilerStep.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using Boo.Lang.Compiler.Ast;
+using Boo.Lang.Compiler.Steps;
+using Boo.Lang.Compiler.Util;
+using Module=Boo.Lang.Compiler.Ast.Module;
+
+namespace Rhino.DSL
+{
+ /// <summary>
+ /// Provides a base class for classes that provide DSL via
+ /// substituting code into one or more members of a class
+ /// created at runtime inheriting from a BaseClassCompilerStep.
+ /// </summary>
+ public abstract class BaseClassCompilerStep: AbstractCompilerStep
+ {
+ private readonly Type baseClass;
+ private readonly string[] namespaces;
+
+ /// <summary>
+ /// Create new instance of <seealso cref="BaseClassCompilerStep"/>
+ /// </summary>
+ /// <param name="baseClass">The base class that will be used</param>
+ /// <param name="namespaces">Namespaces that will be automatically imported into all modules</param>
+ protected BaseClassCompilerStep(Type baseClass, params string[] namespaces)
+ {
+ this.baseClass = baseClass;
+ this.namespaces = namespaces;
+ }
+
+ /// <summary>
+ /// Run this compiler step
+ /// </summary>
+ public override void Run()
+ {
+ if (Context.References.Contains(baseClass.Assembly) == false)
+ Context.Parameters.References.Add(baseClass.Assembly);
+
+ foreach (Module module in CompileUnit.Modules)
+ {
+ foreach (string ns in namespaces)
+ {
+ module.Imports.Add(new Import(module.LexicalInfo, ns));
+ }
+
+ ClassDefinition definition = new ClassDefinition();
+ definition.Name = module.FullName;
+ definition.BaseTypes.Add(new SimpleTypeReference(baseClass.FullName));
+
+ GenerateConstructors(definition);
+
+ // This is called before the module.Globals is set to a new block so that derived classes may retrieve the
+ // block from the module.
+ ExtendBaseClass(module, definition);
+
+ module.Globals = new Block();
+ module.Members.Add(definition);
+ }
+ }
+
+ /// <summary>
+ /// Base class that this BaseClassCompilerStep builds a derived instance of.
+ /// </summary>
+ protected Type BaseClass
+ {
+ get { return baseClass; }
+ }
+
+ private void GenerateConstructors(TypeDefinition definition)
+ {
+ ConstructorInfo[] ctors =
+ baseClass.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ foreach (ConstructorInfo ctor in ctors)
+ {
+ if (ctor.IsPrivate)
+ continue;
+ Constructor constructor = new Constructor(definition.LexicalInfo);
+ definition.Members.Add(constructor);
+ MethodInvocationExpression super = new MethodInvocationExpression(new SuperLiteralExpression());
+ constructor.Body.Add(super);
+ foreach (ParameterInfo info in ctor.GetParameters())
+ {
+ SimpleTypeReference typeReference =
+ new SimpleTypeReference(TypeUtilities.GetFullName(info.ParameterType));
+ constructor.Parameters.Add(new ParameterDeclaration(info.Name,
+ typeReference)
+ );
+ super.Arguments.Add(new ReferenceExpression(info.Name));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Allow a derived class to perform additional operations on the newly created type definition.
+ /// </summary>
+ protected virtual void ExtendBaseClass(Module module, ClassDefinition definition)
+ {
+ }
+ }
+}
View
72 Rhino.DSL/ImplicitBaseClassCompilerStep.cs
@@ -0,0 +1,72 @@
+namespace Rhino.DSL
+{
+ using System;
+ using Boo.Lang.Compiler.Ast;
+ using Module=Boo.Lang.Compiler.Ast.Module;
+
+ /// <summary>
+ /// Takes all the code that exists in a module's global section and put it in a specificied
+ /// method of a class. Allow easy handling of the Anonymous Base Class pattern
+ /// </summary>
+ public class ImplicitBaseClassCompilerStep : BaseClassCompilerStep
+ {
+ private readonly string methodName;
+ private readonly ParameterDeclarationCollection parameters;
+
+ /// <summary>
+ /// Create new instance of <seealso cref="ImplicitBaseClassCompilerStep"/>
+ /// </summary>
+ /// <param name="baseClass">The base class that will be used</param>
+ /// <param name="methodName">The name of the method that will get all the code from globals moved to it.</param>
+ /// <param name="namespaces">Namespaces that would be automatically imported into all modules</param>
+ public ImplicitBaseClassCompilerStep(Type baseClass, string methodName, params string[] namespaces)
+ : this(baseClass, methodName, null, namespaces)
+ {
+ }
+
+ /// <summary>
+ /// Create new instance of <seealso cref="ImplicitBaseClassCompilerStep"/>
+ /// </summary>
+ /// <param name="baseClass">The base class that will be used</param>
+ /// <param name="methodName">The name of the method that will get all the code from globals moved to it.</param>
+ /// <param name="parameters">The parameters of this method</param>
+ /// <param name="namespaces">Namespaces that would be automatically imported into all modules</param>
+ public ImplicitBaseClassCompilerStep(Type baseClass, string methodName, ParameterDeclarationCollection parameters, params string[] namespaces)
+ : base(baseClass, namespaces)
+ {
+ this.methodName = methodName;
+ this.parameters = parameters;
+ }
+
+ /// <summary>
+ /// Allow a derived class to perform additional operations on the newly created type definition.
+ /// </summary>
+ protected override void ExtendBaseClass(Module module, ClassDefinition definition)
+ {
+ Method method = new Method(methodName);
+
+
+ if (parameters != null)
+ {
+ foreach (ParameterDeclaration parameter in parameters)
+ {
+ method.Parameters.Add(parameter);
+ }
+ }
+
+ method.Body = module.Globals;
+ definition.Members.Add(method);
+
+ ExtendBaseClass(definition);
+ }
+
+ /// <summary>
+ /// Allow to extend the base class in additional ways
+ /// </summary>
+ /// <param name="definition">The definition.</param>
+ protected virtual void ExtendBaseClass(TypeDefinition definition)
+ {
+
+ }
+ }
+}
View
105 Rhino.DSL/MacroBlockToParametersTransformer.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Boo.Lang.Compiler.Ast;
+
+namespace Rhino.DSL
+{
+ /// <summary>
+ /// Transforms a macro's block statements to arguments.
+ /// </summary>
+ /// <example>
+ /// SomeMacro:
+ /// GetInteger()
+ /// GetString()
+ ///
+ /// Translates to SomeMacro(GetInteger(), GetString())
+ /// </example>
+ public class MacroBlockToParametersTransformer : DepthFirstTransformer
+ {
+ private readonly string[] macrosToTransform;
+
+ /// <summary>
+ /// Creates an instance of <see cref="MacroBlockToParametersTransformer"/>.
+ /// </summary>
+ /// <param name="macrosToTransform">Names of the macros to transform.</param>
+ public MacroBlockToParametersTransformer(params string[] macrosToTransform)
+ {
+ if (macrosToTransform == null)
+ throw new ArgumentNullException("macrosToTransform");
+ this.macrosToTransform = macrosToTransform;
+ }
+
+ /// <summary>
+ /// Transforms a macro statement.
+ /// </summary>
+ /// <param name="node">The <see cref="MacroStatement"/> node.</param>
+ public override void OnMacroStatement(MacroStatement node)
+ {
+ string macroName = Array.Find(macrosToTransform, delegate(string name)
+ {
+ return name.Equals(node.Name);
+ });
+ if (!String.IsNullOrEmpty(macroName))
+ {
+ StatementTransformer st = new StatementTransformer(node);
+ st.Visit(node);
+ }
+ else
+ {
+ base.OnMacroStatement(node);
+ }
+ }
+
+ private class StatementTransformer : DepthFirstTransformer
+ {
+ private readonly MacroStatement statement;
+
+ public StatementTransformer(MacroStatement statement)
+ {
+ if (statement == null)
+ throw new ArgumentNullException("statement");
+ this.statement = statement;
+ }
+
+ public override void OnBlock(Block node)
+ {
+ if (node.ParentNode == statement)
+ {
+ foreach (Statement s in node.Statements)
+ {
+ MacroStatement macroStatement = s as MacroStatement;
+ if (macroStatement != null)
+ {
+ MethodInvocationExpression mie = new MethodInvocationExpression(s.LexicalInfo);
+ mie.Target = new ReferenceExpression(macroStatement.Name);
+ foreach (Expression arg in macroStatement.Arguments)
+ {
+ mie.Arguments.Add(arg);
+ }
+
+ statement.Arguments.Add(mie);
+ }
+
+ }
+
+ RemoveCurrentNode();
+ }
+ else
+ {
+ base.OnBlock(node);
+ }
+ }
+
+ public override void OnExpressionStatement(ExpressionStatement node)
+ {
+ if (node.ParentNode == statement)
+ {
+ statement.Arguments.Add(node.Expression);
+ RemoveCurrentNode();
+ }
+ base.OnExpressionStatement(node);
+ }
+ }
+ }
+}
View
108 Rhino.DSL/MethodSubstitutionBaseClassCompilerStep.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+using Boo.Lang;
+using Boo.Lang.Compiler.Ast;
+using Module = Boo.Lang.Compiler.Ast.Module;
+
+
+namespace Rhino.DSL
+{
+ /// <summary>
+ /// Takes all macro statements that exist in the modules global section and puts the bodies of those methods
+ /// into corresponding overridable methods on the base class.
+ /// </summary>
+ public class MethodSubstitutionBaseClassCompilerStep : BaseClassCompilerStep
+ {
+ private readonly DepthFirstTransformer[] transformers;
+
+ /// <summary>
+ /// Create an instance of MethodSubstitutionBaseClassCompilerStep
+ /// </summary>
+ public MethodSubstitutionBaseClassCompilerStep(Type baseClassType, params string[] namespaces)
+ : base(baseClassType, namespaces)
+ {
+ }
+
+ /// <summary>
+ /// Create an instance of MethodSubstitutionBaseClassCompilerStep
+ /// </summary>
+ public MethodSubstitutionBaseClassCompilerStep(Type baseClass, DepthFirstTransformer[] transformers, params string[] namespaces)
+ : base(baseClass, namespaces)
+ {
+ this.transformers = transformers;
+ }
+
+ /// <summary>
+ /// Extends the base class by placing the blocks of macros into methods on the base class
+ /// of the same name.
+ /// </summary>
+ /// <example>
+ /// MyMethod:
+ /// PerformActions
+ ///
+ /// If an overridable method called MyMethod exists on <see cref="BaseClassCompilerStep.BaseClass"/>, then
+ /// it is overridden as follows:
+ /// <code>
+ /// public override void MyMethod() { PerformActions(); }
+ /// </code>
+ /// </example>
+ protected override void ExtendBaseClass(Module module, ClassDefinition definition)
+ {
+ List<MethodInfo> methodsThatAreOverridable = new List<MethodInfo>();
+
+ MethodInfo[] baseClassMethods =
+ BaseClass.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.InvokeMethod);
+
+ foreach (MethodInfo method in baseClassMethods)
+ {
+ if(method.DeclaringType==typeof(object))
+ continue;
+ if (method.IsVirtual || method.IsAbstract)
+ methodsThatAreOverridable.Add(method);
+ }
+
+ MethodSubstitutionTransformer mst = new MethodSubstitutionTransformer(methodsThatAreOverridable.ToArray(), definition);
+ mst.Visit(module);
+
+ if (transformers != null)
+ {
+ foreach (DepthFirstTransformer transformer in transformers)
+ transformer.Visit(module);
+ }
+ }
+
+ private class MethodSubstitutionTransformer : DepthFirstTransformer
+ {
+ private readonly ClassDefinition classDefinition;
+ private readonly MethodInfo[] methods;
+
+ public MethodSubstitutionTransformer(MethodInfo[] methods, ClassDefinition classDefinition)
+ {
+ this.classDefinition = classDefinition;
+ this.methods = methods;
+ }
+
+ public override void OnMacroStatement(MacroStatement node)
+ {
+ MethodInfo methodToOverride = Array.Find(methods, delegate(MethodInfo mi) { return mi.Name.Equals(node.Name); });
+
+ if (methodToOverride != null)
+ {
+ Method method = new Method(node.LexicalInfo);
+ method.Name = node.Name;
+ method.Body = node.Block;
+
+ classDefinition.Members.Add(method);
+ }
+ else
+ {
+ base.OnMacroStatement(node);
+ }
+ }
+ }
+ }
+}
View
7 Rhino.DSL/Rhino.DSL-vs2008.csproj
@@ -54,11 +54,14 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="AnonymousBaseClassCompilerStep.cs" />
+ <Compile Include="ImplicitBaseClassCompilerStep.cs" />
+ <Compile Include="BaseClassCompilerStep.cs" />
<Compile Include="DefaultDslEngineCache.cs" />
<Compile Include="FileSystemDslEngineStorage.cs" />
<Compile Include="IDslEngineCache.cs" />
<Compile Include="IDslEngineStorage.cs" />
+ <Compile Include="MacroBlockToParametersTransformer.cs" />
+ <Compile Include="MethodSubstitutionBaseClassCompilerStep.cs" />
<Compile Include="UnderscorNamingConventionsToPascalCaseCompilerStep.cs" />
<Compile Include="UseSymbolsStep.cs" />
<Compile Include="AutoImportCompilerStep.cs" />
@@ -81,4 +84,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
View
8 Rhino.DSL/Rhino.DSL.csproj
@@ -50,11 +50,15 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="AnonymousBaseClassCompilerStep.cs" />
+ <Compile Include="BaseClassCompilerStep.cs" />
<Compile Include="DefaultDslEngineCache.cs" />
<Compile Include="FileSystemDslEngineStorage.cs" />
<Compile Include="IDslEngineCache.cs" />
<Compile Include="IDslEngineStorage.cs" />
+ <Compile Include="ImplicitBaseClassCompilerStep.cs" />
+ <Compile Include="MacroBlockToParametersTransformer.cs" />
+ <Compile Include="MethodSubstitutionBaseClassCompilerStep.cs" />
+ <Compile Include="UnderscorNamingConventionsToPascalCaseCompilerStep.cs" />
<Compile Include="UseSymbolsStep.cs" />
<Compile Include="AutoImportCompilerStep.cs" />
<Compile Include="AutoReferenceFilesCompilerStep.cs" />
@@ -76,4 +80,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
Please sign in to comment.
Something went wrong with that request. Please try again.