Skip to content

Commit 9d198ee

Browse files
authored
Kaleidoscope Chapter 6 docs and comment updates. (#57)
1 parent 074d861 commit 9d198ee

File tree

10 files changed

+341
-40
lines changed

10 files changed

+341
-40
lines changed

Samples/Kaleidoscope/Chapter6/CodeGenerator.cs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,19 @@ internal sealed class CodeGenerator
2929
, IDisposable
3030
, IKaleidoscopeCodeGenerator<Value>
3131
{
32+
// <Initialization>
3233
public CodeGenerator( DynamicRuntimeState globalState )
3334
{
3435
RuntimeState = globalState;
3536
Context = new Context( );
37+
JIT = new KaleidoscopeJIT( );
3638
InitializeModuleAndPassManager( );
3739
InstructionBuilder = new InstructionBuilder( Context );
38-
JIT = new KaleidoscopeJIT( );
3940
FunctionPrototypes = new PrototypeCollection( );
4041
FunctionModuleMap = new Dictionary<string, IJitModuleHandle>( );
4142
NamedValues = new ScopeStack<Value>( );
4243
}
44+
// </Initialization>
4345

4446
public bool DisableOptimizations { get; set; }
4547

@@ -82,7 +84,7 @@ public override Value VisitVariableExpression( [NotNull] VariableExpressionConte
8284

8385
public override Value VisitFunctionCallExpression( [NotNull] FunctionCallExpressionContext context )
8486
{
85-
var function = GetFunction( context.CaleeName );
87+
var function = FindCallTarget( context.CaleeName );
8688
if( function == null )
8789
{
8890
throw new CodeGeneratorException( $"function '{context.CaleeName}' is unknown" );
@@ -102,13 +104,16 @@ public override Value VisitFunctionPrototype( [NotNull] FunctionPrototypeContext
102104
return GetOrDeclareFunction( new Prototype( context ) );
103105
}
104106

107+
// <VisitFunctionDefinition>
105108
public override Value VisitFunctionDefinition( [NotNull] FunctionDefinitionContext context )
106109
{
107110
return DefineFunction( ( Function )context.Signature.Accept( this )
108111
, context.BodyExpression
109112
).Function;
110113
}
114+
// </VisitFunctionDefinition>
111115

116+
// <VisitTopLevelExpression>
112117
public override Value VisitTopLevelExpression( [NotNull] TopLevelExpressionContext context )
113118
{
114119
var proto = new Prototype( $"anon_expr_{AnonNameIndex++}" );
@@ -118,9 +123,11 @@ public override Value VisitTopLevelExpression( [NotNull] TopLevelExpressionConte
118123

119124
var nativeFunc = JIT.GetDelegateForFunction<AnonExpressionFunc>( proto.Identifier.Name );
120125
var retVal = Context.CreateConstant( nativeFunc( ) );
126+
FunctionModuleMap.Remove( function.Name );
121127
JIT.RemoveModule( jitHandle );
122128
return retVal;
123129
}
130+
// </VisitTopLevelExpression>
124131

125132
public override Value VisitExpression( [NotNull] ExpressionContext context )
126133
{
@@ -135,6 +142,7 @@ public override Value VisitExpression( [NotNull] ExpressionContext context )
135142
return lhs;
136143
}
137144

145+
// <VisitConditionalExpression>
138146
public override Value VisitConditionalExpression( [NotNull] ConditionalExpressionContext context )
139147
{
140148
var condition = context.Condition.Accept( this );
@@ -163,7 +171,7 @@ public override Value VisitConditionalExpression( [NotNull] ConditionalExpressio
163171

164172
InstructionBuilder.Branch( phiMergeBlock );
165173

166-
// capture the insert in case generating thenExpression adds new blocks
174+
// capture the insert in case generating else adds new blocks
167175
thenBlock = InstructionBuilder.InsertBlock;
168176

169177
// generate else block
@@ -188,24 +196,9 @@ public override Value VisitConditionalExpression( [NotNull] ConditionalExpressio
188196
phiNode.AddIncoming( elseValue, elseBlock );
189197
return phiNode;
190198
}
199+
// </VisitConditionalExpression>
191200

192-
/*
193-
// Output for-loop as:
194-
// ...
195-
// start = startexpr
196-
// goto loop
197-
// loop:
198-
// variable = phi [start, loopheader], [nextvariable, loopend]
199-
// ...
200-
// bodyexpr
201-
// ...
202-
// loopend:
203-
// step = stepexpr
204-
// nextvariable = variable + step
205-
// endcond = endexpr
206-
// br endcond, loop, endloop
207-
// outloop:
208-
*/
201+
// <VisitForExpression>
209202
public override Value VisitForExpression( [NotNull] ForExpressionContext context )
210203
{
211204
var function = InstructionBuilder.InsertBlock.ContainingFunction;
@@ -297,7 +290,9 @@ public override Value VisitForExpression( [NotNull] ForExpressionContext context
297290
return Context.DoubleType.GetNullValue( );
298291
}
299292
}
293+
// </VisitForExpression>
300294

295+
// <VisitUserOperators>
301296
public override Value VisitUnaryOpExpression( [NotNull] UnaryOpExpressionContext context )
302297
{
303298
// verify the operator was previously defined
@@ -308,7 +303,7 @@ public override Value VisitUnaryOpExpression( [NotNull] UnaryOpExpressionContext
308303
}
309304

310305
string calleeName = UnaryPrototypeContext.GetOperatorFunctionName( context.OpToken );
311-
var function = GetFunction( calleeName );
306+
var function = FindCallTarget( calleeName );
312307
if( function == null )
313308
{
314309
throw new CodeGeneratorException( $"Unknown function reference {calleeName}" );
@@ -338,6 +333,7 @@ public override Value VisitUnaryPrototype( [NotNull] UnaryPrototypeContext conte
338333

339334
return GetOrDeclareFunction( new Prototype( context, context.Name ) );
340335
}
336+
// </VisitUserOperators>
341337

342338
protected override Value DefaultResult => null;
343339

@@ -378,6 +374,7 @@ private Value EmitBinaryOperator( Value lhs, BinaryopContext op, IParseTree righ
378374
case SLASH:
379375
return InstructionBuilder.FDiv( lhs, rhs ).RegisterName( "divtmp" );
380376

377+
// <EmitUserOperator>
381378
default:
382379
{
383380
// User defined op?
@@ -388,30 +385,37 @@ private Value EmitBinaryOperator( Value lhs, BinaryopContext op, IParseTree righ
388385
}
389386

390387
string calleeName = BinaryPrototypeContext.GetOperatorFunctionName( op.Token );
391-
var function = GetFunction( calleeName );
388+
var function = FindCallTarget( calleeName );
392389
if( function == null )
393390
{
394391
throw new CodeGeneratorException( $"Unknown function reference {calleeName}" );
395392
}
396393

397394
return InstructionBuilder.Call( function, lhs, rhs ).RegisterName( "calltmp" );
398395
}
396+
// </EmitUserOperator>
399397
}
400398
}
401399

400+
// <InitializeModuleAndPassManager>
402401
private void InitializeModuleAndPassManager( )
403402
{
404403
Module = Context.CreateBitcodeModule( );
404+
Module.Layout = JIT.TargetMachine.TargetData;
405405
FunctionPassManager = new FunctionPassManager( Module );
406406
FunctionPassManager.AddInstructionCombiningPass( )
407407
.AddReassociatePass( )
408408
.AddGVNPass( )
409409
.AddCFGSimplificationPass( )
410410
.Initialize( );
411411
}
412+
// </InitializeModuleAndPassManager>
412413

413-
private Function GetFunction( string name )
414+
// <FindCallTarget>
415+
private Function FindCallTarget( string name )
414416
{
417+
// lookup the prototype for the function to get the signature
418+
// and create a declaration in this module
415419
if( FunctionPrototypes.TryGetValue( name, out var signature ) )
416420
{
417421
return GetOrDeclareFunction( signature );
@@ -425,7 +429,9 @@ private Function GetFunction( string name )
425429

426430
return null;
427431
}
432+
// </FindCallTarget>
428433

434+
// <GetOrDeclareFunction>
429435
private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = false )
430436
{
431437
var function = Module.GetFunction( prototype.Identifier.Name );
@@ -453,7 +459,9 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
453459

454460
return retVal;
455461
}
462+
// </GetOrDeclareFunction>
456463

464+
// <DefineFunction>
457465
private (Function Function, IJitModuleHandle JitHandle) DefineFunction( Function function, ExpressionContext body )
458466
{
459467
if( !function.IsDeclaration )
@@ -466,7 +474,7 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
466474
// implementation. This is needed, otherwise both the MCJIT
467475
// and OrcJit engines will resolve to the original module, despite
468476
// claims to the contrary in the official tutorial text. (Though,
469-
// to be fare it may have been true in the original JIT and might
477+
// to be fair it may have been true in the original JIT and might
470478
// still be true for the interpreter)
471479
if( FunctionModuleMap.Remove( function.Name, out IJitModuleHandle handle ) )
472480
{
@@ -503,6 +511,7 @@ private Function GetOrDeclareFunction( Prototype prototype, bool isAnonymous = f
503511
InitializeModuleAndPassManager( );
504512
return (function, jitHandle);
505513
}
514+
// </DefineFunction>
506515

507516
// <PrivateMembers>
508517
private readonly DynamicRuntimeState RuntimeState;

Samples/Kaleidoscope/Chapter6/Program.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
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
@@ -35,6 +37,8 @@ public static void Main( string[ ] args )
3537
using( InitializeLLVM( ) )
3638
{
3739
RegisterNative( );
40+
41+
// <generatorloop>
3842
var parser = new ReplParserStack( LanguageLevel.UserDefinedOperators );
3943
using( var generator = new CodeGenerator( parser.GlobalState ) )
4044
{
@@ -43,12 +47,31 @@ public static void Main( string[ ] args )
4347
var replLoop = new ReplLoop<Value>( generator, parser );
4448
replLoop.ReadyStateChanged += ( s, e ) => Console.Write( e.PartialParse ? ">" : "Ready>" );
4549
replLoop.GeneratedResultAvailable += OnGeneratedResultAvailable;
50+
replLoop.CodeGenerationError += OnGeneratorError;
4651

4752
replLoop.Run( );
4853
}
54+
// </generatorloop>
55+
}
56+
}
57+
58+
// <ErrorHandling>
59+
private static void OnGeneratorError( object sender, CodeGenerationExceptionArgs e )
60+
{
61+
var color = Console.ForegroundColor;
62+
Console.ForegroundColor = ConsoleColor.Red;
63+
try
64+
{
65+
Console.Error.WriteLine( e.Exception.Message );
66+
}
67+
finally
68+
{
69+
Console.ForegroundColor = color;
4970
}
5071
}
72+
// </ErrorHandling>
5173

74+
// <ResultProcessing>
5275
private static void OnGeneratedResultAvailable( object sender, GeneratedResultAvailableArgs<Value> e )
5376
{
5477
var source = ( ReplLoop<Value> )sender;
@@ -69,5 +92,6 @@ private static void OnGeneratedResultAvailable( object sender, GeneratedResultAv
6992
break;
7093
}
7194
}
95+
// </ResultProcessing>
7296
}
7397
}

Samples/Kaleidoscope/Kaleidoscope.Parser/BlockDiagGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace Kaleidoscope.Grammar
1616
/// The resulting ".diag" file is convertible to SVG form for documentation.</para>
1717
/// <para>
1818
/// The generated diagrams include a numbered element for binary operator expressions
19-
/// to indicate the precedence value that is diyamically evaluated for the expression.
19+
/// to indicate the precedence value that is dynamically evaluated for the expression.
2020
/// This is particularly useful for debugging custom operator precedence problems.
2121
/// </para>
2222
/// </remarks>

Samples/Kaleidoscope/Kaleidoscope.Parser/DynamicRuntimeState.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ namespace Kaleidoscope.Grammar
1919
///
2020
/// This provides storage and support methods for the runtime global state.
2121
/// In particular, it maintains the language level to use and the current set
22-
/// of operators, including any user defined operators so the parser know how
23-
/// to resolve complex expressions with precednece.
22+
/// of operators, including any user defined operators so the parser knows how
23+
/// to resolve complex expressions with user defined operators and precedence.
2424
/// </remarks>
2525
public class DynamicRuntimeState
2626
{
@@ -106,7 +106,7 @@ internal int GetNextPrecedence( int tokenType )
106106

107107
private bool TryAddOperator( int tokenType, OperatorKind kind, int precedence )
108108
{
109-
// internally operators are stored as token type integers to accomodate
109+
// internally operators are stored as token type integers to accommodate
110110
// simpler condition checks and switching on operator types in code generation
111111
switch( kind )
112112
{

Samples/Kaleidoscope/Kaleidoscope.Parser/Identifier.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ namespace Kaleidoscope
1111
{
1212
/// <summary>Description of an identifier in Kaleidoscope code generation</summary>
1313
/// <remarks>
14-
/// This is distinct from te parse tree nodes as code generation sometimes needs to
15-
/// synthesize an identifier (i.e. Building function the definition for an anonymous
14+
/// This is distinct from the parse tree nodes as code generation sometimes needs to
15+
/// synthesize an identifier (i.e. Building the function definition for an anonymous
1616
/// top level expression)
1717
/// </remarks>
1818
public struct Identifier

Samples/Kaleidoscope/Kaleidoscope.Parser/KaleidoscopeLexer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace Kaleidoscope.Grammar
66
{
77
// partial extension to handle creating virtual tokens/Identifiers depending
8-
// on language feaures enabled.
8+
// on language features enabled.
99
public partial class KaleidoscopeLexer
1010
{
1111
public LanguageLevel LanguageLevel { get; set; }

Samples/Kaleidoscope/Kaleidoscope.Runtime/IKaleidoscopeParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public interface IKaleidoscopeParser
3030
/// <remarks>
3131
/// If the parse fails then the resulting tuple is the default value ( in this case, both items <see langword="null"/>
3232
/// Errors from the parse are reported through error listeners provided
33-
/// to the parser. Normally this is done via the contructor of a type
33+
/// to the parser. Normally this is done via the constructor of a type
3434
/// implementing this interface.
3535
/// </remarks>
3636
(IParseTree parseTree, Parser recognizer) Parse( string txt, DiagnosticRepresentations additionalDiagnostics );

Samples/Kaleidoscope/Kaleidoscope.Runtime/TextReaderExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static IEnumerable<string> ReadLines( this TextReader reader )
4343
/// <returns>Enumerable set of lines that may be partial statements</returns>
4444
/// <remarks>
4545
/// Each value enumerated includes the full text since the last complete statement.
46-
/// That is the Txt from multiple partial statements will include the text of the
46+
/// That is the text from multiple partial statements will include the text of the
4747
/// preceding partial. Once a complete statement is found the entire string is provided
4848
/// with the IsPartial property set to <see langword="false"/>
4949
/// </remarks>
@@ -57,7 +57,7 @@ public static IEnumerable<string> ReadLines( this TextReader reader )
5757
/// <returns>Enumerable set of lines that may be partial statements</returns>
5858
/// <remarks>
5959
/// Each value enumerated includes the full text since the last complete statement.
60-
/// That is the Txt from multiple partial statements will include the text of the
60+
/// That is the text from multiple partial statements will include the text of the
6161
/// preceding partial. Once a complete statement is found the entire string is provided
6262
/// with the IsPartial property set to <see langword="false"/>
6363
/// </remarks>
@@ -66,7 +66,7 @@ public static IEnumerable<string> ReadLines( this TextReader reader )
6666
var bldr = new StringBuilder( );
6767
foreach( string line in lines )
6868
{
69-
var statements = line.Split( ';' );
69+
string[ ] statements = line.Split( ';' );
7070

7171
// if the last line in the group was terminated with a ; the
7272
// the last entry is an empty string, but a single blank line

Samples/Kaleidoscope/Kaleidoscope.Runtime/Utilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static void WaitForDebugger( bool condition )
5454
public static string GetSafeFileName( string name )
5555
{
5656
var bldr = new StringBuilder( name.Length );
57-
var invalidChars = Path.GetInvalidFileNameChars( );
57+
char[ ] invalidChars = Path.GetInvalidFileNameChars( );
5858
foreach( char c in name )
5959
{
6060
bldr.Append( invalidChars.Contains( c ) ? '_' : c );

0 commit comments

Comments
 (0)