Skip to content

Sharpy

Sharpy

A statically-typed Pythonic language for .NET

Sharpy combines Python's clean syntax with .NET's type system and runtime. Write code that looks like Python, runs on .NET, and catches bugs at compile time.

class Greeter:
    name: str

    def __init__(self, name: str):
        self.name = name

    def greet(self) -> str:
        return f"Hello, {self.name}!"

greeter = Greeter("World")
print(greeter.greet())  # Hello, World!

Core Principles

Python Syntax -- Indentation-based blocks, comprehensions, decorators, and dunders. If you know Python, you can read Sharpy.

Static Typing -- Every type is known at compile time. None requires explicit opt-in via T?. No runtime surprises.

.NET Runtime -- Compiles to C# and runs on the .NET CLR. Full interop with any .NET library.

Getting Started

# Install the Sharpy compiler
dotnet tool install -g sharpyc

# Compile and run
sharpyc run hello.spy

# Pass arguments to your program: everything after `--` goes to it
sharpyc run hello.spy -- alpha beta

# Inspect generated C#
sharpyc emit csharp hello.spy

CLI change: options take one value per occurrence

--reference, --project-reference, --module-path and --args each take one value per occurrence and repeat to collect:

sharpyc build app.spy --reference a.dll --reference b.dll

The multi-value spellings --reference a.dll b.dll and --args a b c no longer work. A single occurrence used to keep consuming the bare tokens that followed it, which meant it also swallowed the file you were compiling — sharpyc run --module-path src file.spy bound file.spy to --module-path and then failed with "Required argument missing".

Program arguments now have a conventional spelling: everything after a bare -- is passed to the program being run, as with dotnet run -- and cargo run --. Tokens after -- are never read as compiler options, so sharpyc run app.spy -- --verbose passes --verbose to your program. --args is deprecated in favour of it; --args a --args b still works, but --args a b c does not.

What needs .NET on the machine

The self-contained release archives (sharpyc-<rid>.tar.gz / .zip on the GitHub Releases page) start without any .NET install, and every command that only compiles — build, compile, project without packages, emit — works with nothing else installed. Three things start dotnet and need .NET 10 with dotnet on PATH:

Command Needs
sharpyc run (runs the compiled program) the .NET 10 runtime or SDK
run --self-contained, compile --self-contained (dotnet publish) the .NET 10 SDK
project with <PackageReference> items (dotnet restore) the .NET 10 SDK

Without it these refuse with SPY0913 before compiling anything (sharpyc explain SPY0913). The dotnet tool install channel always has the SDK.

Features

Feature Description
Null safety T? opt-in, ?? coalescing, ?. conditional access
Error propagation ? operator for ergonomic Result/Optional early-return
Pattern matching match with destructuring, guards, and exhaustiveness checking
Tagged unions Result[T, E] and Optional[T] built in
Generics With variance (in/out) and type constraints
Properties Auto-properties and function-style with validation
.NET interop Import and use any .NET library directly
Comprehensions List, dict, and set comprehensions
Generators yield and yield from with lazy evaluation