Boo language has nice code pattern called Generator:
// Generator expressions are defined through the pattern:
<expression> for <declarations> in <iterator> [if|unless <condition>]
// Generator expressions can be used as return values:
def GetCompletedTasks():
return t for t in _tasks if t.IsCompleted
// Generator expressions can be stored in variables:
oddNumbers = i for i in range(10) if i % 2
This pattern simply creates some IEnumerable object via the syntax transformation. We can not have this sugar in C# yet, but that’s how we can leverage the concept:
// Simple syntax
var customerList = new List<Customer>();
for (int i = 0; i < 40; i++)
{
customerList.Add(new Customer
{
Name = "Customer_" + i
});
}
// generator + LINQ syntax
var customers = Generator.For(40).Select(i => new Customer
{
Name = "Customer_" + i
});
Continue reading ‘Generator pattern in C# .NET’
Here’s even shorter way of getting to see the Boo compiler in action with details:
- Get yourself latest SharpDevelop (15MB)
- Create new Boo project
- Paste the code below and hit F5. It will print AST in XML to the console
import System
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines
import Boo.Lang.Compiler
script = """abstract class BaseWorkflow[of X]:
abstract def Process(record as X):
pass
class MyWorkflow(BaseWorkflow[of int]):
def Process(record as int):
print record"""
booC = BooCompiler()
booC.Parameters.Input.Add(StringInput("script", script))
booC.Parameters.Pipeline = ParseAndPrintXml()
booC.Parameters.Ducky = true
context = booC.Run()
if context.GeneratedAssembly is null:
print join(e for e in context.Errors, "\n")
print "Press any key to continue . . . "
Console.ReadKey(true)
It seems trivial so now, but this little snippet could’ve saved me a couple of hours this morning while I’ve been trying to implement custom DSL workflow around a generic base class.
Learning how to implement custom DSL with Boo would have been extremely hard without some help from the Boo compiler itself. You just need to know where to look for it.
For example, you can use custom compiler steps to visualize Boo syntax tree between the transformations. Check out the Boo.Lang.Compiler.Steps namespace for:
- PrintBoo - outputs the AST in Boo format
- PrintAst - outputs the AST in text form
- SerializeToXml - outputs all nodes in Xml
To use these steps, you just need to insert them in the desired spot of the compiler pipeline like:
this.Insert(3, new PrintAst());
this.Insert(4, new PrintBoo());
This is all nice already, but we can make this “print AST information” approach even more useful for us. Here’s the simplified recipe:
Continue reading ‘How to peek inside the compiler pipeline of Boo’
Fluent registration API from the Autofac inversion of control container is really addictive.
I’ve just found myself writing the code for the DSL prototype project, that has nothing to do with the IoC (yet), but has feel similar to the Autofac component registrations:
/// <summary> Default compiler pipeline for this project </summary>
public sealed class MyPipeline : CompileToFile
{
public MyPipeline()
{
var provider = new BaseClassProviderOnRules();
// compile all *.boo from Requests folder against BaseRequestWorkflow
provider.Register<BaseRequestWorkflow>(“Requests”, “InitWorkflow”)
.Importing(“Request.Core”);
// compile all *.boo from Requests folder against BaseRequestDocumenter
// and add “_Documenter” suffix to class names
provider.Register<BaseRequestDocumenter>(“Requests”, “DescribeWorkflow”)
.Naming(file => file + “_Documenter”)
.Importing(“Request.Core”);
provider.Register<BaseClass>(“Samples”, “InitializeMethod”);
// customize the compiler pipeline
Insert(1, new UseSymbolsStep());
Insert(2, new MultiBaseClassCompilerStep(provider));
}
}
Latest Comments