6 Replies - 2292 Views - Last Post: 13 November 2014 - 02:16 PM

#1 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Template Functions & Template Masks

Posted 19 September 2014 - 04:45 PM

Template Functions & Template Mask

Template Functions will allow you return the expression (syntax node) for the body of the function. I'm including statements as an expression as well. Inside them anything but not inside a template hole %{ } will be treat as a code quotation. Anything inside a template hole %{ } will be treated as executable code and evaluated.

C#
template CS.Expr VarDeclaration<T>( String! name, T value )
{
  var %{name} = %{value};
}


VB.net
Template(Of T)( name As String!, Value As T) As VB.Expr
  Dim %{name} As %{GetType(T)} = %{Value}
End Template





Template Mask

Template Mask is closely related to Template Functions instead of synthesising the expression. It generate code to see if a syntax node matches the pattern of the template.

Example

Template Mask IF_BLOCK() As Mask< VB.Expr >
  If %{0} Then
     %{1}
  End If
End Template
 ' Named Mask Holes
Template Mask IF_BLOCK() As Mask< VB.Expr >
  If %{ pred } Then
     %{ body }
  End If
End Template


Will generate a template mask to see if the node is a If Block.
Also note it will match against Else If , Else, etc because the inner body could be any expression.

So how can they used?
The following example would replace the if-block with an if-statement if it contains only a single line of code.


Template IF_Statement( pred As VB.Expr<Bool>, code As VB.Expr ) As VB.Expre
  If %{ pred } Then %{ code }
End Template


 Dim q = IF_BLOCK()
 
 If q.Matches( node ) Then
    If q(1).Lines.Count = 0 Then node =  IF_Statement( q(0), q(1) ) 
 End If
' Using the name mask holes
 If q.Matches( node ) Then
    If q( "code" ).Lines.Count = 0 Then node =  IF_Statement( q("pred"), q("code") ) 
 End If



Since the compiler is generating the template mask. It maybe also possible to provide IDE support to restrict the possible inputs. Eg If_Statement( q( "foo" ), q( "bar" ) are compile-time errors.

This post has been edited by AdamSpeight2008: 19 September 2014 - 04:45 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Template Functions & Template Masks

#2 lucky3  Icon User is offline

  • Friend lucky3 As IHelpable
  • member icon

Reputation: 233
  • View blog
  • Posts: 770
  • Joined: 19-October 11

Re: Template Functions & Template Masks

Posted 08 November 2014 - 01:45 AM

First of, thank you Adam for your contribution. I must admit, I have no idea what this is about. Is this something new for Roslyn, or where should I start looking for? Where do those template and CS.Expr come from? Can you provide some useful links perhaps? I went searching for "template function", "template mask", "CS class", "CS.Expr", and so on. I'm sure I'm not the only one puzzled here :)
Was This Post Helpful? 0
  • +
  • -

#3 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Re: Template Functions & Template Masks

Posted 08 November 2014 - 04:32 PM

lucky3, Have a look at the Roslyn codeplex discussions. (Discussion Topic)

CS.Expr is CSharp expression, VB.Expr is a VB.net expression

VB.Expr<Bool> is a VB.net expression that evaluates to a Boolean, like Func<Bool>

Basic premise to template function and template masks, is to get the compiler to constructor the syntaxtree / syntax expression for you. Rather than the coder have to use the syntaxnode builder functions.

If I just use the codefixes from my blog post Roslyn Diagnostic & Code Fix For Mis-Assignment In Constructor.
Instead I use template functions.
Template Function Prefix_WithUnderscore( target As __ , source As __ ) As VB.Expr
  _%{ target } = %{ source }
End Template

Template Function Prefix_WithMe( target As __ , source As __ ) As VB.Expr
  Me.%{ target } = %{ source }
End Function


template CS.Expr Prefix_WithUnderscore ( __ target, __ source )
{
  _%{ target } = %{ source };
}
template CS.Expr Prefix_ThisDot ( __ target, __ source )
{
  this.%{ target } = %{ source };
}



You can see it is much simpler to write. Template Mask help you to write the diagnostics.

These function are only applicable at compile-time.
Was This Post Helpful? 0
  • +
  • -

#4 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Re: Template Functions & Template Masks

Posted 10 November 2014 - 10:38 AM

lucky3, I been tweaking the syntax a bit.
 |{  }|  Template
 /{  }/  Template Arg Hole


This is to enable executable code to be use when making templates.
For example unpack a tuple as a method's parameter arguments

template unpack(this tu : Tuple , method : Action ) : CS.Expr
{
  |{ /{ method }/ ( /{ tu[0] }/ }|
  for(int i = 1; i < tu.Arity; i++)
  {
    |{, /{ tu[i] }/ }|
  }
  |{ ) }|
}



If tu was Tuple< Int, String, Double > then the following would be the result
 method( (tu.Item1 As Int) , (tu.Item2 As String) , (tu.Item3 As Double) )


Was This Post Helpful? 0
  • +
  • -

#5 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Re: Template Functions & Template Masks

Posted 10 November 2014 - 02:37 PM

Another example that replaces the following construct
int x = 0;
if( cond )
{
  x = 5;
}
else
{
  x = 10;
}


it with an in-line if expression
int x = 0;
x = ( cond ) ? ( 5 ) : ( 10 ) ;



Let's see how do that via templates and template masks.
template mask simple_assignment() : template_mask
{
  |{ /{ target }/ = /{ source }/ ; |}
}

template assignment_viaCondition_ <T>( target : __      , cond   : Expr<Bool> ,
                                       valueA : Expr<T> , valueB : Expr<T> ) : CS.Expr
{
  |{ var /{ target }/ = (/{ cond }/ ) ? ( /{ valueA }/ ) : ( /{ valueB }/ ) ; |} 
}

template mask _IfElse_() : template_mask  
{
  |{ if( /{ cond }/ 
     {
       /{ on_true }/
     }
     else
     {
       /{ on_false }/
     }
   }|
}

AnalyseNode ( node : SyntaxNode )
{
  var mn = template.Match( node , _IfElse_ )
  if( !mn.Valid ) return
  var part_0 = template.Match( mn["on_true"], simple_assignment )
  var part_1 = template.Match( mn["on_false"], simple_assignment )
  if( part_0.Valid && part_1.Valid )
  {
    if( part_0["target"] == part_1["target"] ) 
    { 
      node.ReplaceWith( assignment_viaCondition_( part_0["target"] , mn["cond"] , part_0["source"],  part_1["source"] );
    }
  }
}


Was This Post Helpful? 0
  • +
  • -

#6 lucky3  Icon User is offline

  • Friend lucky3 As IHelpable
  • member icon

Reputation: 233
  • View blog
  • Posts: 770
  • Joined: 19-October 11

Re: Template Functions & Template Masks

Posted 13 November 2014 - 02:02 PM

Hey AdamSpeight2008, I've read your blog post here, and it's a pity there's close to none readers of it. You provided VB.NET and C# examples, but in reality there are only VB.NET examples and no one noticed. I've just created new Azure VM with VS2015 preview, and installed SDK and other recommended VSIX. I will go through diagnostic and code fix scenarios, and will try your example as well. I'll be back with some more questions for sure. Thanks again for being helpful.
Was This Post Helpful? 0
  • +
  • -

#7 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon

Reputation: 2298
  • View blog
  • Posts: 9,535
  • Joined: 29-May 08

Re: Template Functions & Template Masks

Posted 13 November 2014 - 02:16 PM

The example in the blog one works for the VS2014cpt4 release. They change the API use for diagnostics.
Template Function and Template Mask are a feature request I would like to see implement to help with writing code-fixes and diagnostics.

The examples are written in VB.net yes but one does the analyse for C# and another does the VB.net

This post has been edited by AdamSpeight2008: 13 November 2014 - 02:17 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1