velaris-lang 2.18.2__tar.gz
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.
- velaris_lang-2.18.2/.gitattributes +1 -0
- velaris_lang-2.18.2/.github/ISSUE_TEMPLATE/bug_report.md +19 -0
- velaris_lang-2.18.2/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- velaris_lang-2.18.2/.github/workflows/release.yml +78 -0
- velaris_lang-2.18.2/.github/workflows/test.yml +44 -0
- velaris_lang-2.18.2/.gitignore +7 -0
- velaris_lang-2.18.2/CHANGELOG.md +397 -0
- velaris_lang-2.18.2/CONTRIBUTING.md +39 -0
- velaris_lang-2.18.2/LICENSE +21 -0
- velaris_lang-2.18.2/PKG-INFO +199 -0
- velaris_lang-2.18.2/README.md +164 -0
- velaris_lang-2.18.2/SECURITY.md +21 -0
- velaris_lang-2.18.2/TUTORIAL.md +259 -0
- velaris_lang-2.18.2/build_docs.py +351 -0
- velaris_lang-2.18.2/build_playground.py +368 -0
- velaris_lang-2.18.2/docs/errors.html +167 -0
- velaris_lang-2.18.2/docs/floats.html +238 -0
- velaris_lang-2.18.2/docs/floats.md +126 -0
- velaris_lang-2.18.2/docs/index.html +188 -0
- velaris_lang-2.18.2/docs/library.html +210 -0
- velaris_lang-2.18.2/docs/playground.html +248 -0
- velaris_lang-2.18.2/docs/tutorial.html +371 -0
- velaris_lang-2.18.2/editor/vscode/README.md +27 -0
- velaris_lang-2.18.2/editor/vscode/extension.js +122 -0
- velaris_lang-2.18.2/editor/vscode/language-configuration.json +11 -0
- velaris_lang-2.18.2/editor/vscode/package.json +39 -0
- velaris_lang-2.18.2/editor/vscode/syntaxes/velaris.tmLanguage.json +32 -0
- velaris_lang-2.18.2/examples/bench.vel +27 -0
- velaris_lang-2.18.2/examples/builtin_unhandled.vel +7 -0
- velaris_lang-2.18.2/examples/callsite_bad.vel +19 -0
- velaris_lang-2.18.2/examples/caught.vel +13 -0
- velaris_lang-2.18.2/examples/compose.vel +25 -0
- velaris_lang-2.18.2/examples/contract.vel +28 -0
- velaris_lang-2.18.2/examples/contract_broken.vel +15 -0
- velaris_lang-2.18.2/examples/contract_impure.vel +12 -0
- velaris_lang-2.18.2/examples/div_bad.vel +12 -0
- velaris_lang-2.18.2/examples/div_proof.vel +21 -0
- velaris_lang-2.18.2/examples/effects.vel +28 -0
- velaris_lang-2.18.2/examples/escapes.vel +8 -0
- velaris_lang-2.18.2/examples/fail_proof.vel +39 -0
- velaris_lang-2.18.2/examples/fail_proof_bad.vel +22 -0
- velaris_lang-2.18.2/examples/failing.vel +33 -0
- velaris_lang-2.18.2/examples/failing_bad.vel +13 -0
- velaris_lang-2.18.2/examples/features.vel +42 -0
- velaris_lang-2.18.2/examples/fetcher.vel +79 -0
- velaris_lang-2.18.2/examples/floats.vel +19 -0
- velaris_lang-2.18.2/examples/floats_bad.vel +7 -0
- velaris_lang-2.18.2/examples/forloops.vel +36 -0
- velaris_lang-2.18.2/examples/fp_proof.vel +23 -0
- velaris_lang-2.18.2/examples/fp_proof_bad.vel +13 -0
- velaris_lang-2.18.2/examples/funcs.vel +44 -0
- velaris_lang-2.18.2/examples/funcs_bad.vel +13 -0
- velaris_lang-2.18.2/examples/generics.vel +20 -0
- velaris_lang-2.18.2/examples/generics_bad.vel +8 -0
- velaris_lang-2.18.2/examples/grid_bad.vel +12 -0
- velaris_lang-2.18.2/examples/grid_proof.vel +30 -0
- velaris_lang-2.18.2/examples/guess.vel +32 -0
- velaris_lang-2.18.2/examples/hello.vel +23 -0
- velaris_lang-2.18.2/examples/import_bad.vel +8 -0
- velaris_lang-2.18.2/examples/inferred.vel +48 -0
- velaris_lang-2.18.2/examples/lambda_bad.vel +9 -0
- velaris_lang-2.18.2/examples/lambda_contract.vel +20 -0
- velaris_lang-2.18.2/examples/lambda_contract_bad.vel +12 -0
- velaris_lang-2.18.2/examples/lambdas.vel +22 -0
- velaris_lang-2.18.2/examples/ledger.vel +189 -0
- velaris_lang-2.18.2/examples/lib/geo.vel +12 -0
- velaris_lang-2.18.2/examples/lib/money.vel +11 -0
- velaris_lang-2.18.2/examples/list_mixed.vel +6 -0
- velaris_lang-2.18.2/examples/list_oob.vel +8 -0
- velaris_lang-2.18.2/examples/list_proof.vel +24 -0
- velaris_lang-2.18.2/examples/list_proof_bad.vel +13 -0
- velaris_lang-2.18.2/examples/loop.vel +26 -0
- velaris_lang-2.18.2/examples/loop_bad.vel +12 -0
- velaris_lang-2.18.2/examples/loop_proof.vel +25 -0
- velaris_lang-2.18.2/examples/loop_proof_bad.vel +22 -0
- velaris_lang-2.18.2/examples/many_errors.vel +21 -0
- velaris_lang-2.18.2/examples/map_bad.vel +12 -0
- velaris_lang-2.18.2/examples/map_proof.vel +26 -0
- velaris_lang-2.18.2/examples/maps.vel +27 -0
- velaris_lang-2.18.2/examples/maps_bad.vel +7 -0
- velaris_lang-2.18.2/examples/mathlib.vel +12 -0
- velaris_lang-2.18.2/examples/namespaces.vel +13 -0
- velaris_lang-2.18.2/examples/native_build.vel +46 -0
- velaris_lang-2.18.2/examples/native_float.vel +28 -0
- velaris_lang-2.18.2/examples/native_list.vel +40 -0
- velaris_lang-2.18.2/examples/native_text.vel +39 -0
- velaris_lang-2.18.2/examples/net.vel +20 -0
- velaris_lang-2.18.2/examples/ns_bad.vel +8 -0
- velaris_lang-2.18.2/examples/proof_catch.vel +19 -0
- velaris_lang-2.18.2/examples/qlist_bad.vel +17 -0
- velaris_lang-2.18.2/examples/qlist_proof.vel +31 -0
- velaris_lang-2.18.2/examples/rec_list_proof.vel +28 -0
- velaris_lang-2.18.2/examples/rec_proof.vel +26 -0
- velaris_lang-2.18.2/examples/rec_proof_bad.vel +17 -0
- velaris_lang-2.18.2/examples/records.vel +32 -0
- velaris_lang-2.18.2/examples/records_bad.vel +11 -0
- velaris_lang-2.18.2/examples/sample.txt +3 -0
- velaris_lang-2.18.2/examples/sneaky.vel +11 -0
- velaris_lang-2.18.2/examples/sneaky_fixed.vel +12 -0
- velaris_lang-2.18.2/examples/std_bad.vel +10 -0
- velaris_lang-2.18.2/examples/std_test.vel +41 -0
- velaris_lang-2.18.2/examples/std_tour.vel +26 -0
- velaris_lang-2.18.2/examples/text_tools.vel +25 -0
- velaris_lang-2.18.2/examples/tools.vel +16 -0
- velaris_lang-2.18.2/examples/types_bad.vel +11 -0
- velaris_lang-2.18.2/examples/uses_import.vel +11 -0
- velaris_lang-2.18.2/examples/wordcount.vel +150 -0
- velaris_lang-2.18.2/fuzz_native.py +133 -0
- velaris_lang-2.18.2/playground/index.html +248 -0
- velaris_lang-2.18.2/pyproject.toml +28 -0
- velaris_lang-2.18.2/run_tests.py +148 -0
- velaris_lang-2.18.2/stdlib/std.vel +208 -0
- velaris_lang-2.18.2/velaris.py +4791 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* text=auto
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something behaved wrongly
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**What happened**
|
|
8
|
+
|
|
9
|
+
**What you expected**
|
|
10
|
+
|
|
11
|
+
**Smallest .vel program that shows it**
|
|
12
|
+
```
|
|
13
|
+
(paste here)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Output of `velaris doctor`**
|
|
17
|
+
```
|
|
18
|
+
(paste here)
|
|
19
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Something Velaris should be able to do
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**The problem you are trying to solve**
|
|
8
|
+
|
|
9
|
+
**What you wish you could write**
|
|
10
|
+
```
|
|
11
|
+
(sketch the Velaris code you want to exist)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**How you work around it today**
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
binaries:
|
|
9
|
+
strategy:
|
|
10
|
+
fail-fast: false
|
|
11
|
+
matrix:
|
|
12
|
+
include:
|
|
13
|
+
- os: windows-latest
|
|
14
|
+
asset: velaris-windows.exe
|
|
15
|
+
sep: ";"
|
|
16
|
+
- os: ubuntu-latest
|
|
17
|
+
asset: velaris-linux
|
|
18
|
+
sep: ":"
|
|
19
|
+
- os: macos-latest
|
|
20
|
+
asset: velaris-macos
|
|
21
|
+
sep: ":"
|
|
22
|
+
runs-on: ${{ matrix.os }}
|
|
23
|
+
permissions:
|
|
24
|
+
contents: write
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v5
|
|
27
|
+
- uses: actions/setup-python@v6
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.12"
|
|
30
|
+
- name: Install with proofs, native speed, and PyInstaller
|
|
31
|
+
run: pip install ".[full]" pyinstaller
|
|
32
|
+
- name: Build standalone executable
|
|
33
|
+
run: >
|
|
34
|
+
pyinstaller --onefile --name velaris
|
|
35
|
+
--collect-all z3 --collect-all llvmlite
|
|
36
|
+
--add-data "stdlib${{ matrix.sep }}stdlib"
|
|
37
|
+
velaris.py
|
|
38
|
+
- name: Smoke test the executable
|
|
39
|
+
shell: bash
|
|
40
|
+
run: |
|
|
41
|
+
./dist/velaris* --version
|
|
42
|
+
./dist/velaris* doctor
|
|
43
|
+
./dist/velaris* examples/hello.vel
|
|
44
|
+
- name: Rename asset
|
|
45
|
+
shell: bash
|
|
46
|
+
run: |
|
|
47
|
+
cd dist
|
|
48
|
+
for f in velaris velaris.exe; do
|
|
49
|
+
[ -f "$f" ] && mv "$f" "${{ matrix.asset }}"
|
|
50
|
+
done
|
|
51
|
+
ls
|
|
52
|
+
- name: Attach to the GitHub release
|
|
53
|
+
uses: softprops/action-gh-release@v2
|
|
54
|
+
with:
|
|
55
|
+
files: dist/${{ matrix.asset }}
|
|
56
|
+
generate_release_notes: true
|
|
57
|
+
|
|
58
|
+
pypi:
|
|
59
|
+
name: publish to PyPI
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
# until a pending publisher exists on pypi.org this cannot succeed,
|
|
62
|
+
# and a release should not be marked broken for that reason
|
|
63
|
+
continue-on-error: true
|
|
64
|
+
permissions:
|
|
65
|
+
id-token: write # trusted publishing, no API token stored
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v5
|
|
68
|
+
- uses: actions/setup-python@v6
|
|
69
|
+
with:
|
|
70
|
+
python-version: "3.12"
|
|
71
|
+
- name: Build the distribution
|
|
72
|
+
run: |
|
|
73
|
+
pip install build
|
|
74
|
+
python -m build
|
|
75
|
+
- name: Publish
|
|
76
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
77
|
+
with:
|
|
78
|
+
skip-existing: true
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
14
|
+
python: ["3.10", "3.12"]
|
|
15
|
+
deps: [full, minimal]
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v5
|
|
19
|
+
- uses: actions/setup-python@v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python }}
|
|
22
|
+
- name: Install (full - with Z3 proofs and LLVM native)
|
|
23
|
+
if: matrix.deps == 'full'
|
|
24
|
+
run: pip install ".[full]"
|
|
25
|
+
- name: Install (minimal - runtime checks, interpreted)
|
|
26
|
+
if: matrix.deps == 'minimal'
|
|
27
|
+
run: pip install .
|
|
28
|
+
- name: Version
|
|
29
|
+
run: velaris --version
|
|
30
|
+
- name: Test suite
|
|
31
|
+
run: python run_tests.py
|
|
32
|
+
- name: Native and interpreted agree (random programs)
|
|
33
|
+
run: python fuzz_native.py 60
|
|
34
|
+
- name: Velaris tests written in Velaris
|
|
35
|
+
run: velaris test examples/std_test.vel
|
|
36
|
+
- name: Compile check (every example compiles)
|
|
37
|
+
run: velaris check examples/*.vel examples/lib/*.vel stdlib/*.vel || true
|
|
38
|
+
- name: Formatter check (repo is canonically formatted)
|
|
39
|
+
shell: bash
|
|
40
|
+
run: velaris fmt examples/*.vel examples/lib/*.vel stdlib/*.vel --check
|
|
41
|
+
- name: Playground builds
|
|
42
|
+
run: python build_playground.py
|
|
43
|
+
- name: Docs site builds
|
|
44
|
+
run: python build_docs.py
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Velaris changelog
|
|
2
|
+
|
|
3
|
+
## 2.18.2 - Minimal-mode expectations for the newest proofs
|
|
4
|
+
`div_bad.vel` and `grid_bad.vel` demonstrate bugs only the prover can
|
|
5
|
+
see: divide-by-zero on a path that happens not to be taken, and a row
|
|
6
|
+
read that is in range for the example data. Without z3 installed both
|
|
7
|
+
programs simply run, so the test suite expected the wrong verdict and
|
|
8
|
+
every no-dependency leg failed on all three platforms. They are now
|
|
9
|
+
listed with the other proof-only examples, and the suite passes with
|
|
10
|
+
and without the solver.
|
|
11
|
+
|
|
12
|
+
## 2.18.1 - Releases stay green
|
|
13
|
+
The PyPI job added in 2.18 cannot succeed until a pending publisher
|
|
14
|
+
exists on pypi.org, and a release should not be reported as broken for
|
|
15
|
+
a step that is waiting on a one-time setup. It no longer blocks the
|
|
16
|
+
release; the executables build and attach as before.
|
|
17
|
+
|
|
18
|
+
## 2.18 - Records holding lists, and publishing
|
|
19
|
+
A record's fields may now be lists, floats or text and still take part
|
|
20
|
+
in proofs, so `ensures length(result.items) == length(b.items) + 1` is
|
|
21
|
+
proven rather than checked at runtime.
|
|
22
|
+
|
|
23
|
+
Turning that on immediately found a real bug in the ledger app: with
|
|
24
|
+
records fully modelled, the prover could see that `describe` calls
|
|
25
|
+
`money(e.amount)` on an amount nothing had constrained to be positive.
|
|
26
|
+
`money` is now total - a negative amount formats as a refund - and the
|
|
27
|
+
app compiles honestly instead of relying on an assumption nobody
|
|
28
|
+
checked.
|
|
29
|
+
|
|
30
|
+
Releases now publish to PyPI on every tag (trusted publishing, no
|
|
31
|
+
stored token), so installing becomes `pip install velaris-lang`.
|
|
32
|
+
|
|
33
|
+
Also: the version in pyproject.toml had drifted to 1.9.0 while the
|
|
34
|
+
compiler said 2.17. The test suite now fails if the two ever disagree.
|
|
35
|
+
|
|
36
|
+
## 2.17 - for loops, tests in Velaris, and text containment proofs
|
|
37
|
+
`for i in 0 to n` and `for item in xs` are here. They are turned into
|
|
38
|
+
the while loops the rest of the compiler already understands, so
|
|
39
|
+
invariant inference and proofs work through them unchanged - the
|
|
40
|
+
shorter form costs nothing.
|
|
41
|
+
|
|
42
|
+
`velaris test program.vel` runs every function named `test_*` that
|
|
43
|
+
takes no arguments and reports which returned true.
|
|
44
|
+
`examples/std_test.vel` is the first suite: seven tests for the
|
|
45
|
+
standard library, written in Velaris, and CI runs them on every push.
|
|
46
|
+
The language can now test itself.
|
|
47
|
+
|
|
48
|
+
The prover models `contains` on text through Z3's string theory, so
|
|
49
|
+
`ensures contains(result, word)` is proven rather than checked at
|
|
50
|
+
runtime.
|
|
51
|
+
|
|
52
|
+
## 2.16 - Catching the next one, a third app, and a current tutorial
|
|
53
|
+
`fuzz_native.py` generates random Velaris programs - integer maths,
|
|
54
|
+
loops, list scans, text scans, floats, branches - runs each one
|
|
55
|
+
interpreted and natively, and fails if the two ever disagree. CI runs
|
|
56
|
+
it on every push, now across Linux, Windows **and macOS**: the exact
|
|
57
|
+
combination that would have caught the 2.15 problem before it reached
|
|
58
|
+
anyone.
|
|
59
|
+
|
|
60
|
+
`examples/fetcher.vel` is a third real program, and the first to use
|
|
61
|
+
the network: it reads a URL from the command line, checks the status
|
|
62
|
+
before downloading a body, and summarises what it got. Every network
|
|
63
|
+
call is behind `uses net` and can fail, so all three failure paths
|
|
64
|
+
(bad status, unreachable host, no arguments) are visible in the code
|
|
65
|
+
rather than assumed away.
|
|
66
|
+
|
|
67
|
+
TUTORIAL.md is rewritten for the language as it actually is. The old
|
|
68
|
+
one predated lambdas, namespaces, format, args, map proofs, invariant
|
|
69
|
+
inference and the whole toolset - someone arriving today was reading a
|
|
70
|
+
description of a language from fifteen releases ago.
|
|
71
|
+
|
|
72
|
+
## 2.15.1 - Native text building, made portable
|
|
73
|
+
Two examples failed on Windows in 2.15: a function that RETURNS text
|
|
74
|
+
handed a small struct back across the machine-code boundary, and how
|
|
75
|
+
that is done depends on the platform's calling convention. Rather than
|
|
76
|
+
guess at an ABI this project cannot test everywhere, text results now
|
|
77
|
+
stay interpreted. Text built *inside* a native function still uses the
|
|
78
|
+
arena and is still fast (183.5 ms interpreted, 4.1 ms native here).
|
|
79
|
+
|
|
80
|
+
Native compilation is also fail-safe now: if anything about a machine's
|
|
81
|
+
backend disagrees with the compiler, the program runs interpreted and
|
|
82
|
+
behaves identically, instead of failing. A speed optimisation should
|
|
83
|
+
never be able to stop a correct program from running.
|
|
84
|
+
|
|
85
|
+
## 2.15 - Native text building (the arena)
|
|
86
|
+
Concatenation compiles to machine code. Text is built in a scratch
|
|
87
|
+
buffer the runtime owns, reset at every call, so native code never has
|
|
88
|
+
to decide who frees what. If a call needs more room than the buffer
|
|
89
|
+
holds, **nothing is copied**: the buffer grows and the call runs again,
|
|
90
|
+
so the answer is always the one the interpreter would have given. A
|
|
91
|
+
million characters built through a 64 KB starting buffer comes back
|
|
92
|
+
byte-correct, unicode and emoji included, checked against 200 random
|
|
93
|
+
strings.
|
|
94
|
+
|
|
95
|
+
Measured: 172.8 ms interpreted, 0.9 ms native.
|
|
96
|
+
|
|
97
|
+
Getting there needed one more fix: `length` and `code_at` now work on
|
|
98
|
+
any text-valued expression, not just a variable. Before that,
|
|
99
|
+
`length(banner(word))` kept a whole loop interpreted, and crossing the
|
|
100
|
+
native boundary once per iteration was *slower* than staying
|
|
101
|
+
interpreted - the benchmark said so before the fix, which is why the
|
|
102
|
+
benchmark is in the example.
|
|
103
|
+
|
|
104
|
+
## 2.14 - Native text reads, and proven functions run fast
|
|
105
|
+
Text scanning compiles to machine code. Text crosses into native code
|
|
106
|
+
as Unicode code points plus a length, so `length` still counts
|
|
107
|
+
characters and non-English text behaves identically - verified against
|
|
108
|
+
300 random strings including accents and emoji. Reads are
|
|
109
|
+
bounds-guarded like list reads. Measured: 696.8 ms interpreted, 22.3 ms
|
|
110
|
+
native.
|
|
111
|
+
|
|
112
|
+
New builtin `code_at(text, i)` gives the code point at a position with
|
|
113
|
+
no allocation - the operation native scanning needs, and useful
|
|
114
|
+
interpreted too.
|
|
115
|
+
|
|
116
|
+
Two rules changed for the better. A function whose promises are
|
|
117
|
+
**proven** may now compile natively: an unproven promise still needs
|
|
118
|
+
its runtime check, but a proven one is already true, so there is
|
|
119
|
+
nothing to check. And the prover learned `length` on text and a sound
|
|
120
|
+
uninterpreted model of `code_at`, so text-scanning loops can be proven
|
|
121
|
+
at all.
|
|
122
|
+
|
|
123
|
+
Building text (concatenation) stays interpreted - that allocates, and
|
|
124
|
+
allocation gets its own release.
|
|
125
|
+
|
|
126
|
+
## 2.13 - Native lists
|
|
127
|
+
Pure functions that read `List of Int` now compile to machine code.
|
|
128
|
+
The list crosses into native code as a pointer plus a length, and every
|
|
129
|
+
read is bounds-guarded: an out-of-range position records the mistake
|
|
130
|
+
and returns without touching memory, so you get the same E602 you would
|
|
131
|
+
have got interpreted rather than a segfault. Measured on a
|
|
132
|
+
500-element list summed 200 times: 782.6 ms interpreted, 2.7 ms native,
|
|
133
|
+
identical results. Differential-tested as always.
|
|
134
|
+
|
|
135
|
+
Writing to lists (push) stays interpreted - that needs allocation, and
|
|
136
|
+
allocation needs an ownership story this language has not designed yet.
|
|
137
|
+
|
|
138
|
+
## 2.12 - Lists of lists, proven
|
|
139
|
+
A grid is now modelled symbolically - its rows, each row's length, and
|
|
140
|
+
how many rows - so `length`, `get` and `push` on nested lists take part
|
|
141
|
+
in proofs, and an out-of-range row is caught before the program runs
|
|
142
|
+
exactly as it is for a flat list. Nested list *types* also parse now:
|
|
143
|
+
`List of List of Int` was previously a syntax error.
|
|
144
|
+
|
|
145
|
+
That closes the last container with no proof story. Ints, Bools,
|
|
146
|
+
Floats (in IEEE-754), Texts, records, lists, nested lists and maps are
|
|
147
|
+
all proof territory; only Text contents remain runtime-checked.
|
|
148
|
+
|
|
149
|
+
## 2.11 - Invariant inference (the boring ones, for free)
|
|
150
|
+
Loops without a written `invariant` can now be crossed by the prover.
|
|
151
|
+
Candidate invariants are proposed for every counter a loop moves - it
|
|
152
|
+
never goes below, or never above, the value it started at - assumed
|
|
153
|
+
together, and whatever one loop step can break is dropped, repeating
|
|
154
|
+
until the set is stable. (Houdini, kept small.) `examples/inferred.vel`
|
|
155
|
+
proves three promises with no invariant lines at all.
|
|
156
|
+
|
|
157
|
+
Honest about the limits: this infers simple bounds on counters, not
|
|
158
|
+
membership or sortedness, so the standard library's loops still need
|
|
159
|
+
their hand-written invariants.
|
|
160
|
+
|
|
161
|
+
Also fixed something that had been quietly lying since 2.6: `explain`
|
|
162
|
+
and the inspector reported a function as "proven" whenever the file had
|
|
163
|
+
no errors, even when the prover had actually given up and left the
|
|
164
|
+
promise to a runtime check. The status now comes from the prover
|
|
165
|
+
itself, so "proven" means proven.
|
|
166
|
+
|
|
167
|
+
## 2.10 - Contracts on function values
|
|
168
|
+
An inline function can carry `requires` and `ensures` of its own, and
|
|
169
|
+
they are proven like any other function's - so a function value is a
|
|
170
|
+
first class citizen rather than a convenience. Because lambdas are
|
|
171
|
+
lifted to real functions, this needed no new machinery in the prover.
|
|
172
|
+
Errors about them now say "this function value" instead of leaking the
|
|
173
|
+
generated name.
|
|
174
|
+
|
|
175
|
+
## 2.9 - Map proofs
|
|
176
|
+
Maps are now modelled symbolically - the values, plus which keys are
|
|
177
|
+
actually present - so `put`, `get_or` and `has` take part in proofs.
|
|
178
|
+
Promises like "this key now holds one more than before" are proven
|
|
179
|
+
before the program runs, and wrong ones are refuted with the offending
|
|
180
|
+
key. Text values became symbolic strings to make map keys work, which
|
|
181
|
+
also lets Text cross call summaries.
|
|
182
|
+
|
|
183
|
+
Lists remain arrays of Ints: anything else (Text lists, lists of
|
|
184
|
+
lists) is explicitly guarded now and falls back to runtime checks
|
|
185
|
+
rather than being forced into a sort it does not fit.
|
|
186
|
+
|
|
187
|
+
## 2.8 - A second real app, and Text ordering
|
|
188
|
+
`examples/wordcount.vel` reads a file, counts word frequencies and
|
|
189
|
+
prints a ranked histogram - a different shape of program from the
|
|
190
|
+
ledger, exercising maps, records, lambdas, namespaced imports, format,
|
|
191
|
+
args, and three separate failure paths (missing file, unreadable count
|
|
192
|
+
argument, no words found).
|
|
193
|
+
|
|
194
|
+
Writing it found a real hole: Text had no ordering, so `c >= "a"` did
|
|
195
|
+
not compile and words could not be sorted alphabetically. `<`, `>`,
|
|
196
|
+
`<=` and `>=` now work on Text, comparing alphabetically. Promises
|
|
197
|
+
about Text comparisons are checked at runtime rather than proven, and
|
|
198
|
+
the prover does not pretend otherwise.
|
|
199
|
+
|
|
200
|
+
Also: the error de-duplication from 2.5.1 now lives in the shared
|
|
201
|
+
analysis, so `check`, `explain` and the browser inspector report one
|
|
202
|
+
message per problem too.
|
|
203
|
+
|
|
204
|
+
## 2.7 - Reading a codebase
|
|
205
|
+
`velaris check program.vel` compiles without running - for CI, editors,
|
|
206
|
+
and pre-commit hooks - and takes several files at once. `velaris
|
|
207
|
+
explain` now puts *your* functions first and summarises imported
|
|
208
|
+
libraries in one line (`--all` expands them), because the first real
|
|
209
|
+
run of explain buried a ten-function app under eighteen library
|
|
210
|
+
functions. `velaris explain <folder>` maps every .vel file under a
|
|
211
|
+
directory: functions, proven promises, effects, and any errors.
|
|
212
|
+
|
|
213
|
+
## 2.6 - Division proofs, and seeing what your code promises
|
|
214
|
+
`velaris explain program.vel` walks through a file function by
|
|
215
|
+
function: what it may do, what it needs, what it promises, and whether
|
|
216
|
+
those promises are proven or left to runtime. The browser playground
|
|
217
|
+
gains an **Inspect** button showing the same thing as cards, with
|
|
218
|
+
errors and their fixes in place. `--json` gives the whole report as
|
|
219
|
+
data for tools.
|
|
220
|
+
|
|
221
|
+
Contract printing is now precedence-aware, so `(result + 1) * count`
|
|
222
|
+
no longer prints as `result + 1 * count` (it did, on the docs site).
|
|
223
|
+
|
|
224
|
+
## 2.6 - Division proofs
|
|
225
|
+
`/` and `%` on whole numbers are now proof territory: the compiler
|
|
226
|
+
proves the divisor is never zero (E706, with the value that breaks it)
|
|
227
|
+
and can prove what the result means. Translated only when the divisor
|
|
228
|
+
is provably positive, because Velaris floors like Python while Z3's
|
|
229
|
+
integer division is Euclidean - the two disagree on negative divisors,
|
|
230
|
+
so that case falls back to a runtime check rather than a formula that
|
|
231
|
+
would quietly lie.
|
|
232
|
+
|
|
233
|
+
## 2.5.1 - One problem, one message
|
|
234
|
+
The effect checker and type checker could both report the same unknown
|
|
235
|
+
function, so a single mistake printed twice. Identical errors are now
|
|
236
|
+
reported once.
|
|
237
|
+
|
|
238
|
+
## 2.5 - Namespaced imports
|
|
239
|
+
`import "lib/geo.vel" as geo` then `geo.distance(a, b)`. A named import
|
|
240
|
+
prefixes that library's functions, rewriting its internal references so
|
|
241
|
+
the library is unchanged from the inside. Two libraries exporting the
|
|
242
|
+
same name can now be used in one file, which was impossible before.
|
|
243
|
+
Unknown namespaces and unknown functions inside a namespace get their
|
|
244
|
+
own messages (E200 lists what the namespace does offer), and a local
|
|
245
|
+
variable may not shadow an import name (E514). Plus a written piece on
|
|
246
|
+
why float proofs use IEEE-754 rather than reals: docs/floats.md.
|
|
247
|
+
|
|
248
|
+
## 2.4 - The everyday things
|
|
249
|
+
Function values inline: `keep_if(xs, fn(n: Int) -> Bool { return n > 4 })`.
|
|
250
|
+
They are lifted to real top-level functions, so types, effects, proofs
|
|
251
|
+
and native codegen treat them like any other function - and they cannot
|
|
252
|
+
capture surrounding variables, which keeps them pure and gives a clear
|
|
253
|
+
error when you try. Also: `format("hi {}", name)` with placeholder
|
|
254
|
+
count checked at compile time, `args()` for command line arguments,
|
|
255
|
+
`post(url, body)` and `fetch_status(url)` alongside `fetch`. The ledger
|
|
256
|
+
app now uses a lambda for its report sorting.
|
|
257
|
+
|
|
258
|
+
## 2.3 - Public launch polish
|
|
259
|
+
New visual identity across the docs site, playground, and README:
|
|
260
|
+
light professional design, verified-green brand, refined typography.
|
|
261
|
+
Landing page rebuilt. Fixed minimal-mode CI: fail_proof_bad's bug is
|
|
262
|
+
only findable by proof, so without z3 it is expected to run.
|
|
263
|
+
|
|
264
|
+
## 2.2 - Out-of-the-box readiness
|
|
265
|
+
velaris doctor (self-diagnosing setup with exact fixes), velaris new
|
|
266
|
+
(scaffold a project that runs), standalone executables for
|
|
267
|
+
Windows/Linux/macOS built and attached to every release (no Python
|
|
268
|
+
required), SECURITY.md with soundness-is-security policy, issue
|
|
269
|
+
templates, and a semver stability promise in the README.
|
|
270
|
+
|
|
271
|
+
## 2.1 - Documentation site
|
|
272
|
+
build_docs.py generates docs/: landing page, tutorial, a library
|
|
273
|
+
reference parsed from stdlib/std.vel by the real compiler (contracts
|
|
274
|
+
shown), an error index scraped from velaris.py (cannot go stale), and
|
|
275
|
+
the playground. Built in CI; one click from GitHub Pages.
|
|
276
|
+
|
|
277
|
+
## 2.0 - The builtins keep the language's promise (BREAKING)
|
|
278
|
+
to_int, get-on-a-map, read_file, and fetch are now fallible: they must
|
|
279
|
+
be called through check or try, and their failures can finally be
|
|
280
|
+
handled instead of killing the program. Migration is compiler-guided -
|
|
281
|
+
error E520 points at every call needing a wrap. get on a LIST is
|
|
282
|
+
unchanged (bounds are the prover's domain, proven at compile time).
|
|
283
|
+
New: get_or(m, key, default), a total map lookup. All examples
|
|
284
|
+
migrated; guess.vel now survives typos, net.vel survives outages, and
|
|
285
|
+
the ledger's loader shrank.
|
|
286
|
+
|
|
287
|
+
## 1.20 - sort_by + ledger reports
|
|
288
|
+
std.vel gains generic sort_by(xs, key) - sort anything by an Int key
|
|
289
|
+
function. The ledger uses it for a new report command: sorted-by-amount
|
|
290
|
+
listing with biggest, smallest, and totals. The CI session exercises it.
|
|
291
|
+
|
|
292
|
+
## 1.19 - Standard library sprint
|
|
293
|
+
std.vel grows to sixteen functions, all in Velaris: sort (ensures
|
|
294
|
+
is_sorted(result)), min/max (ensures membership), sum, keep_if,
|
|
295
|
+
count_where, join, range_list, is_sorted, insert_sorted; apply_to_each
|
|
296
|
+
and reverse rewritten with typed lets, dropping their nonempty
|
|
297
|
+
requirements. Library requires are enforced at importer call sites.
|
|
298
|
+
|
|
299
|
+
## 1.18 - Float proofs (real IEEE-754)
|
|
300
|
+
Float promises proven in Z3's floating-point theory - bit-for-bit the
|
|
301
|
+
machine's arithmetic. The prover refutes real-number identities that
|
|
302
|
+
rounding breaks, with the exact double as counterexample. FP queries
|
|
303
|
+
get a bigger solver budget; integer proofs stay instant.
|
|
304
|
+
|
|
305
|
+
## 1.17 - Failure-aware proofs
|
|
306
|
+
The prover understands fail / check / try: promises on 'or fail'
|
|
307
|
+
functions are proven for every returning path, fail-guards become
|
|
308
|
+
facts on those paths, and fallible callees' promises flow through try
|
|
309
|
+
and check. CI actions bumped past the Node 20 deprecation.
|
|
310
|
+
|
|
311
|
+
## 1.16 - Quantified list proofs
|
|
312
|
+
`all_of` / `any_of` with a predicate function; in contracts they become
|
|
313
|
+
Z3 foralls/exists with the predicate's body symbolically inlined.
|
|
314
|
+
Fixed a latent soundness-of-reporting hole: an untranslatable
|
|
315
|
+
`requires` now aborts the proof instead of being silently dropped
|
|
316
|
+
(dropped premises manufacture false counterexamples).
|
|
317
|
+
|
|
318
|
+
## 1.15 - Native Float and Bool
|
|
319
|
+
Typed LLVM codegen (f64, typed allocas/boundaries); division stays
|
|
320
|
+
interpreted so divide-by-zero is always a clean error;
|
|
321
|
+
differential-tested against the interpreter.
|
|
322
|
+
|
|
323
|
+
## 1.14 - Record proofs
|
|
324
|
+
Symbolic records (one Z3 value per field): field promises proven,
|
|
325
|
+
record-aware summaries, records printed in counterexamples.
|
|
326
|
+
|
|
327
|
+
## 1.13 - The first real app
|
|
328
|
+
examples/ledger.vel expense tracker; chars/file_exists builtins; typed
|
|
329
|
+
let enabling empty [] and {}; order-flexible signature clauses;
|
|
330
|
+
scripted-stdin testing so interactive apps run in CI.
|
|
331
|
+
|
|
332
|
+
## 1.12 - Continuous integration
|
|
333
|
+
GitHub Actions matrix (Linux/Windows x 3.10/3.12 x full/minimal deps),
|
|
334
|
+
dependency-aware suite, CHANGELOG, CONTRIBUTING.
|
|
335
|
+
|
|
336
|
+
## 1.11 - Language server
|
|
337
|
+
`velaris lsp`: standard LSP over stdio. Effect/type errors on every
|
|
338
|
+
keystroke, full pipeline with Z3 proofs on save; per-file diagnostics
|
|
339
|
+
(bugs in imported files squiggle in those files). Dependency-free VS
|
|
340
|
+
Code client bundled in `editor/vscode`.
|
|
341
|
+
|
|
342
|
+
## 1.10 - Formatter
|
|
343
|
+
`velaris fmt` (in-place, `--stdout`, `--check`). Comment-preserving,
|
|
344
|
+
idempotent, proven meaning-safe by re-running the whole suite on
|
|
345
|
+
formatted code. All repo examples reformatted.
|
|
346
|
+
|
|
347
|
+
## 1.9 - REPL
|
|
348
|
+
`velaris repl`: loose lines run immediately; fn/record/import
|
|
349
|
+
definitions pass effects, types, and proofs before joining the session.
|
|
350
|
+
CLI subcommands (run / repl / version). Unknown functions became a
|
|
351
|
+
friendly E200 everywhere.
|
|
352
|
+
|
|
353
|
+
## 1.8 - Real installation
|
|
354
|
+
`pip install ".[full]"` and a `velaris` command. Standard-library
|
|
355
|
+
search path: `import "std.vel"` works from any folder.
|
|
356
|
+
|
|
357
|
+
## 1.7 - Generics + first stdlib
|
|
358
|
+
`for any T` with call-site inference and clear conflict errors
|
|
359
|
+
(bindings shown). `stdlib/std.vel`: first/last/reverse/index_of/
|
|
360
|
+
contains_item/apply_to_each - written in Velaris.
|
|
361
|
+
|
|
362
|
+
## 1.6 - First-class functions
|
|
363
|
+
`fn(Int) -> Int` as a type; pass by name; call through parameters.
|
|
364
|
+
Only pure functions travel as values, so nothing is smuggled.
|
|
365
|
+
|
|
366
|
+
## 1.5 - Unignorable failure
|
|
367
|
+
`-> Int or fail`, `fail "reason"`, mandatory `check { ok / fail }`
|
|
368
|
+
handling, `try` propagation. Ignoring failure is a compile error.
|
|
369
|
+
|
|
370
|
+
## 1.4 - Maps
|
|
371
|
+
`{"a": 1}` typed `Map of K to V`; get/has/put/keys/length; typed keys
|
|
372
|
+
and values; clean E610 for missing keys.
|
|
373
|
+
|
|
374
|
+
## 1.3 - Float
|
|
375
|
+
Decimal numbers with NO silent Int/Float mixing - conversion is
|
|
376
|
+
explicit (`to_float`, `round`). Proper negation node.
|
|
377
|
+
|
|
378
|
+
## 1.2 - Browser playground
|
|
379
|
+
The real compiler running in-browser via Pyodide. Zero install.
|
|
380
|
+
|
|
381
|
+
## 1.1 - Escapes + editor
|
|
382
|
+
String escapes (\n \t \" \\) with friendly E002; VS Code syntax
|
|
383
|
+
highlighting.
|
|
384
|
+
|
|
385
|
+
## 1.0 - Testers' release
|
|
386
|
+
Multi-error reporting (all broken functions in one run, JSON array for
|
|
387
|
+
agents), `to_text`, `--version`, tutorial.
|
|
388
|
+
|
|
389
|
+
## 0.x - The climb
|
|
390
|
+
0.1 effects (io) - 0.2 effect split (io/net/fs/clock/rand) - 0.3 type
|
|
391
|
+
checking - 0.4 loops - 0.5 contracts (requires/ensures) - 0.6 lists,
|
|
392
|
+
and/or/not, negatives - 0.7 Z3 compile-time proofs - 0.8 modular
|
|
393
|
+
verification with sound false-alarm discipline - 0.9 LLVM native
|
|
394
|
+
compilation (~10,000x on hot loops) - 0.10 loop invariants - 0.11 real
|
|
395
|
+
HTTP fetch - 0.12 interactive input - 0.13 list proofs via array
|
|
396
|
+
theory with bounds obligations - 0.14 else-if, %, text tools - 0.15
|
|
397
|
+
records - 0.16 imports with per-file error blame.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Contributing to Velaris
|
|
2
|
+
|
|
3
|
+
Thanks for looking under the hood.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
pip install ".[full]" # z3-solver for proofs, llvmlite for native
|
|
9
|
+
python run_tests.py # 39 example programs, each with a verdict
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## The one rule
|
|
13
|
+
|
|
14
|
+
Every change must keep `run_tests.py` green in BOTH modes - with the
|
|
15
|
+
optional dependencies and without them (`pip install .` in a clean
|
|
16
|
+
venv). CI enforces this across Linux/Windows and Python 3.10/3.12.
|
|
17
|
+
|
|
18
|
+
## Layout
|
|
19
|
+
|
|
20
|
+
Everything is one readable file, `velaris.py`, in pipeline order:
|
|
21
|
+
lexer -> parser -> loader -> effect checker -> type checker -> proof
|
|
22
|
+
checker (Z3) -> native compiler (LLVM) -> interpreter -> formatter ->
|
|
23
|
+
LSP -> REPL -> CLI. Examples live in `examples/` (half are DESIGNED to
|
|
24
|
+
be rejected - each rejection demonstrates a guarantee). The standard
|
|
25
|
+
library is `stdlib/std.vel`, written in Velaris.
|
|
26
|
+
|
|
27
|
+
## Adding a feature
|
|
28
|
+
|
|
29
|
+
New syntax touches, in order: KEYWORDS/lexer, AST dataclasses, parser,
|
|
30
|
+
expr_str/expr_vars, effect walker (and walk_pure if usable in
|
|
31
|
+
contracts), type checker, prover (or an honest Unprovable fallback),
|
|
32
|
+
native eligibility, interpreter, formatter spacing if needed. Add at
|
|
33
|
+
least one RUNS example and one REJECTED example, register both in
|
|
34
|
+
run_tests.py, and run `velaris fmt` on them.
|
|
35
|
+
|
|
36
|
+
## Error style
|
|
37
|
+
|
|
38
|
+
Every error: a code (Exyz), a plain-English message, a location, and
|
|
39
|
+
numbered fixes. Never claim "proven" unless it is literally true.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gowri Shankar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|