Qwiratry — Qwiratry-TaOP-Parity

Qwiratry TaOP Parity

Plan/Spec for TOP parity work listed in Post-SQL-TaOP-Improvements.md §F.1: behaviour the old Raku-TOP code already had (or documented as first-class) that Qwiratry still lacks — not greenfield TOP concepts (those are Post-SQL §F.5).

Status: Implemented (checklist complete).Parent backlog: Post-SQL §F.1 (items 1.1–1.2). Former Relation/TupleSet ideas live as Maybe under Post-SQL §F.5. Body-cell / per-cell formatting (was F.1.3) moved to Post-SQL §B.6 (order: §F.7.1). Related archives: Qwiratry-TaOP-Textish.md, Qwiratry-TaOP-Basics.md, Qwiratry-TaOP-Plan.md.

Question IDs are stable: Q1, Q2, … stay the same when an item moves from §Open Questions into §Decisions (record the answer under the same Qn). Q4 (body / per-cell formatting) left this document for Post-SQL §B.6; the ID is retired here so later parity questions do not reuse it.

1. Goals

  1. Restore a public multi-phase Format render API matching TOP’s prepare-table / output-header / output-row / output-footer drive, without giving up one-shot render-walkable as the default operator path (phases live on a common Textish role in core — Q1).

  2. Improve HalfHuman emit-side round-trip (space → _ on by default, option to disable — Q3); do not paper over Parse option misuse.

2. Non-goals

  • Greenfield TOP concepts not in old TOP code: View, Section, Lot, DataDictionary, atom, etc. (Post-SQL §F.5).

  • Query output as a Relation without being a Table — stick with emitting Tables like old TOP grep (Q6–Q8; optional Maybe later as Post-SQL §F.5 5.6).

  • TupleSet — never implemented in old TOP; not part of this parity cut (Q9; optional Maybe later as Post-SQL §F.5 5.7).

  • Richer Associative cell stringify beyond current .raku (Post-SQL §F.5 / Textish §6.5 follow-up — not §F.1).

  • Body-cell / per-cell formatting beyond today’s header-only :header-alignment (Post-SQL §B.6 / §F.7.1; was F.1.3).

  • Full Format ParsePull / RenderPull / Supply push (Post-SQL §F.7; Streaming-v2).

  • SQL DatabaseStorage sibling and cursor mapping (Post-SQL §F.3).

  • Aggregate catalogue work (Post-SQL §F.8).

3. Public multi-phase formatter API

(Post-SQL §F.1 item 1.1; also §B.1 / §E.3.2)

3.1. TOP behaviour

TOP formatters are stateful multi-phase. Database::Storage.format loads a formatter and drives:

  1. prepare-table

  2. output-header

  3. output-row (per row)

  4. output-footer

  5. return $formatter.output

HalfHuman and WithBorders in Qwiratry already implement the same phases internally inside one-shot render-walkable.

3.2. Proposed Qwiratry shape

TOP has no shared formatter base/role — HalfHuman and WithBorders each implement the same duck-typed protocol. Qwiratry already decided a shared Textish role in core (Q1); put the public phase methods on Qwiratry::Format::Textish::RenderWalkable (helpers already live there).

Match TOP’s surface:

PieceTOPQwiratry
Phasesprepare-table(), output-header(), output-row($row), output-footersame names / arity
Accumulatorpublic $.outputpublic $.output
Optionsnew(table => …, show-headers => …, …) then phases take no option hashbind options when constructing / preparing the formatter (or at start of render-walkable); phase methods stay option-free like TOP
DriverStorage.format loops rowsthin render-walkable runs the same sequence and returns $.output
Width scanprepare-table walks all rows (needs full table for column widths)same — do not claim true O(1)-memory streaming for width-based Textish

Operators and Table.format continue to call render-walkable by default. Callers who want the TOP drive protocol can construct a Textish Render and call the phase methods themselves.

3.3. Tradeoffs

  • Pro: restores TOP’s public drive protocol; one protocol across Textish Formats; callers can drive phases manually (same as TOP Storage).

  • Con: mutable formatter state, call-order contracts; width-based Textish still scans all rows in prepare-table (same as TOP). Pull/RenderPull remains available long-term (Streaming-v2 / Post-SQL §F.7) but is out of scope for this Textish MVP — Q2.

Decided: Q1, Q2.

4. Stronger HalfHuman round-trip

(Post-SQL §F.1 item 1.2; also §B.5; Textish §5.3 / Non-goals)

4.1. Emit-side focus

HalfHuman Parse is whitespace-split by design. We do not try to make Parse recover from every caller mistake (e.g. Render with :show-headers then Parse without :headers — that is a user error). Round-trip work for this cut is mostly on the emitting side: make Render produce text that Parse can read back when the caller uses matching options.

4.2. Spaces in cells

Dialect rule (Textish / TOP docs): cells should not contain spaces; prefer _. Old TOP code does not implement replacement — HalfHuman only suggests underlines in pod; emit still passes cell strings through unchanged. WithBorders has no such dialect rule (borders separate columns).

Decision (Q3): Qwiratry HalfHuman Render does replace spaces in cell text with underscores; on by default, with an option to turn it off (option name: :spaces-to-underscores, Bool, default True). WithBorders: do not apply — not in TOP, and not needed for that dialect.

4.3. Scope for this cut

  • Emit-side hardening (space → _ per Q3) on HalfHuman only.

  • Tighten Render→Parse tests for simple tables when options match (:show-headers ↔ :headers).

  • Do not promise perfect round-trip for arbitrary Unicode / quoting / multi-line cells; HalfHuman stays a simple whitespace dialect.

  • Do not change Qwiratry’s existing undefined-cell '-' vs TOP HalfHuman '' in this cut (pre-existing dialect difference, not part of §F.1).

Decided: Q3. Golden regressions: Q5.

5. Implementation checklist

  • 1. Implement Textish multi-phase role + thin render-walkable driver; port HalfHuman / WithBorders (Q1, Q2 — Walkable MVP, no Textish RenderPull in this cut).

  • 2. HalfHuman Render space→_ on by default + option to disable (Q3); emit-side round-trip tests when Parse options match Render; on any golden string changes, notify Tim for a call (Q5).

  • 3. Docs: Extending/Adding-Formats, TaOP pod, Changelog; cross-link Post-SQL §F.1 items 1.1–1.2 as done.

6. Open Questions

(None remaining for this cut.)

7. Decisions

  • Q1. Multi-phase methods live on a common Textish role in core (HalfHuman / WithBorders compose it) — not Format base for all Formats, and not HalfHuman-only ad hoc methods without the shared role. Implement on existing Qwiratry::Format::Textish::RenderWalkable. Phase names/arity and public $.output match TOP (§3.2).

  • Q2. Match old TOP for now: public multi-phase under Walkable (render-walkable as thin driver). Do not add Textish RenderPull in this cut; Streaming Pull/Push stay long-term (Post-SQL / Streaming-v2).

  • Q3. Space → _ on HalfHuman Render only: option :spaces-to-underscores, on by default. TOP docs suggested this but did not implement it; WithBorders does not get this transform.

  • Q4. Retired from this document — body-cell / per-cell formatting is Post-SQL §B.6 (order §F.7.1; not old TOP parity).

  • Q5. Do not silently require bit-identical goldens as a hard rule. When HalfHuman/WithBorders (or related) golden strings change, notify Tim, who will decide whether each change is correct.

  • Q6. Stick with emitting Tables for query / relational results (as old TOP grep does); no separate result-Relation concrete type in this cut.

  • Q7. N/A for this cut — result Tables keep the usual Table/Storage face.

  • Q8. N/A for this cut — no distinct result-Relation discovery path.

  • Q9. TupleSet is not part of this parity document (never implemented in old TOP).

8. References

Qwiratry v0.11.0

Declarative query and data-walking architecture for Raku, with transformers, molds, walkers, I/O pipelines, and aggregate functions.

Authors

  • Tim Nelson

License

Dependencies

SlangifyImplementation::Loader:ver<0.0.9+>Glob::Grammar

Test Dependencies

Provides

  • Qwiratry
  • Qwiratry::Aggregate::AggSub
  • Qwiratry::Aggregate::AggSub::Compiler
  • Qwiratry::Aggregate::Avg
  • Qwiratry::Aggregate::BodyRewrite
  • Qwiratry::Aggregate::Count
  • Qwiratry::Aggregate::DenseRank
  • Qwiratry::Aggregate::Driver
  • Qwiratry::Aggregate::Rank
  • Qwiratry::Aggregate::Sum
  • Qwiratry::AggregateFunction
  • Qwiratry::Context
  • Qwiratry::DatabaseStorage
  • Qwiratry::DatabaseStorage::CSVdemo
  • Qwiratry::DatabaseStorage::Location
  • Qwiratry::DatabaseStorage::Location::Tree
  • Qwiratry::DatabaseStorage::Memory
  • Qwiratry::FieldMode
  • Qwiratry::Format
  • Qwiratry::Format::Base
  • Qwiratry::Format::CSVdemo
  • Qwiratry::Format::HalfHuman
  • Qwiratry::Format::JSONdemo
  • Qwiratry::Format::NDJSONdemo
  • Qwiratry::Format::Textish::RenderWalkable
  • Qwiratry::Implementation::Loader
  • Qwiratry::Location
  • Qwiratry::Location::Base
  • Qwiratry::Location::File
  • Qwiratry::Mold
  • Qwiratry::Mold::Compiler
  • Qwiratry::Mold::Registry
  • Qwiratry::Mold::Slang
  • Qwiratry::MovingFrameAggregateFunction
  • Qwiratry::Operator::Capability
  • Qwiratry::Operator::IO
  • Qwiratry::Operator::MapReduce
  • Qwiratry::Operator::Navigation
  • Qwiratry::Operator::Set
  • Qwiratry::Query::Evaluator::Eager
  • Qwiratry::Query::Evaluator::Filter
  • Qwiratry::Query::Evaluator::Join
  • Qwiratry::Query::Evaluator::Lazy
  • Qwiratry::Query::Evaluator::MapReduce
  • Qwiratry::Query::Evaluator::Navigation
  • Qwiratry::Query::Evaluator::Relational
  • Qwiratry::Query::Evaluator::Row
  • Qwiratry::Query::Evaluator::Set
  • Qwiratry::Query::Evaluator::Union
  • Qwiratry::Query::Extract
  • Qwiratry::Query::NamedJoins
  • Qwiratry::Query::RelationCommon
  • Qwiratry::Query::Runtime
  • Qwiratry::Query::Selector
  • Qwiratry::Query::Slang
  • Qwiratry::Query::Slang::Ops
  • Qwiratry::Query::Slang::Topic
  • Qwiratry::Query::Specificity
  • Qwiratry::Query::Topic
  • Qwiratry::QueryCursor
  • Qwiratry::QueryIterator
  • Qwiratry::QueryMatch
  • Qwiratry::Setup
  • Qwiratry::Singleton
  • Qwiratry::Strategy
  • Qwiratry::Strategy::ControlSignal
  • Qwiratry::Strategy::FinishResult
  • Qwiratry::Strategy::RewriteSpec
  • Qwiratry::Strategy::Traversal
  • Qwiratry::Suggest
  • Qwiratry::TaOP
  • Qwiratry::Table
  • Qwiratry::Table::Schema
  • Qwiratry::Transformer
  • Qwiratry::Transformer::Copy
  • Qwiratry::Transformer::TreeRewrite
  • Qwiratry::Tree::Navigator
  • Qwiratry::Tree::Navigator::Base
  • Qwiratry::Tree::Navigator::Filesystem
  • Qwiratry::Tree::Navigator::Match
  • Qwiratry::Tree::Navigator::RakuAST
  • Qwiratry::Tree::Replace
  • Qwiratry::Walker
  • Qwiratry::Walker::Capabilities
  • Qwiratry::Walker::Factory
  • Qwiratry::Walker::Implementation::Table
  • Qwiratry::Walker::Implementation::Tree
  • Qwiratry::Walker::Implementation::TreeWithPath
  • Qwiratry::Walker::Master
  • Qwiratry::Walker::Providing
  • TypedIterator
  • WalkCursor
  • X::Qwiratry

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.