Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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
26 Rhino.DSL-vs2008.sln
View
@@ -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
4 Rhino.DSL.Tests/AnonymousBaseClassTestFixture.cs
View
@@ -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();
}
-}
+}
2  Rhino.DSL.Tests/DslFactoryFixture/DslEngineFixture.cs
View
@@ -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"));
4 Rhino.DSL.Tests/DslFactoryFixture/DslFixtureIntegrationFixture.cs
View
@@ -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"));
}
}
-}
+}
4 Rhino.DSL.Tests/FeaturesDSL/WithActionsDSLFixture.cs
View
@@ -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")
}
}
-}
+}
5 Rhino.DSL.Tests/MethodSubstitutionBaseClass.boo
View
@@ -0,0 +1,5 @@
+SomeAbstractMethod:
+ System.Console.WriteLine("abstract")
+
+SomeVirtualMethod:
+ System.Console.WriteLine("virtual")
65 Rhino.DSL.Tests/MethodSubstitutionBaseClassTestFixture.cs
View
@@ -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()
+ {
+
+ }
+ }
+}
4 Rhino.DSL.Tests/OrderDSL/OrderActionsDslEngine.cs
View
@@ -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());
}
}
-}
+}
6 Rhino.DSL.Tests/Rhino.DSL.Tests-v2008.csproj
View
@@ -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>
5 Rhino.DSL.Tests/SchedulingDSL/SchedulingDslEngine.cs
View
@@ -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"));
}
}
-}
+}
118 Rhino.DSL/AnonymousBaseClassCompilerStep.cs
View
@@ -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)
- {
- }
- }
-}
102 Rhino.DSL/BaseClassCompilerStep.cs
View
@@ -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)
+ {
+ }
+ }
+}
72 Rhino.DSL/ImplicitBaseClassCompilerStep.cs
View
@@ -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)
+ {
+
+ }
+ }
+}
105 Rhino.DSL/MacroBlockToParametersTransformer.cs
View
@@ -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);
+ }
+ }
+ }
+}
108 Rhino.DSL/MethodSubstitutionBaseClassCompilerStep.cs
View
@@ -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);
+ }
+ }
+ }
+ }
+}
7 Rhino.DSL/Rhino.DSL-vs2008.csproj
View
@@ -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>
8 Rhino.DSL/Rhino.DSL.csproj
View
@@ -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.