Upload
robin-sedlaczek
View
256
Download
1
Embed Size (px)
Citation preview
Roslyn – Ein offener Compiler. Ja, und nun?@ .NET Summit 2016
Robin Sedlaczek | CTO Fairmas GmbH | .NET User Group Berlin
RobinSedlaczek
RobinSedlaczek
CTO der Fairmas GmbH in Berlin Community Leader DNUG Berlin Blogger / .NET Code Geek Sprecher MSDN Moderator Freier Autor (Entwickler.de, Heise, DotNetPro, Informatik aktuell) Open Source (SharpGL, Roslyn, FxCopAnalyzers)
Robin Sedlaczek
RobinSedlaczek
Click to edit Master subtitle style
RobinSedlaczek
01 | Überblick
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
RobinSedlaczek
[email protected] COMPILER-BLACKBOX
Compiler sind klassisch gesehen Blackboxes Geschlossene Softwarekomponenten Übersetzen Quellcode in etwas Ausführbares
(Binärdateien)
Compiler
/// <summary> /// This is the base class for all /// shaders (vertex and fragment). It /// offers functionality which is core /// to all shaders, such as file /// loading and binding. /// </summary> public class Shader { public void Create(OpenGL gl, uint shaderType, string source) { // Create the OpenGL shader object. shaderObject = gl.CreateShader(shaderType);
// Set the shader source. gl.ShaderSource(shaderObject, source);
// Compile the shader object. gl.CompileShader(shaderObject);
// Now that we've compiled the shader, check // it's compilation status. If it's not // compiled properly, we're going to throw // an exception. if (GetCompileStatus(gl) == false) { throw new ShaderCompilationException( string.Format(
"Failed to compile shader {0}.", shaderObject), GetInfoLog(gl)); } }
Code File
1 1 0 0 10 1 11 1 0 1 01 1 10 1 1 1 1 0 0 11 0 1 0 11 1 0 0 1 0 1 10 1 1 1 0 11 1 0 1 0 0 0 11 0 1 0 10 1 1 1 1 0 0 11 0 1 0 11 1 0 0 1 0 1 10 1 1 0 11 0 1 0 1
Binary File
RobinSedlaczek
[email protected] PROBLEM MIT DER BLACKBOX
tiefes Verständnis des Codes während Übersetzung Wissen, dass von IDEs und Werkzeugen genutzt werden
könnte Problem: Wissen steht nach Kompilierung nicht mehr zur
Verfügung Devs/Toolhersteller müssen ggf. Code selbst analysieren
Compiler
RobinSedlaczek
[email protected]ÖSUNG DES PROBLEMS
Aufbrechen der Blackbox Bereitstellung einer API-Schicht über dem Compiler Bereitstellung der Compiler-Ergebnisse über Objektmodelle
Phase 1 Phase 2 Phase 3 Phase 4
Blackbox wird zur Plattform:
.NET Compiler Platform
RobinSedlaczek
[email protected]/NUTZEN
Zugriff auf Compiler-Wissen zu jeder Zeit Code-bezogenen Aufgaben in eigenen Anwendungen Metaprogrammierung Codetransformation und Codegenerierung Interaktivität (VS Immediate Window, C# Script, REPL) Einbettung C#/VB in DSLs
Soweit die technische Sicht…
RobinSedlaczek
[email protected] SOURCE
Roslyn ist Open Source! https://github.com/dotnet/roslyn
Verwaltet von der .NET Foundation http://www.dotnetfoundation.org/projects
Einblicke und Debugging des Codes Mitwirkung der Community Fork für eigene Zwecke
RobinSedlaczek
[email protected] STUDIO
VS 2015: umfassender Umbau der IDE; Editor- und Sprachfeatures basieren nun auf Roslyn
.NET Compiler Platform SDK als VS-Extension verfügbar 3 Projektvorlagen (Analyzer, Refactoring, Stand-Alone) Syntax Visualizer Visual Studio 2015 SDK vorausgesetzt
Compiler/Workspace-APIs als NuGet-Packages verfügbar Scripting-API als NuGet-Package verfügbar
Click to edit Master subtitle style
RobinSedlaczek
02 | Grundlagen
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
RobinSedlaczek
[email protected] TUT EIN COMPILER?
Übersetzt z.B. VB.NET, C# nach IL Code, C# nach Maschinencode (.NET Native), C/C++ in Maschinencode...
Compiler
/// <summary> /// This is the base class for all /// shaders (vertex and fragment). It /// offers functionality which is core /// to all shaders, such as file /// loading and binding. /// </summary> public class Shader { public void Create(OpenGL gl, uint shaderType, string source) { // Create the OpenGL shader object. shaderObject = gl.CreateShader(shaderType);
// Set the shader source. gl.ShaderSource(shaderObject, source);
// Compile the shader object. gl.CompileShader(shaderObject);
// Now that we've compiled the shader, check // it's compilation status. If it's not // compiled properly, we're going to throw // an exception. if (GetCompileStatus(gl) == false) { throw new ShaderCompilationException( string.Format(
"Failed to compile shader {0}.", shaderObject), GetInfoLog(gl)); } }
Code File
1 1 0 0 10 1 11 1 0 1 01 1 10 1 1 1 1 0 0 11 0 1 0 11 1 0 0 1 0 1 10 1 1 1 0 11 1 0 1 0 0 0 11 0 1 0 10 1 1 1 1 0 0 11 0 1 0 11 1 0 0 1 0 1 10 1 1 0 11 0 1 0 1
Binary File
Allgemein: übersetzt Programm aus formaler Quellsprache in semantisch äquivalente formale Zielsprache
RobinSedlaczek
Aber wie genau macht der Compiler das? Wie kann der Compiler eine einfache Textdatei inhaltlich
verstehen? Wie verwandelt er den Text in ausführbare Bits und
Bytes?
RobinSedlaczek
[email protected]ÜRLICHE VS. FORMALE SPRACHEN
Komplexität Ständiger Fluss Mehrdeutigkeit Fehlertoleranz
RobinSedlaczek
[email protected] SIND FORMALE SPRACHEN?
Mathematische Beschreibung einer Sprache
Alphabet + Wortbildungsregeln Werden durch Zustandsautomaten
erkannt Klassifiziert in Chomsky-Hierarchie„Menge von Wörtern, die über einem
bestimmten Alphabet und nach definierten Regeln gebildet werden können.“
RobinSedlaczek
[email protected] FORMALE SPRACHE
Mathematische Beschreibung = formale Grammatik
V = nicht-terminale ZeichenΣ = terminale Zeichen (Alphabet)R = Produktionen (Regeln)S = Startsymbol (aus V)
RobinSedlaczek
[email protected] FORMALE SPRACHE
Definition: Die Sprache beinhaltet Bedingungsanweisungen. Diese können verschachtelt sein. Bedingungsanweisungen können etwas auf wahr oder falsch testen.
V = { expr, condition, left, right }Σ = { id, if, (, ), {, }, true, false, == }R = { expr if (condition) { expr }, condition left == right, left id, left true, left false, right id, right true, right false }S = expr
Findest Du den Fehler In der Grammatik-
Definition? Was passiert, wenn wir das
nicht fixen? Wie müsste der Fix aussehen?
RobinSedlaczek
[email protected] FORMALE SPRACHE
Ist der folgende Ausdruck Teil der Sprache?
Start: expr
(1) if (condition) { expr }
(1) if (condition) { if (condition) { } }
(2) if (left == right) { if (condition)
{ } }
(2) if (left == right) { if (left == right)
{ } }
(3) if (id == right) { if (left == right)
{ } }
(7) if (id == true) { if (left == right)
{ } }
(5) if (id == true) { if (false == right) {
} }
(6) if (id == true) { if (false == id)
{ } }
V = { expr, condition, left, right }Σ = { id, if, (, ), {, }, true, false, == }R = { expr if (condition) { expr }, condition left == right, left id, left true, left false, right id, right true, right false }S = expr
(1)(2)(3)(4)(5)(6)(7)(8)
Ausdruck ist Teil der Sprache!
if (id == true) { if (false == id) { } }
RobinSedlaczek
Formales Beschreiben von Textstrukturen (Grammatik)
Programmiersprachen
Textstrukturen können mit Algorithmus erkannt werden (Parsen)
Einlesen, Syntaxüberprüfung
BEISPIEL FORMALE SPRACHEWas bedeutet das für einen Compiler?
RobinSedlaczek
[email protected] FORMALE SPRACHE
expr
conditionif (
AST (Abstract Syntax
Tree)
) { }expr
Start: expr
if (condition) { expr }
if (condition) { if (condition) { } }
if (left == right) { if (condition)
{ } }
if (left == right) { if (left == right) {
} }
if (id == right) { if (left == right)
{ } }
if (id == true) { if (left == right) { }
}
if (id == true) { if (false == right) {
} }
if (id == true) { if (false == id)
{ } }
conditionif ( )
{ }
left == right
left == right
id
true
false
id
nicht-terminalterminal
RobinSedlaczek
Textstrukturen (Syntax) als Baumstruktur darstellbar
Analyse und Auswertung des Baums Syntaxanalyse Tiefes Verständnis der Textstruktur
BEISPIEL FORMALE SPRACHEWas bedeutet das für einen Compiler?
RobinSedlaczek
[email protected] EINES COMPILERS
Zerlegen des Quelltextes in Tokens
Parsen der Tokens in die Syntax, die von der Grammatik vorgegeben ist (AST)
Tokenizer/Lexer Parser
Lexikalische Analyse
Syntaktische Analyse
RobinSedlaczek
Aufbau des Codes Strukturen, Klassen, Aufzählungen Methoden, Eigenschaften, Variablen Bedingungen, Schleifen …
SYNTAXANALYSEWas weiß der Compiler?
RobinSedlaczek
Was weiß der Compiler bisher nicht?
public virtual void Initialize(int count){ particles.Clear();
for (int i = 0; i < count; i++) { Particle particle = new BasicParticle();
particle.Intialize(rand);
particles.Add(particle); }}
Von welchem Typ sind die Parameter?
Welche Member dürfen aufgerufen werden?
Welche Variablen sind hier gültig?
Semantik!
RobinSedlaczek
Symboltabelle
Deklarationen analysieren
SYMBOLE /// <summary> /// This is the base class for all /// shaders (vertex and fragment). It /// offers functionality which is core /// to all shaders, such as file /// loading and binding. /// </summary> public class Shader { public void Create(OpenGL gl, uint shaderType, string source) { // Create the OpenGL shader object. shaderObject = gl.CreateShader(shaderType);
// Set the shader source. gl.ShaderSource(shaderObject, source);
// Compile the shader object. gl.CompileShader(shaderObject);
// Now that we've compiled the shader, check // it's compilation status. If it's not // compiled properly, we're going to throw // an exception. if (GetCompileStatus(gl) == false) { throw new ShaderCompilationException( string.Format( "Failed to compile shader {0}.", shaderObject), GetInfoLog(gl)); } } Code
File
Assemblies
Benannte Symbole bilden Symboltabelle aufbauen Typen und Typsignaturen bekannt
machen
Referenz
RobinSedlaczek
Symboltabelle
/// <summary> /// This is the base class for all /// shaders (vertex and fragment). It /// offers functionality which is core /// to all shaders, such as file /// loading and binding. /// </summary> public class Shader { public void Create(OpenGL gl, uint shaderType, string source) { // Create the OpenGL shader object. shaderObject = gl.CreateShader(shaderType);
// Set the shader source. gl.ShaderSource(shaderObject, source);
// Compile the shader object. gl.CompileShader(shaderObject);
// Now that we've compiled the shader, check // it's compilation status. If it's not // compiled properly, we're going to throw // an exception. if (GetCompileStatus(gl) == false) { throw new ShaderCompilationException( string.Format(
"Failed to compile shader {0}.", shaderObject), GetInfoLog(gl)); } }
Code File
var my = new MyType();
public void DoSomething(MyType my) { … }
public event EventHandler MyEvent;
Identifier im Code zu Symbolen zuordnen Bedeutung des Codes
Semantische Analyse
RobinSedlaczek
[email protected] EINES COMPILERS
Zerlegen des Quelltextes in Tokens
Parsen der Tokens in die Syntax, die von der Grammatik vorgegeben ist (AST)
Typdeklarationen aus Code und Metadaten zu benannten Symbolen (Symboltabelle)
Identifier in Code abstimmen/verbinden mit benannten Symbolen
Tokenizer/Lexer Parser Symbols Binder
Lexikalische Analyse
Syntaktische Analyse
Semantische Analyse
RobinSedlaczek
[email protected] EINES COMPILERS
Zerlegen des Quelltextes in Tokens
Parsen der Tokens in die Syntax, die von der Grammatik vorgegeben ist (AST)
Typdeklarationen aus Code und Metadaten zu benannten Symbolen (Symboltabelle)
Identifier in Code abstimmen/verbinden mit benannten Symbolen
Plattformunabhängige Optimierungen
Plattformabhängige Optimierungen
All gesammelten Informationen werden in Binary/Assembly ausgegeben
Tokenizer/Lexer Parser Symbols Binder CodeGen
PreprocessorCode
GeneratorCodeGen
Postprocessor
Lexikalische Analyse
Syntaktische Analyse
Semantische Analyse
Synthese-Phase
Click to edit Master subtitle style
RobinSedlaczek
03 | APIs
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
RobinSedlaczek
[email protected] 1 – COMPILER SERVICES
RobinSedlaczek
[email protected] 1 – COMPILER SERVICES
Compiler API- Sprachspezifische Objektmodelle für alle Phasen der
Kompilierung- Unveränderlicher Snapshot eines Compiler-Aufrufes - Keine Abhängigkeiten zu Visual Studio
Diagnostics API- Erweiterbare API (Analyzers)- Hängt sich direkt in Analysephase- Fehler, Warnungen, Informationen
RobinSedlaczek
[email protected] 2 – WORKSPACES
RobinSedlaczek
[email protected] 2 – WORKSPACES
RobinSedlaczek
[email protected] 2 – WORKSPACES
Objektmodell zur Darstellung einer Solution Einstiegspunkt für Solution-weite Analysen und
Refactorings Zugriff auf Compiler Services
RobinSedlaczek
[email protected] 3 – SCRIPTING
C#-Engine zur Ausführung von Codeausschnitten Code wird in Host ausgeführt, der verfügbare
Objekte stellt
Verwendet für REPL in VS C# Interactive Window Ab VS 2015 Update 1
RobinSedlaczek
[email protected] - NAMESPACES
Microsoft.CodeAnalysis Microsoft.CodeAnalysis.Workspaces Microsoft.CodeAnalysis.Scripting
Microsoft.CodeAnalysis.CSharp Microsoft.CodeAnalysis.CSharp.Workspaces Microsoft.CodeAnalysis.CSharp.Scripting
Microsoft.CodeAnalysis.VisualBasic Microsoft.CodeAnalysis.VisualBasic.Workspaces
Click to edit Master subtitle style
RobinSedlaczek
04 | Syntax- und Symbolanalyse
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
RobinSedlaczek
var tree = CSharpSyntaxTree.ParseText(sourceCode);
var node = tree.GetRoot();
SyntaxTree ist abstrakt Parsing über sprachspezifische
Ableitung SyntaxTree ist immutable
RobinSedlaczek
node.ChildNodes()node.ChildTokens()
node.GetLeadingTrivia()node.GetTrailingTrivia()
node.DescendantNodes()node.DescendantTokens()node.DescendantTrivia()
token.LeadingTriviatoken.TrailingTrivia
trivia.GetStructure()trivia.GetStructure()
Traversierung des Syntaxbaums
RobinSedlaczek
public.void.Do(string.what).{.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what).........DontDo();.}.
SYNTAX NODE SyntaxNode (Declarations, Statements, Clauses,
Expressions)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what).........DontDo();.}.
SYNTAX NODE SyntaxNode (Declarations, Statements, Clauses,
Expressions)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)).........DontDo();.}.
SYNTAX NODE SyntaxNode (Declarations, Statements, Clauses,
Expressions)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)).........DontDo();.}.
SYNTAX NODE SyntaxNode (Declarations, Statements, Clauses,
Expressions)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX NODE SyntaxNode (Declarations, Statements, Clauses,
Expressions)
RobinSedlaczek
[email protected] NODE
SyntaxNode (Declarations, Statements, Clauses, Expressions)
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX TOKEN SyntaxToken (Keyword, Identifier, Operator,
Punctuation)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX TOKEN SyntaxToken (Keyword, Identifier, Operator,
Punctuation)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX TOKEN SyntaxToken (Keyword, Identifier, Operator,
Punctuation)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX TOKEN SyntaxToken (Keyword, Identifier, Operator,
Punctuation)
RobinSedlaczek
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
SYNTAX TOKEN SyntaxToken (Keyword, Identifier, Operator,
Punctuation)
RobinSedlaczek
[email protected] TOKEN
SyntaxToken (Keyword, Identifier, Operator, Punctuation)
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
RobinSedlaczek
[email protected] TOKEN
SyntaxToken (Keyword, Identifier, Operator, Punctuation)
public void Do(string what){.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what)........DontDo();.}.
RobinSedlaczek
public.void.Do(string.what).{.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what).........DontDo();.}.
SYNTAX TRIVIA SyntaxTrivia (Leerzeichen, Kommentare, Pre-processor
Direktiven)
RobinSedlaczek
[email protected] KINDS
Kind()-Erweiterungsmethode identifiziert exaktes Syntaxelement für Node, Token und Trivia Enum: Microsoft.CodeAnalysis.CSharp.SyntaxKind (463 Werte) Enum: Microsoft.CodeAnalysis.VisualBasic.SyntaxKind (642 Werte)
public enum SyntaxKind : ushort{ None, List, Argument, ArgumentList, ClassDeclaration, MethodDeclaration, NewKeyword, DollarToken, PercentToken, OpenBracketToken, CloseBracketToken, …}
RobinSedlaczek
[email protected] TYPES
Syntaxtypen für alle Syntaxelemente (sprachspezifisch) Namespace: Microsoft.CodeAnalysis.CSharp.Syntax (214
Klassen) Namespace: Microsoft.CodeAnalysis.VisualBasic.Syntax (275
Klassen)public.void.Do(string.what).{.....var.so.=.true;..#if.DEBUG.....so.=.false;.#endif......if.(so.==.what).........DontDo();.}.
2
3
1
4
1 – MethodDeclarationSyntax2 – ParameterListSyntax3 – VariableDeclarationSyntax4 – IfStatementSyntax
RobinSedlaczek
[email protected] KINDS VS. SYNTAX TYPES
Was passt hier nicht?463(C#)
642(VB) Types Kinds vs. 214 (C#)275 (VB)
Syntax Types sind allgemeiner als Kinds Ein Typ für ähnliche Syntaxelemente By Design
RobinSedlaczek
[email protected] KINDS VS. SYNTAX TYPES
1 : 1 - Beziehungen zwischen Types und Kinds Es gibt aber ein paar
Ausnahmen! Beispiele…
RobinSedlaczek
[email protected] KINDS VS. SYNTAX TYPES
a = 1;a *= 2;a += 4;
1 | 1true && true;true || false;
Kind für jeden binären Operator (logisch, arithmetisch, Bit-Verschiebung, Verbundzuweisung)
Ein Syntaxtype für binäre Ausdrücke.
Binärer Ausdruck
RobinSedlaczek
[email protected] KINDS VS. SYNTAX TYPES
myObject.MyMember
myObject->MyMember
dictionary!name
Member-Zugriff
(C#)
(VB)
Kind für einfachen Member-Zugriff, Zugriff über Zeiger und Zugriff auf Dictionary in VB.
Ein Syntaxtype für Member-Zugriffe.
RobinSedlaczek
[email protected] ANALYSE
Compilation ist abstrakt Semantische Analyse über
Ableitungen Symboltabelle ist immutable
var compilation = CSharpCompilation .Create("CodeInCurrentProject") .AddReferences(references) .AddSyntaxTrees(trees);
var semanticModel = compilation.GetSemanticModel(tree);var emitResult = compilation.Emit(path);
Click to edit Master subtitle style
RobinSedlaczek
05 | Time to Code
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
Click to edit Master subtitle style
RobinSedlaczek
Time to Code | Am Anfang war die Konsole…
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
Click to edit Master subtitle style
RobinSedlaczek
Time to Code | Refactoring, Analzyer & CodeFix
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
Click to edit Master subtitle style
RobinSedlaczek
Real World Example | Semantic Versioning
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
RobinSedlaczek
Click to edit Master subtitle style
RobinSedlaczek
Real World Example | Critical Code
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
Click to edit Master subtitle style
RobinSedlaczek
Real World Example | Application Scripting
Robin Sedlaczek | Chief Technical Officer at Fairmas GmbH
Click to edit Master subtitle style
RobinSedlaczek
Roslyn - Ein offener Compiler. Ja, und nun?
„Nun seid Ihr dran!“
RobinSedlaczek.wordpress.comRobinSedlaczek
RobinSedlaczek
[email protected], CODE, CODE
SensitiveCodeMarker (Critical Code) Demo: Verwendung von Roslyn in Kombination mit Visual Studio-Erweiterungen Erweiterung bewirkt Markierung von kritischem Code im Code-Editor als Hilfe für den Entwickler https://github.com/robinsedlaczek/WaveDev.SensitiveCodeMarker (VS-Extension) https://github.com/robinsedlaczek/WaveDev.RoomsReservationSystemDemo (Testprojekt)
ModelR (Application Scripting) Demo: sinnvolle Verwendung von C# Scripting in einer eigenen Anwendung Verteiltes 3D-Modellierungstool basierend auf SignalR, WPF, MVVM Light und SharpGL Mittels C# Scripting wird das Tool erweiterbar und automatisierbar gemacht https://github.com/robinsedlaczek/ModelR