Code Generation

                         Lecture 10
                          May 4, 2010




                                                  Course IN4308
     Eelco Visser
                                       Master Computer Science
http://eelcovisser.org             Delft University of Technology
Coming up
Lecture 8: Context-sensitive transformation
   ★ design 2
   ★ transformation with dynamic rewrite rules

Lecture 9: Static analysis & error checking
   ★ name resolution, reference resolution
   ★ type analysis

Lecture 10: Code generation
   ★ string templates, code generation by model transformation
   ★ concrete object syntax

Lecture 11: Code generation strategies
   ★ customization of generated code
Code Generation
Code Generation: From Model to Code


Model
  ★ structured representation (abstract syntax)
  ★ produced by parser
  ★ checked for consistency
  ★ transformed to core language

Code
  ★ program text
  ★ no structure
  ★ for consumption by interpreter or compiler
Example: Data Model to Database Schema

entity Blog {
  name :: String
  entries :: List<BlogEntry>
}



         CREATE TABLE IF NOT EXISTS ‘Blog‘ (
           ‘id‘ int(11) NOT NULL auto_increment,
           ‘name‘ text,
           PRIMARY KEY (‘id‘)
         ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

         CREATE TABLE IF NOT EXISTS ‘Blog_entries_BlogEntry‘ (
           ‘parent‘ int(11) NOT NULL,
           ‘value‘ int(11) NOT NULL
         ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
Traversing Abstract Syntax Trees


Pattern matching

 Field(name, SimpleType(x))




Accessor Functions

 if(t instanceof Field) {
   name := t.name();
   if(t.type() instanceof SimpleType) {
     ...
   }
 }
Print Statements
Printing Code

entity-to-sql =
  ?Entity(name, fields);
  <printstring> "DROP TABLE IF EXISTS ‘";
  <printstring> name;
  <printstring> "‘;n";
  <printstring> "CREATE TABLE IF NOT EXISTS ‘";
  <printstring> name;
  <printstring> "‘ ( n";
  <printstring> "‘id‘ int(11) NOT NULL auto_increment;n";
  <map(field-to-sql(|name); printstring> fields;
  <printstring> "PRIMARY KEY (‘id‘)n";
  <printstring> ") ENGINE=MyISAM DEFAULT CHARSET=latin1 ";
  <printstring> "AUTO_INCREMENT=1 ;nn"
Printing Code



Advantages
  ★ accessible (easy to implement in any language)
  ★ concrete syntax
  ★ good performance

Disadvantages
  ★ order of evaluation
  ★ code fragments disrupted to splice meta-data
  ★ no formatting
Composing Strings
String Composition

entity-to-sql :
  Entity(name, fields) ->
  <concat-strings>
     ["DROP TABLE IF EXISTS ‘",name,"‘;n",
      "CREATE TABLE IF NOT EXISTS ‘",name,"‘ ( n",
      "‘id‘ int(11) NOT NULL auto_increment, n",
        <map(field-to-sql(|name));concat-strings> fields,
      "PRIMARY KEY (‘id‘)n",
      ") ENGINE=MyISAM DEFAULT AUTO_INCREMENT=1 ;nn"
   ]

field-to-sql(|entity) :
  Field(name, SimpleType(type)) ->
  <concat-strings>["‘",name,"‘ ",<type-to-sqltype> type,",n"]
String Composition


Advantages
  ★ concrete syntax
  ★ assembly of code fragments independent of order of evaluation




Disadvantages
  ★ disrupted code fragments
  ★ quotes
  ★ escapes
Template Engine
Template Engine



<<DEFINE entity_to_sql FOR entity>>
  DROP TABLE IF EXISTS ‘<<entity.name>>‘;
  CREATE TABLE IF NOT EXISTS ‘<<entity.name>>‘ (
    ‘id‘ int(11) NOT NULL auto_increment,
    <<EXPAND type_to_sqltype FOREACH entity.fields>>
    PRIMARY KEY (‘id‘)
  ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
<<ENDDEFINE>




            DSL for model to text generation
Template Engine

Advantages
  ★ concrete syntax
  ★ less quoting
  ★ long code fragments
  ★ anti-quotation instead of string concatenation
  ★ no escapes of string meta characters

Disadvantages
  ★ no syntax check
  ★ result is string / printed
  ★ no structure
  ★ integrate separate language
String Interpolation
String Interpolation

entity-to-sql :
  Entity(name, fields) ->
    $[DROP TABLE IF EXISTS ‘[name]‘;
       CREATE TABLE IF NOT EXISTS ‘[name]‘ (
       ‘id‘ int(11) NOT NULL auto_increment,
        [<map(field-to-sql(|name))> fields]
       PRIMARY KEY (‘id‘)
       ) ENGINE=MyISAM DEFAULT AUTO_INCREMENT=1;
     ]

field-to-sql(|entity) :
  Field(name, SimpleType(type)) ->
  $[‘[name]‘ [<type-to-sqltype> type]]
String Interpolation


Advantages
  ★ concrete syntax
  ★ assembly of code fragments independent of order of evaluation
  ★ long code fragments
  ★ anti-quotation instead of string concatenation
  ★ no escapes of string meta characters
  ★ formatting, relative indentation

Disadvantages
  ★ escaping of string interpolation meta characters
Composing ASTs
Code Generation by Model Transformation



Code represented as AST
   ★ (typechecked) structured representation

Text generation by pretty-printing
   ★ separate code formatting from code generation

Apply transformations after generation
   ★ aspect weaving
   ★ optimization
Composing Abstract Syntax Trees

grammar-to-signature :
  Grammar(ss, ps) -> Signature(ss, cds)
  where cds := <map(production-to-consdecl)> ps

production-to-consdecl :
  Prod(symbols, sym, annos) -> ConsDecl(x, types, sort)
  where x := <annos-to-constructor> annos
      ; types := <filter(symbol-to-type)> symbols
      ; sort := sym

annos-to-constructor :
  [Anno(Application("cons", [Constant(c)]))] -> constr
  where constr := <unescape; un-double-quote> c
Composing Abstract Syntax Trees




Advantages
  ★ syntax check through type system (if available)
  ★ automatic formatting
  ★ transformation after generation

Disadvantages
  ★ no concrete syntax
Deriving Rewrite Rules
private $name;
    How does this scale?                          function getName(){
                                                    return $this->name;
                                                  }
                                                  function setName($val){
                                                    $this->name = $val;
                                                  }



generate-entity-field-code :
  Field(name, SimpleType(t)) ->
  [ InstanceVariable(Modifiers([Private()]),[Normal(Variable(Simple(name)))])
  , FunctionDecl(get, [], [
      Return(Some(ObjectAccess(Variable(Simple("this")),
             ObjectProperty(Simple(name)))))])
  , FunctionDecl(set, [Param(Variable(Simple("val")))], [
      Expr(Assign(ObjectAccess(Variable(Simple("this")),
                                ObjectProperty(Simple(name))),
                  Variable(Simple("val"))))])
  ]
  with get := <camelcase>["get",name]
  with set := <camelcase>["set",name]
Concrete Object Syntax
Concrete Syntax Patterns


generate-entity-field-code :
  FieldDefinition(str_name, type) -> php-member* |[
     private $str_name ;
     function str_get() {
       return $this->str_name;
     }
     function str_set($val) {
       $this->str_name = $val;
     }
  ]|
  where <is-primitive-type> type
  with str_get := <camelcase>["get",str_name]
  with str_set := <camelcase>["set",str_name]
Concrete Syntax Ingredients



Quotation of code fragment
   ★ |[ .... ]|

Disambiguation through tagging
   ★ php-member*|[ ... ]|

Meta-variables
   ★ $this->str_name = $val
Implementing Concrete Object Syntax



Extending meta-language
  ★ Stratego + PHP



Parsing meta-programs


Normalizing to core syntax
Extending the Meta-Language (1)



module Stratego
exports
  context-free syntax
    Int                               ->   Term   {cons("Int")}
    String                            ->   Term   {cons("Str")}
    Var                               ->   Term   {cons("Var")}
    Id "(" {Term ","}* ")"            ->   Term   {cons("Op")}
    Term "->" Term                    ->   Rule   {cons("RuleNoCond")}
    Term "->" Term "where" Strategy   ->   Rule   {cons("Rule")}
Extending the Meta-Language (2)



module StrategoPHP
imports PHP
exports
  context-free syntax
    "php-member" "|[" ClassMember "]|" -> Term{cons("ToMetaExpr")}
    "php-member*""|[" ClassMember* "]|" -> Term{cons("ToMetaExpr")}
  variables
    "expr_"[A-Za-z0-9_]+ -> Expr {prefer}
    "str_"[A-Za-z0-9_]+ -> String {prefer}
Parsing Concrete Object Syntax

Field(name, SimpleType(t)) -> php-member|[ private $str_name; ]|

==> parse

Rule(Op("Field", [Var("name"), Op("SimpleType",[Var("t")])]),
     ToMetaExpr(InstanceVariable(Modifiers([Private()]),
                  [Normal(Variable(Simple(meta-var("str_name"))))])))

==> meta-explode

Rule(Op("Field", [Var("name"), Op("SimpleType",[Var("t")])]),
     Op("InstanceVariable",[
       Op("Modifiers", [Op("Cons",[Op("Private",[]),Op("Nil",[])])]),
       Op("Cons", [Op("Normal",[Op("Variable",[Op("Simple",
                                       [Var("str_name")])])]),
                   Op("Nil",[])])]))

==> pretty-print

Field(name, SimpleType(t)) ->
InstanceVariable(Modifiers([Private()]),[Normal(Variable(Simple(str_name)))])
Summary of Code Generation Techniques


Print statements              String interpolation
  ★ easy                        ★ template engine built-in

String composition            Abstract syntax
  ★ out of order evaluation     ★ precise, transformation
                                   after generation
Template engines
                              Concrete object syntax
  ★ less quoting
                                ★ precise
                                ★ concrete
Schedule
Case 3
  ★ Deadline extension: May 9 23:59

Case 4
  ★ `take home exam’
  ★ Questions about lectures 11 to 14
  ★ Deadline: June 15

Design 2
  ★ Syntax for your DSL

Next
  ★ No lecture next week (May 11)
  ★ Lecture 11: code generation policies

Code Generation

  • 1.
    Code Generation Lecture 10 May 4, 2010 Course IN4308 Eelco Visser Master Computer Science http://eelcovisser.org Delft University of Technology
  • 2.
    Coming up Lecture 8:Context-sensitive transformation ★ design 2 ★ transformation with dynamic rewrite rules Lecture 9: Static analysis & error checking ★ name resolution, reference resolution ★ type analysis Lecture 10: Code generation ★ string templates, code generation by model transformation ★ concrete object syntax Lecture 11: Code generation strategies ★ customization of generated code
  • 3.
  • 4.
    Code Generation: FromModel to Code Model ★ structured representation (abstract syntax) ★ produced by parser ★ checked for consistency ★ transformed to core language Code ★ program text ★ no structure ★ for consumption by interpreter or compiler
  • 5.
    Example: Data Modelto Database Schema entity Blog { name :: String entries :: List<BlogEntry> } CREATE TABLE IF NOT EXISTS ‘Blog‘ ( ‘id‘ int(11) NOT NULL auto_increment, ‘name‘ text, PRIMARY KEY (‘id‘) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS ‘Blog_entries_BlogEntry‘ ( ‘parent‘ int(11) NOT NULL, ‘value‘ int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
  • 6.
    Traversing Abstract SyntaxTrees Pattern matching Field(name, SimpleType(x)) Accessor Functions if(t instanceof Field) { name := t.name(); if(t.type() instanceof SimpleType) { ... } }
  • 7.
  • 8.
    Printing Code entity-to-sql = ?Entity(name, fields); <printstring> "DROP TABLE IF EXISTS ‘"; <printstring> name; <printstring> "‘;n"; <printstring> "CREATE TABLE IF NOT EXISTS ‘"; <printstring> name; <printstring> "‘ ( n"; <printstring> "‘id‘ int(11) NOT NULL auto_increment;n"; <map(field-to-sql(|name); printstring> fields; <printstring> "PRIMARY KEY (‘id‘)n"; <printstring> ") ENGINE=MyISAM DEFAULT CHARSET=latin1 "; <printstring> "AUTO_INCREMENT=1 ;nn"
  • 9.
    Printing Code Advantages ★ accessible (easy to implement in any language) ★ concrete syntax ★ good performance Disadvantages ★ order of evaluation ★ code fragments disrupted to splice meta-data ★ no formatting
  • 10.
  • 11.
    String Composition entity-to-sql : Entity(name, fields) -> <concat-strings> ["DROP TABLE IF EXISTS ‘",name,"‘;n", "CREATE TABLE IF NOT EXISTS ‘",name,"‘ ( n", "‘id‘ int(11) NOT NULL auto_increment, n", <map(field-to-sql(|name));concat-strings> fields, "PRIMARY KEY (‘id‘)n", ") ENGINE=MyISAM DEFAULT AUTO_INCREMENT=1 ;nn" ] field-to-sql(|entity) : Field(name, SimpleType(type)) -> <concat-strings>["‘",name,"‘ ",<type-to-sqltype> type,",n"]
  • 12.
    String Composition Advantages ★ concrete syntax ★ assembly of code fragments independent of order of evaluation Disadvantages ★ disrupted code fragments ★ quotes ★ escapes
  • 13.
  • 14.
    Template Engine <<DEFINE entity_to_sqlFOR entity>> DROP TABLE IF EXISTS ‘<<entity.name>>‘; CREATE TABLE IF NOT EXISTS ‘<<entity.name>>‘ ( ‘id‘ int(11) NOT NULL auto_increment, <<EXPAND type_to_sqltype FOREACH entity.fields>> PRIMARY KEY (‘id‘) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1; <<ENDDEFINE> DSL for model to text generation
  • 15.
    Template Engine Advantages ★ concrete syntax ★ less quoting ★ long code fragments ★ anti-quotation instead of string concatenation ★ no escapes of string meta characters Disadvantages ★ no syntax check ★ result is string / printed ★ no structure ★ integrate separate language
  • 16.
  • 17.
    String Interpolation entity-to-sql : Entity(name, fields) -> $[DROP TABLE IF EXISTS ‘[name]‘; CREATE TABLE IF NOT EXISTS ‘[name]‘ ( ‘id‘ int(11) NOT NULL auto_increment, [<map(field-to-sql(|name))> fields] PRIMARY KEY (‘id‘) ) ENGINE=MyISAM DEFAULT AUTO_INCREMENT=1; ] field-to-sql(|entity) : Field(name, SimpleType(type)) -> $[‘[name]‘ [<type-to-sqltype> type]]
  • 18.
    String Interpolation Advantages ★ concrete syntax ★ assembly of code fragments independent of order of evaluation ★ long code fragments ★ anti-quotation instead of string concatenation ★ no escapes of string meta characters ★ formatting, relative indentation Disadvantages ★ escaping of string interpolation meta characters
  • 19.
  • 20.
    Code Generation byModel Transformation Code represented as AST ★ (typechecked) structured representation Text generation by pretty-printing ★ separate code formatting from code generation Apply transformations after generation ★ aspect weaving ★ optimization
  • 21.
    Composing Abstract SyntaxTrees grammar-to-signature : Grammar(ss, ps) -> Signature(ss, cds) where cds := <map(production-to-consdecl)> ps production-to-consdecl : Prod(symbols, sym, annos) -> ConsDecl(x, types, sort) where x := <annos-to-constructor> annos ; types := <filter(symbol-to-type)> symbols ; sort := sym annos-to-constructor : [Anno(Application("cons", [Constant(c)]))] -> constr where constr := <unescape; un-double-quote> c
  • 22.
    Composing Abstract SyntaxTrees Advantages ★ syntax check through type system (if available) ★ automatic formatting ★ transformation after generation Disadvantages ★ no concrete syntax
  • 23.
  • 24.
    private $name; How does this scale? function getName(){ return $this->name; } function setName($val){ $this->name = $val; } generate-entity-field-code : Field(name, SimpleType(t)) -> [ InstanceVariable(Modifiers([Private()]),[Normal(Variable(Simple(name)))]) , FunctionDecl(get, [], [ Return(Some(ObjectAccess(Variable(Simple("this")), ObjectProperty(Simple(name)))))]) , FunctionDecl(set, [Param(Variable(Simple("val")))], [ Expr(Assign(ObjectAccess(Variable(Simple("this")), ObjectProperty(Simple(name))), Variable(Simple("val"))))]) ] with get := <camelcase>["get",name] with set := <camelcase>["set",name]
  • 25.
  • 26.
    Concrete Syntax Patterns generate-entity-field-code: FieldDefinition(str_name, type) -> php-member* |[ private $str_name ; function str_get() { return $this->str_name; } function str_set($val) { $this->str_name = $val; } ]| where <is-primitive-type> type with str_get := <camelcase>["get",str_name] with str_set := <camelcase>["set",str_name]
  • 27.
    Concrete Syntax Ingredients Quotationof code fragment ★ |[ .... ]| Disambiguation through tagging ★ php-member*|[ ... ]| Meta-variables ★ $this->str_name = $val
  • 28.
    Implementing Concrete ObjectSyntax Extending meta-language ★ Stratego + PHP Parsing meta-programs Normalizing to core syntax
  • 29.
    Extending the Meta-Language(1) module Stratego exports context-free syntax Int -> Term {cons("Int")} String -> Term {cons("Str")} Var -> Term {cons("Var")} Id "(" {Term ","}* ")" -> Term {cons("Op")} Term "->" Term -> Rule {cons("RuleNoCond")} Term "->" Term "where" Strategy -> Rule {cons("Rule")}
  • 30.
    Extending the Meta-Language(2) module StrategoPHP imports PHP exports context-free syntax "php-member" "|[" ClassMember "]|" -> Term{cons("ToMetaExpr")} "php-member*""|[" ClassMember* "]|" -> Term{cons("ToMetaExpr")} variables "expr_"[A-Za-z0-9_]+ -> Expr {prefer} "str_"[A-Za-z0-9_]+ -> String {prefer}
  • 31.
    Parsing Concrete ObjectSyntax Field(name, SimpleType(t)) -> php-member|[ private $str_name; ]| ==> parse Rule(Op("Field", [Var("name"), Op("SimpleType",[Var("t")])]), ToMetaExpr(InstanceVariable(Modifiers([Private()]), [Normal(Variable(Simple(meta-var("str_name"))))]))) ==> meta-explode Rule(Op("Field", [Var("name"), Op("SimpleType",[Var("t")])]), Op("InstanceVariable",[ Op("Modifiers", [Op("Cons",[Op("Private",[]),Op("Nil",[])])]), Op("Cons", [Op("Normal",[Op("Variable",[Op("Simple", [Var("str_name")])])]), Op("Nil",[])])])) ==> pretty-print Field(name, SimpleType(t)) -> InstanceVariable(Modifiers([Private()]),[Normal(Variable(Simple(str_name)))])
  • 32.
    Summary of CodeGeneration Techniques Print statements String interpolation ★ easy ★ template engine built-in String composition Abstract syntax ★ out of order evaluation ★ precise, transformation after generation Template engines Concrete object syntax ★ less quoting ★ precise ★ concrete
  • 33.
    Schedule Case 3 ★ Deadline extension: May 9 23:59 Case 4 ★ `take home exam’ ★ Questions about lectures 11 to 14 ★ Deadline: June 15 Design 2 ★ Syntax for your DSL Next ★ No lecture next week (May 11) ★ Lecture 11: code generation policies