Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .build/checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -euo pipefail
cd "$(dirname "$0")/.."
configuration="${FSCRIPT_BUILD_CONFIG:-Release}"
cli=(dotnet "src/FScript/bin/$configuration/net10.0/fscript.dll")
cli=(dotnet "src/FScript/bin/$configuration/net11.0/fscript.dll")
run_node_tests() {
local report=$1
shift
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/test-vscode-debugger.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ let calculate value =
answer * 2
calculate 41
SCRIPT
python3 - "$fixture/workspace/.vscode/settings.json" "$repo/src/FScript/bin/Release/net10.0/fscript.dll" <<'PYSETTINGS'
python3 - "$fixture/workspace/.vscode/settings.json" "$repo/src/FScript/bin/Release/net11.0/fscript.dll" <<'PYSETTINGS'
import json,pathlib,sys
pathlib.Path(sys.argv[1]).write_text(json.dumps({
'fscript.lsp.enabled': True,
'fscript.server.path': str(pathlib.Path(sys.argv[2]).parents[5] / 'src/FScript.LanguageServer/bin/Release/net10.0/FScript.LanguageServer.dll'),
'fscript.server.path': str(pathlib.Path(sys.argv[2]).parents[5] / 'src/FScript.LanguageServer/bin/Release/net11.0/FScript.LanguageServer.dll'),
'fscript.cli.path': sys.argv[2],
'terminal.integrated.enablePersistentSessions': False
}))
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/verify-release-cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dotnet build "$repo_root/samples/ffi/Provider/FfiSample.fsproj" -c Release

mkdir -p "$test_root/source"
printf "[runtime]\nextern-assemblies = ['%s']\n" \
"$repo_root/samples/ffi/Provider/bin/Release/net10.0/FScript.Ffi.Sample.dll" > "$test_root/source/fscript.toml"
"$repo_root/samples/ffi/Provider/bin/Release/net11.0/FScript.Ffi.Sample.dll" > "$test_root/source/fscript.toml"
printf 'Math.sqrt 81.0\n' > "$test_root/source/check.fss"
for target in csharp dotnet; do
"$cli" compile "$test_root/source/check.fss" --target "$target" --output "$test_root/$target"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to FScript are documented in this file.

## [Unreleased]

- Run the FScript CLI and language server on .NET 11 and target .NET 11 when compiling scripts to .NET or C#.
- Document how compiled programs optimize `List.init`.

## [0.90.3]
Expand Down
4 changes: 3 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<PropertyGroup>
<UseLocalFScriptExtensibility Condition="'$(UseLocalFScriptExtensibility)' == ''">false</UseLocalFScriptExtensibility>
<FScriptExtensibilityProject>$(MSBuildThisFileDirectory)../FScript.Extensibility/src/FScript.Extensibility/FScript.Extensibility.fsproj</FScriptExtensibilityProject>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
<!-- Keep the assembly version used by the published FScript.Extensibility SDK. -->
<FSharpCoreImplicitPackageVersion>10.1.404</FSharpCoreImplicitPackageVersion>
<LangVersion>preview</LangVersion>
<Deterministic>false</Deterministic>
<IsPackable>false</IsPackable>
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ benchmark-evaluation:
# Compile once, then compare exported native functions against optimized F#.
benchmark-dotnet-comparison:
dotnet build benchmarks/FScript.DotNet.Comparison/FScript.DotNet.Comparison.fsproj -c Release
DOTNET_TieredCompilation=0 DOTNET_ReadyToRun=0 dotnet benchmarks/FScript.DotNet.Comparison/bin/Release/net10.0/FScript.DotNet.Comparison.dll $(or $(iterations),500) $(or $(rounds),9) "$(or $(output),out/benchmarks/dotnet-vs-fsharp)" $(if $(filter true,$(verify)),--verify-only)
DOTNET_TieredCompilation=0 DOTNET_ReadyToRun=0 dotnet benchmarks/FScript.DotNet.Comparison/bin/Release/net11.0/FScript.DotNet.Comparison.dll $(or $(iterations),500) $(or $(rounds),9) "$(or $(output),out/benchmarks/dotnet-vs-fsharp)" $(if $(filter true,$(verify)),--verify-only)

fable-build:
dotnet tool restore
Expand Down
2 changes: 1 addition & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ variable config { default = "Release" }

locals {
versions = {
dotnet_sdk: "10.0.403"
dotnet_sdk: "11.0.100"
node: "22"
terrabuild: "latest"
vsce: "4.0.0"
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/FScript.DotNet.Comparison/CompareArtifacts.fsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Build the comparison project in Release before running this script.
#r "bin/Release/net10.0/FScript.DotNet.Reference.dll"
#r "bin/Release/net10.0/FScript.DotNet.Comparison.dll"
#r "bin/Release/net11.0/FScript.DotNet.Reference.dll"
#r "bin/Release/net11.0/FScript.DotNet.Comparison.dll"

open System
open System.IO
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/FScript.DotNet.Comparison/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This comparison measures native managed functions generated by the FScript .NET backend against equivalent F# compiled in Release mode. It also dumps both assemblies' IL. It does not measure either interpreter, Native AOT, command startup, or publishing.

Run from the repository root with the .NET 10 SDK:
Run from the repository root with the .NET 11 SDK:

```sh
make benchmark-dotnet-comparison
Expand All @@ -16,7 +16,7 @@ The Make target builds in Release, then starts a separate process with tiered co

```sh
dotnet build benchmarks/FScript.DotNet.Comparison -c Release
dotnet benchmarks/FScript.DotNet.Comparison/bin/Release/net10.0/FScript.DotNet.Comparison.dll 500 9 out/comparison-default
dotnet benchmarks/FScript.DotNet.Comparison/bin/Release/net11.0/FScript.DotNet.Comparison.dll 500 9 out/comparison-default
```

Do not run concurrent builds or benchmarks. Repeat the process several times on an idle machine; compare medians and the per-round spread, rather than a single run. These measurements are diagnostic, not performance promises or CI timing thresholds.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/native-aot-size.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The optional `--size-optimized` profile sets `InvariantGlobalization=true`, `Use

## Analysis and validation

For size attribution, publish the generated assembly through an isolated SDK project whose post-`CoreCompile` target copies the generated PE over its placeholder assembly, matching `DotNetPackaging`. Set `IlcGenerateMapFile=true`, `IlcGenerateMstatFile=true`, and, when investigating a dependency, `IlcGenerateDgmlFile=true`. The SDK writes maps, statistics, and dependency graphs under `obj/Release/net10.0/<rid>/native/`. Compare `ResourceData` and native `MethodCode` nodes in the XML map, then follow dependency graph edges to find the root of unexpected code. FScript's regular publisher deletes this temporary project after compilation.
For size attribution, publish the generated assembly through an isolated SDK project whose post-`CoreCompile` target copies the generated PE over its placeholder assembly, matching `DotNetPackaging`. Set `IlcGenerateMapFile=true`, `IlcGenerateMstatFile=true`, and, when investigating a dependency, `IlcGenerateDgmlFile=true`. The SDK writes maps, statistics, and dependency graphs under `obj/Release/net11.0/<rid>/native/`. Compare `ResourceData` and native `MethodCode` nodes in the XML map, then follow dependency graph edges to find the root of unexpected code. FScript's regular publisher deletes this temporary project after compilation.

The sample integration tests publish both profiles, inspect the executable for the exact target GLFW payload and absence of every other GLFW payload, move the executable away from scripts and provider DLLs, run headless frames without a .NET installation, and check invalid frame limits. macOS ARM64 size budgets leave SDK headroom while catching the original all-platform resource regression. A packed-buffer test checks all uploaded position and normal components. Real OpenGL validation uses `--frames 3` and checks the renderer's count of teapot-colored framebuffer pixels.

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/compilation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FScript can run inside a host application or compile into a program that runs on

| Output | Command options | Use it when |
| --- | --- | --- |
| .NET assembly | `--target dotnet` | You want compiled execution with FScript's assembly optimizations. Run the DLL with .NET 10. |
| .NET assembly | `--target dotnet` | You want compiled execution with FScript's assembly optimizations. Run the DLL with .NET 11. |
| Self-contained executable | `--target dotnet --single-file [--runtime <rid>]` | You want one distributable executable that includes the .NET runtime. |
| Native AOT executable | `--target dotnet --aot [--runtime <rid>]` | You want dependencies trimmed and compiled into a native executable. |
| C# project | `--target csharp` | You want to inspect, edit, or integrate generated source in a .NET build. |
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/compile-to-csharp.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Compile to C#

The C# backend writes an independently buildable .NET 10 project. Use it when generated source belongs in your build, when you need to inspect a translated program, or when you want to make further changes in C#.
The C# backend writes an independently buildable .NET 11 project. Use it when generated source belongs in your build, when you need to inspect a translated program, or when you want to make further changes in C#.

For FScript's additional call, closure, tail-recursion, and pruning optimizations, use the [.NET assembly target](./compile-to-dotnet.md). Building generated C# does not enable those assembly-only passes.

Expand All @@ -12,7 +12,7 @@ dotnet build out/hello-csharp/Program.csproj -c Release
dotnet run --project out/hello-csharp/Program.csproj -c Release -- Ada
```

Building the generated project requires the .NET 10 SDK. From the FScript checkout, generation can instead use:
Building the generated project requires the .NET 11 SDK. From the FScript checkout, generation can instead use:

```sh
dotnet run --project src/FScript -- compile samples/hello.fss --target csharp --output out/hello-csharp
Expand Down
14 changes: 7 additions & 7 deletions docs/guides/compile-to-dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ The .NET backend compiles a typed FScript program into an optimized .NET assembl

| Operation | Requirements |
| --- | --- |
| Generate a `.dll` with `--target dotnet` | FScript and a .NET 10 runtime; no SDK required. Roslyn is bundled with FScript and emits the assembly in-process. |
| Publish with `--single-file` | .NET 10 SDK available through `dotnet` on PATH. |
| Publish with `--aot` | .NET 10 SDK plus the target platform's native build tools; build on the target OS. |
| Generate a `.dll` with `--target dotnet` | FScript and a .NET 11 runtime; no SDK required. Roslyn is bundled with FScript and emits the assembly in-process. |
| Publish with `--single-file` | .NET 11 SDK available through `dotnet` on PATH. |
| Publish with `--aot` | .NET 11 SDK plus the target platform's native build tools; build on the target OS. |

Running FScript itself from source with `dotnet run` requires the SDK to build FScript. That is separate from the installed compiler's requirements. A generated ordinary DLL needs a .NET 10 runtime to run; published single-file and AOT executables do not require a .NET installation on the destination machine.
Running FScript itself from source with `dotnet run` requires the SDK to build FScript. That is separate from the installed compiler's requirements. A generated ordinary DLL needs a .NET 11 runtime to run; published single-file and AOT executables do not require a .NET installation on the destination machine.

## Runnable .NET assembly

Expand All @@ -21,7 +21,7 @@ dotnet out/fibonacci-dotnet/fibonacci.dll

Compiled entry points print the final value by default. Add `--no-result` when compiling to suppress it and allow proven-pure discarded computations to be pruned. Explicit output, failures, and exit-code writes remain observable. Without this flag, library callers can retrieve the typed value through `Run` and format it explicitly with `FormatResult`; in discard mode, `Run` returns unit.

Output includes a `.dll`, runtime configuration, and required external managed dependencies. The minimum runtime is .NET 10. Arguments after the assembly name become `Env.Arguments`.
Output includes a `.dll`, runtime configuration, and required external managed dependencies. The minimum runtime is .NET 11. Arguments after the assembly name become `Env.Arguments`.

```sh
dotnet run --project src/FScript -- compile samples/basic/basic.fss --target dotnet --output out/basic-dotnet
Expand Down Expand Up @@ -66,7 +66,7 @@ Without that separator, `dotnet run` can consume `--runtime` itself and fail whi

Windows output has an `.exe` extension; macOS and Linux output has no extension. Use a fresh output directory when switching from DLL output: existing files are not deleted. External data such as BASIC source files remains program input and is not bundled.

Publishing requires a .NET 10 SDK on the build machine and may restore runtime/compiler packs from NuGet. Native AOT additionally requires the platform's native build tools (Xcode Command Line Tools on macOS; Clang and zlib headers on Linux; Visual Studio C++ build tools on Windows). Native AOT must be built on the target OS; single-file managed publishing can target another OS. The executables still use normal OS libraries. See Microsoft's [single-file](https://learn.microsoft.com/dotnet/core/deploying/single-file/) and [Native AOT](https://learn.microsoft.com/dotnet/core/deploying/native-aot/) deployment documentation.
Publishing requires a .NET 11 SDK on the build machine and may restore runtime/compiler packs from NuGet. Native AOT additionally requires the platform's native build tools (Xcode Command Line Tools on macOS; Clang and zlib headers on Linux; Visual Studio C++ build tools on Windows). Native AOT must be built on the target OS; single-file managed publishing can target another OS. The executables still use normal OS libraries. See Microsoft's [single-file](https://learn.microsoft.com/dotnet/core/deploying/single-file/) and [Native AOT](https://learn.microsoft.com/dotnet/core/deploying/native-aot/) deployment documentation.

Single-file publishing trims dependencies when all reachable FFI calls have static CLR bindings. Reachable legacy provider dispatch disables managed trimming to preserve its registration contract. Bundled native runtime libraries may be extracted by the .NET host at startup. Native AOT trims and compiles dependencies, so FFI libraries must be AOT-compatible. Dynamic loading or reflection-heavy providers may produce SDK diagnostics instead of a runnable native binary. Packaging failures are reported as `FSN710x`, including the SDK's diagnostics.

Expand All @@ -86,7 +86,7 @@ For the teapot example, `samples/ffi/fscript.toml` supplies the provider path:

```toml
[runtime]
extern-assemblies = ["Provider/bin/Release/net10.0/FScript.Ffi.Sample.dll"]
extern-assemblies = ["Provider/bin/Release/net11.0/FScript.Ffi.Sample.dll"]
```

Build the provider first, then analyze or compile without extra assembly flags:
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/compiler-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The IR form writes `<directory>/<program-name>.fsir`.

All targets create missing parent directories and deterministically replace files owned by the selected output on a repeated invocation. An unknown target is rejected before the output directory is created. Filesystem failures are reported as `FSA5101` diagnostics.

The C# target writes an independently buildable .NET 10 project. The .NET target writes `<program-name>.dll`, runtime configuration, and managed dependencies. Both support existing FFI providers selected through `fscript.toml` or `--extern-assembly`; `--reference` adds managed dependencies. Generated programs execute compiled methods without an interpreter. Compiled entry points display the final value by default; `--no-result` suppresses that display.
The C# target writes an independently buildable .NET 11 project. The .NET target writes `<program-name>.dll`, runtime configuration, and managed dependencies. Both support existing FFI providers selected through `fscript.toml` or `--extern-assembly`; `--reference` adds managed dependencies. Generated programs execute compiled methods without an interpreter. Compiled entry points display the final value by default; `--no-result` suppresses that display.

## FFI configuration with `fscript.toml`

Expand All @@ -24,7 +24,7 @@ For example, `samples/ffi/fscript.toml` contains:

```toml
[runtime]
extern-assemblies = ["Provider/bin/Release/net10.0/FScript.Ffi.Sample.dll"]
extern-assemblies = ["Provider/bin/Release/net11.0/FScript.Ffi.Sample.dll"]
```

Assembly paths in the manifest resolve from the manifest directory. Local provider projects must be built before either command loads their configured DLLs. For C# and .NET output, compilation automatically references the providers and their colocated managed dependencies; `--reference` adds other managed assemblies when needed.
Expand Down Expand Up @@ -58,7 +58,7 @@ out/ffi/main --headless

On Windows the executable is `main.exe`. Native AOT requires the platform's native toolchain.

For a self-contained executable, add `--single-file` to the .NET target. For a Native AOT executable, use `--aot`. Publishing defaults to the current platform; pass `--runtime <rid>` to select another target. An explicitly supplied `--runtime` requires a value. Runtime identifiers use .NET names such as `osx-arm64`, `linux-x64`, and `win-x64`. Both options require a .NET 10 SDK for publishing and are rejected for other backends.
For a self-contained executable, add `--single-file` to the .NET target. For a Native AOT executable, use `--aot`. Publishing defaults to the current platform; pass `--runtime <rid>` to select another target. An explicitly supplied `--runtime` requires a value. Runtime identifiers use .NET names such as `osx-arm64`, `linux-x64`, and `win-x64`. Both options require a .NET 11 SDK for publishing and are rejected for other backends.

See [Compilation](./compilation.md), [Compile to .NET](./compile-to-dotnet.md), [Compile to C#](./compile-to-csharp.md), [Compilation and optimizations](./compiler-optimizations.md), and [Compile and Interpret FScript IR](./interpret-ir.md). The normative representations are documented in the [typed HIR](../specs/typed-hir.md) and [executable LIR](../specs/executable-lir.md) specifications.

Expand Down
Loading
Loading