Building DSLs On CLR and DLR (Microsoft.NET)

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Favorites, Groups & Events

    Building DSLs On CLR and DLR (Microsoft.NET) - Presentation Transcript

    1. Building DSL s on the CLR and DLR
    2. VitalyBaum vbaum@live.com butaji MaximMoiseev maxim.moiseev@gmail.com moiseev
    3. http://altdotnet.org http://spbalt.net/
    4. The short annotation DOMAIN SPECIFIC LANGUAGES
    5. Domain Specific Languages (DSLs) are limited forms of computer language designed for a specific class of problems.
    6. 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.”
    7. Paul Graham “*Lisp Programmers+ follow a principle which could be called bottom-up design-- changing the language to suit the problem.”
    8. DSLS CLASSIFICATION
    9. Types of DSL Internal External • Written in host • Separate to host language language • Conventional use of • Needs the subset of host language compiler/interpreter to syntax execute
    10. Types of DSL Internal External • Tied to base language • Lack of Symbolic • Awkward with Integration mainstream • Complex parser/generator technologies • Ignorant IDEs • (language cacophony)
    11. Types of DSL Internal External • LINQ (C#) • Regexp • Monads (Haskell) • SQL • Workflows (F#) • CSS • Sequence expressions • Ant (F#) • XSLT • List comprehensions (Haskell, Python)
    12. Types of DSL Graphical DSL Log Workflow Activity Clear Activity Shutdown Activity
    13. DSL Oriented .NET Languages LANGUAGES
    14. F# Ruby Lisp Python Boo C# Smalltalk
    15. F# Ruby Lisp Python CLR Boo DLR C# Smalltalk
    16. I <3
    17. The important advantages over a GPL WHY SHOULD WE USE DSL?
    18. 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.
    19. 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.
    20. 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.
    21. Why is DSL good? Business Peoples and “Rules” Developers and their “Magic”
    22. Read and Write director of finance for the client bank to edit, test, and deploy the business rules of the system without any assistance from IT
    23. Read Write
    24. DSL Building Patterns PATTERNS
    25. Better code readability • Fluent interfaces • Extension methods • LINQ • Workflows • Syntactic sugar • AdHoc LINQ
    26. Fluent interfaces Expect .Once .On(…) .Method(…) .WithAnyArguments() .Will( Return.Value(…) ) NMock mocking library usage
    27. Fluent interfaces Expect public static Expect {…} .Once IRecieverSyntax .On(…) IMethodSyntax .Method(…) IArgumentSyntax .WithAnyArguments() IActionSyntax .Will( Return.Value(…) IAction )
    28. Fluent interfaces public class ExpectationBuilder: IReceiverSyntax, IMethodSyntax, IArgumentSyntax, IActionSyntax {…} public IMethodSyntax On(…){ // … return this; } public IArgumentSyntax Method(…){ // … return this; }
    29. Combinations today.at 3.pm 3.days.from_today at(3.pm)
    30. 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}")
    31. String interpolation print("Now is ${date.Now}.") print("Tomorrow will be ${date.Now + 1d}")
    32. Extension methods DateTime now = VS DateTime res = DateTime.Now; 3.Days() TimeSpan span = .From( TimeSpan.FromDays(3); DateTime.Now DateTime res = ) now + span;
    33. 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; } }
    34. Man, there’s LINQ already Can’t we use that?
    35. We do
    36. LINQ string s1 = GetS1(); VS var res = string s2 = GetS2(); from a in GetS1() string res = from b in GetS2() string.Empty; select a + b; if(s1 != null && s2 != null){ res = s1 + s2; }
    37. 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>(); }
    38. 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); }
    39. 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 little daunting and that using other names might be wise.“ [F# Workflows and Haskell Monads, Expert F#, p232]
    40. C# is no fun. Want more!
    41. Yeah?! F# you!
    42. Workflows type Чо<'a> = | Ничо | Чото of 'a let bindMaybe x f = match x with | Ничо -> Ничо | Чото y -> f y type MaybeBuilder() = member x.Return(what) = Чото what member x.Bind(m, f) = bindMaybe m f let чокак = new MaybeBuilder()
    43. Workflows let first = чокак , let! x = Чото 6 let! y = Чото 5 return (x + y) } let second = чокак , let! x = Ничо let! y = Чото 5 return x+y }
    44. Syntactic sugar
    45. Sweeties • Partial application • Pipelining • Composition • List comprehension • Operators overriding • AST modifications • Measurement units
    46. Million years ago there wasn’t LINQ And I still program C# 2. Can I have some DSL?
    47. AdHoc LINQ Calculation<Item> calculation = Time.Between( Select.First(thisYear), Select.Last(thisYear) );
    48. Simples DSLs on .NET SAMPLES
    49. Validation DSL : IronPython discussion demo discussion
    50. Validation DSL : IronPython public class User : ValidationBase { [Validation("first_name_length")] public string FirstName { get; set; } }
    51. 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>
    52. Validation DSL : IronPython PythonEngine::Execute(“python code here”)
    53. Validation DSL : Boo Rules (Boo) Model (C#) ASP.NET MVC Application
    54. Validation DSL : Boo public class User { public string Username { get; set; } public string Password { get; set; } }
    55. Validation DSL : Boo rule_for "User": validate def(x): results = create_results() if string.IsNullOrEmpty(x.Username) return results
    56. Validation DSL : Boo Boo.Lang.Interpreter. InteractiveInterpreter _interpreter; Func<List<ValidationResult>> createResults = (() => new List<ValidationResult>()); _interpreter.SetValue("create_results", createResults);
    57. Validation DSL : Boo Boo: results.Add(fail("Username and Password are required")) C#: CompilerContext ctx = _interpreter.EvalCompilerInput(new FileInput(_filePath)); foreach (CompilerError error in ctx.Errors) { sb.AppendLine(error.Message); }
    58. Object2RSS DSL : Boo Rules (Boo) Model (C#) ASP.NET MVC Application
    59. 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; } }
    60. 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")
    61. 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(); }
    62. 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"); } }
    63. A BDD framework for .NET and Mono SPECTER FRAMEWORK
    64. MiniBar specification tutorial
    65. MiniBar specification tutorial import Specter.Framework import 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()
    66. MiniBar specification tutorial import Specter.Framework import Bender context "At Bender's bar": _bar as duck setup: [NUnit.Framework.TestFixture] subject _bar = Bender.MiniBar()class EmptyStack: 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()
    67. MiniBar specification tutorial import Specter.Framework [NUnit.Framework.SetUp] import Bender def SetUp(): context "At Bender's bar": _bar as duck subject _bar = setup: subject _bar = Bender.MiniBar() 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()
    68. MiniBar specification tutorial import Specter.Framework import 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) [NUnit.Framework.Test] then I get drunk": specify "If I drink more than ten beers for i in range(10): def BarDrinkOneBeerMustNotThrow(): _bar.DrinkOneBeer() Assert.DoesNotThrow(_bar. DrinkOneBeer()) { _bar.DrinkOneBeer() }.Must.Throw()
    69. MiniBar specification tutorial [NUnit.Framework.Test] import Specter.Framework import Bender def IfIDrink5BeersThenIOwe5Bucks(): context "At Bender's bar": for i in range(5): _bar as duck _bar.DrinkOneBeer() setup: Int32MustModule.Must(_bar.Balance, “Bar subject _bar = Bender.MiniBar() -5").Equal(-5) balance must equal 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()
    70. MiniBar specification tutorial [NUnit.Framework.Test] import Specter.Framework import Bender contextdef IfiDrinkMoreThanTenBeersThenIGetDrunk(): "At Bender's bar": _bar as duck setup: for i in range(10): _bar.DrinkOneBeer() subject _bar = Bender.MiniBar() specify { _bar.DrinkOneBeer() }.Must.Not.Throw() Assert.Throws((typeof(InvalidOperationExc specify "If I drink 5 beers then I owe 5 bucks": eption), _bar.DrinkOneBeer()) 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()
    71. MiniBar specification tutorial
    72. MiniBar specification tutorial namespace Bender class MiniBar: def DrinkOneBeer(): pass [getter(“Balance”)+ _balance = 0
    73. MiniBar specification tutorial
    74. MiniBar specification tutorial namespace Bender class MiniBar: def DrinkOneBeer(): _balance-- if _balance < -10: raise System.Exception("i'm drunk") [getter(“Balance”)+ _balance = 0
    75. MiniBar specification tutorial
    76. thx.
    77. 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/
    78. Resources • http://www.code- magazine.com/article.aspx?quickid=0902041 &page=1 (Building Domain Specific Languages in C#) • http://bradfordcross.blogspot.com/2009/01/e xternal-dsl-vs-internal-dsl-smack- down_24.html (External DSL vs. Internal DSL Smack Down)
    79. 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
    SlideShare Zeitgeist 2009

    + Vitaly BaumVitaly Baum Nominate

    custom

    206 views, 0 favs, 0 embeds more stats

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 206
      • 206 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 0
    • Downloads 4
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?