Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

KernelF: a functional core for domain-specific languages in JetBrains MPS


Published on

Slides of Mikhail Barash's talk at ClojuTRE 2018 / Small FP conference (Helsinki, September 13th, 2018).

Published in: Software
  • Login to see the comments

KernelF: a functional core for domain-specific languages in JetBrains MPS

  1. 1. KernelF Turku Centre for Computer Science Mikhail Barash Åbo Akademi Finland a functional core @mikhail_barash for DSLs
  2. 2. Domain-Specific Languages
  3. 3. 1997
  4. 4. John, CEO publishing company left right top bottom 1 page enumeration margins single page range open interval 20..30 40- measurement units mm cm inches
  5. 5. 1999
  6. 6. Hi, We've just got new order, diary No: 1999/3456/32-A. It's books, covers 250g/m2. Left: 30 mm Top: 15 mm Right: 20 mm Bottom: 1 in Thanks, secretary typesetter some structure
  7. 7. 2000
  8. 8. Jane, developer
  9. 9. typesetter developer
  10. 10. 2001
  11. 11. start marker end marker row: start.row + 1 col: start.col + 6 row: start.row + 4 col: start.col + 8 error messages typesetter
  12. 12. 2002
  13. 13. 1,2,20-30,40- implemented “manually”error messages
  14. 14. 2003
  15. 15. error messages typesetter developer
  16. 16. 2007
  17. 17. typesetter developer cryptic error messages
  18. 18. DSL without tailored IDE will not be used
  19. 19. 2010s
  20. 20. Language workbenches requires parsingtextual DSL automates definition of languageslanguage workbench implementing IDE is tedious vital for adoption and success of languageIDE automates creation of IDEs for languages
  21. 21. IDEA-level custom IDE rich notation custom auto complete intentions (quick fixes) domain-specific error messages
  22. 22. key representation of program abstract syntax tree (AST) can be projected into different representations text diagrams tables forms textual form of code only meant for the programmer but it is unambiguous can look ambiguous no parsing needed Projectional editing How does MPS work?
  23. 23. “variable declaration” expression
  24. 24. Embedding Expressions Language into Page Margins Language
  25. 25. Pages Margins DSL with embedded expressions language ”variable declaration” expression enabling expressions into already defined Page Margins DSL
  26. 26. Embedding languages embedding not in the sense “embedded DSL” “internal DSL” Scala XML Lang A Lang B neither A nor B change should work even with conflicting syntaxes non-invasive embedding
  27. 27. KernelF “expressions language” Markus Voelter
  28. 28. Overview of KernelF primitive types arithmetical and comparison operations higher-order functions number option types attempt types null values exception handling static types user-defined types tuples functional type inference Boolean string enum record + - * / == != > < >= <= no generics no algebraic types built-in collections are generic not designed for building abstractions abstractions – in host DSL keyword-rich many first-class constructs enum with data all immutable
  29. 29. natural notation for mathematical expressions Excel-style spreadsheet within code
  30. 30. Number types int float too much focused on need of programmers business domain doesn’t find them useful no usual types numbers with range and precision number[10|20]{2} number[0|inf] number[-inf|inf]{0} positive integer integer, unlimited range decimal with 2 decimal places, value between 10 and 20 number{2} number[2.2|3.8] range as specified, precision derived decimal with 2 decimal places, unlimited range
  31. 31. Type tags additional information attached to a typetag checked by type system display(airportCode : string) require only capitalized strings display(airportCode : string<capitalized>) <!tag>unary tags doesn’t have the taghas the tag unspecified n-ary tags set of ordered values easy normal hard val simpleText : string<easy> = “I go to school.” val normalText : string<normal> = “This is an abstract painting.” val complexText : string<hard> = “We semi-classically quantize circular strings.” <tag> fun sendToProfessor(text: string<hard->) fun publishInTwitter(text: string<easy+>) fun printOnTShirt(text: string<normal>) hard, normal, easy easy, normal, hard toAllUpper(s : string) : string<capitalized>
  32. 32. Option types handle null values in a typesafe way val x : option<number> = if something then 1 else none a term in an expression evaluates to none the whole expression is none⇒ test whether an option does contain a value isSome(x)
  33. 33. Attempt types error handling type system support for error handling base type attempt type error literals attempt< baseType | err1, err2, ..., errN > fun getWeather(city: string): attempt<number[-40|40] | timeout, notFound> = if ... then getTemp else if ... then error(timeout) else error(notFound) val displayDegrees : string = try getWeather(“Helsinki”) => val + “ degrees” error<timeout> => “Timeout” error<notFound> => “Not found” “payload” to be handled by calling code
  34. 34. via metaprogramming “Flexible” language adding new first-class constructs removing constructs exchangeable primitive types overriding syntax new syntax for existing language constructs replace primitive types with types from the domain LISP extensibleRacket parser-based extend the language, but not the IDE syntactic style difficult for non-programmers only textual languages language workbench
  35. 35. Natural language function calls @syntax{ accelerate to @[to] with @[at] } car.accelerate to 10 with 2 car.accelerate(10, 2) ext fun accelerate (this: Car, to: int, at: int) = ... also appears in autocomplete menu positional arguments less easily perceived by business users
  36. 36. Stateful language effect tracking expressions don’t have side effects results of function calls can be cached KernelF can be extended to support expressions with side effects which functions can be cached? effects read write idempotence
  37. 37. Stateful language boxes immutable data can’t change a value after it’s been created invent new name for new value boxes do not require mutable version of all immutable data structures immutable its contents can change box val counter: box<int> = box(0) fun increase() { counter.update(counter.val + 1) } read effectmodify effect counter.update(it + 1) current content of the box val a = list(1, 2, 3) val b =