Libraryless. Click here for Pure Java version (3315L/20K).
1 | sclass MetaTransformer { |
2 | sinterface StructureHandler { |
3 | default O transform(O o, IF1 recurse) { null; } |
4 | void visit(O o, IVF1 recurse); |
5 | } |
6 | |
7 | L<StructureHandler> structureHandlers; |
8 | //bool keepUnknown; // assume true for now |
9 | Set seen; // initialize to identityHashSet() if you want to check for cycles |
10 | |
11 | *() {} |
12 | *(StructureHandler... handlers) { structureHandlers = asList(handlers); } |
13 | |
14 | void addStructureHandler aka add(StructureHandler sh) { |
15 | structureHandlers.add(sh); |
16 | } |
17 | |
18 | // if f returns null, go through structure |
19 | // if f returns an object, do not recurse into it |
20 | // TODO: honor seen |
21 | O transform(IF1 f, O o) { |
22 | ping(); |
23 | O x = f.get(o); |
24 | ifdef MetaTransformer_debug |
25 | printVars_str("MetaTransformer.transform", +f, +o, +x); |
26 | endifdef |
27 | if (x != null) ret x; |
28 | |
29 | IF1 recurse = liftFunction(f); |
30 | fOr (StructureHandler h : structureHandlers) { |
31 | ping(); |
32 | ifdef MetaTransformer_debug |
33 | print("Calling structure handler " + h + " on " + className(o)); |
34 | endifdef |
35 | try object h.transform(o, recurse); |
36 | } |
37 | |
38 | //ret keepUnknown ? o : null; |
39 | ret o; |
40 | } |
41 | |
42 | // transform without result |
43 | void visit(IVF1 f, O o) { |
44 | ping(); |
45 | if (o == null) ret; |
46 | if (seen != null && !seen.add(o)) ret; |
47 | f.get(o); |
48 | |
49 | fOr (StructureHandler h : structureHandlers) { |
50 | ping(); |
51 | ifdef MetaTransformer_debug |
52 | print("Calling structure handler " + h + " on " + className(o)); |
53 | endifdef |
54 | IVF1 recurse = x -> { |
55 | markPointer(o, x); |
56 | visit(f, x); |
57 | }; |
58 | h.visit(o, recurse); |
59 | } |
60 | } |
61 | |
62 | void visit_vstack(IVF1 f, O o) { |
63 | vstackCompute(new visit_vstackComputable(f, o)); |
64 | } |
65 | |
66 | record visit_vstackComputable(IVF1 f, O o) extends VStackComputableWithStep { |
67 | void step(VStack stack) { |
68 | if (step == 0) { |
69 | ping(); |
70 | if (o == null) ret with stack.ret(); |
71 | step++; |
72 | } |
73 | |
74 | if (step == 1) { |
75 | if (seen != null && !seen.add(o)) ret with stack.ret(); |
76 | ++step; |
77 | } |
78 | |
79 | if (step == 2) { |
80 | f.get(o); |
81 | ++step; |
82 | } |
83 | |
84 | stack.replace(new ForEach_vstack<>(structureHandlers, h -> { |
85 | ifdef MetaTransformer_debug |
86 | print("Calling structure handler " + h + " on " + className(o)); |
87 | endifdef |
88 | IVF1 recurse = x -> { |
89 | markPointer(o, x); |
90 | stack.call(new visit_vstackComputable(f, x)); |
91 | }; |
92 | h.visit(o, recurse); |
93 | })); |
94 | } |
95 | } |
96 | |
97 | // lift transformer function to handle structures |
98 | IF1 liftFunction(IF1 f) { |
99 | ret o -> transform(f, o); |
100 | } |
101 | |
102 | // check if any element satisfies a predicate. |
103 | // Note: might even be faster without the cancel point logic |
104 | bool any(IPred<O> pred, O o) { |
105 | new Flag flag; |
106 | withCancelPoint(cp -> |
107 | visit(x -> { if (pred.get(x)) { flag.raise(); cancelTo(cp); } }, o) |
108 | ); |
109 | ret flag.isUp(); |
110 | } |
111 | |
112 | void addVisitor(IVF1 visitor) { |
113 | if (visitor == null) ret; |
114 | addStructureHandler(new StructureHandler { |
115 | public void visit(O o, IVF1 recurse) { |
116 | visitor.get(o); |
117 | } |
118 | }); |
119 | } |
120 | |
121 | void avoidCycles { |
122 | seen = identityHashSet(); |
123 | } |
124 | |
125 | swappable void markPointer(O a, O b) {} |
126 | } |
Began life as a copy of #1027751
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027774 |
Snippet name: | MetaTransformer |
Eternal ID of this version: | #1027774/39 |
Text MD5: | 7bc1ba1ee2245f85963e160efe0a1c20 |
Transpilation MD5: | a936ed4dd735eb13a972444ffbdde981 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-06-29 06:50:46 |
Source code size: | 3344 bytes / 126 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 341 / 839 |
Version history: | 38 change(s) |
Referenced in: | [show references] |