|
29 | 29 | import java.util.List; |
30 | 30 |
|
31 | 31 | /** |
32 | | - * The {@link CodeFrame} represents a frame (i.e. scope) of code, appending {@link Code} to the {@code 'codeList'} |
| 32 | + * The {@link CodeFrame} represents a frame (i.e. scope) of generated code by appending {@link Code} to the {@link #codeList} |
33 | 33 | * as {@link Token}s are rendered, and adding names to the {@link NameSet}s with {@link Template#addStructuralName}/ |
34 | | - * {@link Template#addDataName}. {@link Hook}s can be added to a frame, which allows code to be inserted at that |
35 | | - * location later. When a {@link Hook} is {@link Hook#anchor}ed, it separates the Template into an outer and inner |
36 | | - * {@link CodeFrame}, ensuring that names that are added inside the inner frame are only available inside that frame. |
| 34 | + * {@link Template#addDataName}. {@link Hook}s can be added to a code frame, which allows code to be inserted at that |
| 35 | + * location later. |
37 | 36 | * |
38 | 37 | * <p> |
39 | | - * On the other hand, each {@link TemplateFrame} represents the frame (or scope) of exactly one use of a |
40 | | - * Template. |
| 38 | + * The {@link CodeFrame} thus implements the {@link Name} non-transparency aspect of {@link ScopeToken}. |
41 | 39 | * |
42 | 40 | * <p> |
43 | | - * For simple Template nesting, the {@link CodeFrame}s and {@link TemplateFrame}s overlap exactly. |
44 | | - * However, when using {@link Hook#insert}, we simply nest {@link TemplateFrame}s, going further "in", |
45 | | - * but we jump to an outer {@link CodeFrame}, ensuring that we insert {@link Code} at the outer frame, |
46 | | - * and operating on the names of the outer frame. Once the {@link Hook#insert}ion is complete, we jump |
47 | | - * back to the caller {@link TemplateFrame} and {@link CodeFrame}. |
| 41 | + * The {@link CodeFrame}s are nested relative to the order of the final rendered code. This can |
| 42 | + * diverge from the nesting order of the {@link Template} when using {@link Hook#insert}, where |
| 43 | + * the execution jumps from the current (caller) {@link CodeFrame} scope to the scope of the |
| 44 | + * {@link Hook#anchor}. This ensures that the {@link Name}s of the anchor scope are accessed, |
| 45 | + * and not the ones from the caller scope. Once the {@link Hook#insert}ion is complete, we |
| 46 | + * jump back to the caller {@link CodeFrame}. |
| 47 | + * |
| 48 | + * <p> |
| 49 | + * Note, that {@link CodeFrame}s and {@link TemplateFrame}s often go together. But they do diverge when |
| 50 | + * we call {@link Hook#insert}. On the {@link CodeFrame} side, the inserted scope is nested in the anchoring |
| 51 | + * scope, so that the inserted scope has access to the Names of the anchoring scope, and not the caller |
| 52 | + * scope. But the {@link TemplateFrame} of the inserted scope is nested in the caller scope, so |
| 53 | + * that the inserted scope has access to hashtag replacements of the caller scope, and not the |
| 54 | + * anchoring scope. |
| 55 | + */ |
| 56 | + |
| 57 | +/* |
| 58 | + * Below, we look at an example, and show the use of CodeFrames (c) and TemplateFrames (t). |
| 59 | + * |
| 60 | + * Explanations: |
| 61 | + * - Generally, every scope has a CodeFrame and a TemplateFrame. There can be multiple |
| 62 | + * scopes inside a Template, and so there can be multiple CodeFrames and TemplateFrames. |
| 63 | + * In the drawing below, we draw the frames vertically, and give each a unique id. |
| 64 | + * - When we nest scopes inside scopes, we create a new CodeFrame and a new TemplateFrame, |
| 65 | + * and so they grow the same nested structure. Example: t3 is nested inside t2 and |
| 66 | + * c3 is nested inside c2b. |
| 67 | + * - The exception to this: |
| 68 | + * - At a hook.anchor, there are two CodeFrames. The first one (e.g. c2a) we call the |
| 69 | + * hook CodeFrame, it is kept empty until we insert code to the hook. The second |
| 70 | + * (e.g. c2b) we call the inner CodeFrame of the anchoring, into which we keep |
| 71 | + * generating the code that is inside the scope of the hook.anchor. |
| 72 | + * - At a hook.insert, the TemplateFrame (e.g. t4) is nested into the caller (e.g. t3), |
| 73 | + * while the CodeFrame (e.g. c4) is nested into the anchoring CodeFrame (e.g. c2a). |
| 74 | + * |
| 75 | + * Template( |
| 76 | + * t1 c1 |
| 77 | + * t1 c1 |
| 78 | + * t1 c1 Anchoring Scope |
| 79 | + * t1 c1 hook.anchor(scope( |
| 80 | + * t1 c1 t2 c2a |
| 81 | + * t1 c1 t2 c2a <------ CodeFrame nesting--------+ |
| 82 | + * t1 c1 t2 c2a with generated code | |
| 83 | + * t1 c1 t2 and Names | |
| 84 | + * t1 c1 t2 ^ | |
| 85 | + * t1 c1 t2 +- Two CodeFramees | |
| 86 | + * t1 c1 t2 v | |
| 87 | + * t1 c1 t2 | |
| 88 | + * t1 c1 t2 c2b | |
| 89 | + * t1 c1 t2 c2b | |
| 90 | + * t1 c1 t2 c2b Caller Scope | |
| 91 | + * t1 c1 t2 c2b ... scope( | |
| 92 | + * t1 c1 t2 c2b ... t3 c3 | Insertion Scope |
| 93 | + * t1 c1 t2 c2b ... t3 c3 | hook.insert(transparentScope( |
| 94 | + * t1 c1 t2 c2b ... t3 c3 | t4 c4 |
| 95 | + * t1 c1 t2 c2b ... t3 c3 +---- t4 ----c4 |
| 96 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 |
| 97 | + * t1 c1 t2 c2b ... t3 c3 <-- TemplateFrame nesting ---t4 c4 |
| 98 | + * t1 c1 t2 c2b ... t3 c3 with hashtag t4 c4 // t: Concerns Template Frame |
| 99 | + * t1 c1 t2 c2b ... t3 c3 and setFuelCost t4 c4 // c: Concerns Code Frame |
| 100 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 "use hashtag #x" -> t: hashtag queried in Insertion (t4) and Caller Scope (t3) |
| 101 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 c: code added to Anchoring Scope (c2a) |
| 102 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 |
| 103 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 let("x", 42) -> t: hashtag definition escapes to Caller Scope (t3) because |
| 104 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 Insertion Scope is transparent |
| 105 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 |
| 106 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 dataNames(...)...sample() -> c: sample from Insertion (c4) and Anchoring Scope (c2a) |
| 107 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 (CodeFrame nesting: c2a -> c4) |
| 108 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 addDataName(...) -> c: names escape to the Caller Scope (c3) because |
| 109 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 Insertion Scope is transparent |
| 110 | + * t1 c1 t2 c2b ... t3 c3 t4 c4 |
| 111 | + * t1 c1 t2 c2b ... t3 c3 )) |
| 112 | + * t1 c1 t2 c2b ... t3 c3 |
| 113 | + * t1 c1 t2 c2b ... t3 c3 |
| 114 | + * t1 c1 t2 c2b ... ) |
| 115 | + * t1 c1 t2 c2b |
| 116 | + * t1 c1 t2 c2b |
| 117 | + * t1 c1 )) |
| 118 | + * t1 c1 |
| 119 | + * t1 c1 |
| 120 | + * ) |
| 121 | + * |
48 | 122 | */ |
49 | 123 | class CodeFrame { |
50 | 124 | public final CodeFrame parent; |
@@ -78,25 +152,16 @@ public static CodeFrame makeBase() { |
78 | 152 | } |
79 | 153 |
|
80 | 154 | /** |
81 | | - * Creates a normal frame, which has a {@link #parent} and which defines an inner |
82 | | - * {@link NameSet}, for the names that are generated inside this frame. Once this |
83 | | - * frame is exited, the name from inside this frame are not available anymore. |
84 | | - */ |
85 | | - public static CodeFrame make(CodeFrame parent) { |
86 | | - return new CodeFrame(parent, false); |
87 | | - } |
88 | | - |
89 | | - /** |
90 | | - * Creates a special frame, which has a {@link #parent} but uses the {@link NameSet} |
91 | | - * from the parent frame, allowing {@link Template#addDataName}/ |
92 | | - * {@link Template#addStructuralName} to persist in the outer frame when the current frame |
93 | | - * is exited. This is necessary for {@link Hook#insert}, where we would possibly want to |
94 | | - * make field or variable definitions during the insertion that are not just local to the |
95 | | - * insertion but affect the {@link CodeFrame} that we {@link Hook#anchor} earlier and are |
96 | | - * now {@link Hook#insert}ing into. |
| 155 | + * Creates a normal frame, which has a {@link #parent}. It can either be |
| 156 | + * transparent for names, meaning that names are added and accessed to and |
| 157 | + * from an outer frame. Names that are added in a transparent frame are |
| 158 | + * still available in the outer frames, as far out as the next non-transparent |
| 159 | + * frame. If a frame is non-transparent, this frame defines an inner |
| 160 | + * {@link NameSet}, for the names that are generated inside this frame. Once |
| 161 | + * this frame is exited, the names from inside this frame are not available. |
97 | 162 | */ |
98 | | - public static CodeFrame makeTransparentForNames(CodeFrame parent) { |
99 | | - return new CodeFrame(parent, true); |
| 163 | + public static CodeFrame make(CodeFrame parent, boolean isTransparentForNames) { |
| 164 | + return new CodeFrame(parent, isTransparentForNames); |
100 | 165 | } |
101 | 166 |
|
102 | 167 | void addString(String s) { |
|
0 commit comments