Skip to content

Commit d872f61

Browse files
RexJaeschkeBillWagner
authored andcommitted
tweak table formatting
Add support for top-level statements Add support for top-level statements fix md formatting tweak generated entry-point signature table Update basic-concepts.md Add mention of attribute System.Runtime.CompilerServices.CallerMemberName mention invoking method in top-level statement situation fix link
1 parent b637ac5 commit d872f61

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-3
lines changed

standard/attributes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ The file path may be affected by `#line` directives ([§6.5.8](lexical-structure
819819
820820
The attribute `System.Runtime.CompilerServices.CallerMemberNameAttribute` is allowed on optional parameters when there is a standard implicit conversion ([§10.4.2](conversions.md#1042-standard-implicit-conversions)) from `string` to the parameter’s type.
821821
822-
If a function invocation from a location within the body of a function member or within an attribute applied to the function member itself or its return type, parameters or type parameters in source code omits an optional parameter with the `CallerMemberNameAttribute`, then a string literal representing the name of that member is used as an argument to the invocation instead of the default parameter value.
822+
If a function invocation from a location within the body of a function member or within an attribute applied to the function member itself or its return type, parameters or type parameters in source code omits an optional parameter with the `CallerMemberNameAttribute`, then a string literal representing the name of that member is used as an argument to the invocation instead of the default parameter value. (In the case of a function invocation from a top-level statement (§top-level-statements), the member name is that generated by the implementation.)
823823
824824
For invocations that occur within generic methods, only the method name itself is used, without the type parameter list.
825825

standard/basic-concepts.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,20 @@
22

33
## 7.1 Application startup
44

5+
<<<<<<< HEAD
56
A program may be compiled either as a ***class library*** to be used as part of other applications, or as an ***application*** that may be started directly. The mechanism for determining this mode of compilation is implementation-defined and external to this specification.
7+
=======
8+
### §app-startup-general General
9+
10+
A program may be compiled either as a ***class library*** to be used as part of other applications, or as an ***application*** that may be started directly. The mechanism for determining this mode of compilation is implementation-specific and external to this specification.
11+
12+
The entry point of an application may be specified in either of the following ways:
13+
14+
1. Explicitly, by declaring a method with appropriate characteristics (§named-entry-point).
15+
1. Implicitly, by using top-level statements (§top-level-statements).
16+
17+
### §named-entry-point Using a named entry point
18+
>>>>>>> 04e6903 (tweak table formatting)
619
720
A program compiled as an application shall contain at least one method qualifying as an entry point by satisfying the following requirements:
821

@@ -47,6 +60,166 @@ If the effective entry point’s return type is `int`, the return value from the
4760

4861
Other than the situations listed above, entry point methods behave like those that are not entry points in every respect. In particular, if the entry point is invoked at any other point during the application’s lifetime, such as by regular method invocation, there is no special handling of the method: if there is a parameter, it may have an initial value of `null`, or a non-`null` value referring to an array that contains null references. Likewise, the return value of the entry point has no special significance other than in the invocation from the execution environment.
4962

63+
### §top-level-statements Using top-level statements
64+
65+
Any one compilation unit ([§14.2](namespaces.md#142-compilation-units) in an application may contain one or more *statement_list*s—collectively called ***top-level statements***—in which case, the meaning is as if those *statement_list*s were combined in the block body of a static method within a partial class called `Program` in the global namespace, as follows:
66+
67+
```csharp
68+
partial class Program
69+
{
70+
static «AsyncAndReturnType» «Main»(string[] args)
71+
{
72+
// top-level statements
73+
}
74+
}
75+
```
76+
77+
The class name `Program` shall be referenceable by name from within the application. However, the method name `«Main»` is used here for illustrative purposes only. The actual name generated by the implementation is unspecified, and cannot be referenced by name from within the application. It is, however, available via the attribute `System.Runtime.CompilerServices.CallerMemberName` ([§23.5.6.4](attributes.md#23564-the-callermembername-attribute)).
78+
79+
The method is designated as the entry point of the program. Explicitly declared methods (including static ones called `Main`) that by convention could be considered as entry point candidates (§named-entry-point) shall be ignored for that purpose.
80+
81+
The entry-point method has one parameter, `string[] args`. This parameter is in scope within the top-level statements and not otherwise. Regular name conflict/shadowing rules apply.
82+
83+
Async operations are allowed in top-level statements to the degree they are allowed in statements within a named async entry-point method. However, they are not required.
84+
85+
The tokens that are generated in place of `«AsyncAndReturnType»` are determined based on operations used by the top-level statements, as follows:
86+
87+
| **Top-level code contains** | **Generated entry-point signature**
88+
| ----------------------- | -------------------------------
89+
| No `await` or `return` with value | `private static void «Main»(string[] args)`
90+
| `return` with value only | `private static int «Main»(string[] args)`
91+
| `await` only | `private static async Task «Main»(string[] args)`
92+
| `await` and `return` with value | `private static async Task<int> «Main»(string[] args)`
93+
94+
This is illustrated by the following sets of top-level statements:
95+
96+
**Set 1**
97+
98+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements2A", expectedOutput:["cmd-line args length = 0"]} -->
99+
```csharp
100+
using System;
101+
Console.WriteLine($"cmd-line args length = {args.Length}");
102+
C c = new C();
103+
public class C {}
104+
```
105+
106+
whose implementation-generated code is
107+
108+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements2B", expectedOutput:["cmd-line args length = 0"]} -->
109+
```csharp
110+
using System;
111+
partial class Program
112+
{
113+
static void «Main»(string[] args)
114+
{
115+
Console.WriteLine($"cmd-line args length = {args.Length}");
116+
C c = new C();
117+
}
118+
}
119+
public class C {}
120+
```
121+
122+
*Note*: As required by the grammar for *compilation_unit* ([§14.2](namespaces.md#142-compilation-units)), top-level statements must come after *using_directive*s and before *namespace_member_declaration*s, such as types. *end note*
123+
124+
**Set 2**
125+
126+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements3A", expectedOutput:["Hi!"]} -->
127+
```csharp
128+
System.Console.WriteLine("Hi!");
129+
return 2;
130+
```
131+
132+
whose implementation-generated code is
133+
134+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements3B", expectedOutput:["Hi!"]} -->
135+
```csharp
136+
partial class Program
137+
{
138+
static int «Main»(string[] args)
139+
{
140+
System.Console.WriteLine("Hi!");
141+
return 2;
142+
}
143+
}
144+
```
145+
146+
**Set 3**
147+
148+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements4A", expectedOutput:["Hi!"]} -->
149+
```csharp
150+
using System;
151+
using System.Threading.Tasks;
152+
await Task.Delay(1000);
153+
Console.WriteLine("Hi!");
154+
```
155+
156+
whose implementation-generated code is
157+
158+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements4B", expectedOutput:["Hi!"]} -->
159+
```csharp
160+
using System;
161+
using System.Threading.Tasks;
162+
partial class Program
163+
{
164+
static async Task «Main»(string[] args)
165+
{
166+
await Task.Delay(1000);
167+
Console.WriteLine("Hi!");
168+
}
169+
}
170+
```
171+
172+
**Set 4**
173+
174+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements5A", expectedOutput:["Hi!"]} -->
175+
```csharp
176+
using System;
177+
using System.Threading.Tasks;
178+
await Task.Delay(1000);
179+
Console.WriteLine("Hi!");
180+
return 0;
181+
```
182+
183+
whose implementation-generated code is
184+
185+
<!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements5B", expectedOutput:["Hi!"]} -->
186+
```csharp
187+
using System;
188+
using System.Threading.Tasks;
189+
partial class Program
190+
{
191+
static async Task<int> «Main»(string[] args)
192+
{
193+
await Task.Delay(1000);
194+
Console.WriteLine("Hi!");
195+
return 0;
196+
}
197+
}
198+
```
199+
200+
The implementation-generated class `Program` can be augmented by user-written code that declares one or more partial classes called `Program`.
201+
202+
> *Example*: Consider the following:
203+
>
204+
> <!-- Example: {template:"standalone-console-without-using", name:"TopLevelStatements6"} -->
205+
> ```csharp
206+
> M1(); // call top-level static local function M1
207+
> M2(); // call top-level non-static local function M2
208+
>
209+
> static void M1() { } // static local function
210+
> void M2() { } // non-static local function
211+
>
212+
> Program.M1(); // call static method M1
213+
> new Program().M2(); // call non-static method M2
214+
> partial class Program
215+
> {
216+
> static void M1() { } // static method
217+
> void M2() { } // non-static method
218+
> }
219+
> ```
220+
>
221+
> As the first two declarations for `M1` and `M2` get wrapped inside the generated entry-point method, they are local functions. However, the second two declarations are methods, as they are declared inside a class rather than a method. *end example*
222+
50223
## 7.2 Application termination
51224
52225
***Application termination*** returns control to the execution environment.
@@ -708,6 +881,17 @@ Within the scope of a local variable, it is a compile-time error to refer to the
708881
>
709882
> *end note*
710883
884+
<<<<<<< HEAD
885+
=======
886+
As described in §top-level-statements, top-level source tokens are enclosed by the generated entry-point method.
887+
888+
For the purpose of simple-name evaluation, once the global namespace is reached, first, an attempt is made to evaluate the name within the generated entry point method and only if this attempt fails is the evaluation within the global namespace declaration performed.
889+
890+
This could lead to name shadowing of namespaces and types declared within the global namespace as well as to shadowing of imported names.
891+
892+
If the simple name evaluation occurs outside of the top-level statements and the evaluation yields a top-level local variable or function, a compile-time error results.
893+
894+
>>>>>>> 04e6903 (tweak table formatting)
711895
### 7.7.2 Name hiding
712896
713897
#### 7.7.2.1 General

standard/namespaces.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ Using directives ([§14.5](namespaces.md#145-using-directives)) are provided to
88

99
## 14.2 Compilation units
1010

11-
A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input.
11+
A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input.
1212

1313
```ANTLR
1414
compilation_unit
1515
: extern_alias_directive* using_directive* global_attributes?
16-
namespace_member_declaration*
16+
statement_list* namespace_member_declaration*
1717
;
1818
```
1919

standard/portability-issues.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ A conforming implementation is required to document its choice of behavior in ea
5454

5555
## B.4 Unspecified behavior
5656

57+
1. The name of the entry-point method generated to contain top-level statements (§top-level-statements).
5758
1. The time at which the finalizer (if any) for an object is run, once that object has become eligible for finalization ([§7.9](basic-concepts.md#79-automatic-memory-management)).
5859
1. The representation of `true` ([§8.3.9](types.md#839-the-bool-type)).
5960
1. The value of the result when converting out-of-range values from `float` or `double` values to an integral type in an `unchecked` context ([§10.3.2](conversions.md#1032-explicit-numeric-conversions)).

0 commit comments

Comments
 (0)