Skip to content

Commit 8a4eb28

Browse files
Refactor code gen
1 parent de92e13 commit 8a4eb28

2 files changed

Lines changed: 40 additions & 41 deletions

File tree

DeveloperCore.REPL/REPL.vb

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ Imports NuGet.ProjectManagement
1313
Imports NuGet.Protocol.Core.Types
1414
Imports NuGet.Resolver
1515
'TODO: Child variables only
16+
'TODO: Async
1617
'TODO: Non method things
18+
'TODO: Maybe replace variable references with dictionary lookups
19+
'TODO: State save should be inserted before all returns
1720
Public Class REPL
1821
Private _imports As New List(Of ImportsStatementSyntax)
1922
Private _state As New Dictionary(Of String, Object)
@@ -22,8 +25,8 @@ Public Class REPL
2225
Private ReadOnly _nugetCache As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "DeveloperCore.REPL", "NuGetCache")
2326

2427
Public Function Evaluate(str As String) As EvaluationResults
25-
Dim newStatement As StatementSyntax = SyntaxCreator.ParseStatement(str)
26-
Dim comp As VisualBasicCompilation = GetCompilation(str)
28+
Dim newStatement As StatementSyntax = SyntaxFactory.ParseExecutableStatement(str)
29+
Dim comp As VisualBasicCompilation = GetCompilation(newStatement)
2730
Using ms As New MemoryStream
2831
Dim res As EmitResult = comp.Emit(ms)
2932
Dim results As Object
@@ -37,34 +40,43 @@ Public Class REPL
3740
End Using
3841
End Function
3942

40-
Public Function GetCompilation(str As String) As VisualBasicCompilation
41-
Dim newStatement As StatementSyntax = SyntaxCreator.ParseStatement(str)
43+
Public Function GetCompilation(newStatement As StatementSyntax) As VisualBasicCompilation
4244
Dim stateName As String = GetRandomString(10)
43-
Dim unit As CompilationUnitSyntax = SyntaxFactory.ParseCompilationUnit(GetUnit(newStatement, stateName).ToString)
44-
Dim method As MethodBlockSyntax = unit.DescendantNodes.OfType(Of MethodBlockSyntax).First
45-
unit = unit.ReplaceNode(method, UpdateMethod(method, stateName)).NormalizeWhitespace
45+
Dim unit As CompilationUnitSyntax = SyntaxFactory.ParseCompilationUnit(GetCompilationUnit(newStatement).ToString)
46+
Dim classNode As ClassBlockSyntax = unit.DescendantNodes.OfType(Of ClassBlockSyntax).First
47+
unit = unit.ReplaceNode(classNode, classNode.AddMembers(GetMethod(stateName, newStatement))).NormalizeWhitespace
4648
Return CompilationCreator.GetCompilation(unit).AddReferences(_references).AddSyntaxTrees(_trees)
4749
End Function
4850

49-
Private Function UpdateMethod(method As MethodBlockSyntax, stateName As String) As MethodBlockSyntax
50-
Dim stateVars As New List(Of VariableDeclaratorSyntax)
51-
For Each key As String In _state.Keys
52-
Dim var As VariableDeclaratorSyntax = SyntaxFactory.VariableDeclarator(SyntaxFactory.ModifiedIdentifier(key)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(GetTypeName(key)))).WithInitializer(SyntaxFactory.EqualsValue(SyntaxFactory.ParseExpression($"{stateName}(""{key}"")")))
53-
stateVars.Add(var)
54-
Next
55-
method = method.WithStatements(method.Statements.Insert(0, SyntaxFactory.LocalDeclarationStatement(New SyntaxTokenList().Add(SyntaxFactory.ParseToken("Dim")), New SeparatedSyntaxList(Of VariableDeclaratorSyntax)().AddRange(stateVars)))).NormalizeWhitespace
56-
Dim retIndex As Integer = method.Statements.IndexOf(method.DescendantNodes.OfType(Of ReturnStatementSyntax).First)
57-
Dim varUpdates As New List(Of StatementSyntax)
58-
Dim vars As VariableDeclaratorSyntax() = method.DescendantNodes.OfType(Of VariableDeclaratorSyntax).ToArray
59-
For Each var As VariableDeclaratorSyntax In vars
60-
Dim name As String = var.Names.First.Identifier.Text
61-
If Not _state.ContainsKey(name) Then
62-
varUpdates.Add(SyntaxFactory.ParseExecutableStatement($"{stateName}.Add(""{name}"", {name})"))
63-
Else
64-
varUpdates.Add(SyntaxFactory.ParseExecutableStatement($"{stateName}(""{name}"") = {name}"))
65-
End If
66-
Next
67-
method = method.WithStatements(method.Statements.InsertRange(retIndex, varUpdates))
51+
Private Function GetCompilationUnit(statement As StatementSyntax) As CompilationUnitSyntax
52+
Dim unit As CompilationUnitSyntax = SyntaxFactory.CompilationUnit().AddMembers(SyntaxCreator.GetModule()).AddImports(_imports.Concat(If(TypeOf statement Is ImportsStatementSyntax, {DirectCast(statement, ImportsStatementSyntax)}, {})).ToArray).NormalizeWhitespace
53+
Return unit
54+
End Function
55+
56+
Private Function GetMethod(stateName As String, statement As StatementSyntax) As MethodBlockSyntax
57+
Dim method As MethodBlockSyntax = SyntaxCreator.GetMethod(stateName)
58+
Dim defaultReturn As ReturnStatementSyntax = SyntaxFactory.ReturnStatement(SyntaxFactory.NothingLiteralExpression(SyntaxFactory.ParseToken("Nothing")))
59+
If TypeOf statement Is ImportsStatementSyntax Then
60+
method = method.AddStatements(defaultReturn)
61+
Else
62+
Dim stateVars As New List(Of VariableDeclaratorSyntax)
63+
For Each key As String In _state.Keys
64+
Dim var As VariableDeclaratorSyntax = SyntaxFactory.VariableDeclarator(SyntaxFactory.ModifiedIdentifier(key)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(GetTypeName(key)))).WithInitializer(SyntaxFactory.EqualsValue(SyntaxFactory.ParseExpression($"{stateName}(""{key}"")")))
65+
stateVars.Add(var)
66+
Next
67+
Dim varDeclaration As LocalDeclarationStatementSyntax = SyntaxFactory.LocalDeclarationStatement(New SyntaxTokenList().Add(SyntaxFactory.ParseToken("Dim")), New SeparatedSyntaxList(Of VariableDeclaratorSyntax)().AddRange(stateVars))
68+
Dim varUpdates As New List(Of StatementSyntax)
69+
Dim vars As VariableDeclaratorSyntax() = varDeclaration.Declarators.Concat(statement.DescendantNodes.OfType(Of VariableDeclaratorSyntax)).ToArray
70+
For Each var As VariableDeclaratorSyntax In vars
71+
Dim name As String = var.Names.First.Identifier.Text
72+
If Not _state.ContainsKey(name) Then
73+
varUpdates.Add(SyntaxFactory.ParseExecutableStatement($"{stateName}.Add(""{name}"", {name})"))
74+
Else
75+
varUpdates.Add(SyntaxFactory.ParseExecutableStatement($"{stateName}(""{name}"") = {name}"))
76+
End If
77+
Next
78+
method = method.WithStatements(New SyntaxList(Of StatementSyntax)().AddRange({varDeclaration, statement}).AddRange(varUpdates).Add(defaultReturn))
79+
End If
6880
Return method
6981
End Function
7082

@@ -79,11 +91,6 @@ Public Class REPL
7991
End Try
8092
End Function
8193

82-
Private Function GetUnit(statement As StatementSyntax, param As String)
83-
Dim unit As CompilationUnitSyntax = SyntaxCreator.GetCompilationUnit(SyntaxCreator.GetModule.AddMembers(SyntaxCreator.GetMainMethod(param).AddStatements(If(TypeOf statement Is ImportsStatementSyntax, {}, {statement}).Concat({SyntaxFactory.ReturnStatement(SyntaxFactory.NothingLiteralExpression(SyntaxFactory.ParseToken("Nothing")))}).ToArray))).AddImports(_imports.Concat(If(TypeOf statement Is ImportsStatementSyntax, {DirectCast(statement, ImportsStatementSyntax)}, {})).ToArray).NormalizeWhitespace
84-
Return unit
85-
End Function
86-
8794
Private Function GetTypeName(key As String) As String
8895
Dim obj As Object = _state(key)
8996
If obj Is Nothing Then
@@ -94,7 +101,7 @@ Public Class REPL
94101
End If
95102
End Function
96103

97-
Public Function GetTypeName(type As Type) As String
104+
Private Function GetTypeName(type As Type) As String
98105
If type.IsGenericType Then
99106
Return SyntaxFactory.GenericName(GetGenericNameActual(type), SyntaxFactory.TypeArgumentList(New SeparatedSyntaxList(Of TypeSyntax)().AddRange(type.GenericTypeArguments.Select(Function(x) SyntaxFactory.ParseTypeName(GetTypeName(x)))))).NormalizeWhitespace.ToFullString
100107
ElseIf type.IsArray Then

DeveloperCore.REPL/SyntaxCreator.vb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,8 @@ Public Class SyntaxCreator
88
Return SyntaxFactory.ClassBlock(SyntaxFactory.ClassStatement(SyntaxFactory.ParseToken("Expression"))).AddImplements(SyntaxFactory.ImplementsStatement(SyntaxFactory.ParseTypeName("DeveloperCore.REPL.IExpression")))
99
End Function
1010

11-
Public Shared Function GetMainMethod(param As String) As MethodBlockSyntax
11+
Public Shared Function GetMethod(param As String) As MethodBlockSyntax
1212
Return SyntaxFactory.FunctionBlock(SyntaxFactory.FunctionStatement("Evaluate").AddImplementsClauseInterfaceMembers(SyntaxFactory.QualifiedName(SyntaxFactory.ParseTypeName("DeveloperCore.REPL.IExpression"), SyntaxFactory.ParseName("Evaluate"))).AddParameterListParameters(SyntaxFactory.Parameter(SyntaxFactory.ModifiedIdentifier(param)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName("System.Collections.Generic.Dictionary(Of String, Object)")))))
1313
End Function
1414

15-
Public Shared Function ParseStatement(str As String) As StatementSyntax
16-
Return SyntaxFactory.ParseExecutableStatement(str)
17-
End Function
18-
19-
Public Shared Function GetCompilationUnit(node As SyntaxNode) As CompilationUnitSyntax
20-
Return SyntaxFactory.CompilationUnit().AddMembers(node)
21-
End Function
22-
2315
End Class

0 commit comments

Comments
 (0)