Skip to content

Commit a09c484

Browse files
authored
Kaleidoscope Chapter 3 docs (#54)
* Kaleidoscope Chapter 3 docs * Updated the rest of the Kaleidoscope samples to match changes from CH3
1 parent 6bb6ba0 commit a09c484

File tree

22 files changed

+526
-166
lines changed

22 files changed

+526
-166
lines changed

Samples/Kaleidoscope/Chapter2/Program.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
[assembly: SuppressMessage( "StyleCop.CSharp.DocumentationRules", "SA1652:Enable XML documentation output", Justification = "Sample application" )]
1111

12+
#pragma warning disable SA1512, SA1513, SA1515 // single line comments used to tag regions for extraction into docs
13+
1214
namespace Kaleidoscope
1315
{
1416
public static class Program
@@ -20,7 +22,7 @@ public static void Main( string[ ] args )
2022
{
2123
// Using language level that includes the complete set
2224
// of language features to allow exploring and verifying
23-
// the parser support for the whole language.
25+
// <generatorloop>
2426
var parser = new ReplParserStack( LanguageLevel.MutableVariables );
2527
using( var generator = new CodeGenerator( parser.GlobalState ) )
2628
{
@@ -36,14 +38,17 @@ public static void Main( string[ ] args )
3638

3739
replLoop.Run( );
3840
}
41+
// </generatorloop>
3942
}
4043

44+
// <ProcessResults>
4145
private static void OnGeneratedResultAvailable( object sender, GeneratedResultAvailableArgs<int> e )
4246
{
4347
if( e.Recognizer.NumberOfSyntaxErrors == 0 )
4448
{
4549
Console.WriteLine( "Parsed {0}", e.ParseTree.GetType( ).Name );
4650
}
4751
}
52+
// </ProcessResults>
4853
}
4954
}

Samples/Kaleidoscope/Chapter3/CodeGenerator.cs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public void Dispose( )
4242
Context.Dispose( );
4343
}
4444

45+
public BitcodeModule GeneratedModule => Module;
46+
47+
// <Generate>
4548
public Value Generate( Parser parser, IParseTree tree, DiagnosticRepresentations additionalDiagnostics )
4649
{
4750
if( parser.NumberOfSyntaxErrors > 0 )
@@ -51,22 +54,21 @@ public Value Generate( Parser parser, IParseTree tree, DiagnosticRepresentations
5154

5255
return Visit( tree );
5356
}
57+
// </Generate>
5458

5559
public override Value VisitParenExpression( [NotNull] ParenExpressionContext context )
5660
{
5761
return context.Expression.Accept( this );
5862
}
5963

64+
// <VisitConstExpression>
6065
public override Value VisitConstExpression( [NotNull] ConstExpressionContext context )
6166
{
6267
return Context.CreateConstant( context.Value );
6368
}
69+
// </VisitConstExpression>
6470

65-
public override Value VisitExternalDeclaration( [NotNull] ExternalDeclarationContext context )
66-
{
67-
return context.Signature.Accept( this );
68-
}
69-
71+
// <VisitVariableExpression>
7072
public override Value VisitVariableExpression( [NotNull] VariableExpressionContext context )
7173
{
7274
string varName = context.Name;
@@ -77,6 +79,7 @@ public override Value VisitVariableExpression( [NotNull] VariableExpressionConte
7779

7880
return value;
7981
}
82+
// </VisitVariableExpression>
8083

8184
public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpressionContext context )
8285
{
@@ -90,41 +93,55 @@ public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpress
9093
return InstructionBuilder.Call( function, args ).RegisterName( "calltmp" );
9194
}
9295

96+
// <FunctionDeclarations>
97+
public override Value VisitExternalDeclaration( [NotNull] ExternalDeclarationContext context )
98+
{
99+
return context.Signature.Accept( this );
100+
}
101+
93102
public override Value VisitFunctionPrototype( [NotNull] FunctionPrototypeContext context )
94103
{
95104
return GetOrDeclareFunction( new Prototype( context ) );
96105
}
106+
// </FunctionDeclarations>
97107

108+
// <VisitFunctionDefinition>
98109
public override Value VisitFunctionDefinition( [NotNull] FunctionDefinitionContext context )
99110
{
100111
return DefineFunction( ( Function )context.Signature.Accept( this )
101112
, context.BodyExpression
102113
);
103114
}
115+
// </VisitFunctionDefinition>
104116

117+
// <VisitTopLevelExpression>
105118
public override Value VisitTopLevelExpression( [NotNull] TopLevelExpressionContext context )
106119
{
107120
var proto = new Prototype( $"anon_expr_{AnonNameIndex++}" );
108121
var function = GetOrDeclareFunction( proto );
109122

110123
return DefineFunction( function, context.expression() );
111124
}
125+
// </VisitTopLevelExpression>
112126

127+
// <VisitExpression>
113128
public override Value VisitExpression( [NotNull] ExpressionContext context )
114129
{
115130
// Expression: PrimaryExpression (op expression)*
116131
// the sub-expressions are in evaluation order
117-
var lhs = context.primaryExpression( ).Accept( this );
132+
var lhs = context.Atom.Accept( this );
118133
foreach( var (op, rhs) in context.OperatorExpressions )
119134
{
120135
lhs = EmitBinaryOperator( lhs, op, rhs );
121136
}
122137

123138
return lhs;
124139
}
140+
// </VisitExpression>
125141

126142
protected override Value DefaultResult => null;
127143

144+
// <EmitBinaryOperator>
128145
private Value EmitBinaryOperator( Value lhs, BinaryopContext op, IParseTree rightTree )
129146
{
130147
var rhs = rightTree.Accept( this );
@@ -166,12 +183,14 @@ private Value EmitBinaryOperator( Value lhs, BinaryopContext op, IParseTree righ
166183
throw new CodeGeneratorException( $"Invalid binary operator {op.Token.Text}" );
167184
}
168185
}
186+
// </EmitBinaryOperator>
169187

170188
private Function GetFunction( string name )
171189
{
172190
return Module.GetFunction( name );
173191
}
174192

193+
// <GetOrDeclareFunction>
175194
private Function GetOrDeclareFunction( Prototype prototype )
176195
{
177196
var function = Module.GetFunction( prototype.Identifier.Name );
@@ -194,7 +213,9 @@ private Function GetOrDeclareFunction( Prototype prototype )
194213

195214
return retVal;
196215
}
216+
// </GetOrDeclareFunction>
197217

218+
// <DefineFunction>
198219
private Function DefineFunction( Function function, ExpressionContext body )
199220
{
200221
if( !function.IsDeclaration )
@@ -222,6 +243,7 @@ private Function DefineFunction( Function function, ExpressionContext body )
222243

223244
return function;
224245
}
246+
// </DefineFunction>
225247

226248
// <PrivateMembers>
227249
private readonly DynamicRuntimeState RuntimeState;

Samples/Kaleidoscope/Chapter3/Program.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,48 @@
1414

1515
[assembly: SuppressMessage( "StyleCop.CSharp.DocumentationRules", "SA1652:Enable XML documentation output", Justification = "Sample application" )]
1616

17+
#pragma warning disable SA1512, SA1513, SA1515 // single line comments used to tag regions for extraction into docs
18+
1719
namespace Kaleidoscope
1820
{
1921
public static class Program
2022
{
2123
/// <summary>C# version of the LLVM Kaleidoscope language tutorial</summary>
22-
/// <param name="args">Ignored...</param>
23-
[SuppressMessage( "Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Standard required signature" )]
24+
/// <param name="args">Command line arguments to the application</param>
25+
/// <remarks>
26+
/// The only supported command line option at present is 'WaitForDebugger'
27+
/// This parameter is optional and if used must be the first parameter.
28+
/// Setting 'WaitForDebugger' will trigger a wait loop in Main() to wait
29+
/// for an attached debugger if one is not yet attached. This is useful
30+
/// for mixed mode native+managed debugging as the SDK project system does
31+
/// not support that on launch.
32+
/// </remarks>
2433
public static void Main( string[ ] args )
2534
{
26-
WaitForDebugger( );
35+
WaitForDebugger( args.Length > 0 && string.Compare( args[0], "waitfordebugger", StringComparison.InvariantCultureIgnoreCase ) == 0 );
2736

2837
using( InitializeLLVM( ) )
2938
{
3039
RegisterNative( );
40+
41+
// <generatorloop>
3142
var parser = new ReplParserStack( LanguageLevel.SimpleExpressions );
3243
using( var generator = new CodeGenerator( parser.GlobalState ) )
3344
{
34-
Console.WriteLine( "LLVM Kaleidoscope Interpreter - {0}", parser.LanguageLevel );
45+
Console.WriteLine( "Llvm.NET Kaleidoscope Interpreter - {0}", parser.LanguageLevel );
3546

3647
var replLoop = new ReplLoop<Value>( generator, parser );
3748
replLoop.ReadyStateChanged += ( s, e ) => Console.Write( e.PartialParse ? ">" : "Ready>" );
3849
replLoop.GeneratedResultAvailable += OnGeneratedResultAvailable;
3950

4051
replLoop.Run( );
52+
Console.WriteLine( generator.GeneratedModule.WriteToString( ) );
4153
}
54+
// </generatorloop>
4255
}
4356
}
4457

58+
// <ResultProcessing>
4559
private static void OnGeneratedResultAvailable( object sender, GeneratedResultAvailableArgs<Value> e )
4660
{
4761
var source = ( ReplLoop<Value> )sender;
@@ -63,5 +77,6 @@ private static void OnGeneratedResultAvailable( object sender, GeneratedResultAv
6377
break;
6478
}
6579
}
80+
// </ResultProcessing>
6681
}
6782
}

Samples/Kaleidoscope/Chapter4/CodeGenerator.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
using static Kaleidoscope.Grammar.KaleidoscopeParser;
2121

22+
#pragma warning disable SA1512, SA1513, SA1515 // single line comments used to tag regions for extraction into docs
23+
2224
namespace Kaleidoscope
2325
{
2426
/// <summary>Static extension methods to perform LLVM IR Code generation from the Kaleidoscope AST</summary>
@@ -27,6 +29,7 @@ internal sealed class CodeGenerator
2729
, IDisposable
2830
, IKaleidoscopeCodeGenerator<Value>
2931
{
32+
// <Initialization>
3033
public CodeGenerator( DynamicRuntimeState globalState )
3134
{
3235
RuntimeState = globalState;
@@ -38,6 +41,7 @@ public CodeGenerator( DynamicRuntimeState globalState )
3841
FunctionModuleMap = new Dictionary<string, IJitModuleHandle>( );
3942
NamedValues = new Dictionary<string, Value>( );
4043
}
44+
// </Initialization>
4145

4246
public bool DisableOptimizations { get; set; }
4347

@@ -67,11 +71,6 @@ public override Value VisitConstExpression( [NotNull] ConstExpressionContext con
6771
return Context.CreateConstant( context.Value );
6872
}
6973

70-
public override Value VisitExternalDeclaration( [NotNull] ExternalDeclarationContext context )
71-
{
72-
return context.Signature.Accept( this );
73-
}
74-
7574
public override Value VisitVariableExpression( [NotNull] VariableExpressionContext context )
7675
{
7776
string varName = context.Name;
@@ -95,6 +94,11 @@ public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpress
9594
return InstructionBuilder.Call( function, args ).RegisterName( "calltmp" );
9695
}
9796

97+
public override Value VisitExternalDeclaration( [NotNull] ExternalDeclarationContext context )
98+
{
99+
return context.Signature.Accept( this );
100+
}
101+
98102
public override Value VisitFunctionPrototype( [NotNull] FunctionPrototypeContext context )
99103
{
100104
return GetOrDeclareFunction( new Prototype( context ) );
@@ -124,7 +128,7 @@ public override Value VisitExpression( [NotNull] ExpressionContext context )
124128
{
125129
// Expression: PrimaryExpression (op expression)*
126130
// the sub-expressions are in evaluation order
127-
var lhs = context.primaryExpression( ).Accept( this );
131+
var lhs = context.Atom.Accept( this );
128132
foreach( var (op, rhs) in context.OperatorExpressions )
129133
{
130134
lhs = EmitBinaryOperator( lhs, op, rhs );
@@ -244,7 +248,7 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
244248
// implementation. This is needed, otherwise both the MCJIT
245249
// and OrcJit engines will resolve to the original module, despite
246250
// claims to the contrary in the official tutorial text. (Though,
247-
// to be fare it may have been true in the original JIT and might
251+
// to be fair it may have been true in the original JIT and might
248252
// still be true for the interpreter)
249253
if( FunctionModuleMap.Remove( function.Name, out IJitModuleHandle handle ) )
250254
{
@@ -280,6 +284,7 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
280284
return (function, jitHandle);
281285
}
282286

287+
// <PrivateMembers>
283288
private readonly DynamicRuntimeState RuntimeState;
284289
private static int AnonNameIndex;
285290
private readonly Context Context;
@@ -295,5 +300,6 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
295300
/// <returns>Result of evaluating the expression</returns>
296301
[UnmanagedFunctionPointer( System.Runtime.InteropServices.CallingConvention.Cdecl )]
297302
private delegate double AnonExpressionFunc( );
303+
// </PrivateMembers>
298304
}
299305
}

Samples/Kaleidoscope/Chapter4/Program.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,26 @@ namespace Kaleidoscope
1919
public static class Program
2020
{
2121
/// <summary>C# version of the LLVM Kaleidoscope language tutorial</summary>
22-
/// <param name="args">Ignored...</param>
23-
[SuppressMessage( "Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Standard required signature" )]
22+
/// <param name="args">Command line arguments to the application</param>
23+
/// <remarks>
24+
/// The only supported command line option at present is 'WaitForDebugger'
25+
/// This parameter is optional and if used must be the first parameter.
26+
/// Setting 'WaitForDebugger' will trigger a wait loop in Main() to wait
27+
/// for an attached debugger if one is not yet attached. This is useful
28+
/// for mixed mode native+managed debugging as the SDK project system does
29+
/// not support that on launch.
30+
/// </remarks>
2431
public static void Main( string[ ] args )
2532
{
26-
WaitForDebugger( );
33+
WaitForDebugger( args.Length > 0 && string.Compare( args[0], "waitfordebugger", StringComparison.InvariantCultureIgnoreCase ) == 0 );
2734

2835
using( InitializeLLVM( ) )
2936
{
3037
RegisterNative( );
3138
var parser = new ReplParserStack( LanguageLevel.SimpleExpressions );
3239
using( var generator = new CodeGenerator( parser.GlobalState ) )
3340
{
34-
Console.WriteLine( "LLVM Kaleidoscope Interpreter - {0}", parser.LanguageLevel );
41+
Console.WriteLine( "Llvm.NET Kaleidoscope Interpreter - {0}", parser.LanguageLevel );
3542

3643
var replLoop = new ReplLoop<Value>( generator, parser );
3744
replLoop.ReadyStateChanged += ( s, e ) => Console.Write( e.PartialParse ? ">" : "Ready>" );

0 commit comments

Comments
 (0)