pyfun-lang 0.0.1__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,426 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyfun-lang
3
+ Version: 0.0.1
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: Intended Audience :: Education
7
+ Classifier: Programming Language :: Python
8
+ Classifier: Programming Language :: Rust
9
+ Classifier: Topic :: Software Development :: Compilers
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Summary: An F#-inspired, functional-first language that compiles to readable Python.
13
+ Keywords: functional,compiler,fsharp,transpiler,education
14
+ Author: Simon Treanor
15
+ License-Expression: Apache-2.0
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
18
+ Project-URL: Repository, https://github.com/simontreanor/Pyfun
19
+
20
+ # Pyfun
21
+
22
+ **Functional programming for the language classrooms already teach.**
23
+
24
+ Pyfun is an F#-inspired, functional-first language that compiles to readable Python. It brings
25
+ algebraic data types, exhaustive matching, currying, inferred effects, and units of measure to the
26
+ Python ecosystem, and its Rust compiler checks every one of them before a single line of Python is
27
+ emitted.
28
+
29
+ It exists to make functional programming teachable where students already are. CS courses run on
30
+ Python; learning FP usually means leaving it for Haskell, OCaml, or F# and adopting a whole new
31
+ ecosystem students rarely touch again. Pyfun keeps them in Python, with no new runtime and no new
32
+ package manager, and compiles to Python they can read, so every concept stays visible in the code
33
+ they already understand.
34
+
35
+ ```fsharp
36
+ type Shape = Circle float | Rect float float
37
+
38
+ # `area` handles Circle but forgets Rect, so Pyfun refuses to compile it:
39
+ let area s =
40
+ match s:
41
+ case Circle r: 3.14159 * r * r
42
+ ```
43
+
44
+ ```console
45
+ $ pyfun check shapes.pyfun
46
+ error: non-exhaustive match: `Rect _ _` is not matched
47
+ --> 4:3
48
+ |
49
+ 4 | match s:
50
+ | ^^^^^^^^
51
+ ```
52
+
53
+ > Plain Python compiles and runs this, then silently returns `None` the day a `Rect` reaches it,
54
+ > and you debug the `TypeError` an hour downstream. Pyfun's Rust compiler checks types, effects,
55
+ > units, and match exhaustiveness **before a single line of Python is emitted**, then hands you
56
+ > code you can read, diff, and ship.
57
+
58
+ ---
59
+
60
+ ## Made for the classroom
61
+
62
+ Teaching FP normally forces a detour: a new language, a new toolchain, and a new ecosystem the
63
+ students abandon the moment the course ends. Pyfun removes the detour.
64
+
65
+ - **They already have the runtime.** Pyfun compiles to plain Python, so anything a student writes
66
+ runs on the interpreter already installed on every lab machine. No VM, no new package manager.
67
+ - **The concepts stay visible.** `pyfun compile` shows the Python your functional code becomes, so a
68
+ student watches an ADT turn into a class, a `match` into `match`/`case`, and currying into a
69
+ closure. They learn the idea and how it maps to the imperative code they know.
70
+ - **Good habits are enforced, not suggested.** The compiler refuses to skip a case, ignore a `None`,
71
+ or mutate what should stay immutable, so students learn to handle every path because the tool insists.
72
+ - **A small, learnable core.** Pyfun is deliberately compact, so the language stays out of the way of
73
+ the ideas you are teaching.
74
+
75
+ Pyfun is a real, general-purpose language, not a toy. But teaching is why it exists.
76
+
77
+ ---
78
+
79
+ ## Why Pyfun over plain Python?
80
+
81
+ Python is the best ecosystem in the world, and even with `mypy`/`pyright` bolted on, large Python
82
+ programs still fail in ways a compiler could have caught. Pyfun keeps the ecosystem and makes the
83
+ checks mandatory.
84
+
85
+ | | Plain Python | Pyfun |
86
+ |---|---|---|
87
+ | **Type errors** | `mypy`/`pyright` are optional and unsound; they warn, they don't gate | found at compile time; no Python is emitted until they pass |
88
+ | **`None` handling** | `AttributeError: 'NoneType'…` | `Option a` with exhaustive `match`; the compiler makes you handle `None` |
89
+ | **Missing `case`** | silently falls through, returns `None` | **exhaustiveness error** with a concrete missing-case witness |
90
+ | **Mutation** | everything is mutable, everywhere | immutable by default; `let mut` + `<-` is opt-in and tracked |
91
+ | **Side effects** | invisible | **inferred and tracked**; `let pure` is a compile-checked promise |
92
+ | **Units / dimensions** | a comment and a prayer | `10<N> / 2<m^2> : float<Pa>`, checked and then erased |
93
+ | **Runtime** | CPython | **CPython**: Pyfun *is* Python once compiled |
94
+
95
+ **Why not just `mypy`/`pyright`?** They're a gradual, optional overlay: unsound by design, never
96
+ required, and one `# type: ignore` from silence. They report; they don't gate. Pyfun makes the same
97
+ class of check *mandatory*: it blocks compilation, infers the signatures pyright often needs spelled
98
+ out, and there is no untyped Pyfun to fall back to. And you keep the entire Python ecosystem while
99
+ you do it.
100
+
101
+ ---
102
+
103
+ ## Type-checked Python interop
104
+
105
+ `extern` imports **any** Python callable or value at a Pyfun type. The dotted target is imported
106
+ for you; the boundary is *effectful by default* (a Python call can do anything), and `pure` opts
107
+ out where you know better. Once imported, the function is a first-class curried Pyfun value:
108
+ type-checked, effect-tracked, and partially applicable.
109
+
110
+ ```fsharp
111
+ extern pure mean: List float -> float = statistics.mean
112
+ extern pure stdev: List float -> float = statistics.stdev
113
+
114
+ type Summary = { n: int, mean: float, stdev: float }
115
+
116
+ let summarize xs =
117
+ Summary { n = List.len xs, mean = mean xs, stdev = stdev xs }
118
+
119
+ let report xs =
120
+ let s = summarize xs
121
+ f"n={s.n} mean={s.mean} sd={s.stdev}"
122
+
123
+ print (report [1.0, 2.0, 3.0, 4.0])
124
+ ```
125
+
126
+ `pyfun compile` turns that into Python you'd be happy to have written by hand:
127
+
128
+ ```python
129
+ import statistics
130
+
131
+ class Summary:
132
+ __match_args__ = ('n', 'mean', 'stdev')
133
+ def __init__(self, n, mean, stdev):
134
+ self.n = n
135
+ self.mean = mean
136
+ self.stdev = stdev
137
+ def __repr__(self):
138
+ return f"Summary({self.n!r}, {self.mean!r}, {self.stdev!r})"
139
+ # ...structural __eq__/__hash__/ordering elided...
140
+
141
+ def summarize(xs):
142
+ return Summary(len(xs), statistics.mean(xs), statistics.stdev(xs))
143
+
144
+ def report(xs):
145
+ s = summarize(xs)
146
+ return f"n={s.n} mean={s.mean} sd={s.stdev}"
147
+
148
+ print(report([1.0, 2.0, 3.0, 4.0]))
149
+ ```
150
+
151
+ ```console
152
+ $ pyfun run stats.pyfun
153
+ n=4 mean=2.5 sd=1.2909944487358056
154
+ ```
155
+
156
+ Notice what the compiler does:
157
+
158
+ - **No wrapper layer.** `statistics.mean(xs)` is called directly. `List` *is* a Python `list`,
159
+ and a Pyfun record *is* a plain class. There is no runtime, no VM, no marshalling.
160
+ - **Effects tracked across the boundary.** A bare `extern` is `io` at full application, so it
161
+ can't be called from a `let pure`. Mark it `pure` (like `statistics.mean`) and it composes into
162
+ pure code. You can even annotate other effect labels: `extern fetch: string ->{async} string = httpx.get`.
163
+ - **Exceptions become values.** `try (parseInt s) : Result int Exception` catches whatever the
164
+ Python side raises and hands you a `Result` to `match` on. The imperative FFI edge becomes the
165
+ FP error type, with `errorKind` and `errorMessage` fields.
166
+
167
+ ```fsharp
168
+ extern parseInt: string -> int = int # Python's built-in int()
169
+
170
+ let safe s = Result.withDefault 0 (try (parseInt s))
171
+ print (safe "42") # 42
172
+ print (safe "oops") # 0 (the ValueError was caught into an Error)
173
+ ```
174
+
175
+ ---
176
+
177
+ ## A whistle-stop tour
178
+
179
+ Everything below type-checks, compiles, and runs today. See
180
+ [`examples/hello.pyfun`](examples/hello.pyfun) for the exhaustive version.
181
+
182
+ **Algebraic data types, records, and exhaustive matching.** `None` cannot bite you:
183
+
184
+ ```fsharp
185
+ type Shape = Circle float | Rect float float
186
+
187
+ let area s =
188
+ match s:
189
+ case Circle r: 3.14159 * r * r
190
+ case Rect w h: w * h
191
+ # forget a case and the compiler reports the missing witness, e.g. `Rect _ _ is not matched`
192
+ ```
193
+
194
+ **Pipelines, currying, composition.** F#'s `|>`, `<|`, `>>`, `<<`, and operator sections `(+)`:
195
+
196
+ ```fsharp
197
+ let describe =
198
+ List.filter (fun x -> x > 0)
199
+ >> List.map ((*) 2)
200
+ >> List.fold (+) 0
201
+
202
+ let total = [1, -2, 3] |> describe # (1 + 3) * 2 = 8
203
+ ```
204
+
205
+ **Inferred effects.** Purity is a checked promise, never boilerplate:
206
+
207
+ ```fsharp
208
+ let pure add a b = a + b # OK: no effects
209
+ # let pure shout n = print n # compile error: `print` performs `io`
210
+ ```
211
+
212
+ **Units of measure.** Dimensional analysis at compile time, erased at runtime:
213
+
214
+ ```fsharp
215
+ measure m
216
+ measure s
217
+ measure kg
218
+ measure N = kg m / s^2 # derived aliases expand to base units
219
+
220
+ let speed = 100<m> / 10<s> # float<m/s>
221
+ let force = 10<N>
222
+ # let bad = 100<m> + 10<s> # compile error: m vs s
223
+ let side = sqrt 16.0<m^2> # float<m>, unit-aware roots
224
+ ```
225
+
226
+ **Computation expressions** (F#'s showcase feature): `result`, `seq`, `async`, plus your own:
227
+
228
+ ```fsharp
229
+ let checked ok v =
230
+ result { # railway-oriented; short-circuits on Error
231
+ let! x = if ok then Ok v else Error "bad"
232
+ return x + 1
233
+ }
234
+ ```
235
+
236
+ **Rich literals and strings.** F-strings, raw strings, triple-quotes, scientific notation,
237
+ digit separators, hex/octal/binary:
238
+
239
+ ```fsharp
240
+ let planck = 6.626e-34
241
+ let million = 1_000_000
242
+ let mask = 0xFF
243
+ let who = "Ada"
244
+ let line = f"{who} scored {million} ({String.upper who})"
245
+ let path = r"C:\Users\pyfun" # raw string, backslashes literal
246
+ ```
247
+
248
+ And a standard library that reads like F#'s: module-qualified `List` / `Set` / `Map` / `Option` /
249
+ `Result` / `Seq` / `String` (`List.map`, `Map.tryFind`, `Result.bind`, lazy `Seq.take`,
250
+ `String.split`), tuples, active patterns, typed holes for type-driven development, and
251
+ multi-file projects with `import`.
252
+
253
+ ---
254
+
255
+ ## How Pyfun compares
256
+
257
+ A few projects bring functional or statically-typed code to Python. Here is the field, and the
258
+ bet Pyfun makes within it:
259
+
260
+ - **[Fable](https://fable.io)** compiles real F# to Python, the most capable option by far, because
261
+ it *is* F#, with the whole language and a mature ecosystem. The trade-offs: it needs the **.NET
262
+ toolchain**, and its output depends on a **runtime library** (`fable_library`).
263
+ - **[Erg](https://erg-lang.org)** is a statically-typed, Python-compatible language with a rich type
264
+ system and marker-based effect control. It is the closest to Pyfun in ambition, though "rusty"/OO
265
+ rather than ML-family, with *explicit* effect annotations.
266
+ - **[Coconut](https://coconut-lang.org)** is a functional *superset* of Python; static typing is an
267
+ optional MyPy add-on, so nothing is enforced.
268
+ - **Dynamic dialects** (**Hy**, **Mochi**, **Dogelang**) are dynamically-typed FP/Lisp languages
269
+ that run on Python; they share the last column, since they trade static guarantees for Python's
270
+ dynamism.
271
+
272
+ Legend: ✅ yes · ⚠️ partial · ➖ different approach · ❌ no
273
+
274
+ | | **Pyfun** | **Fable** | **Erg** | **Coconut** | **Dynamic dialects** |
275
+ |---|:--:|:--:|:--:|:--:|:--:|
276
+ | FP-first language (not a Python superset) | ✅ | ✅ | ✅ | ➖ | ⚠️ |
277
+ | ML / F#-family syntax | ✅ | ✅ | ➖ | ➖ | ❌ |
278
+ | **Mandatory** static typing | ✅ | ✅ | ✅ | ❌ | ❌ |
279
+ | Type inference | ✅ | ✅ | ✅ | ➖ | ❌ |
280
+ | **Zero** annotations required | ✅ | ⚠️ | ⚠️ | ❌ | ➖ |
281
+ | ADTs + **enforced** exhaustiveness | ✅ | ✅ | ⚠️ | ⚠️ | ❌ |
282
+ | **Inferred** effects (never annotated) | ✅ | ❌ | ➖ | ❌ | ❌ |
283
+ | Units of measure | ✅ | ✅ | ❌ | ❌ | ❌ |
284
+ | Computation expressions | ✅ | ✅ | ❌ | ❌ | ❌ |
285
+ | Nested record-update (`{ p with a.b = v }`) | ✅ | ✅ | ❌ | ❌ | ➖ |
286
+ | Typed holes (type-driven dev) | ✅ | ❌ | ❌ | ❌ | ❌ |
287
+ | Chained comparisons (`a < b < c`) | ✅ | ❌ | ⚠️ | ✅ | ✅ |
288
+ | Compiler-as-gatekeeper | ✅ | ✅ | ✅ | ❌ | ❌ |
289
+ | **Self-contained output** (no runtime library) | ✅ | ❌ | ❌ | ❌ | ➖ |
290
+ | **No .NET / host-runtime toolchain** | ✅ | ❌ | ✅ | ➖ | ➖ |
291
+ | Python-library interop | ✅ | ✅ | ✅ | ✅ | ✅ |
292
+ | Maturity / production use | ❌ pre-1.0 | ⚠️ Py beta | ⚠️ | ✅ | ⚠️ |
293
+ | Language surface (built-in constructs) | ⚠️ small core | ✅ full F# | ⚠️ | ✅ Python superset | ✅ |
294
+ | Community, docs, support | ❌ solo | ✅ | ⚠️ | ✅ | ⚠️ |
295
+
296
+ Pyfun's strengths are the bold rows: **self-contained, runtime-free Python output** (a `List` is a
297
+ `list`, a record is a plain class), a **single dependency-free compiler** with no .NET, **inferred
298
+ effects**, and a language **designed for Python interop first**. On several rows it reaches past F#
299
+ itself, borrowing inferred effects from Koka, typed holes from Haskell and Idris, and Python-style
300
+ chained comparisons. Every tool here reaches the full Python ecosystem
301
+ (the interop row), so Pyfun's small core costs nothing in libraries; it just buys simplicity.
302
+
303
+ Reach for Fable when you want all of F# and are happy to bring the .NET toolchain and a runtime
304
+ library along. Reach for Pyfun when you want the emitted Python to be a first-class, readable
305
+ artifact you own outright, or when you are teaching functional programming to people who live in
306
+ Python.
307
+
308
+ ---
309
+
310
+ ## Getting started
311
+
312
+ Pyfun runs on the Python you already have. You need two things:
313
+
314
+ - **Python 3.12+** on your `PATH`, to run the emitted code.
315
+ - **[Rust](https://rustup.rs/)** to build the compiler (it auto-selects the pinned 1.96 toolchain).
316
+ *Prebuilt binaries and a `pip install` path are on the roadmap, which will remove this step.*
317
+
318
+ **Install the `pyfun` compiler** onto your `PATH`:
319
+
320
+ ```bash
321
+ cargo install --git https://github.com/simontreanor/Pyfun pyfun
322
+ ```
323
+
324
+ Or build from a clone, if you want to hack on the compiler itself:
325
+
326
+ ```bash
327
+ git clone https://github.com/simontreanor/Pyfun
328
+ cd Pyfun
329
+ cargo install --path .
330
+ ```
331
+
332
+ **Try it** on the bundled examples:
333
+
334
+ ```bash
335
+ pyfun run examples/hello.pyfun # compile, then execute via python
336
+ pyfun check examples/hello.pyfun # type-check, rustc-style diagnostics
337
+ pyfun repl # interactive REPL
338
+ ```
339
+
340
+ **Write your first program.** Save this as `hello.pyfun`:
341
+
342
+ ```fsharp
343
+ type Shape = Circle float | Rect float float
344
+
345
+ let area s =
346
+ match s:
347
+ case Circle r: 3.14159 * r * r
348
+ case Rect w h: w * h
349
+
350
+ print (area (Circle 2.0))
351
+ ```
352
+
353
+ Then run it (prints `12.56636`), or see the Python it becomes:
354
+
355
+ ```bash
356
+ pyfun run hello.pyfun # 12.56636
357
+ pyfun compile hello.pyfun # emit readable Python to stdout
358
+ pyfun compile hello.pyfun -o hello.py
359
+ ```
360
+
361
+ Multi-file projects just work: `import Geometry` pulls in a sibling `geometry.pyfun`, and any
362
+ command drives the whole graph (`pyfun run examples/modules/main.pyfun`).
363
+
364
+ ---
365
+
366
+ ## Editor support
367
+
368
+ Pyfun ships a dependency-free language server (`pyfun lsp`) and a VS Code client in
369
+ [`editors/vscode/`](editors/vscode/). Over resilient analysis that survives a half-typed file, you get:
370
+
371
+ - **Diagnostics** as you type
372
+ - **Hover** showing the inferred type *and* effect of any expression, binding, or parameter
373
+ - **Go-to-definition** and **find-references**, across files
374
+ - **Rename**, project-wide, for values, constructors, and types
375
+ - **Completion**, **document symbols**, and **workspace symbols**
376
+
377
+ Build and install the extension from [`editors/vscode/`](editors/vscode/); once `pyfun` is on your
378
+ `PATH`, it launches `pyfun lsp` automatically.
379
+
380
+ ---
381
+
382
+ ## How it works
383
+
384
+ Pyfun is a dependency-free Rust crate that runs a classic pipeline, and the compiler is the
385
+ gatekeeper: **nothing is emitted until every check passes.**
386
+
387
+ ```
388
+ .pyfun ──► lexer ──► parser ──► Hindley–Milner type inference ──► Python-AST IR ──► readable .py
389
+ │ │ (+ effects, units, exhaustiveness) │
390
+ offside recursive lowered, not
391
+ rule descent string-spliced
392
+ ```
393
+
394
+ - **Type inference** is full HM with let-generalization: you never annotate a value. The only
395
+ types you write are in `type`/`extern` declarations, and every signature is inferred. It also does
396
+ unit-of-measure inference (abelian-group unification), effect-row inference, and Maranget-style
397
+ exhaustiveness with concrete witnesses.
398
+ - **Lowering** targets a Python-AST IR and emits real, formatted Python: curried functions
399
+ collapse to n-ary `def`s and direct calls (closures only for genuine partial application), CEs
400
+ desugar to their natural Python (`async`/`await`, generators, railway `Result`), and units erase.
401
+ - **No CPython fork.** Pyfun is a front end for the Python ecosystem, not a competing runtime.
402
+
403
+ The full language design and rationale live in [`DESIGN.md`](DESIGN.md).
404
+
405
+ ---
406
+
407
+ ## Status
408
+
409
+ MVP showcase complete and runnable: ADTs, records, tuples, computation expressions (including
410
+ user-defined builders), units of measure, mutability, inferred multi-label effects, general Python
411
+ FFI via `extern`, a module-qualified standard library, string interpolation, active patterns,
412
+ typed holes, file-based modules, and a full LSP. See [`ROADMAP.md`](ROADMAP.md) for what's next.
413
+
414
+ This is a solo, actively-developed project: the MVP is feature-complete and runnable, but it's
415
+ pre-1.0. Expect sharp edges; the language surface is stabilizing but not frozen.
416
+
417
+ ---
418
+
419
+ ## License
420
+
421
+ Pyfun is free and open source under the **[Apache License 2.0](LICENSE)**: use, modify, and
422
+ redistribute it, including commercially. The accompanying [`NOTICE`](NOTICE) names **Simon Treanor**
423
+ as the original author; keep it with any redistribution or derivative work.
424
+
425
+ Copyright © 2026 Simon Treanor.
426
+
@@ -0,0 +1,7 @@
1
+ pyfun_lang-0.0.1.data/scripts/pyfun.exe,sha256=ONYG0soqF4JUfCAuxsFCugLKbDB81rKDoOGNqmr_COU,2545664
2
+ pyfun_lang-0.0.1.dist-info/METADATA,sha256=arzv0P9OzwvsPb5v3RPPN32VWeW31FuDx_NKAq0thw8,17801
3
+ pyfun_lang-0.0.1.dist-info/WHEEL,sha256=2zDlIYIdD4m4N3p5DVEG3iJhGLdhsBQgdH-FqVkAur8,94
4
+ pyfun_lang-0.0.1.dist-info/licenses/LICENSE,sha256=WfhY6jTFgvhspmH4_bSjiDobcsOuwCOqEnlrHq7-2es,11544
5
+ pyfun_lang-0.0.1.dist-info/licenses/NOTICE,sha256=0dh8STks8l8o3qwuJkERNTfbhR_dS1FEcGpyKDJm1C0,665
6
+ pyfun_lang-0.0.1.dist-info/sboms/pyfun.cyclonedx.json,sha256=MvVzbYvaXOUa0boFOYHlWn4hM9WaEz79nbAfB2iF-eg,1815
7
+ pyfun_lang-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.14.1)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Simon Treanor
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,15 @@
1
+ Pyfun
2
+ Copyright (c) 2026 Simon Treanor
3
+
4
+ This product includes software originally designed and written by
5
+ Simon Treanor (the "Original Author").
6
+
7
+ Pyfun is an FP-first programming language that compiles to readable Python,
8
+ together with its Rust compiler, type checker, language server, and tooling.
9
+ The language design, compiler architecture, and this codebase are the
10
+ original work of Simon Treanor.
11
+
12
+ If you redistribute this software or any derivative work, you must retain
13
+ this NOTICE file and the accompanying LICENSE, and you must preserve the
14
+ attribution to the Original Author, in accordance with the terms of the
15
+ Apache License, Version 2.0.
@@ -0,0 +1,70 @@
1
+ {
2
+ "bomFormat": "CycloneDX",
3
+ "specVersion": "1.5",
4
+ "version": 1,
5
+ "serialNumber": "urn:uuid:eabf6451-2935-49dd-981f-064e436fc2a5",
6
+ "metadata": {
7
+ "timestamp": "2026-07-05T15:15:46.747191100Z",
8
+ "tools": [
9
+ {
10
+ "vendor": "CycloneDX",
11
+ "name": "cargo-cyclonedx",
12
+ "version": "0.5.9"
13
+ }
14
+ ],
15
+ "authors": [
16
+ {
17
+ "name": "Simon Treanor"
18
+ }
19
+ ],
20
+ "component": {
21
+ "type": "application",
22
+ "bom-ref": "path+file:///D:/a/Pyfun/Pyfun#pyfun@0.0.1",
23
+ "author": "Simon Treanor",
24
+ "name": "pyfun",
25
+ "version": "0.0.1",
26
+ "description": "An F#-inspired, functional-first language that compiles to readable Python.",
27
+ "scope": "required",
28
+ "licenses": [
29
+ {
30
+ "expression": "Apache-2.0"
31
+ }
32
+ ],
33
+ "purl": "pkg:cargo/pyfun@0.0.1?download_url=file://.",
34
+ "externalReferences": [
35
+ {
36
+ "type": "vcs",
37
+ "url": "https://github.com/simontreanor/Pyfun"
38
+ }
39
+ ],
40
+ "components": [
41
+ {
42
+ "type": "library",
43
+ "bom-ref": "path+file:///D:/a/Pyfun/Pyfun#pyfun@0.0.1 bin-target-0",
44
+ "name": "pyfun",
45
+ "version": "0.0.1",
46
+ "purl": "pkg:cargo/pyfun@0.0.1?download_url=file://.#src/lib.rs"
47
+ },
48
+ {
49
+ "type": "application",
50
+ "bom-ref": "path+file:///D:/a/Pyfun/Pyfun#pyfun@0.0.1 bin-target-1",
51
+ "name": "pyfun",
52
+ "version": "0.0.1",
53
+ "purl": "pkg:cargo/pyfun@0.0.1?download_url=file://.#src/main.rs"
54
+ }
55
+ ]
56
+ },
57
+ "properties": [
58
+ {
59
+ "name": "cdx:rustc:sbom:target:all_targets",
60
+ "value": "true"
61
+ }
62
+ ]
63
+ },
64
+ "components": [],
65
+ "dependencies": [
66
+ {
67
+ "ref": "path+file:///D:/a/Pyfun/Pyfun#pyfun@0.0.1"
68
+ }
69
+ ]
70
+ }