Skip to content

Commit

Permalink
comment for Expression (#980)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenzhitong authored Mar 12, 2024
1 parent 53a383a commit 4661dd2
Show file tree
Hide file tree
Showing 34 changed files with 820 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// Methods for converting the creation of an object of an anonymous type into a series of instructions.
/// </summary>
/// <param name="model">The semantic model providing context and information about the anonymous object creation.</param>
/// <param name="expression">The syntax representation of the anonymous object creation statement being converted.</param>
/// <remarks>
/// Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first.
/// The type name is generated by the compiler and is not available at the source code level.
/// The type of each property is inferred by the compiler.
/// </remarks>
/// <example>
/// The following example shows an anonymous type that is initialized with two properties named Amount and Message.
/// <c>var v = new { Amount = 108, Message = "Hello" };</c>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/anonymous-types">Anonymous types</seealso>
private void ConvertAnonymousObjectCreationExpression(SemanticModel model, AnonymousObjectCreationExpressionSyntax expression)
{
AddInstruction(OpCode.NEWARRAY0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// Converts the code for constructing arrays and initializing arrays into OpCodes.
/// This method includes analyzing the array length, array type, array dimension and initial data.
/// </summary>
/// <param name="model">The semantic model providing context and information about the array creation.</param>
/// <param name="expression">The syntax representation of the array creation statement being converted.</param>
/// <exception cref="CompilationException">Only one-dimensional arrays are supported, otherwise an exception is thrown.</exception>
/// <remarks>
/// When the array is initialized to null, this code converts it to "array length" + OpCode.NEWBUFFER (only for byte[]) or OpCode.NEWARRAY_T.
/// When the array is not initialized to null, this code converts the initialized constants one by one in reverse order, then adds the "array length" and OpCode.PACK
/// </remarks>
/// <example>
/// Example of a array creation syntax:
/// <c>var array = new byte[4];</c>
/// The compilation result of the example code is: OpCode.PUSH4, OpCode.NEWBUFFER
/// <c>var array = new int[4] { 5, 6, 7, 8};</c>
/// The compilation result of the example code is: OpCode.PUSH8, OpCode.PUSH7, OpCode.PUSH6, OpCode.PUSH5, OpCode.PUSH4, OpCode.PACK
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/arrays">Arrays</seealso>
private void ConvertArrayCreationExpression(SemanticModel model, ArrayCreationExpressionSyntax expression)
{
ArrayRankSpecifierSyntax specifier = expression.Type.RankSpecifiers[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,32 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// Converts the code for null-coalescing assignment expression into OpCodes.
/// The null-coalescing assignment operator ??= assigns the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null.
/// The ??= operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
/// Null-coalescing assignment expressions are a new feature introduced in C# 8.0(Released September, 2019).
/// </summary>
/// <param name="model">The semantic model providing context and information about coalesce assignment expression.</param>
/// <param name="expression">The syntax representation of the coalesce assignment expression statement being converted.</param>
/// <exception cref="CompilationException">Thrown when the syntax is not supported.</exception>
/// <example>
/// <code>
/// public class Cat
/// {
/// public string Name { get; set; }
/// }
/// </code>
/// <code>
/// Cat nullableCat = null;
/// Cat nonNullableCat = new() { Name = "Mimi" };
/// nullableCat ??= nonNullableCat;
/// Runtime.Log("Nullable cat: " + nullableCat.Name);
/// </code>
/// <c>nullableCat ??= nonNullableCat;</c> this line is evaluated as
/// <c>nullableCat = nullableCat ?? nonNullableCat;</c> is evaluated as <c>if (nullableCat == null) nullableCat = nonNullableCat;</c>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator">?? and ??= operators - the null-coalescing operators</seealso>
private void ConvertCoalesceAssignmentExpression(SemanticModel model, AssignmentExpressionSyntax expression)
{
switch (expression.Left)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// Converts the code for complex assignment (or compound assignment) expression into OpCodes.
/// </summary>
/// <param name="model">The semantic model providing context and information about complex assignment expression.</param>
/// <param name="expression">The syntax representation of the complex assignment expression statement being converted.</param>
/// <exception cref="CompilationException">Thrown when the syntax is not supported.</exception>
/// <remarks>
/// For a binary operator op, a compound assignment expression of the form "x op= y" is equivalent to "x = x op y" except that x is only evaluated once.
/// </remarks>
/// <example>
/// The following example demonstrates the usage of compound assignment with arithmetic operators:
/// The corresponding code branch is "ConvertComplexAssignmentExpression"
/// <code>
/// int a = 5;
/// a += 9;
/// Runtime.Log(a.ToString());
/// a -= 4;
/// Runtime.Log(a.ToString());
/// a *= 2;
/// Runtime.Log(a.ToString());
/// a /= 4;
/// Runtime.Log(a.ToString());
/// a %= 3;
/// Runtime.Log(a.ToString());
/// </code>
/// output: 14, 10, 20, 5, 2
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/assignment-operator#compound-assignment">Compound assignment</seealso>
private void ConvertComplexAssignmentExpression(SemanticModel model, AssignmentExpressionSyntax expression)
{
ITypeSymbol type = model.GetTypeInfo(expression).Type!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,23 @@ namespace Neo.Compiler;

partial class MethodConvert
{

/// <summary>
/// Converts the code for simple assignment expression into OpCodes.
/// The assignment operator = assigns the value of its right-hand operand to a variable,
/// a property, or an indexer element given by its left-hand operand.
/// </summary>
/// <param name="model">The semantic model providing context and information about simple assignment expression.</param>
/// <param name="expression">The syntax representation of the simple assignment expression statement being converted.</param>
/// <exception cref="CompilationException">Thrown when the syntax is not supported.</exception>
/// <remarks>
/// The result of an assignment expression is the value assigned to the left-hand operand.
/// The type of the right-hand operand must be the same as the type of the left-hand operand or implicitly convertible to it.
/// </remarks>
/// <example>
/// The assignment operator = is right-associative, that is, an expression of the form
/// <c>a = b = c</c> is evaluated as <c>a = (b = c)</c>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/assignment-operator">Assignment operators</seealso>
private void ConvertSimpleAssignmentExpression(SemanticModel model, AssignmentExpressionSyntax expression)
{
ConvertExpression(model, expression.Right);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,31 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// Converts the code for assignment expression into OpCodes.
/// Include assignment operator (=), null-coalescing assignment operator (??=) and compound assignment(+=, -=, *=, /= ... )
/// </summary>
/// <param name="model">The semantic model providing context and information about assignment expression.</param>
/// <param name="expression">The syntax representation of the assignment expression statement being converted.</param>
/// <example>
/// The following code covers three branches. If you want to see the example code for only one of the branches,
/// you can look at the comments of the corresponding method.
/// <code>
/// public class Cat
/// {
/// public string Name { get; set; }
/// }
/// </code>
/// <code>
/// Cat nullableCat = null;
/// Cat nonNullableCat = new() { Name = "Mimi" };
/// nullableCat ??= nonNullableCat;
/// var logInfo = "Nullable cat: ";
/// logInfo += nullableCat.Name;
/// Runtime.Log(log);
/// </code>
/// </example>
/// <seealso cref="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/assignment-operator"/>
private void ConvertAssignmentExpression(SemanticModel model, AssignmentExpressionSyntax expression)
{
switch (expression.OperatorToken.ValueText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// The conditional logical OR operator ||, also known as the "short-circuiting" logical OR operator, computes the logical OR of its operands.
/// The result of x || y is true if either x or y evaluates to true.
/// Otherwise, the result is false. If x evaluates to true, y isn't evaluated.
///
/// The conditional logical AND operator &&, also known as the "short-circuiting" logical AND operator, computes the logical AND of its operands.
/// The result of x && y is true if both x and y evaluate to true.
/// Otherwise, the result is false. If x evaluates to false, y isn't evaluated.
///
/// The is operator checks if the run-time type of an expression result is compatible with a given type. The is operator also tests an expression result against a pattern.
///
/// The as operator explicitly converts the result of an expression to a given reference or nullable value type. If the conversion isn't possible, the as operator returns null. Unlike a cast expression, the as operator never throws an exception.
///
/// The null-coalescing operator ?? returns the value of its left-hand operand if it isn't null;
/// otherwise, it evaluates the right-hand operand and returns its result.
/// The ?? operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
/// </summary>
/// <param name="model">The semantic model providing context and information about binary expression.</param>
/// <param name="expression">The syntax representation of the binary expression statement being converted.</param>
/// <exception cref="CompilationException">If an unsupported operator is encountered</exception>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators">Boolean logical operators - AND, OR</seealso>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast">Type-testing operators and cast expressions - is, as</seealso>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator">?? operators - the null-coalescing operators</seealso>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators">Bitwise and shift operators</seealso>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators">Arithmetic operators</seealso>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators">Boolean logical operators - AND, OR, NOT, XOR</seealso>
private void ConvertBinaryExpression(SemanticModel model, BinaryExpressionSyntax expression)
{
switch (expression.OperatorToken.ValueText)
Expand Down
22 changes: 22 additions & 0 deletions src/Neo.Compiler.CSharp/MethodConvert/Expression/CastExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,28 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// This method converts a cast expression to OpCodes.
/// A cast expression of the form (T)E performs an explicit conversion of the result of expression E to type T.
/// If no explicit conversion exists from the type of E to type T, a compile-time error occurs.
/// </summary>
/// <param name="model">The semantic model providing context and information about cast expression.</param>
/// <param name="expression">The syntax representation of the cast expression statement being converted.</param>
/// <remarks>
/// This method determines the source type and the target type of the cast expression.
/// If the cast can be resolved to a method symbol, it calls the corresponding method.
/// Otherwise, it generates OpCodes based on the types involved in the cast operation.
/// </remarks>
/// <example>
/// This code is cast a ByteString type to an ECPoint type,
/// where the source type is ByteString and the target type is ECPoint.
/// <code>
/// ByteString bytes = ByteString.Empty;
/// ECPoint point = (ECPoint)bytes;
/// Runtime.Log(point.ToString());
/// </code>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#cast-expression">Cast expression</seealso>
private void ConvertCastExpression(SemanticModel model, CastExpressionSyntax expression)
{
ITypeSymbol sType = model.GetTypeInfo(expression.Expression).Type!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,39 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// The checked and unchecked statements specify the overflow-checking context for integral-type arithmetic operations and conversions.
/// When integer arithmetic overflow occurs, the overflow-checking context defines what happens.
/// In a checked context, a System.OverflowException is thrown;
/// if overflow happens in a constant expression, a compile-time error occurs.
/// </summary>
/// <param name="model">The semantic model providing context and information about checked and unchecked statement.</param>
/// <param name="expression">The syntax representation of the checked and unchecked statement being converted.</param>
/// <example>
/// Use the checked keyword to qualify the result of the temp*2 calculation and use a try catch to handle the overflow if it occurs.
/// <code>
/// try
/// {
/// int temp = int.MaxValue;
/// int a = checked(temp * 2);
/// }
/// catch (OverflowException)
/// {
/// Runtime.Log("Overflow");
/// }
/// </code>
/// </example>
/// <remarks>
/// This code is not called when the checked keyword modifies a block of statements, for example.
/// <code>
/// checked
/// {
/// int a = temp * 2;
/// }
/// </code>
/// For a checked statement, see <see cref="ConvertCheckedStatement(SemanticModel, CheckedStatementSyntax)"/>
/// </remarks>
/// <seealso href="https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/arithmetic-operators#integer-arithmetic-overflow">Integer arithmetic overflow</seealso>
private void ConvertCheckedExpression(SemanticModel model, CheckedExpressionSyntax expression)
{
_checkedStack.Push(expression.Keyword.IsKind(SyntaxKind.CheckedKeyword));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,36 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// This method converts a null-conditional access expression to OpCodes.
/// </summary>
/// /// <param name="model">The semantic model providing context and information about null-conditional access expression.</param>
/// <param name="expression">The syntax representation of the null-conditional access expression statement being converted.</param>
/// <remarks>
/// The method evaluates the expression and checks if it is null.
/// If the expression is not null, it converts the 'WhenNotNull' part of the expression.
/// If the resulting type of the expression is 'System.Void', it handles the case differently by dropping the result.
/// A null-conditional operator applies a member access (?.) or element access (?[]) operation to its operand only if that operand evaluates to non-null;
/// otherwise, it returns null.
/// It will jump to <see cref="ConvertMemberBindingExpression"/> and <see cref="ConvertElementBindingExpression"/> to handle the case where the variable or array is not null.
/// </remarks>
/// <example>
/// If Block is not null, get the block's timestamp; otherwise, it returns null.
/// <code>
/// var block = Ledger.GetBlock(10000);
/// var timestamp = block?.Timestamp;
/// Runtime.Log(timestamp.ToString());
/// </code>
/// If array is not null, get the array's element; otherwise, it returns null.
/// <code>
/// var a = Ledger.GetBlock(10000);
/// var b = Ledger.GetBlock(10001);
/// var array = new[] { a, b };
/// var firstItem = array?[0];
/// Runtime.Log(firstItem?.Timestamp.ToString());
/// </code>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-">Null-conditional operators ?. and ?[]</seealso>
private void ConvertConditionalAccessExpression(SemanticModel model, ConditionalAccessExpressionSyntax expression)
{
ITypeSymbol type = model.GetTypeInfo(expression).Type!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ namespace Neo.Compiler;

partial class MethodConvert
{
/// <summary>
/// This method converts a ternary conditional expression to OpCodes.
/// </summary>
/// /// <param name="model">The semantic model providing context and information about ternary conditional expression.</param>
/// <param name="expression">The syntax representation of the ternary conditional expression statement being converted.</param>
/// <example>
/// The conditional operator ?:, also known as the ternary conditional operator,
/// evaluates a Boolean expression and returns the result of one of the two expressions,
/// depending on whether the Boolean expression evaluates to true or false, as the following example shows:
/// <code>
/// var index = 10000;
/// var current = Ledger.CurrentIndex;
/// var state = current > index ? "start" : "stop";
/// Runtime.Log(state.ToString());
/// </code>
/// </example>
/// <seealso href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator">?: operator - the ternary conditional operator</seealso>
private void ConvertConditionalExpression(SemanticModel model, ConditionalExpressionSyntax expression)
{
JumpTarget falseTarget = new();
Expand Down
Loading

0 comments on commit 4661dd2

Please sign in to comment.