• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / py-slang / 30364728049

28 Jul 2026 01:42PM UTC coverage: 86.159% (+0.02%) from 86.135%
30364728049

Pull #365

github

web-flow
Merge f40245f48 into f2ea265c1
Pull Request #365: Add draw_data builtin (Data Visualizer support)

4428 of 5532 branches covered (80.04%)

Branch coverage included in aggregate %.

27 of 29 new or added lines in 4 files covered. (93.1%)

9590 of 10738 relevant lines covered (89.31%)

179915.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/conductor/dataVisualizer/toDataVisualizerNode.ts
1
import type { RefIdAllocator } from "@sourceacademy/runner-data-visualizer";
2
import type { SerializedDataVisualizerNode } from "@sourceacademy/common-data-visualizer";
3

4
import { Value } from "../../engines/cse/stash";
5
import { toPythonString } from "../../stdlib/utils";
1✔
6

7
/**
8
 * Converts one py-slang runtime {@link Value} into a {@link SerializedDataVisualizerNode}. Purely
9
 * mechanical โ€” dispatches on `Value.type` and recurses into list elements. No cycle-detection or
10
 * classification happens here; that's entirely the host's job (see `BaseDataVisualizerRunnerPlugin`'s
11
 * doc comment in `@sourceacademy/runner-data-visualizer`).
12
 *
13
 * A SICP ยง2 pair *is* a length-2 `ListValue` in py-slang โ€” there's no separate pair type โ€” so every
14
 * list, regardless of length, becomes the wire format's N-ary `"array"` node; the host distinguishes
15
 * "pair" from "list" by `children.length`, not by tag.
16
 */
17
export function toDataVisualizerNode(
1✔
18
  value: Value,
19
  refs: RefIdAllocator,
20
): SerializedDataVisualizerNode {
21
  switch (value.type) {
22!
22
    case "none":
23
      return { type: "empty" };
1✔
24
    case "list": {
25
      const { refId, alreadySeen } = refs.get(value);
7✔
26
      if (alreadySeen) {
7✔
27
        return { type: "ref", refId };
2✔
28
      }
29
      return {
5✔
30
        type: "array",
31
        refId,
32
        children: value.value.map(element => toDataVisualizerNode(element, refs)),
11✔
33
      };
34
    }
35
    case "closure":
36
    case "function":
37
    case "multi_lambda":
38
    case "builtin": {
39
      const { refId, alreadySeen } = refs.get(value);
2✔
40
      if (alreadySeen) {
2✔
41
        return { type: "ref", refId };
1✔
42
      }
43
      return { type: "function", refId, displayValue: toPythonString(value) };
1✔
44
    }
45
    case "number":
46
    case "bool":
47
    case "complex":
48
    case "string":
49
    case "error":
50
    case "bigint":
51
    case "opaque":
52
      return { type: "leaf", displayValue: toPythonString(value), label: value.type };
12✔
53
    default:
NEW
54
      value satisfies never;
×
NEW
55
      return { type: "leaf", displayValue: String(value), label: "unknown" };
×
56
  }
57
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc