hoodscript 1.1.0__tar.gz → 1.3.0__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.
- {hoodscript-1.1.0 → hoodscript-1.3.0}/CHANGELOG.md +106 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/CONTRIBUTING.md +19 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/PKG-INFO +34 -1
- {hoodscript-1.1.0 → hoodscript-1.3.0}/README.md +21 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/SECURITY.md +4 -2
- hoodscript-1.3.0/docs/adr/0004-no-regional-dialect-overlays.md +45 -0
- hoodscript-1.3.0/docs/grammar.ebnf +59 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/onboarding.md +30 -2
- hoodscript-1.3.0/examples/quickstart.ipynb +142 -0
- hoodscript-1.3.0/examples/solutions/beatlab/stage1.hs +10 -0
- hoodscript-1.3.0/examples/solutions/beatlab/stage2.hs +15 -0
- hoodscript-1.3.0/examples/solutions/beatlab/stage3.hs +11 -0
- hoodscript-1.3.0/examples/solutions/beatlab/stage4.hs +14 -0
- hoodscript-1.3.0/examples/solutions/beatlab/stage5.hs +13 -0
- hoodscript-1.3.0/examples/solutions/cookout/stage1.hs +9 -0
- hoodscript-1.3.0/examples/solutions/cookout/stage2.hs +8 -0
- hoodscript-1.3.0/examples/solutions/cookout/stage3.hs +5 -0
- hoodscript-1.3.0/examples/solutions/cookout/stage4.hs +26 -0
- hoodscript-1.3.0/examples/solutions/cookout/stage5.hs +13 -0
- hoodscript-1.3.0/examples/solutions/dropday/stage1.hs +13 -0
- hoodscript-1.3.0/examples/solutions/dropday/stage2.hs +14 -0
- hoodscript-1.3.0/examples/solutions/dropday/stage3.hs +12 -0
- hoodscript-1.3.0/examples/solutions/dropday/stage4.hs +11 -0
- hoodscript-1.3.0/examples/solutions/dropday/stage5.hs +16 -0
- hoodscript-1.3.0/examples/solutions/level1.hs +9 -0
- hoodscript-1.3.0/examples/solutions/level2.hs +9 -0
- hoodscript-1.3.0/examples/solutions/level3.hs +14 -0
- hoodscript-1.3.0/examples/solutions/level4.hs +18 -0
- hoodscript-1.3.0/examples/solutions/level5.hs +38 -0
- hoodscript-1.3.0/examples/solutions/level6.hs +14 -0
- hoodscript-1.3.0/examples/solutions/level7.hs +37 -0
- hoodscript-1.3.0/examples/solutions/level8.hs +41 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/pyproject.toml +13 -2
- hoodscript-1.3.0/scripts/gen_ebnf.py +33 -0
- hoodscript-1.3.0/scripts/hooks/pre-push +11 -0
- hoodscript-1.3.0/scripts/install-hooks.sh +7 -0
- hoodscript-1.3.0/src/hoodarcade/__init__.py +9 -0
- hoodscript-1.3.0/src/hoodarcade/cli.py +344 -0
- hoodscript-1.3.0/src/hoodarcade/core/runtime.py +148 -0
- hoodscript-1.3.0/src/hoodarcade/core/ui.py +232 -0
- hoodscript-1.3.0/src/hoodarcade/games/beatlab.py +393 -0
- hoodscript-1.3.0/src/hoodarcade/games/cookout.py +446 -0
- hoodscript-1.3.0/src/hoodarcade/games/dropday.py +415 -0
- hoodscript-1.3.0/src/hoodfarm/__init__.py +3 -0
- hoodscript-1.3.0/src/hoodfarm/cli.py +249 -0
- hoodscript-1.3.0/src/hoodfarm/drone.py +158 -0
- hoodscript-1.3.0/src/hoodfarm/grid.py +216 -0
- hoodscript-1.3.0/src/hoodfarm/levels.py +402 -0
- hoodscript-1.3.0/src/hoodfarm/renderer.py +249 -0
- hoodscript-1.3.0/src/hoodfarm/runner.py +224 -0
- hoodscript-1.3.0/src/hoodlib/__init__.py +9 -0
- hoodscript-1.3.0/src/hoodlib/disk.py +177 -0
- hoodscript-1.3.0/src/hoodscript/__init__.py +16 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/_version.py +2 -2
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/cli.py +60 -1
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/errors/translator.py +4 -1
- hoodscript-1.3.0/src/hoodscript/kernel/__init__.py +12 -0
- hoodscript-1.3.0/src/hoodscript/kernel/__main__.py +13 -0
- hoodscript-1.3.0/src/hoodscript/kernel/installer.py +54 -0
- hoodscript-1.3.0/src/hoodscript/kernel/kernel.py +292 -0
- hoodscript-1.3.0/src/hoodscript/kernel/magics.py +104 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/patterns.py +21 -11
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/traceback_handler.py +1 -1
- hoodscript-1.3.0/src/hoodscript/zen.py +60 -0
- hoodscript-1.3.0/src/vibe.py +8 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/test_exec_sites.py +1 -1
- hoodscript-1.3.0/tests/test_arcade.py +224 -0
- hoodscript-1.3.0/tests/test_arcade_gates.py +72 -0
- hoodscript-1.3.0/tests/test_fuzz_ebnf.py +178 -0
- hoodscript-1.3.0/tests/test_game_engine.py +249 -0
- hoodscript-1.3.0/tests/test_grammar_ebnf.py +19 -0
- hoodscript-1.3.0/tests/test_hoodlib_disk.py +101 -0
- hoodscript-1.3.0/tests/test_kernel.py +159 -0
- hoodscript-1.3.0/tests/test_kernel_zmq.py +88 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_patterns.py +13 -0
- hoodscript-1.1.0/src/hoodscript/__init__.py +0 -9
- {hoodscript-1.1.0 → hoodscript-1.3.0}/.gitignore +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/CODE_OF_CONDUCT.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/LICENSE +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/SPRINT_PLAN.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/adr/0001-token-pipeline-over-parser.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/adr/0002-keyword-reconciliation.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/adr/0003-inclusive-ranges.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/adr/README.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/archive/HOODSCRIPT_COMPLETE_MASTER_SYSTEM.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/archive/HOODSCRIPT_FULL_ENGINEERING_SUITE.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/archive/HOODSCRIPT_UNSPRED_FEATURES_ROADMAP.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/curriculum.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/docs/keywords.md +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/out.txt +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/app.js +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/bundle.js +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/examples.js +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/hoodscript-latest-py3-none-any.whl +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/index.html +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/style.css +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/playground/worker.js +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/scripts/build_playground.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/scripts/gen_keywords.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/__main__.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/cache.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/constants.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/debugger.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/errors/__init__.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/errors/catalog.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/errors/renderer.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/formatter.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/importer.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/linter.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/lsp.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/migrator.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/repl.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/sandbox.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/stubs.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/transpiler.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/src/hoodscript/tutor.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/conftest.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/deep_nesting.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/fork_bomb.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/huge_literal.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/import_escapes.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/infinite_recursion.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/open_file.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/pathological_indent.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/runaway_output.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/corpus/runaway_time.hs +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/test_corpus.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/test_fuzz.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/security/test_sandbox.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_cli.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_conformance.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_debugger.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_docs.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_errors.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_fmt.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_grammar_canonical.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_importer.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_keywords_doc.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_learn.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_lint.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_lsp_features.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_playground.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_release.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_repl.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_transpiler.py +0 -0
- {hoodscript-1.1.0 → hoodscript-1.3.0}/tests/test_vscode_extension.py +0 -0
|
@@ -3,6 +3,111 @@
|
|
|
3
3
|
All notable changes to HoodScript. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
Versioning: the keyword set is the public API; changing it is at least a minor bump.
|
|
5
5
|
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [1.3.0] — 2026-09-12
|
|
9
|
+
|
|
10
|
+
Three features that were on `main` but not on PyPI: the two games and the
|
|
11
|
+
ecosystem sprint. Keyword set unchanged (v1.1); minor bump for the new
|
|
12
|
+
packages and CLI commands.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `hoodarcade levels [game]`: the stage table for one game (`list` stays the
|
|
17
|
+
all-games form). Added while aligning a stale "Arcade + Ecosystem" prompt
|
|
18
|
+
with the release — the reconciliation is `PROMPTS.md` §3.5.
|
|
19
|
+
|
|
20
|
+
- **The Drone Was Replaced** (`hoodfarm`, `pip install "hoodscript[farm]"`, also
|
|
21
|
+
`hoodscript farm …`): a terminal grid-automation game in the style of *The
|
|
22
|
+
Farmer Was Replaced*. Program a drone (`bot.move/harvest/plant/water/till/
|
|
23
|
+
inspect_ground/measure_water`, `bot.bag/energy/ticks_used`) in HoodScript
|
|
24
|
+
across 8 levels (single-tile harvest → loops → 2D traversal → conditional
|
|
25
|
+
weeding → irrigation → inventory quotas → companion planting → an
|
|
26
|
+
energy-budgeted supply chain). Rich TUI with emoji tiles, telemetry,
|
|
27
|
+
inventory ledger and log console (ASCII fallback); `hoodfarm play <level>`
|
|
28
|
+
hot-reloads `solution.hs` on save; `hoodfarm run --benchmark` and
|
|
29
|
+
`hoodfarm test` run headless with proper exit codes. Deterministic ticks.
|
|
30
|
+
Reference solutions for all 8 levels in `examples/solutions/`.
|
|
31
|
+
- QA on acceptance (external batch): it shipped with a **private game lexicon**
|
|
32
|
+
— `cook`/`serve`/`run_thru`/`Facts` (cut under Rule Zero) and `dip`
|
|
33
|
+
remapped to `break` — so 7 of 8 solutions did not parse under `hoodscript`
|
|
34
|
+
and the game taught a different language. Removed; every starter template
|
|
35
|
+
and solution translated to v1.1 and verified to win through the real
|
|
36
|
+
transpiler. Crashes now go through the JPE engine with the player's line and
|
|
37
|
+
the game state ("drone at (2, 4), energy 0, tick 50"). Cut builtin aliases
|
|
38
|
+
injected as globals (`span`, `lineup`, `ledger`, `count_up`) removed.
|
|
39
|
+
Tests guard all of it (no cut word as a code token anywhere in the game).
|
|
40
|
+
|
|
41
|
+
- **HoodArcade** (`hoodarcade`, `pip install "hoodscript[arcade]"`, also
|
|
42
|
+
`hoodscript arcade …`): three terminal games, five stages each, with Rich
|
|
43
|
+
viewports (grill rack + Spades table, 16-step 808 matrix, SNKRS drop feed),
|
|
44
|
+
hot-reload on save, and progress in `~/.hoodarcade/progress.json`:
|
|
45
|
+
*Big Mama's Cookout* (grill timing, the potato-salad exception test, aux-cord
|
|
46
|
+
sorting, a Spades rule engine, an autonomous Spades partner), *BeatLab 808*
|
|
47
|
+
(four-on-the-floor, trap-hat triplets by modulo, sample chopping, 808 glide
|
|
48
|
+
interpolation, a full arrangement), *Drop Day* (stock monitor, legit-check
|
|
49
|
+
filter, exponential backoff with `tryna`/`catch`, multi-cart, a circular
|
|
50
|
+
trade-graph search). Reference solutions for all 15 stages.
|
|
51
|
+
- QA on acceptance (external batch): same defect as the farm — a **private
|
|
52
|
+
lexicon** (`cook`/`serve`/`run_thru`/`Facts`, `dip`→`break`) meant no stage
|
|
53
|
+
solution ran under `hoodscript`; removed, everything translated to v1.1.
|
|
54
|
+
**Every "starter" template was the finished solution** — a player opened a
|
|
55
|
+
stage already solved; all 15 rewritten as real scaffolds (API shown,
|
|
56
|
+
algorithm left to the player; tests assert scaffolds fail and solutions
|
|
57
|
+
pass). Crashes in player code, including ones the stage checkers catch, now
|
|
58
|
+
surface as JPE reports with the failing line; a checker fed the wrong
|
|
59
|
+
return type fails the stage in plain English instead of raising.
|
|
60
|
+
|
|
61
|
+
- **HPEP 20 — The Zen of HoodScript.** `hoodscript zen` (add `--notes` to see
|
|
62
|
+
which file each line points at) and `import vibe` from any program, like
|
|
63
|
+
`import this`. Nineteen lines, each a decision this repo actually made.
|
|
64
|
+
- **`docs/grammar.ebnf`** — the formal grammar as its own artifact, generated
|
|
65
|
+
from `GRAMMAR.md` by `scripts/gen_ebnf.py`; a test fails if they drift and
|
|
66
|
+
another checks every keyword has a production (that found `ask` missing).
|
|
67
|
+
- **Grammar-directed fuzzing** (`tests/test_fuzz_ebnf.py`, Hypothesis): generates
|
|
68
|
+
valid programs from the grammar and asserts they transpile, compile, keep
|
|
69
|
+
their line count, contain no leaked sentinels or keywords, and that
|
|
70
|
+
`py2hood(transpile(p))` transpiles back to the same Python. Found and fixed
|
|
71
|
+
two pattern-layer bugs on its first run: `x = ask "name? "` was a syntax
|
|
72
|
+
error (R12 only fired at statement start; now anywhere), and `holla (x)` was
|
|
73
|
+
not reversible (whitespace now decides: `holla(x)` is a call, `holla (x)` is
|
|
74
|
+
the statement form). `HYPOTHESIS_PROFILE=thorough` runs 2,000 examples per
|
|
75
|
+
property.
|
|
76
|
+
- **`hoodlib.disk`** — atomic, thread-safe JSON/CSV read/write and backups,
|
|
77
|
+
standard library only (`from hoodlib import disk`). Errors are the Python
|
|
78
|
+
exceptions the crash reporter already explains.
|
|
79
|
+
- **ADR-0004: no regional dialect overlays.** A proposal for Bay Area / Atlanta
|
|
80
|
+
/ DMV / MLE token overlays was declined under Rule Zero; a cited, single-
|
|
81
|
+
variety Tier B extension remains possible via the sourcing procedure. Two
|
|
82
|
+
companion proposals (`hoodpkg`/`hood.lock`, and a `hoodlib` with AES-GCM and
|
|
83
|
+
an async HTTP client) were dropped as duplicating Python and its packaging.
|
|
84
|
+
|
|
85
|
+
## [1.2.0] — 2026-09-11
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **Interactive Jupyter Notebook Kernel & IPython Magics** (`src/hoodscript/kernel/`, `examples/quickstart.ipynb`):
|
|
90
|
+
- Dedicated standalone Jupyter kernel (`hoodscript-kernel` / `HoodScriptKernel`) subclassing `ipykernel.kernelbase.Kernel`.
|
|
91
|
+
- Automatic 1:1 transpilation of notebook cells to Python prior to execution in the kernel's persistent namespace.
|
|
92
|
+
- Rich HTML plain-English JPE error cards rendered in-cell with collapsible raw Python tracebacks.
|
|
93
|
+
- Dynamic tab autocompletion over HoodScript keywords, patterns, exception names, and namespace variables.
|
|
94
|
+
- Cell and line inspection magics: `%hood_transpile` (preview generated Python without executing) and `%hood_tb` (toggle raw traceback view).
|
|
95
|
+
- IPython extension (`%load_ext hoodscript`) providing `%%hood` and `%%hood_transpile` for hybrid Python/HoodScript notebooks and Google Colab.
|
|
96
|
+
- CLI installer subcommand: `hoodscript kernel install [--user] [--prefix PREFIX]`.
|
|
97
|
+
- Interactive starter notebook: `examples/quickstart.ipynb`.
|
|
98
|
+
- Optional dependency extra: `pip install hoodscript[jupyter]`.
|
|
99
|
+
- QA (audited end to end over ZMQ with `jupyter_client` before acceptance; four
|
|
100
|
+
defects fixed): `holla` output never reached the cell (the base `Kernel`
|
|
101
|
+
never tells ipykernel's stdout stream which cell is running — `set_parent`
|
|
102
|
+
now does); a trailing bare expression displayed nothing (now shown as the
|
|
103
|
+
result, like IPython); crash cards showed the *Python* line (`def f()`) and,
|
|
104
|
+
for syntax errors, a stdlib `ast.py` frame (cells are registered in
|
|
105
|
+
`linecache` as `<notebook>`, a program pseudo-file; syntax errors carry no
|
|
106
|
+
frames); `%load_ext hoodscript` as documented did not work (only
|
|
107
|
+
`hoodscript.kernel` did) and `examples/quickstart.ipynb` had no kernelspec
|
|
108
|
+
metadata. `tests/test_kernel_zmq.py` drives the real kernel process.
|
|
109
|
+
|
|
110
|
+
|
|
6
111
|
## [1.1.0] — 2026-09-11
|
|
7
112
|
|
|
8
113
|
The reconciled language. Every keyword is now either cited in
|
|
@@ -179,5 +284,6 @@ PEP 552 bytecode cache, CLI, REPL, crash reports with `*Trip` names,
|
|
|
179
284
|
`py2hood` / `hood2py`, stub generator, pygls language server (diagnostics,
|
|
180
285
|
hover, completion). Keyword set later found to be uncited — see v1.1.0.
|
|
181
286
|
|
|
287
|
+
[1.2.0]: https://github.com/khaoticdev62/hoodscript/compare/v1.1.0...v1.2.0
|
|
182
288
|
[1.1.0]: https://github.com/khaoticdev62/hoodscript/compare/bf801ab...v1.1.0
|
|
183
289
|
[1.0.0]: https://github.com/khaoticdev62/hoodscript/commits/bf801ab
|
|
@@ -64,6 +64,15 @@ Before every push:
|
|
|
64
64
|
ruff check && pytest
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
Enforce it locally once per clone — the versioned pre-push hook runs exactly
|
|
68
|
+
this and refuses the push if it fails:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
./scripts/install-hooks.sh
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
(If you pipe `ruff check` into anything, you lose its exit code. Don't.)
|
|
75
|
+
|
|
67
76
|
That is exactly what CI runs, on Ubuntu, macOS, and Windows × Python
|
|
68
77
|
3.10–3.13, plus a CLI smoke test. Python's exception *messages* differ between
|
|
69
78
|
versions (`was never closed` vs `EOF in multi-line statement`), so a catalog
|
|
@@ -107,6 +116,16 @@ with a gate. Commit at the gate with a message that says what changed and
|
|
|
107
116
|
why; the changelog is written from those messages. Update `CLAUDE.md` when a
|
|
108
117
|
decision changes — stale context is worse than none.
|
|
109
118
|
|
|
119
|
+
## Landing changes
|
|
120
|
+
|
|
121
|
+
`main` is protected: the Ubuntu/macOS/Windows test legs and the build must be
|
|
122
|
+
green, force-pushes and deletions are refused, and pull requests need a
|
|
123
|
+
code-owner review (`.github/CODEOWNERS`). **Work you did not write yourself —
|
|
124
|
+
an agent's output included — lands as a pull request**, gets `/code-review`
|
|
125
|
+
and the end-to-end audit in [`PROMPTS.md`](PROMPTS.md) §2.8, and only then
|
|
126
|
+
merges. Two batches arrived on 2026-09-11 claiming completion with defects
|
|
127
|
+
their own tests could not see; that is why.
|
|
128
|
+
|
|
110
129
|
## Working with an AI agent
|
|
111
130
|
|
|
112
131
|
Paste the standing brief from [`PROMPTS.md`](PROMPTS.md) §0 at the top of
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hoodscript
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: A production-grade Python 3 conlang based on AAVE with 1:1 AST parity.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.10
|
|
8
8
|
Provides-Extra: all
|
|
9
|
+
Requires-Dist: ipykernel>=6.0.0; extra == 'all'
|
|
10
|
+
Requires-Dist: ipython>=8.0.0; extra == 'all'
|
|
9
11
|
Requires-Dist: jedi>=0.19.1; extra == 'all'
|
|
10
12
|
Requires-Dist: mypy>=1.9.0; extra == 'all'
|
|
11
13
|
Requires-Dist: prompt-toolkit>=3.0.40; extra == 'all'
|
|
12
14
|
Requires-Dist: pygls<2,>=1.3.1; extra == 'all'
|
|
13
15
|
Requires-Dist: rich>=13.7; extra == 'all'
|
|
14
16
|
Requires-Dist: ruff>=0.3.0; extra == 'all'
|
|
17
|
+
Provides-Extra: arcade
|
|
18
|
+
Requires-Dist: rich>=13.7; extra == 'arcade'
|
|
15
19
|
Provides-Extra: dev
|
|
16
20
|
Requires-Dist: build>=1.1.0; extra == 'dev'
|
|
17
21
|
Requires-Dist: debugpy>=1.8.0; extra == 'dev'
|
|
18
22
|
Requires-Dist: hatch-vcs>=0.4.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: hypothesis>=6.100; extra == 'dev'
|
|
24
|
+
Requires-Dist: ipykernel>=6.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: ipython>=8.0.0; extra == 'dev'
|
|
19
26
|
Requires-Dist: jedi>=0.19.1; extra == 'dev'
|
|
20
27
|
Requires-Dist: mypy>=1.9.0; extra == 'dev'
|
|
21
28
|
Requires-Dist: prompt-toolkit>=3.0.40; extra == 'dev'
|
|
@@ -24,6 +31,11 @@ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
|
24
31
|
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
25
32
|
Requires-Dist: rich>=13.7; extra == 'dev'
|
|
26
33
|
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
34
|
+
Provides-Extra: farm
|
|
35
|
+
Requires-Dist: rich>=13.7; extra == 'farm'
|
|
36
|
+
Provides-Extra: jupyter
|
|
37
|
+
Requires-Dist: ipykernel>=6.0.0; extra == 'jupyter'
|
|
38
|
+
Requires-Dist: ipython>=8.0.0; extra == 'jupyter'
|
|
27
39
|
Provides-Extra: lsp
|
|
28
40
|
Requires-Dist: jedi>=0.19.1; extra == 'lsp'
|
|
29
41
|
Requires-Dist: pygls<2,>=1.3.1; extra == 'lsp'
|
|
@@ -96,9 +108,12 @@ with `PYTHONPATH=src` and use `python3 -m hoodscript` instead of `hoodscript`.
|
|
|
96
108
|
hoodscript hello.hs # transpile + execute
|
|
97
109
|
hoodscript -c hello.hs # print the Python it becomes
|
|
98
110
|
hoodscript repl --mirror # interactive REPL (hood> prompt; chill to exit; --mirror shows the Python)
|
|
111
|
+
hoodscript playground # launch in-browser Pyodide WebAssembly playground
|
|
112
|
+
hoodscript kernel install # Jupyter kernel (pip install "hoodscript[jupyter]"); or %load_ext hoodscript
|
|
99
113
|
hoodscript fmt|lint <file.hs> # formatter / linter (pip install "hoodscript[tools]")
|
|
100
114
|
hoodscript learn [topic] # interactive tutor driving docs/curriculum.md
|
|
101
115
|
hoodscript # a short tour of all commands
|
|
116
|
+
hoodscript zen # the Zen of HoodScript (HPEP 20); or `import vibe`
|
|
102
117
|
hoodscript lsp # language server over stdio, for editors
|
|
103
118
|
hoodscript make-stubs f.py # emit a .pyi-style stub with empty bodies
|
|
104
119
|
```
|
|
@@ -158,6 +173,24 @@ Everything else — `if`, `else`, `while`, `import`, `with`, `match`, `None`,
|
|
|
158
173
|
`self`, every builtin — is Python's own word, and every Python keyword still
|
|
159
174
|
works in a `.hs` file.
|
|
160
175
|
|
|
176
|
+
## Play
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pip install "hoodscript[farm]"
|
|
180
|
+
hoodfarm levels # the 8 challenges
|
|
181
|
+
hoodfarm play 1 # edit solution.hs in your editor; the farm re-runs on every save
|
|
182
|
+
hoodfarm run my.hs -b # headless benchmark, exit 0 on pass
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
*The Drone Was Replaced*: program a farming drone in HoodScript, one level at
|
|
186
|
+
a time. Same language, same crash reports — the game just adds a `bot`.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
pip install "hoodscript[arcade]"
|
|
190
|
+
hoodarcade # Big Mama's Cookout · BeatLab 808 · Drop Day
|
|
191
|
+
hoodarcade play cookout 1 # edit the solution file; the stage re-runs on save
|
|
192
|
+
```
|
|
193
|
+
|
|
161
194
|
## Learn
|
|
162
195
|
|
|
163
196
|
- [`docs/onboarding.md`](docs/onboarding.md) — from zero to a running program in ten minutes
|
|
@@ -58,9 +58,12 @@ with `PYTHONPATH=src` and use `python3 -m hoodscript` instead of `hoodscript`.
|
|
|
58
58
|
hoodscript hello.hs # transpile + execute
|
|
59
59
|
hoodscript -c hello.hs # print the Python it becomes
|
|
60
60
|
hoodscript repl --mirror # interactive REPL (hood> prompt; chill to exit; --mirror shows the Python)
|
|
61
|
+
hoodscript playground # launch in-browser Pyodide WebAssembly playground
|
|
62
|
+
hoodscript kernel install # Jupyter kernel (pip install "hoodscript[jupyter]"); or %load_ext hoodscript
|
|
61
63
|
hoodscript fmt|lint <file.hs> # formatter / linter (pip install "hoodscript[tools]")
|
|
62
64
|
hoodscript learn [topic] # interactive tutor driving docs/curriculum.md
|
|
63
65
|
hoodscript # a short tour of all commands
|
|
66
|
+
hoodscript zen # the Zen of HoodScript (HPEP 20); or `import vibe`
|
|
64
67
|
hoodscript lsp # language server over stdio, for editors
|
|
65
68
|
hoodscript make-stubs f.py # emit a .pyi-style stub with empty bodies
|
|
66
69
|
```
|
|
@@ -120,6 +123,24 @@ Everything else — `if`, `else`, `while`, `import`, `with`, `match`, `None`,
|
|
|
120
123
|
`self`, every builtin — is Python's own word, and every Python keyword still
|
|
121
124
|
works in a `.hs` file.
|
|
122
125
|
|
|
126
|
+
## Play
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
pip install "hoodscript[farm]"
|
|
130
|
+
hoodfarm levels # the 8 challenges
|
|
131
|
+
hoodfarm play 1 # edit solution.hs in your editor; the farm re-runs on every save
|
|
132
|
+
hoodfarm run my.hs -b # headless benchmark, exit 0 on pass
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
*The Drone Was Replaced*: program a farming drone in HoodScript, one level at
|
|
136
|
+
a time. Same language, same crash reports — the game just adds a `bot`.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install "hoodscript[arcade]"
|
|
140
|
+
hoodarcade # Big Mama's Cookout · BeatLab 808 · Drop Day
|
|
141
|
+
hoodarcade play cookout 1 # edit the solution file; the stage re-runs on save
|
|
142
|
+
```
|
|
143
|
+
|
|
123
144
|
## Learn
|
|
124
145
|
|
|
125
146
|
- [`docs/onboarding.md`](docs/onboarding.md) — from zero to a running program in ten minutes
|
|
@@ -50,14 +50,16 @@ To protect host environments against runaway workloads, the sandbox enforces thr
|
|
|
50
50
|
|
|
51
51
|
## 4. Code Execution Audit
|
|
52
52
|
|
|
53
|
-
`exec`/`eval` appear in exactly
|
|
53
|
+
`exec`/`eval` appear in exactly six places, all on code objects produced by
|
|
54
54
|
`compile()` from the transpiler's output of the user's own source — never on
|
|
55
55
|
text from anywhere else:
|
|
56
56
|
1. `src/hoodscript/cli.py` — running a file
|
|
57
57
|
2. `src/hoodscript/repl.py` — the interactive session (`eval` first, `exec` fallback)
|
|
58
58
|
3. `src/hoodscript/debugger.py` — running a file under debugpy
|
|
59
59
|
4. `src/hoodscript/tutor.py` — running a curriculum lesson
|
|
60
|
-
`
|
|
60
|
+
5. `src/hoodscript/kernel/kernel.py` — executing notebook cells in the HoodScript kernel
|
|
61
|
+
6. `src/hoodscript/kernel/magics.py` — executing `%%hood` cells in IPython / Google Colab
|
|
62
|
+
`tests/security/test_exec_sites.py` fails if a seventh appears.
|
|
61
63
|
|
|
62
64
|
### Why this is safe and equivalent to `compile()`:
|
|
63
65
|
- `transpile()` performs strictly lexical substitution over Python's `tokenize.tokenize` stream and deterministic character-preserving pattern transforms (Rules R1–R12).
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# ADR-0004: No Regional Dialect Overlays (Rule Zero Stands)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Accepted (2026-09-12)
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
A proposal asked for a "modular regional dialect engine": token overlays for
|
|
8
|
+
Bay Area, Atlanta, DMV, and UK Drill / MLE slang, selectable via `hood.toml` or
|
|
9
|
+
`--dialect`, resolving to standard HoodScript tokens before transpilation.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
**Not adopted.** The keyword set is governed by Rule Zero and the sourcing
|
|
13
|
+
procedure in `hoodscript/docs/lexical-sourcing.md` §5. A dialect overlay is a
|
|
14
|
+
keyword table; every entry in it would need the same evidence as every other
|
|
15
|
+
keyword, and an owner-signed `GRAMMAR.md` revision. Four overlays of roughly
|
|
16
|
+
fifteen words each is four times the size of the entire v1.1 reconciliation.
|
|
17
|
+
|
|
18
|
+
Three further reasons:
|
|
19
|
+
|
|
20
|
+
1. **It grows the wrong tier.** The language's thesis is Tier A — AAVE aspect
|
|
21
|
+
marking (`be`, `steady`, `BIN`, `done`) mapped onto execution semantics.
|
|
22
|
+
Overlays add only Tier B naming, which was deliberately capped small:
|
|
23
|
+
"every alias is a thing to learn, and 1:1 legibility suffers as aliases
|
|
24
|
+
grow." Regional slang is also the most perishable vocabulary there is,
|
|
25
|
+
which is exactly what Rule Zero excludes.
|
|
26
|
+
2. **The mechanism is the known failure mode.** "Resolve dialect tokens to
|
|
27
|
+
standard tokens first" is the private-keyword-map pattern that three
|
|
28
|
+
external batches reintroduced in one day (2026-09-11/12), two of which
|
|
29
|
+
silently changed the meaning of `dip`. See CHANGELOG, QA sections.
|
|
30
|
+
3. **A player who learns a dialect learns a language that runs nowhere else.**
|
|
31
|
+
The 1:1 promise is that what you write in HoodScript is HoodScript.
|
|
32
|
+
|
|
33
|
+
## The door that stays open
|
|
34
|
+
The named varieties are real objects of sociolinguistic study. A *cited*
|
|
35
|
+
extension — one variety, each word through the seven steps, `UNVERIFIED`
|
|
36
|
+
where the literature is thin, signed by the owner — would be a legitimate
|
|
37
|
+
Tier B addition and can be proposed with `PROMPTS.md` §2.1. It is a sourcing
|
|
38
|
+
sprint first and a loader second, if ever.
|
|
39
|
+
|
|
40
|
+
## Consequences
|
|
41
|
+
- No `--dialect` flag, no dialect section in any config, no overlay loader.
|
|
42
|
+
- `constants.py` remains the single keyword table; `patterns.py` the single
|
|
43
|
+
multi-token layer.
|
|
44
|
+
- Proposals that arrive with a dialect map are declined at review with a
|
|
45
|
+
pointer to this ADR.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
(* HoodScript v1.1 — formal grammar (EBNF).
|
|
2
|
+
Descriptive: the implementation is a token rewrite (src/hoodscript/transpiler.py)
|
|
3
|
+
plus the pattern rules R1–R12 (src/hoodscript/patterns.py), not a parser.
|
|
4
|
+
This file is extracted verbatim from GRAMMAR.md; tests/test_grammar_ebnf.py
|
|
5
|
+
fails if the two drift. Edit GRAMMAR.md, then regenerate:
|
|
6
|
+
python scripts/gen_ebnf.py > docs/grammar.ebnf
|
|
7
|
+
*)
|
|
8
|
+
|
|
9
|
+
program = { statement } ;
|
|
10
|
+
|
|
11
|
+
statement = output_stmt | assignment | const_decl | func_def | class_def
|
|
12
|
+
| return_stmt | habitual_loop | continuative_loop | while_loop
|
|
13
|
+
| conditional | try_stmt | throw_stmt | import_stmt
|
|
14
|
+
| loop_control | pass_stmt | python_stmt | expr_stmt ;
|
|
15
|
+
|
|
16
|
+
output_stmt = "holla" [ expression { "," expression } | "(" [ args ] ")" ] ;
|
|
17
|
+
input_expr = "ask" ( expression | "(" [ args ] ")" ) ;
|
|
18
|
+
assignment = target "=" expression ;
|
|
19
|
+
const_decl = "BIN" IDENT "=" expression ;
|
|
20
|
+
|
|
21
|
+
func_def = [ "finna" ] "bet" IDENT "(" [ params ] ")" ":" block ;
|
|
22
|
+
return_stmt = ( "dip" | "return" ) [ expression ] ;
|
|
23
|
+
class_def = "fam" IDENT [ "(" IDENT { "," IDENT } ")" ] ":" block ;
|
|
24
|
+
|
|
25
|
+
habitual_loop = "be" target "in" expression ":" block ;
|
|
26
|
+
continuative_loop = "steady" ":" block ;
|
|
27
|
+
while_loop = "while" expression ":" block ;
|
|
28
|
+
loop_control = "skip" | "break" ;
|
|
29
|
+
pass_stmt = "chill" ;
|
|
30
|
+
|
|
31
|
+
conditional = "if" expression ":" block
|
|
32
|
+
{ "else" "if" expression ":" block }
|
|
33
|
+
[ "else" ":" block ] ;
|
|
34
|
+
|
|
35
|
+
try_stmt = "tryna" ":" block { handler } [ "regardless" ":" block ] ;
|
|
36
|
+
handler = "catch" [ expression [ "as" IDENT ] ] ":" block ;
|
|
37
|
+
throw_stmt = "throw" [ expression ] ;
|
|
38
|
+
|
|
39
|
+
import_stmt = "import" dotted [ "as" IDENT ]
|
|
40
|
+
| "from" dotted "import" IDENT { "," IDENT } ;
|
|
41
|
+
|
|
42
|
+
python_stmt = (* any Python statement: with, match, del, global, nonlocal,
|
|
43
|
+
assert, yield, decorators, comprehensions — passed through *) ;
|
|
44
|
+
|
|
45
|
+
block = INDENT { statement } DEDENT ;
|
|
46
|
+
|
|
47
|
+
expression = or_expr ;
|
|
48
|
+
or_expr = and_expr { "or" and_expr } ;
|
|
49
|
+
and_expr = not_expr { "and" not_expr } ;
|
|
50
|
+
not_expr = [ "ain't" [ "nobody" ] | "not" ] comparison ;
|
|
51
|
+
comparison = term { comp_op term } ;
|
|
52
|
+
primary = NUMBER | STRING | IDENT
|
|
53
|
+
| "cap" | "no" "cap" | "None"
|
|
54
|
+
| "it's" expression
|
|
55
|
+
| "done" expression
|
|
56
|
+
| input_expr
|
|
57
|
+
| "(" expression ")"
|
|
58
|
+
| list_lit | dict_lit | range_lit | python_expr ;
|
|
59
|
+
range_lit = expression ".." expression ;
|
|
@@ -219,14 +219,42 @@ Speaks the Language Server Protocol over stdio. Provides:
|
|
|
219
219
|
Point any LSP-capable editor at that command for the `hoodscript` language ID.
|
|
220
220
|
A VS Code extension manifest lives in `editors/vscode/`.
|
|
221
221
|
|
|
222
|
-
## 11.
|
|
222
|
+
## 11. Jupyter Notebooks & Google Colab
|
|
223
|
+
|
|
224
|
+
Use HoodScript interactively inside JupyterLab, classic Notebooks, or Google Colab:
|
|
225
|
+
|
|
226
|
+
### Option A: Dedicated Jupyter Kernel
|
|
227
|
+
```bash
|
|
228
|
+
pip install hoodscript[jupyter]
|
|
229
|
+
hoodscript kernel install
|
|
230
|
+
jupyter lab
|
|
231
|
+
```
|
|
232
|
+
Select the **HoodScript** kernel from the launcher. Every cell executes native HoodScript with tab completion and rich plain-English JPE error cards.
|
|
233
|
+
|
|
234
|
+
### Option B: Google Colab & Existing Python Notebooks
|
|
235
|
+
In the first cell:
|
|
236
|
+
```python
|
|
237
|
+
!pip install hoodscript[jupyter]
|
|
238
|
+
%load_ext hoodscript
|
|
239
|
+
```
|
|
240
|
+
Now write HoodScript in any cell using `%%hood`:
|
|
241
|
+
```ipython
|
|
242
|
+
%%hood
|
|
243
|
+
bet calculate(x):
|
|
244
|
+
dip x * 10
|
|
245
|
+
|
|
246
|
+
holla "Result:", calculate(4.2)
|
|
247
|
+
```
|
|
248
|
+
Preview the generated Python anytime with `%%hood_transpile`.
|
|
249
|
+
|
|
250
|
+
## 12. Run the tests
|
|
223
251
|
|
|
224
252
|
```bash
|
|
225
253
|
pytest # with the venv
|
|
226
254
|
PYTHONPATH=src pytest tests/ # without an editable install
|
|
227
255
|
```
|
|
228
256
|
|
|
229
|
-
##
|
|
257
|
+
## 13. Where to go next
|
|
230
258
|
|
|
231
259
|
- [`curriculum.md`](curriculum.md) — ten lessons covering the whole language
|
|
232
260
|
- [`../agents.md`](../agents.md) — how the transpiler, importer, cache, and
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# HoodScript Interactive Quickstart Notebook\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"Welcome to **HoodScript** in Jupyter! HoodScript maps authentic AAVE keywords **1:1 to Python 3** and explains every error in **plain conversational English**.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"### Two Ways to Use HoodScript in Notebooks:\n",
|
|
12
|
+
"1. **Native HoodScript Kernel**: Select `HoodScript` from the kernel dropdown.\n",
|
|
13
|
+
"2. **IPython Magic**: In a standard Python notebook or Google Colab, run `%load_ext hoodscript` and use `%%hood` at the top of cells."
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"cell_type": "code",
|
|
18
|
+
"execution_count": null,
|
|
19
|
+
"metadata": {},
|
|
20
|
+
"outputs": [],
|
|
21
|
+
"source": [
|
|
22
|
+
"# Lesson 1: Values, Booleans, and holla\n",
|
|
23
|
+
"name = \"Khris\"\n",
|
|
24
|
+
"age = 28\n",
|
|
25
|
+
"verified = no cap # True\n",
|
|
26
|
+
"fake = cap # False\n",
|
|
27
|
+
"\n",
|
|
28
|
+
"holla \"User:\", name, \"Age:\", age, \"Verified:\", verified"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"cell_type": "markdown",
|
|
33
|
+
"metadata": {},
|
|
34
|
+
"source": [
|
|
35
|
+
"### Live Transpilation Inspection\n",
|
|
36
|
+
"HoodScript adheres strictly to the **1:1 Law**: every line of HoodScript corresponds to valid Python with preserved line numbers.\n",
|
|
37
|
+
"Use `%hood_transpile` to inspect the generated Python code:"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"cell_type": "code",
|
|
42
|
+
"execution_count": null,
|
|
43
|
+
"metadata": {},
|
|
44
|
+
"outputs": [],
|
|
45
|
+
"source": [
|
|
46
|
+
"%hood_transpile\n",
|
|
47
|
+
"be i in 1..5:\n",
|
|
48
|
+
" if i == 3:\n",
|
|
49
|
+
" skip\n",
|
|
50
|
+
" holla \"Lap:\", i"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"cell_type": "markdown",
|
|
55
|
+
"metadata": {},
|
|
56
|
+
"source": [
|
|
57
|
+
"### Loops and Inclusive Ranges: `be` and `1..n`\n",
|
|
58
|
+
"`be x in xs` represents habitual action (Python's `for x in xs`). `1..5` is an inclusive range (1, 2, 3, 4, 5)."
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"cell_type": "code",
|
|
63
|
+
"execution_count": null,
|
|
64
|
+
"metadata": {},
|
|
65
|
+
"outputs": [],
|
|
66
|
+
"source": [
|
|
67
|
+
"total = 0\n",
|
|
68
|
+
"be i in 1..10:\n",
|
|
69
|
+
" total = total + i\n",
|
|
70
|
+
"\n",
|
|
71
|
+
"holla \"Sum of 1..10 is:\", total"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"cell_type": "markdown",
|
|
76
|
+
"metadata": {},
|
|
77
|
+
"source": [
|
|
78
|
+
"### Functions and Classes: `bet`, `dip`, and `fam`\n",
|
|
79
|
+
"`bet` defines a function; `dip` returns with a value; `fam` defines a class."
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"cell_type": "code",
|
|
84
|
+
"execution_count": null,
|
|
85
|
+
"metadata": {},
|
|
86
|
+
"outputs": [],
|
|
87
|
+
"source": [
|
|
88
|
+
"bet apply_discount(price, pct=0.15):\n",
|
|
89
|
+
" dip price * (1.0 - pct)\n",
|
|
90
|
+
"\n",
|
|
91
|
+
"fam Shopper:\n",
|
|
92
|
+
" bet __init__(self, name, wallet):\n",
|
|
93
|
+
" self.name = name\n",
|
|
94
|
+
" self.wallet = wallet\n",
|
|
95
|
+
"\n",
|
|
96
|
+
" bet purchase(self, item_name, original_price):\n",
|
|
97
|
+
" final_price = apply_discount(original_price)\n",
|
|
98
|
+
" self.wallet = self.wallet - final_price\n",
|
|
99
|
+
" holla self.name, \"bought\", item_name, \"for\", final_price, \"| Balance remaining:\", self.wallet\n",
|
|
100
|
+
"\n",
|
|
101
|
+
"buyer = Shopper(\"Sam\", 150.0)\n",
|
|
102
|
+
"buyer.purchase(\"Sneakers\", 80.0)"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"cell_type": "markdown",
|
|
107
|
+
"metadata": {},
|
|
108
|
+
"source": [
|
|
109
|
+
"### Plain-English Error Handling: `tryna`, `catch`, and `ZeroSplitTrip`\n",
|
|
110
|
+
"Exceptions are never dumped as raw Python tracebacks; they are rendered with plain-English explanations, causes, and suggestions."
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"cell_type": "code",
|
|
115
|
+
"execution_count": null,
|
|
116
|
+
"metadata": {},
|
|
117
|
+
"outputs": [],
|
|
118
|
+
"source": [
|
|
119
|
+
"tryna:\n",
|
|
120
|
+
" result = 100 / 0\n",
|
|
121
|
+
"catch ZeroSplitTrip as err:\n",
|
|
122
|
+
" holla \"Caught expected error:\", err\n",
|
|
123
|
+
"regardless:\n",
|
|
124
|
+
" holla \"Execution completed clean.\""
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
"metadata": {
|
|
129
|
+
"language_info": {
|
|
130
|
+
"name": "hoodscript",
|
|
131
|
+
"file_extension": ".hs",
|
|
132
|
+
"mimetype": "text/x-hoodscript"
|
|
133
|
+
},
|
|
134
|
+
"kernelspec": {
|
|
135
|
+
"name": "hoodscript",
|
|
136
|
+
"display_name": "HoodScript",
|
|
137
|
+
"language": "hoodscript"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"nbformat": 4,
|
|
141
|
+
"nbformat_minor": 2
|
|
142
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Stage 1: Four on the Floor
|
|
2
|
+
# Instructions: Load 16-step patterns for 'Kick' and 'Snare'.
|
|
3
|
+
|
|
4
|
+
kicks = [0, 4, 8, 12]
|
|
5
|
+
snares = [4, 12]
|
|
6
|
+
|
|
7
|
+
sequencer.load_track("Kick", kicks)
|
|
8
|
+
sequencer.load_track("Snare", snares)
|
|
9
|
+
sequencer.play()
|
|
10
|
+
holla("Classic 4-on-the-floor sequence loaded!")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Stage 2: Trap Hat Triplets
|
|
2
|
+
# Instructions: Generate hi-hat steps combining straight 8ths and a triplet roll.
|
|
3
|
+
|
|
4
|
+
hats = []
|
|
5
|
+
# Standard 8th notes on even steps 0 to 10
|
|
6
|
+
be step in range(12):
|
|
7
|
+
if step % 2 == 0:
|
|
8
|
+
hats.append(step)
|
|
9
|
+
|
|
10
|
+
# Triplet roll on turnaround steps 12 to 15
|
|
11
|
+
be step in range(12, 16):
|
|
12
|
+
hats.append(step)
|
|
13
|
+
|
|
14
|
+
sequencer.load_track("HiHat", hats)
|
|
15
|
+
holla("Trap hats rolling across matrix: ", hats)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Stage 3: Soul Sample Chopper
|
|
2
|
+
# Instructions: Chop 16 consecutive 1000ms slices onto pads 1 to 16, reversing every 4th pad.
|
|
3
|
+
|
|
4
|
+
be i in range(1, 17):
|
|
5
|
+
start_ms = (i - 1) * 1000
|
|
6
|
+
end_ms = i * 1000
|
|
7
|
+
mpc.chop_sample(start_ms, end_ms, i)
|
|
8
|
+
if i % 4 == 0:
|
|
9
|
+
mpc.reverse_pad(i)
|
|
10
|
+
|
|
11
|
+
holla("Vinyl chopped and reversed into 16 quantized MPC pads!")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Stage 4: 808 Slide Calculus
|
|
2
|
+
# Instructions: Define calculate_808_glide(start_note, end_note, steps) returning linear frequency curve.
|
|
3
|
+
|
|
4
|
+
bet calculate_808_glide(start_note, end_note, steps):
|
|
5
|
+
freqs = {"C1": 32.70, "D1": 36.71, "E1": 41.20, "F1": 43.65, "G1": 49.00, "A1": 55.00}
|
|
6
|
+
f_start = freqs[start_note]
|
|
7
|
+
f_end = freqs[end_note]
|
|
8
|
+
|
|
9
|
+
result = []
|
|
10
|
+
step_delta = (f_end - f_start) / (steps - 1)
|
|
11
|
+
be i in range(steps):
|
|
12
|
+
result.append(round(f_start + (i * step_delta), 2))
|
|
13
|
+
|
|
14
|
+
dip result
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Stage 5: The Metro Drop
|
|
2
|
+
# Instructions: Assemble full track arrangement, drop producer tag, and render final WAV.
|
|
3
|
+
|
|
4
|
+
bet produce_metro_drop(mpc, sequencer, mastering):
|
|
5
|
+
mpc.set_bpm(144)
|
|
6
|
+
|
|
7
|
+
sequencer.load_track("Kick", [0, 6, 8, 14])
|
|
8
|
+
sequencer.load_track("Snare", [4, 12])
|
|
9
|
+
sequencer.load_track("808", [0, 6, 8, 14])
|
|
10
|
+
sequencer.load_track("HiHat", [0, 2, 4, 6, 8, 10, 12, 13, 14, 15])
|
|
11
|
+
|
|
12
|
+
mastering.drop_tag("metro_tag.wav", 4)
|
|
13
|
+
mastering.render_wav("hit_single_master.wav")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Stage 1: Grill Master Basics
|
|
2
|
+
# Instructions: Loop through all grill items, season with Lawry's, and flip twice so they are cooked!
|
|
3
|
+
|
|
4
|
+
items = grill.get_items()
|
|
5
|
+
be item in items:
|
|
6
|
+
grill.season(item, "Lawry's Seasoned Salt")
|
|
7
|
+
grill.flip(item)
|
|
8
|
+
grill.flip(item)
|
|
9
|
+
holla("Cooked to perfection: ", item)
|