Repository navigation
Lists as trees (listtree, P34 B) - #51
Merged
Merged
Conversation
A list whose first element is a string is drawn as a tree below its text: in the visualizer's variables (switch in the options menu), in the full-value dialog and, on request («Baum»), for a REPL value. The runtime sends the trees (_glpython_tree_of); TreeView draws them with the package's own layout. Behind capability listTree / embed feature listtree, off by default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… narrow The node positions now come from d3-flextree (van der Ploeg 2014, tidy trees for nodes of different widths), which moves subtrees together where their rows allow; rendering stays ours. A tree wider than its place scrolls inside TreeView: it starts with the root in the middle, shows ‹ › where more is hidden, and takes the focus for the arrow keys, Home and End. The console's «Baum» is no longer underlined while open. Browser checks for the layout of parser-like and uneven trees and for the narrow view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
treeLayout.ts implements van der Ploeg (2014) itself, with d3-flextree's changes (centres, a subtree first moved next to its sibling), so the positions stay the same. d3-flextree is a devDependency for test:layout only, which compares the positions on the course's trees and 500 random ones and checks that nothing of d3 is in the builds or the notices. The scroll hints are a fade with a plain arrow over the tree's whole height, without a border or a node colour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First part of P34:
TreeView+ B (lists as trees), as decided. «Baum» (A) and the IDE link (C) follow later.What
Rule (generic): a non-empty list whose first element is a string is a tree. That string is the node's label, and the other elements are its children: a subtree where they meet the rule too, otherwise a leaf. Labels appear without quotes and string leaves with quotes, so
['+', 'a', 'b']reads as an operator with two text values. The list's text always stays as it is, with the tree below it.Where:
aria-pressedsays it's open). It shows the tree below the value in the transcript and hides it again. Forparse(…)in the REPL, this is your point 6.6.Off by default:
listTree, embed featurelisttree. Likecoverage, it isn't part of «everything», so published courses don't change.Limits:
Text alternative: each tree is an image for screen readers, described by the list's text.
TreeView(shared with A later):src/treeLayout.ts(about 200 lines), follows the Java code in the paper's appendix and is cited there.d3-flextreeis a devDependency only: the oracle intest:layout. Nothing of it or ofd3-hierarchyis indist/,dist-embed/orTHIRD_PARTY_NOTICES.md.ch, SVG edges,--glp-*tokens only. Positions are in characters of the code font and in em, so a tree scales with the font around it, also withsize=large.TreeView.--glp-accentoutline.Layout measurement: width in characters
breitparse("2 + 3 * 4")=['+', 2, ['*', 3, 4]]parse("(2 + 3) * 4")=['*', ['+', 2, 3], 4]parse("-(1 + 2)")=['-', ['+', 1, 2]]parse("x + 1")=['+', ['var', 'x'], 1]parse("f(1, 2)")=['f', 1, 2]['+', ['*', 2, ['-', 7, 3]], ['/', ['+', 1, 2], 3]]['+', ['+', ['+', 1, 2], 3], ['f', ['var', 'x']]]The same node widths and gap (2 characters) apply in both columns. flextree is narrower on half of the trees, by 2.5 to 5 characters (13–19 %): those with a leaf beside a deeper subtree. It never comes out wider. The
parseoutputs are the course'sparser.py.The table's flextree column is now our port's, and
test:layoutchecks that it equals flextree's.Runtime:
session.pyhas_glpython_tree_of({label, children}/{leaf}). The REPL result carriestree.trees: {text: index}, resulttrees: [...], each tree stored once.Screenshots at 1000 px and 420 px (console and dialog, in the LiaScript player with glpython-liascript#30) are in my report in the session.
Checks
scripts/check-runtime-trees.py, added totest:runtime:['Anna', 'Ben'],['f'], leaves of every kind, shortened texts);tree;trees, stored once, and no new full values.scripts/check-console-browser.mjs, withfeatures=listtree:[1, 2].scripts/check-tree-layout.mjs(npm run test:layout, in CI):d3-flextree's, within 1e-6: on the eight trees of the table, with their measured widths, and on 500 random trees (0–4 children, depth ≤ 5, labels 1–12 characters, fixed seed);d3-*module in the source maps ofdist/anddist-embed/, and no flextree, d3-hierarchy or WTFPL inTHIRD_PARTY_NOTICES.md. I checked that this fails when flextree is bundled.breitincluded, each opened with «Baum» in the REPL and measured in the DOM:breit:lint,test:runtime,test:protocol,test:hints,test:layoutandtest:consolepass.How it goes live / testing in a course
listtree(off by default, likecoverage). Merge it after this PR. A course that uses it needs a patch version bump.Manual tests (desktop, and iPad with an external keyboard)
In a block with
features=run,repl,visualize,listtree:baum = parse("2 + 3 * 4")with yourparse. The variables show the text and below it the tree+→2,*→3,4.t = parse("-(1 + 2)"),u = parse("f(1, 2)"),v = parse("x + 1"),w = parse('"a" + "b"'):v:varwith the leaf'x';w:+with'a'and'b'.parse("(1 + 2) * (3 - 4) / f(5, 6, 7)")): «Baum zeigen» opens the dialog. Esc closes it.auswerten(parse("2 + 3 * 4"))with your recursive evaluator: each box'sbaumparameter shows its subtree. On the iPad, check the space with nested boxes.parse("2 + 3 * 4")→ «Baum» shows the tree and hides it again.[1, 2]has no «Baum».listtree: nothing of this appears.breit = ["f", ["g", "erstes", "zweites"], ["h", "drittes", "viertes"], ["k", "fünftes"]], thenbreit→ «Baum».fin the middle. Both edges fade out, each with a grey ‹ or ›, and the hints read as part of the frame, not as nodes.breittoo: «Baum zeigen» opens the dialog, also centred, with hints.Follow-ups (not fixed)
parseoutput.🤖 Generated with Claude Code