Metadata-Version: 2.4
Name: toyc
Version: 0.2.7
Summary: A toy compiler with GPU backends (Vulkan + OpenGL)
Author: spy1345a
License: MIT License
        
        Copyright (c) 2026 spy1345a
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
        associated documentation files (the "Software"), to deal in the Software without restriction, including
        without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
        following conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or substantial
        portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
        LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
        EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
        IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
        USE OR OTHER DEALINGS IN THE SOFTWARE.
        
Project-URL: Homepage, https://github.com/spy1345a/toyc-repo
Project-URL: Repository, https://github.com/spy1345a/toyc-repo
Keywords: compiler,gpu,vulkan,opengl,toy
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pyopengl>=3.1
Requires-Dist: vulkan>=1.3.275.1
Provides-Extra: vulkan
Requires-Dist: vulkan; extra == "vulkan"
Provides-Extra: opengl
Requires-Dist: PyOpenGL; extra == "opengl"

# toyc

Toy expression compiler (`+ - * /`, parens, variables) with CPU and
Vulkan GPU backends. Both execute the same AST — compare the results.

```python
from toyc import Cpu, GpuVulkan

Cpu.run("1 + 2")          # 3   (ints stay ints)
GpuVulkan.run("1 + 2")    # 3.0 (GPU is float32)
```

## Install

```bash
pip install toyc
sudo apt install glslang-tools   # builds the bundled shaders on first run
```

Python 3.10+. Needs a Vulkan driver.

## Usage

```python
Cpu.run("program.toy")                          # file
Cpu.run("program.toy", env={"a": 1})            # variables
Cpu.run("program.toy", silent=True)             # capture, don't print
Cpu.run("out.toyc")                             # compiled file
Compiler.compile("program.toy")                 # write program.toyc

GpuVulkan.run("program.toy", env={"a": 10.0, "b": 5.0})
GpuVulkan.run("program.toy", env=[{...}, {...}])  # auto-batch → [..]
GpuVulkan.run("program.toy", cache=False)         # skip .toyc write
GpuVulkan.run("program.toyc")                     # cached result, no dispatch
```

`run()` takes an inline string, a `.toy` path, or a `.toyc` path.
`.toyc` caches hold a scalar (single) or a float list (batch).

## GPU session

Setup costs ~15–40 ms once; a dispatch ~0.5 ms. One shared session
per process, thread-safe, never torn down per call:

```python
GpuVulkan.startup()    # optional warmup; first call does it lazily
GpuVulkan.run(...)
GpuVulkan.shutdown()   # also automatic at process exit
```

## Batch (where the GPU wins)

One expression, many variable sets, one dispatch per chunk:

```python
results = GpuVulkan.run_batch("prog.toy", [{"a": 1.0}, {"a": 2.0}])
```

Chunking at the recommended batch size is automatic. Singles → CPU
(~0.1 ms vs ~1 ms); bulk → GPU (~23× at N=2000 on RX 580).

## Timing & bench

`timed=True` prints a report and returns `(result, timing)` (seconds):

```python
cpu_val, cpu_t = Cpu.run("program.toy", timed=True)
gpu_val, gpu_t = GpuVulkan.run("program.toy", timed=True)
```

`toyc.bench` needs no loops from you — one equation + knobs, test
values auto-generated:

```python
from toyc.bench import bench, batch_bench, summarize, to_csv

rows = bench("a + b * 2", backend="cpu", n=100, repeat=5)
rows = batch_bench("a + b * 2", backend="vulkan", n=2000, repeat=3)
to_csv(rows, "timings.csv")

import pandas as pd                       # your plotting, your deps
pd.DataFrame(rows).groupby("backend")["total"].mean().plot.bar()
```

Rows carry `backend, program, mode, n, repeat, total,
total_time_taken, per_eval, check_err` + per-stage columns. Batch rows
additionally carry `num_batches` (dispatch chunks used) and
`batch_size` (instances per chunk).
`summarize(rows)` collapses to one row per (backend, program).

## Semantics (CPU ≡ GPU)

| Case | Behavior |
|------|----------|
| Value | Numerically equal (`15` vs `15.0` — GPU is float32, ~1e-6 error) |
| `1/0`, `1/(a-a)`, `0/0` | `ZeroDivisionError("Division by zero in VM")` |
| Missing variable | `NameError("Undefined variable: 'q'")` |

Pipeline: Lexer → Parser → AST → Evaluator/Cpu, or Flattener →
compute shader (`toyc/gpu/vulkan/comp*.glsl`).

## License

See [LICENSE](toyc/LICENSE).
