Skip to content

Commit a6ccf57

Browse files
committed
plan: Add plan
1 parent c4909c4 commit a6ccf57

1 file changed

Lines changed: 159 additions & 0 deletions

File tree

plan.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Plan: Enable Strict Entry Point Main Function Requirement
2+
3+
## Problem Summary
4+
5+
In `src/Sharpy.Compiler/Semantic/Validation/ModuleLevelValidatorV2.cs` (lines 111-123), there is commented-out code that would enforce the requirement that **entry point files must have a `main()` function**. This is currently disabled for "backward compatibility."
6+
7+
According to the language specification in `docs/language_specification/program_entry_point.md`:
8+
> "Every executable Sharpy program requires a `main()` function as its entry point"
9+
10+
The validator currently:
11+
1. ✅ Rejects bare executable statements when there IS a `main()` function present
12+
2. ✅ Rejects bare executable statements in non-entry-point (library) modules
13+
3. ❌ Allows entry point files without a `main()` function (for backward compatibility)
14+
15+
## Current State Analysis
16+
17+
### Test Fixtures Already Compliant
18+
After analysis, **all test fixture files that are entry points already have `main()` functions**. The files without `main()` are all library modules (in multi-file test scenarios), which correctly don't need one.
19+
20+
### Files Without `main()` (Library Modules - Correct)
21+
These are all imported modules, not entry points:
22+
- `imports/import_with_classes/math_utils.spy`
23+
- `imports/simple_import_test/math_utils.spy`
24+
- `imports/module_import_access/calculator.spy`
25+
- `module_imports/geometry_shapes/geometry.spy`
26+
- `module_imports/geometry_shapes/validators.spy`
27+
- `module_imports/complex_type_relationships/geometry.spy`
28+
- `module_imports/complex_type_relationships/calculator.spy`
29+
- `cross_module_inheritance/*/*.spy` (all library files)
30+
31+
These files are correctly identified as non-entry-points via `IsEntryPoint = false`.
32+
33+
### Error Test Cases (Already Testing the Rules)
34+
- `errors/main_function_with_statements.spy` - Tests rejection of bare executable statements when `main()` exists
35+
- `errors/module_level_executable_statement.spy` - Tests rejection of bare `print()` at module level
36+
37+
## Implementation Plan
38+
39+
### Phase 1: Enable Strict Enforcement
40+
41+
**File:** `src/Sharpy.Compiler/Semantic/Validation/ModuleLevelValidatorV2.cs`
42+
43+
Uncomment and modify the entry point validation logic (lines 111-123):
44+
45+
```csharp
46+
// Entry point files should have a main() function
47+
if (_context.IsEntryPoint && !hasMainFunction)
48+
{
49+
AddError(_context,
50+
"Entry point file requires a 'main()' function",
51+
module.LineStart, module.ColumnStart);
52+
}
53+
```
54+
55+
**Rationale for removing the inner condition:** The original commented code had an inner check `if (executableStatements.Count == 0 && untypedVariables.Count == 0)` which would only error if there were NO executable statements AND NO untyped variables. This seems backwards - we should always require `main()` for entry points regardless of whether there are other violations.
56+
57+
### Phase 2: Add Error Test Case
58+
59+
**New file:** `src/Sharpy.Compiler.Tests/Integration/TestFixtures/errors/entry_point_missing_main.spy`
60+
61+
```python
62+
# Error test: Entry point file must have a main() function
63+
64+
counter: int = 0
65+
66+
def helper() -> int:
67+
return counter + 1
68+
69+
# No main() function defined - this is an error for entry point files
70+
```
71+
72+
**New file:** `src/Sharpy.Compiler.Tests/Integration/TestFixtures/errors/entry_point_missing_main.error`
73+
74+
```
75+
Entry point file requires a 'main()' function
76+
```
77+
78+
### Phase 3: Update Unit Tests
79+
80+
**File:** `src/Sharpy.Compiler.Tests/Semantic/Validation/ModuleLevelValidatorV2Tests.cs`
81+
82+
Add a test case verifying that entry point files without `main()` are rejected:
83+
84+
```csharp
85+
[Fact]
86+
public void EntryPointFile_WithoutMainFunction_ReportsError()
87+
{
88+
// Arrange: Entry point file with only declarations, no main()
89+
var source = @"
90+
counter: int = 0
91+
92+
def helper() -> int:
93+
return 42
94+
";
95+
var (module, context) = ParseWithContext(source, isEntryPoint: true);
96+
var validator = new ModuleLevelValidatorV2();
97+
98+
// Act
99+
validator.Validate(module, context);
100+
101+
// Assert
102+
Assert.True(context.Diagnostics.HasErrors);
103+
Assert.Contains(context.Diagnostics.Errors,
104+
e => e.Message.Contains("Entry point file requires a 'main()' function"));
105+
}
106+
107+
[Fact]
108+
public void LibraryModule_WithoutMainFunction_NoError()
109+
{
110+
// Arrange: Library module (not entry point) with only declarations
111+
var source = @"
112+
counter: int = 0
113+
114+
def helper() -> int:
115+
return 42
116+
";
117+
var (module, context) = ParseWithContext(source, isEntryPoint: false);
118+
var validator = new ModuleLevelValidatorV2();
119+
120+
// Act
121+
validator.Validate(module, context);
122+
123+
// Assert
124+
Assert.False(context.Diagnostics.HasErrors);
125+
}
126+
```
127+
128+
### Phase 4: Verify All Tests Pass
129+
130+
Run the full test suite to ensure:
131+
1. All existing tests still pass (they all have `main()`)
132+
2. The new error test case works correctly
133+
3. Library modules (non-entry-points) are not affected
134+
135+
```bash
136+
dotnet test
137+
```
138+
139+
## Risk Assessment
140+
141+
**Low Risk:** All existing test fixture files already have `main()` functions, so this change should not break any existing tests. The change only affects:
142+
1. The theoretical case of an entry point file without `main()` (which was "working" via backward compatibility)
143+
2. Adding proper validation for what the spec already requires
144+
145+
## Acceptance Criteria
146+
147+
1. ✅ Entry point files without `main()` produce error: "Entry point file requires a 'main()' function"
148+
2. ✅ Library modules without `main()` continue to work (no error)
149+
3. ✅ Entry point files WITH `main()` continue to work
150+
4. ✅ All existing tests pass
151+
5. ✅ New error test case added and passing
152+
6. ✅ Unit tests for the validator updated
153+
154+
## Files to Modify
155+
156+
1. `src/Sharpy.Compiler/Semantic/Validation/ModuleLevelValidatorV2.cs` - Enable strict enforcement
157+
2. `src/Sharpy.Compiler.Tests/Semantic/Validation/ModuleLevelValidatorV2Tests.cs` - Add unit tests
158+
3. `src/Sharpy.Compiler.Tests/Integration/TestFixtures/errors/entry_point_missing_main.spy` - New error test
159+
4. `src/Sharpy.Compiler.Tests/Integration/TestFixtures/errors/entry_point_missing_main.error` - Expected error message

0 commit comments

Comments
 (0)