Download - Building DSLs on CLR and DLR (.NET)
![Page 1: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/1.jpg)
Building
DSLs
on the CLR and DLR
![Page 3: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/3.jpg)
http://spbalt.net/
http://altdotnet.org
![Page 4: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/4.jpg)
DOMAIN SPECIFIC LANGUAGES
The short annotation
![Page 5: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/5.jpg)
Domain Specific Languages (DSLs)
are limited forms of computer language designed for a specific class of problems.
![Page 6: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/6.jpg)
Martin Fowler
“(DSL) is a computer language that's
targeted to a particular kind of problem,
rather than a general purpose language
that's aimed at any kind of software
problem.”
![Page 7: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/7.jpg)
Paul Graham
“*Lisp Programmers+ follow a principle
which could be called bottom-up design--
changing the language to suit the
problem.”
![Page 8: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/8.jpg)
DSLS CLASSIFICATION
![Page 9: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/9.jpg)
Types of DSL
Internal
• Written in host language
• Conventional use of subset of host language syntax
External
• Separate to host language
• Needs the compiler/interpreter to execute
![Page 10: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/10.jpg)
Types of DSL
Internal
• Tied to base language
• Awkward with mainstream
External
• Lack of Symbolic Integration
• Complex parser/generator technologies
• Ignorant IDEs
• (language cacophony)
![Page 11: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/11.jpg)
Types of DSL
Internal
• LINQ (C#)
• Monads (Haskell)
• Workflows (F#)
• Sequence expressions (F#)
• List comprehensions (Haskell, Python)
External
• Regexp
• SQL
• CSS
• Ant
• XSLT
![Page 12: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/12.jpg)
Types of DSL
Log Activity
Clear Activity
Shutdown ActivityW
ork
flo
w
Graphical DSL
![Page 13: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/13.jpg)
LANGUAGES
DSL Oriented .NET Languages
![Page 14: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/14.jpg)
Lisp
Smalltalk
Ruby
Python
Boo
C#
F#
![Page 15: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/15.jpg)
Lisp
Smalltalk
Ruby
Python
Boo DLRCLR
C#
F#
![Page 16: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/16.jpg)
I <3
![Page 17: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/17.jpg)
WHY SHOULD WE USE DSL?
The important advantages over a GPL
![Page 18: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/18.jpg)
Why should we use DSL
• Domain-specific abstractions: a DSL provides pre-defined abstractions to directly represent concepts from the application domain. Consequently, domain experts themselves can understand, validate, modify, and often even develop DSL program
• Domain-specific concrete syntax: a DSL offers a natural notation for a given domain and avoids syntactic clutter that often results when using a GPL.
![Page 19: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/19.jpg)
Why should we use DSL
• Domain-specific error checking: a DSL enables building static analyzers that can find more errors than similar analyzers for a GPL and that can report the errors in language familiar to the domain expert.
• Domain-specific optimizations: a DSL creates opportunities for generating optimized code base on domain-specific knowledge, which is usually not available to a compiler for a GPL.
![Page 20: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/20.jpg)
Why should we use DSL
• Domain-specific tool support: a DSL creates opportunities to improve any tooling aspect of a development environment, including, editors, debuggers, version control, etc.; the domain-specific knowledge that is explicitly captured by a DSL can be used to provide more intelligent tool support for developers.
![Page 21: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/21.jpg)
Why is DSL good?
Business Peoples and
“Rules”
Developers and their “Magic”
![Page 22: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/22.jpg)
Read Writeand
director of finance for the client bank to edit, test,
and deploy the business rules of the system without any assistance from IT
![Page 23: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/23.jpg)
Read Write
![Page 24: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/24.jpg)
PATTERNS
DSL Building Patterns
![Page 25: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/25.jpg)
Better code readability
• Fluent interfaces
• Extension methods
• LINQ
• Workflows
• Syntactic sugar
• AdHoc LINQ
![Page 26: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/26.jpg)
Fluent interfaces
Expect
.Once
.On(…)
.Method(…)
.WithAnyArguments()
.Will(
Return.Value(…)
)
NMock mocking library usage
![Page 27: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/27.jpg)
Fluent interfaces
Expect
.Once
.On(…)
.Method(…)
.WithAnyArguments()
.Will(
Return.Value(…)
)
public static Expect {…}
IRecieverSyntax
IMethodSyntax
IArgumentSyntax
IActionSyntax
IAction
![Page 28: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/28.jpg)
Fluent interfaces
public class ExpectationBuilder:IReceiverSyntax,IMethodSyntax,IArgumentSyntax,IActionSyntax {…}
public IMethodSyntax On(…){// …return this;
}public IArgumentSyntax Method(…){
// …return this;
}
![Page 29: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/29.jpg)
Combinations
today.at 3.pm
3.days.from_today at(3.pm)
![Page 30: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/30.jpg)
Timespan Literals
print(50s) // 50 seconds
print(1d) // 1 day
print(2m) // 2 minutes
print(42ms) // 42 miliseconds
print("Tomorrow this time will be: ${date.Now + 1d}")
![Page 31: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/31.jpg)
String interpolation
print("Now is ${date.Now}.")
print("Tomorrow will be ${date.Now + 1d}")
![Page 32: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/32.jpg)
Extension methods
DateTime now = DateTime.Now;
TimeSpan span =
TimeSpan.FromDays(3);
DateTime res =
now + span;
DateTime res =
3.Days()
.From(
DateTime.Now
)
VS
![Page 33: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/33.jpg)
Extension methods
public static class MyExtensions {
public static TimeSpan Days(this int i) {return TimeSpan.FromDays(i);
}
public static DateTime From(this TimeSpan span, DateTime dt) {return dt + span;
}
}
![Page 34: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/34.jpg)
Man, there’s LINQ alreadyCan’t we use that?
![Page 35: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/35.jpg)
We do
![Page 36: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/36.jpg)
LINQ
string s1 = GetS1();
string s2 = GetS2();
string res =
string.Empty;
if(s1 != null && s2 != null){
res = s1 + s2;
}
var res =
from a in GetS1()
from b in GetS2()
select a + b;
VS
![Page 37: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/37.jpg)
LINQ
public class Maybe<T> {
public T Value { get; private set; }public bool HasValue { get; private set; }
private Maybe() { HasValue = false; }
public Maybe(T value) {Value = value;HasValue = true;
}
public static readonly Maybe<T> Nothing = new Maybe<T>();}
![Page 38: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/38.jpg)
LINQ
public static Maybe<T> ToMaybe<T>(this T value) {return new Maybe<T>(value);
}
public static Maybe<U> SelectMany<T, U>(this Maybe<T> src, Func<T, Maybe<U>> f) {
if (!src.HasValue) {return Maybe<U>.Nothing;
}return f(src.Value);
}
![Page 39: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/39.jpg)
Important
• LINQ is a Monad
• F# Workflows are monads
• What isn’t?!
"[W]hen the designers of F# talked with the designers of Haskell about this, they agreed that the word monad is a bit obscure and sounds a littledaunting and that using other names might be wise.“
[F# Workflows and Haskell Monads, Expert F#, p232]
![Page 40: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/40.jpg)
C# is no fun.
Want more!
![Page 41: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/41.jpg)
Yeah?! F# you!
![Page 42: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/42.jpg)
Workflows
type Чо<'a> =| Ничо| Чото of 'a
let bindMaybe x f = match x with| Ничо -> Ничо| Чото y -> f y
type MaybeBuilder() =member x.Return(what) = Чото whatmember x.Bind(m, f) = bindMaybe m f
let чокак = new MaybeBuilder()
![Page 43: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/43.jpg)
Workflows
let first = чокак ,
let! x = Чото 6let! y = Чото 5return (x + y)
}
let second =чокак ,
let! x = Ничоlet! y = Чото 5return x+y
}
![Page 44: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/44.jpg)
Syntactic sugar
![Page 45: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/45.jpg)
Sweeties
• Partial application
• Pipelining
• Composition
• List comprehension
• Operators overriding
• AST modifications
• Measurement units
![Page 46: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/46.jpg)
Million years ago there wasn’t LINQAnd I still program C# 2. Can I have some DSL?
![Page 47: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/47.jpg)
AdHoc LINQ
Calculation<Item> calculation =
Time.Between(
Select.First(thisYear),
Select.Last(thisYear)
);
![Page 48: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/48.jpg)
SAMPLES
Simples DSLs on .NET
![Page 49: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/49.jpg)
![Page 50: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/50.jpg)
Validation DSL : IronPython
discussion demo discussion
![Page 51: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/51.jpg)
Validation DSL : IronPython
public class User : ValidationBase
{
[Validation("first_name_length")]
public string FirstName { get; set; }
}
![Page 52: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/52.jpg)
Validation DSL : IronPython
<rule name="last_name_length" message="Last name must be at least 2 characters">
<![CDATA[result = property_value != None and len(property_value) >= 2]]>
</rule>
![Page 53: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/53.jpg)
Validation DSL : IronPython
PythonEngine::Execute(“python code here”)
![Page 54: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/54.jpg)
![Page 55: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/55.jpg)
Validation DSL : Boo
ASP.NET MVC
Application
Model (C#)
Rules (Boo)
![Page 56: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/56.jpg)
Validation DSL : Boo
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
![Page 57: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/57.jpg)
Validation DSL : Boo
rule_for "User":
validate def(x):
results = create_results()
if string.IsNullOrEmpty(x.Username)
return results
![Page 58: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/58.jpg)
Validation DSL : Boo
Boo.Lang.Interpreter. InteractiveInterpreter_interpreter;
Func<List<ValidationResult>> createResults = (() => new List<ValidationResult>());
_interpreter.SetValue("create_results", createResults);
![Page 59: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/59.jpg)
Validation DSL : Boo
Boo:
results.Add(fail("Username and Password are required"))
C#:
CompilerContext ctx = _interpreter.EvalCompilerInput(newFileInput(_filePath));
foreach (CompilerError error in ctx.Errors)
{
sb.AppendLine(error.Message);}
![Page 60: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/60.jpg)
Object2RSS DSL : Boo
ASP.NET MVC
Application
Model (C#)
Rules (Boo)
![Page 61: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/61.jpg)
Object2RSS DSL : Boo
public class Product{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public DateTime CreateDate { get; set; }
public Manufacturer Manufacturer { get; set; }}
![Page 62: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/62.jpg)
Object2RSS DSL : Boo
rule_for "Product":
title def(x):
return "${x.Manufacturer.Name.ToUpper()} -${x.Name}"
description def(x):
return x.Description
link def(x):
return "http://codevoyeur.com/products/${x.Id}"
pubDate def(x):
return x.CreateDate.ToString("s")
![Page 63: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/63.jpg)
Object2RSS DSL : Boo
var engine = new RssDslEngine();foreach (T item in items)
{writer.WriteStartElement("item");List<string> fields = RssFieldFactory.Create();fields.ForEach(x =>
writer.WriteElementString(x, engine.Execute(item, x)));writer.WriteEndElement();
}
![Page 64: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/64.jpg)
Object2RSS DSL : Boo
public string Execute(object o, string field){
string ruleName = o.GetType().Name;if (_rules.ContainsKey(ruleName)){
return _rules[ruleName][field].Invoke(o);}else{
throw new ApplicationException("Invalid rule name");
}}
![Page 65: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/65.jpg)
SPECTER FRAMEWORK
A BDD framework for .NET and Mono
![Page 66: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/66.jpg)
MiniBar specification tutorial
![Page 67: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/67.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
![Page 68: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/68.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
[NUnit.Framework.TestFixture]class EmptyStack:
![Page 69: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/69.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
[NUnit.Framework.SetUp] def SetUp():
subject _bar = Bender.MiniBar()
![Page 70: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/70.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
[NUnit.Framework.Test]def BarDrinkOneBeerMustNotThrow():
Assert.DoesNotThrow(_bar. DrinkOneBeer())
![Page 71: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/71.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
[NUnit.Framework.Test]def IfIDrink5BeersThenIOwe5Bucks():
for i in range(5):_bar.DrinkOneBeer()
Int32MustModule.Must(_bar.Balance, “Bar balance must equal -5").Equal(-5)
![Page 72: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/72.jpg)
MiniBar specification tutorial
import Specter.Frameworkimport Bender context "At Bender's bar":
_bar as duck setup:
subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() specify "If I drink 5 beers then I owe 5 bucks":
for i in range(5): _bar.DrinkOneBeer()
_bar.Balance.Must.Equal(-5) specify "If I drink more than ten beers then I get drunk":
for i in range(10): _bar.DrinkOneBeer()
{ _bar.DrinkOneBeer() }.Must.Throw()
[NUnit.Framework.Test]def IfiDrinkMoreThanTenBeersThenIGetDrunk():
for i in range(10): _bar.DrinkOneBeer()
Assert.Throws((typeof(InvalidOperationException), _bar.DrinkOneBeer())
![Page 73: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/73.jpg)
MiniBar specification tutorial
![Page 74: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/74.jpg)
MiniBar specification tutorial
namespace Bender
class MiniBar:
def DrinkOneBeer():
pass
[getter(“Balance”)+
_balance = 0
![Page 75: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/75.jpg)
MiniBar specification tutorial
![Page 76: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/76.jpg)
MiniBar specification tutorial
namespace Bender
class MiniBar:
def DrinkOneBeer():
_balance--
if _balance < -10:
raise System.Exception("i'mdrunk")
[getter(“Balance”)+
_balance = 0
![Page 77: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/77.jpg)
MiniBar specification tutorial
![Page 78: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/78.jpg)
thx.
![Page 79: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/79.jpg)
Need more?
• http://www.microsoft.com/soa/products/oslo.aspx
• http://www.jetbrains.com/mps/index.html
• http://blogs.msdn.com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx
• http://www.google.com/
![Page 80: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/80.jpg)
Resources
• http://www.code-magazine.com/article.aspx?quickid=0902041&page=1 (Building Domain Specific Languages in C#)
• http://bradfordcross.blogspot.com/2009/01/external-dsl-vs-internal-dsl-smack-down_24.html (External DSL vs. Internal DSL Smack Down)
![Page 81: Building DSLs on CLR and DLR (.NET)](https://reader030.vdocuments.site/reader030/viewer/2022020122/5527f9d94a7959d83d8b45bb/html5/thumbnails/81.jpg)
Resources
• http://www.paulgraham.com/
• http://martinfowler.com/
• http://en.wikipedia.org/wiki/Domain-specific_programming_language
• http://msdn.microsoft.com/en-us/library/bb126235.aspx