Hey HN
I’ve been building *W++*, a scripting language that looks like Python but runs on the .NET runtime. It started as a fun side project, but it evolved into something surprisingly powerful — and potentially useful:
Key Features:
- Python-style syntax with semicolon-based simplicity
- Compiles to .NET IL with experimental JIT support
- Can run interpreted or compiled
- Built-in CLI for managing projects, running, and building
- Supports importing NuGet packages and converts them to .ingot modules automatically
- MIT licensed and fully open-source
You can even do things like:
wpp
import Newtonsoft.Json
let person = new JObject()
person["name"] = "Alice"
print person["name"];
Use Cases:
Game scripting (Unity, OpenTK support in progress)
Education (gentle intro to .NET without C# syntax)
Blazor scripting
Embeddable scripting engine for .NET apps
GitHub:
https://github.com/sinisterMage/WPlusPlus
I’d love feedback, ideas, and thoughts.
Thanks for reading — and if you’ve ever said “I wish Python ran on .NET,” this might be for you.
That said, in 2025 if I was already willing to utilize C#/.NET, I would probably prefer an "internal" DSL approach [0] - i.e., one that leverages the host language directly and builds the abstractions on top.
Examples of this would be fluent interfaces and methods like ConfigureDomainServices(Action<DomainServiceBuilder>). I know some developers frown on this approach, but I've embraced it as the least terrible way to go about handling things like AspNetCore web server configuration and setting up complicated data transformation pipelines. If these techniques are good enough for configuring a modern, production grade web server, they are probably good enough for configuring your domain too.
I spent a solid 3 years building & supporting an IronPython stack on the old 4.x .NET Framework and I learned a lot of lessons about how bad things can get when you begin coloring outside the lines. Memory leaks were probably the most difficult thing to reason about. Object lifecycles are already pretty tricky without the hosted language on top.
[0]: https://martinfowler.com/dsl.html