What's wrong
EntryPoint exists so that "the name, the parameter spelling and the wiring that runs it are the generator's business" (Coder/Ast/EntryPoint.cs). In practice each generator writes it exactly where it sits in the AST, and no placement produces a runnable program in every target:
Where the EntryPoint is |
C# |
C++ |
C |
Rust |
Go |
SourceFile member |
public static int Main() at top level: CS0106 |
ok |
ok |
ok |
ok |
NamespaceDeclaration("App") member |
CS0116 (a namespace can't contain a method) |
App::main: undefined reference to main at link |
ok |
pub mod App { fn main() }: E0601 main function not found |
ok |
ClassDeclaration("Program") member |
ok |
member Program::main: undefined reference to main |
function body inside a typedef struct: syntax error |
dropped silently (pub struct Program {}) |
dropped silently (type Program struct{}) |
C# writes a bare public static … Main in every position (CSharpGenerator.GenerateEntryPoint, Coder/Languages/CSharpGenerator.cs:926-943). EntryPointTests.Schema_TakesAnEntryPointAsAMemberButNotAsAStatement accepts it as a class member on purpose, "which is where C# puts Main", but that is exactly the position C++, C, Rust and Go can't use.
Repro (confirmed with dotnet build / g++ / rustc)
EntryPoint main = new() { ReturnsExitCode = true };
main.Body.Add(new ReturnStatement(new LiteralExpression<int>(0)));
SourceFile file = new("app");
NamespaceDeclaration ns = new("App");
ns.Members.Add(main);
file.Members.Add(ns);
// C#: namespace App { public static int Main() { return 0; } } -> CS0116
// C++: namespace App { int main() { return 0; } } -> ld: undefined reference to `main'
// Rust: pub mod App { ... fn main() {...} } -> error[E0601]
Why it matters
A caller who wants one AST to produce a runnable program in every language has no placement that works. Two of the failures (Rust and Go inside a class) produce no error or note at all: the program just has no entry point.
Suggested fix / acceptance criteria
What's wrong
EntryPointexists so that "the name, the parameter spelling and the wiring that runs it are the generator's business" (Coder/Ast/EntryPoint.cs). In practice each generator writes it exactly where it sits in the AST, and no placement produces a runnable program in every target:EntryPointisSourceFilememberpublic static int Main()at top level: CS0106NamespaceDeclaration("App")memberApp::main: undefined reference tomainat linkpub mod App { fn main() }: E0601mainfunction not foundClassDeclaration("Program")memberProgram::main: undefined reference tomaintypedef struct: syntax errorpub struct Program {})type Program struct{})C# writes a bare
public static … Mainin every position (CSharpGenerator.GenerateEntryPoint,Coder/Languages/CSharpGenerator.cs:926-943).EntryPointTests.Schema_TakesAnEntryPointAsAMemberButNotAsAStatementaccepts it as a class member on purpose, "which is where C# putsMain", but that is exactly the position C++, C, Rust and Go can't use.Repro (confirmed with dotnet build / g++ / rustc)
Why it matters
A caller who wants one AST to produce a runnable program in every language has no placement that works. Two of the failures (Rust and Go inside a class) produce no error or note at all: the program just has no entry point.
Suggested fix / acceptance criteria
EntryPointoutside a type is wrapped inpublic static class Program { … }. Inside a type it stays as it is today.EntryPointinside a namespace or module is written at file scope, where the toolchain looks for it. For Rust, a rootfn maincan callApp::run.EntryPointinside a class is written at file scope, or at least reported withWriteInexpressible, and never dropped silently.NamespaceDeclaration) is compiled and linked by every language's compile test.