Repository navigation
Conversation
…lection Add the surface forms the relation redesign needs, as unresolved AST nodes: - IndexNode for x[rel] and x[rel.col] — an atom, a bare name indexed. - ColumnRefNode for a dotted column selection in a kwarg value, over=rel.k, by=rel.v, along=rel.d, and the bracketed list rel.[a, b]. Both are unresolved: resolution rewrites them in a later commit. Until then no declaration reaches them, so the loader still refuses the new syntax downstream. The nodes join UNRESOLVED in the golden node-census test, beside NameNode. Verified: pixi run pytest (1285 passed), pyrefly clean, ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…x[rel] Replace at(), into=, partition by=, and the "walk" concept with a dot syntax. Every relation operator joins the operand to the relation on shared dims, then reduces; three forms differ in what they drop: - sum(x, over=rel.k) sums key column k away; the value and other keys ride in. - sum(x, by=rel.v) groups onto value column v; the whole key is summed away. - x[rel] indexes: reads the value at the key, replacing at(x, by=rel). - shift/sum_back/position take along=rel.k (partition by=rel folded in); within= stays for group selection; position(rel.k) has no bare form. The dot picks columns; a bare rel is all of them; a list mirrors sum(by=[a, b]). The index operand is a name or a parenthesized expression, and x[a, b] indexes through several relations at once. Internals: the parser reads ColumnRefNode and IndexNode; resolution rewrites an index to the internal `index` operator (at renamed), and both sum forms and the index build one Join whose dim rule is uniformly (inner - consumed) | landed. The dead is_function_read guard in the key-join is dropped — no sum can be degenerate now that indexing is its own operator. Migrated: the operator example set, the golden completeness model, the PyPSA examples, and every test fixture asserting the retired spelling; the operator-math table, notation page and gallery pages regenerate from them. Verified: pixi run pytest (1280 passed), pyrefly clean, ruff clean, compile-tex (31 documents), docs generators current. The Walk class and internal "walk" identifiers are not yet renamed to join/reduce vocabulary — a follow-up churn commit with no behaviour change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The language redesign dropped the "walk" metaphor: a relation operator joins the operand to the relation, then reduces. Rename the internal structure to match — program.Walk -> program.Join, the walks fields on GroupSum/At/RelationNode/ Translate/Window -> joins, and the "walk" wording in the docstrings and the one schema description that named the retired over=/into= spelling. No behaviour change. The AST-traversal walk() and its Walk visitor in typesetting are a different concept and stay. The schema regenerates with the corrected description only. Verified: pixi run pytest (1280 passed), pyrefly clean, ruff clean, schema current. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Documentation build overview
16 files changed ·
|
|
@coroa I have a few opinions:
main: sum(p, by=slot_of, over=generator, into=bus) <= cap
509: sum(p, over=slot_of.generator) <= cap
# REFUSED: the expression carries dims ['technology'] that are not in its dims: ['bus', 'period']
# over= lands on every value column, so technology comes along
#509: sum(p, by=slot_of.bus) <= capAssumes: dimensions:
generator: { dtype: str }
period: { dtype: int }
bus: { dtype: str }
technology: { dtype: str }
relations:
slot_of: { key: [generator, period], value: [bus, technology] }
variables:
p: { dims: [generator, period], bounds: { lower: 0 } }As a side note for now: I found a few bugs. Can you confirm they are bugs? Or am i misunderstanding a design choice as a bug?
|
|
I really don't like issues, too much scattered information. Re 1: I'm fine with separating at/indexing out. It does not change much. I do like indexing better. Re 2: I guess the implementation is buggy then. dimensions:
generator: { dtype: str }
period: { dtype: int }
bus: { dtype: str }
technology: { dtype: str }
relations:
slot_of: { key: [generator, period], value: [bus, technology] }
parameters:
cap: { dims: [period, bus] } # was that your assumption, as well?
variables:
p: { dims: [generator, period], bounds: { lower: 0 } }is what i imagine you should be saying for this case, and then my assumption that by can only name value columns was wrong. and it should be able to include key columns. |
…join Replace the one generic RelationNode and its Join structure with three per-operation resolved nodes — SumRelationNode, IndexRelationNode and PartitionRelationNode. Each holds the columns the author named and derives its own frame, so a consumer reads a relation in the operation's own terms rather than decoding a shared consumed/produced/joined triple. over= is desugared to by= at resolution, and the frame-dependent checks stay one node-level call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…elation list takes dotted members Four bugs in the relation dot syntax, each a load that should refuse or a crash that should be a message: - An index reading two value columns over one dimension — `cap[ends.[bus0, bus1]]`, bare `cap[ends]`, or two relations each reading it — loaded and read one column, deduping the collision away. It now refuses, as the sum side already did. Two relations keyed over one dimension still loads: they join at a shared key, which is what `tech_cap[gen_bus, gen_tech]` does. - A dotted member in an index or `by=` list dropped its dot. A relation list now takes dotted members uniformly, so `by=[a.x, b.y]` and `x[a.x, b.y]` read the named columns, and `by=rel.[x, y]` is the same grouping written from one relation. - A macro formal standing where a relation does — bare in `x[rel]`, or before a dot in `by=rel.v` — was never substituted; expansion left the formal name in place. It now substitutes, and a formal bound to an expression where a relation belongs is refused rather than crashing. - `sum(x, over=rel.k)` naming an undeclared relation crashed with a KeyError. The `over=`/partition path now guards the name like the `by=` path, so it is a "does not name a relation" refusal. The grammar reads a bracketed relation list as relation references, so `NameListNode` carries `NameNode | ColumnRefNode` members; `within=` reads its members bare through `.names` and refuses a dotted one. pixi run pytest — 1293 passed. pyrefly, ruff, docs-build --strict, compile-tex (31) all clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Closed in favor of #540 Will revisit for syntax discussions |
Note
The following content was generated by AI.
Implements the dot syntax PR #506 documents. Stacked on that docs PR. Every relation operator joins the operand on shared dims, then reduces; the retired at()/into=/partition-by=/"walk" are gone.
The design, the diff, and how it was verified
The surface
sum(x, over=rel.k)sums key columnkaway; the value and other keys ride in.sum(x, by=rel.v)groups onto value columnv; the whole key is summed away.x[rel]indexes: reads the value at the key, replacingat(x, by=rel). The operand is a name or(expr);x[a, b]indexes through several relations at once.shift/sum_back/positiontakealong=rel.k/position(rel.k);within=stays;positionhas no bare form.relis all of them.Three commits
feat(parser)— the grammar readsx[rel]andrel.colas unresolved nodes.feat(language)— resolution rewrites the index to an internalindexoperator (atrenamed); both sum forms and the index build oneJoinwhose dim rule is uniformly(inner - consumed) | landed. The deadis_function_readguard on the key-join is dropped — no sum can be degenerate now that indexing is its own operator. Examples, the golden model, PyPSA models, and every fixture asserting the retired spelling migrated; the generated tables/pages regenerate from them.chore— the internalWalkstructure renamed toJoin(you asked for the "walk" vocabulary gone); no behaviour change. The AST-traversalwalk()is a different concept and stays.Verification
pixi run pytest— 1280 passed.pixi run pyrefly check src/— 0 errors.pixi run ruff check— clean.pixi run compile-tex— 31 documents.pixi run docs-build—--strict, clean.Deliberately not done
Atinternally (notIndex) — it is not "walk" vocabulary, so renaming it was out of scope; say the word and it is a one-commit follow-up.sum(by=[a, b])); a dotted member in a list is not wired.Departure from a Part 2 default: the branch lives in the primary checkout, not the
../wt/worktree AGENTS.md prescribes, because the sandbox permits writes only inside the repo directory.🤖 Generated with Claude Code