Skip to content

Commit ec823d8

Browse files
feat: teach defaultdict and map/filter on the canvas (curriculum phase 0c/0d)
- defaultdict(factory): dict box carrying a default factory; a missing-key read both returns and stores the factory value - map(fn, it) / filter(pred, it): lazy iterator objects that hold a reference to both the source iterator and the function, drawn as a reference chain - functools.reduce(fn, it): eager fold - bare constructor names (int, list, ...) now resolve to builtin objects so they can be passed as factory/transform arguments - canvas + snapshot: mapiter/filteriter edges (source + fn), defaultdict factory tag and entry refs - new 'Defaults & Functional' series: 4 levels (35 total across 9 series) - README/DESIGN updated to 35 levels / 9 series
1 parent 05ec0dc commit ec823d8

10 files changed

Lines changed: 487 additions & 26 deletions

File tree

‎DESIGN.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@ Supported subset (deliberately small, pedagogically sharp):
2626
- Function `def` / call / `return`, local frames, nested calls
2727
- `print`, `type`, `id`, `len`, `is`, `==`, arithmetic, comparisons
2828
- `import copy as cp` (simulated module) → `cp.copy` (shallow) / `cp.deepcopy`
29+
- `import collections as c` → `c.defaultdict(factory)` → dict box with a default-factory
30+
- `import functools as f` → `f.reduce(fn, it)` → eager fold
2931
- `iter(x)` / `next(it)` → stateful iterator object (source reference + cursor)
32+
- `map(fn, it)` / `filter(pred, it)` → lazy iterator object (source + function reference)
3033
- Plotting: `scatter(xs, ys, "title")` / `line(xs, ys, "title")` → SVG board
3134
- Meta: `help`, `levels`, `level`, `goal`, `hint`, `solution`, `undo`, `reset`, `golf`, `script`
3235

33-
Out of scope v0: classes/OOP, real imports (only the simulated `copy` module), control flow
36+
Out of scope v0: classes/OOP, real imports (only the simulated `copy`, `collections`, `functools`
37+
modules), control flow
3438
(`if`/`for`/`while`), exceptions (except parse/runtime errors shown cleanly), comprehensions beyond
3539
simple cases, I/O, async, `range`/`sorted`/`min`/`max`/`abs`.
3640

@@ -43,7 +47,7 @@ simulated module whose data structures are first-class heap objects on this canv
4347
```
4448
src/engine/ simulated Python runtime (tokenizer, parser, evaluator, memory,
4549
session) + goal checks (checks.ts) — the TreeCompare analogue
46-
src/levels/ 8-series / 31-level catalog + per-level goals, par, solutions
50+
src/levels/ 9-series / 35-level catalog + per-level goals, par, solutions
4751
src/ui/ app shell, memory canvas, plot board, REPL, dialog, script editor
4852
src/style.css design tokens + layout
4953
index.html app shell entry

‎README.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Type Python-subset statements. Meta-commands:
4141
| Command | Effect |
4242
|---------|--------|
4343
| `help` | subset + meta overview |
44-
| `levels` | list the 31 levels / 8 series |
44+
| `levels` | list the 35 levels / 9 series |
4545
| `level <id>` | load a level (e.g. `level first-name`) |
4646
| `lesson` | open the current level's lesson text |
4747
| `goal` / `guide` | focus the right-hand guide panel |
@@ -63,12 +63,13 @@ A deliberately small, pedagogically sharp subset — not CPython:
6363
- **Methods:** `.append` `.insert` `.extend` `.pop` `.remove` `.copy` `.get` `.update` `.keys` `.clear`
6464
- **Functions:** `def` / call / `return`, local frames, nested calls
6565
- **Builtins:** `print` `len` `type` `id` `str` `int` `bool` `list` `dict` `set`
66-
- **Modules:** `import copy as cp` — `cp.copy` (shallow) and `cp.deepcopy`
66+
- **Modules:** `import copy as cp` — `cp.copy` (shallow) and `cp.deepcopy`; `import collections as c` — `c.defaultdict`; `import functools as f` — `f.reduce`
6767
- **Iterators:** `iter(x)` and `next(it)` — a stateful iterator object you advance by hand
68+
- **Functional:** `map(fn, it)` / `filter(pred, it)` — lazy iterator objects; `f.reduce(fn, it)` — an eager fold
6869
- **Plotting:** `scatter(xs, ys, "title")` `line(xs, ys, "title")`
6970
- **Operators:** arithmetic, comparisons, `is`, `==`
7071

71-
Not in v0: classes, real module imports (only the simulated `copy`), control flow (`if`/`for`/`while`), exceptions (beyond clean parse/runtime errors), comprehensions, I/O, async, `range`/`sorted`/`min`/`max`/`abs`, full CPython semantics.
72+
Not in v0: classes, real module imports (only the simulated `copy`, `collections`, `functools`), control flow (`if`/`for`/`while`), exceptions (beyond clean parse/runtime errors), comprehensions, I/O, async, `range`/`sorted`/`min`/`max`, full CPython semantics.
7273

7374
A planned curriculum extends this with numpy, pandas, re, datetime and more — all drawn on the same memory canvas. See `docs/ENGINE-EXTENSION.md` and `docs/adr/002-library-modules.md`.
7475

@@ -77,7 +78,7 @@ A planned curriculum extends this with numpy, pandas, re, datetime and more —
7778
```
7879
src/engine/ simulated runtime (tokenizer, parser, evaluator, memory, session)
7980
+ goal checks (checks.ts) — the "TreeCompare" analogue
80-
src/levels/ 8-series / 31-level catalog + per-level goals, par, solutions
81+
src/levels/ 9-series / 35-level catalog + per-level goals, par, solutions
8182
src/ui/ app shell, memory canvas, plot board, REPL, dialog, script editor
8283
src/style.css design tokens + layout
8384
tests/ vitest unit + level-solution tests
@@ -89,7 +90,7 @@ The engine is intentionally a **teaching subset**, not CPython. Every state tran
8990

9091
## Levels
9192

92-
Eight series — Names & Bindings, Aliasing & Copy, Containers in Memory, **Copy Semantics** (shallow vs deep), **Iterators & Iterables**, Mutation & Methods, Functions & Frames, Plotting & Capstone. Each of the 31 levels has a brief, optional hint, a goal (predicate or target snapshot), a statement-par for golf, and a worked solution.
93+
Nine series — Names & Bindings, Aliasing & Copy, Containers in Memory, **Copy Semantics** (shallow vs deep), **Iterators & Iterables**, **Defaults & Functional** (defaultdict, map, filter), Mutation & Methods, Functions & Frames, Plotting & Capstone. Each of the 35 levels has a brief, optional hint, a goal (predicate or target snapshot), a statement-par for golf, and a worked solution.
9394

9495
## Tech
9596

‎src/engine/checks.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,14 @@ export const preds = {
225225
};
226226
},
227227

228+
/** `name` is a defaultdict (not a plain dict). */
229+
isDefaultDict(name: string) {
230+
return (snapshot: Snapshot): boolean => {
231+
const view = slotView(name, snapshot);
232+
return view?.type === 'defaultdict';
233+
};
234+
},
235+
228236
/**
229237
* A plot has been drawn (optionally of a specific kind).
230238
*/

0 commit comments

Comments
 (0)