Un language pour dominer le monde !

(version humble: Un DSL pour se simplifier la vie)

Ludovic L'HOURS github.com/madbrain

Un language ok, mais pour quoi faire ?

  • Quel paradigme (Impératif, Fonctionel, Objet, Déclaratif, etc.) ?
  • Quel public ?
  • Quelle utilisation ?
  • Analysons la concurrence !

La galaxie des langages

Langages généralistes / DSL

Est ce qu'un nouveau langage généraliste est vraiment utile ?

Il existe par contre de nombreux domaines où un langage spécifique (DSL) serait judicieux

Le métier du plombier

  • Vocabulaire : Valve, Filtre, Pompe, etc.
  • Objectif : décrire et analyser des réseaux hydrauliques

Le langage du plombier

main:inlet -> valve -> f1:filter { transfert: x^2 + 1 }

f1 -> pump { power: 500W, pressure: 1 bar }
   -> heater { power: 2kW }
   -> acc:accumulator
   -> o1:outlet

f1 -> v1:valve -> o2:outlet

v1 + acc -> mixer -> o3:outlet

Langages généralistes / DSL

Un langage dédié (Domain specific language) est un langage de programmation dont les spécifications sont conçues pour répondre aux contraintes d'un domaine d'application précis
AvantagesInconvénients
Plus expressifNouvelle syntaxe
Plus compactPérimètre réduit*

*implique plusieurs langages (cf. HTML, CSS, JS)

Utilisation du DSL

%plumber --pipe-diameter input.plumb
42
%plumber --pipe-diameter other-input.plumb
Exception in thread "main" org.plumber.parser.ParseException: Parse Error
	at org.plumber.parser.Parser.doParseLiteral(Parser.java:21)
	at org.plumber.parser.Parser.doParseExpression(Parser.java:17)
	at org.plumber.parser.Parser.doParseStatement(Parser.java:13)
	at org.plumber.parser.Parser.doParseFile(Parser.java:9)
	at org.plumber.parser.Parser.parse(Parser.java:5)
	at org.plumber.interpreter.Launcher.main(Launcher.java:7)

WTF?!?

Le langage et son écosystème

Le langage, afin d'être exploitable par le plus grand nombre, doit être associé à des outils qui fournissent:

  • Indication des erreurs
  • Aide à la résolution des erreurs
  • Aide à la saisie (complétion)
  • Templates
  • Search/Query
  • Refactorings (renommage, etc.)
  • => Intégré dans mon IDE
  • => Coût de réalisation élevé

DSL externe/interne

Un DSL interne est écrit en utilisant un langage hôte, on peut donc profiter de l'outillage associé à ce langage hôte.

Exemple de DSL interne (Java):

  • JOOQ
  • Mockito / AssertJ
  • Gatling

Construction d'un DSL interne

  • Pattern Builder
  • Fluent API (method chaining)
  • Dérivation de construction Objet depuis des règles de grammaire [Source blog JOOQ]

Règles de construction

  • Grammaire d'entrée admissible
  • Grosso modo équivalent à LL(1)
  • Chaque interface est un état
  • Chaque méthode (mot clé) fait changer d'état

interface Start {
  End singleWord();
  End parameterisedWord(String parameter);
  Intermediate1 word1();
  Intermediate2 word2();
  Intermediate3 word3();
}
interface End {
  void end();
}
interface Intermediate1 extends End {
  End optionalWord();
}
interface Intermediate2 {
  End wordChoiceA();
  End wordChoiceB();
}
interface Intermediate3 extends End {
  Intermediate3 word3();
}

Exemple avec le langage du plombier

  • Network ::= Statement+
  • Statement ::= Element ( "->" Element )+
  • Element ::= IDENT
    | (IDENT ":")? ElementName ("{" ... "}")?
  • ElementName ::= "pump" | "filter" | ...

Exemple avec le langage du plombier transformé

  • Network ::= Statement+
  • Statement ::= Element ( "->" Element )+
  • Element ::= "ref" IDENT
    | ElementName (":" IDENT)? ("{" ... "}")?
  • ElementName ::= "pump" | "filter" | ...

public interface NewElementBuilder {
    ElementBuilder pump();
    ElementBuilder filter();
    ElementBuilder pump(String name);
    ElementBuilder filter(String name);
    NextElementBuilder ref(String name);
}
public interface ElementBuilder extends NextElementBuilder {
    ParametersBuilder parameters();
}
public interface NextElementBuilder extends NewElementBuilder {
    NewElementBuilder pipe();
}

builder()
  .pump("main").pipe().filter("f1").parameters().pipe().pump()
  .ref("f1").pipe().pump();

Conclusion

Pour créer son propre langage :

  • Démarrer rapidement avec un DSL interne
  • Embrayer sur un DSL externe user friendly
  • Booster votre DSL externe en l'intégrant à votre IDE
  • Et enfin on obtient...

Des questions ?