Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: samples/todomvc/dart/todomvc_presenter_model.dart

Issue 2035023003: Remove service-compiler related code. (Closed) Base URL: git@github.com:dartino/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 // Should become auto-generated.
6
7 library todomvc_presenter_model;
8
9 import 'todomvc_service.dart';
10
11 /*
12 The presentation model should be generated by a terse description.
13 For example, the presenter model for this sample might have been declared as:
14
15 struct Immutable {
16 union {
17 Atom;
18 Cons;
19 }
20 }
21
22 struct Atom {
23 union {
24 void nil;
25 int32 num;
26 bool truth;
27 String str;
28 }
29 }
30
31 struct Cons {
32 Immutable fst;
33 Immutable snd;
34 }
35
36 service TodoListPresenter {
37 void Create(String);
38 void Delete(Int32);
39 void Complete(Int32);
40 void Clear();
41 }
42
43 From the description we would generate dart classes and their path descriptors
44 for each struct together with the diff algorithm. For services we would create
45 command descriptors. All of these would come with serialization support for
46 wire transfer.
47
48 Until then, all of the above is implemented below.
49
50 */
51
52 // Tracing to ease debugging on dartino...
53 bool TRACE = false;
54 void trace(obj) { if (TRACE) print(" $obj"); }
55
56 // Some constants.
57
58 const TAG_CONS_FST = 0;
59 const TAG_CONS_SND = 1;
60 const TAG_CONS_DELETE_EVENT = 2;
61 const TAG_CONS_COMPLETE_EVENT = 3;
62 const TAG_CONS_UNCOMPLETE_EVENT = 4;
63
64 // The event manager maintains a mapping from the active handler ids transferred
65 // as part of the presentation graph to the handler callbacks.
66 class EventManager {
67 Map<int, EventHandler> _handlers = new Map();
68
69 int _lfsr = 0xABBA;
70
71 int get _next {
72 // 16 bits with taps 16, 14, 13, 11.
73 int lfsr = _lfsr;
74 int bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1;
75 lfsr = (lfsr >> 1) | (bit << 15);
76 _lfsr = lfsr;
77 return lfsr;
78 }
79
80 int register(EventHandler handler) {
81 if (handler == null) return 0;
82 if (handler.allocated) {
83 // After event manager reset we must re-register event handlers.
84 int id = handler.id;
85 EventHandler registered = _handlers[id];
86 if (registered == null) {
87 _handlers[id] = handler;
88 } else if (registered != handler) {
89 print("ERROR: attempt to re-register event handler: $id");
90 }
91 return id;
92 }
93 int id = _next;
94 // TODO(zerny): Do something clever once completing the lfsr sequence.
95 while (_handlers.containsKey(id)) id = _next;
96 trace("registered event-handler id: $id");
97 _handlers[id] = handler;
98 handler.allocate(id);
99 return id;
100 }
101
102 void unregister(EventHandler handler) {
103 if (handler == null) return;
104 // TODO(zerny): replace by assert.
105 int id = handler.id;
106 if (!handler.allocated) {
107 print("ERROR: attempt to unregister unallocated event handler: $id");
108 return;
109 }
110 trace("unregistered event-handler id: $id");
111 assert(_handlers[id] == handler);
112 handler.delete();
113 _handlers.remove(id);
114 }
115
116 void call(int id) {
117 assert(id > 0);
118 EventHandler handler = _handlers[id];
119 if (handler == null) {
120 print("ERROR: attempt to call non-exisiting event handler: $id");
121 return;
122 }
123 handler.call();
124 }
125
126 void clear() {
127 _handlers.clear();
128 }
129 }
130
131 // Immutable model for the presentation (reused as a mutable mirror on the
132 // "host" side). (just sexp to simulate a "rich structure" for now)
133
134 abstract class Immutable {
135 void diff(Immutable other, Path path, MyPatchSet patches);
136 void serialize(NodeBuilder builder, EventManager events);
137 void unregisterEvents(EventManager events);
138 }
139
140 class EventHandler extends Immutable {
141 final Function _handler;
142 int _id = 0;
143
144 EventHandler(this._handler);
145
146 int get id => _id;
147 bool get allocated => _id > 0;
148 bool get deleted => _id < 0;
149
150 void call() {
151 assert(allocated);
152 _handler();
153 }
154
155 void allocate(int id) {
156 assert(!deleted);
157 _id = id;
158 }
159
160 void delete() {
161 _id = -1;
162 }
163
164 static void staticDiff(EventHandler self,
165 EventHandler other,
166 Path path,
167 MyPatchSet patches) {
168 if (identical(self, other)) return;
169 // TODO(zerny): Do we want to consider another definition of equality here?
170 // Currently only the same physically allocated event-handler object is
171 // considered "the same", but we could refine that to be if the _handler
172 // object is "the same" (which it typically won't be because of closure
173 // allocation). Also, if we do so, we need to make sure that the allocated
174 // event ids are updated to be the same too, otherwise we could end up with
175 // an unallocated event handler being referenced from the binding layer.
176 patches.add(path, self, other);
177 }
178
179 void diff(Immutable other, Path path, MyPatchSet patches) {
180 EventHandler.staticDiff(this, other, path, patches);
181 }
182
183 // TODO(zerny): Event handler fields should not be encoded in Node.
184 void serialize(NodeBuilder builder, EventManager events) {
185 builder.num = events.register(this);
186 }
187
188 void unregisterEvents(EventManager events) {
189 events.unregister(this);
190 }
191 }
192
193 abstract class Atom extends Immutable {
194 final value;
195 Atom(this.value) {
196 trace("Allocating Atom");
197 }
198 String toString() => "value($value)";
199
200 void diff(Immutable other, Path path, MyPatchSet patches) {
201 trace("Atom::diff $this ~=~ $other");
202 if (other is Atom && value == other.value)
203 return;
204 patches.add(path, this, other);
205 }
206
207 void unregisterEvents(EventManager events) { }
208 }
209
210 class Cons extends Immutable {
211 final Immutable fst, snd;
212 final EventHandler deleteEvent, completeEvent, uncompleteEvent;
213
214 Cons(this.fst, this.snd,
215 [ this.deleteEvent,
216 this.completeEvent,
217 this.uncompleteEvent ]) {
218 trace("Allocating Cons");
219 }
220
221 String toString() => "($fst . $snd)";
222
223 void diff(Immutable other, Path path, MyPatchSet patches) {
224 if (identical(this, other)) return;
225 if (other is! Cons) {
226 patches.add(path, this, other);
227 return;
228 }
229 Cons otherCons = other;
230 fst.diff(otherCons.fst, new ConsFst(path), patches);
231 snd.diff(otherCons.snd, new ConsSnd(path), patches);
232 EventHandler.staticDiff(
233 deleteEvent,
234 otherCons.deleteEvent,
235 new ConsDeleteEvent(path), patches);
236 EventHandler.staticDiff(
237 completeEvent,
238 otherCons.completeEvent,
239 new ConsCompleteEvent(path), patches);
240 EventHandler.staticDiff(
241 uncompleteEvent,
242 otherCons.uncompleteEvent,
243 new ConsUncompleteEvent(path), patches);
244 }
245
246 void serialize(NodeBuilder builder, EventManager events) {
247 trace("Cons::serialize: $this");
248 ConsBuilder cons = builder.initCons();
249 cons.deleteEvent = events.register(deleteEvent);
250 cons.completeEvent = events.register(completeEvent);
251 cons.uncompleteEvent = events.register(uncompleteEvent);
252 fst.serialize(cons.initFst(), events);
253 snd.serialize(cons.initSnd(), events);
254 }
255
256 void unregisterEvents(EventManager events) {
257 events.unregister(deleteEvent);
258 events.unregister(completeEvent);
259 events.unregister(uncompleteEvent);
260 fst.unregisterEvents(events);
261 snd.unregisterEvents(events);
262 }
263 }
264
265 class Nil extends Atom {
266 Nil() : super(null);
267 void serialize(NodeBuilder builder, EventManager events) {
268 trace("Nil::serialize");
269 builder.setNil();
270 }
271 }
272
273 class Bool extends Atom {
274 Bool(bool value) : super(value);
275 void serialize(NodeBuilder builder, EventManager events) {
276 trace("Bool::serialize: $this");
277 builder.truth = value;
278 }
279 }
280
281 class Num extends Atom {
282 Num(num value) : super(value);
283 void serialize(NodeBuilder builder, EventManager events) {
284 trace("Num::serialize: $this");
285 builder.num = value;
286 }
287 }
288
289 class Str extends Atom {
290 Str(String value) : super(value);
291 void serialize(NodeBuilder builder, EventManager events) {
292 trace("Str::serialize: $this");
293 builder.str = value;
294 }
295 }
296
297
298 // Path in the immutable model. (We probably won't need an actual representation
299 // of these. We could just construct the serialized form on the fly).
300
301 // Note that (serialize) reverses the path description. Ie, we construct the
302 // path 'inside-out' and read it 'outside-in' on the host side.
303
304 abstract class Path {
305 final Path parent;
306 Path(this.parent);
307 int get tag;
308
309 static void serialize(Path inner, PatchBuilder builder) {
310 trace("Path::serialize: path($inner)");
311 int length = 0;
312 for (Path current = inner; current != null; current = current.parent) {
313 ++length;
314 }
315 var out = builder.initPath(length);
316 for (Path current = inner; current != null; current = current.parent) {
317 out[--length] = current.tag;
318 }
319 }
320
321 String toString() => "$parent;$tag";
322 }
323
324 class ConsFst extends Path {
325 ConsFst(Path parent) : super(parent);
326 int get tag => TAG_CONS_FST;
327 }
328
329 class ConsSnd extends Path {
330 ConsSnd(Path parent) : super(parent);
331 int get tag => TAG_CONS_SND;
332 }
333
334 class ConsDeleteEvent extends Path {
335 ConsDeleteEvent(Path parent) : super(parent);
336 int get tag => TAG_CONS_DELETE_EVENT;
337 }
338
339 class ConsCompleteEvent extends Path {
340 ConsCompleteEvent(Path parent) : super(parent);
341 int get tag => TAG_CONS_COMPLETE_EVENT;
342 }
343
344 class ConsUncompleteEvent extends Path {
345 ConsUncompleteEvent(Path parent) : super(parent);
346 int get tag => TAG_CONS_UNCOMPLETE_EVENT;
347 }
348
349 // Patch description
350
351 class MyPatchSet {
352 List<Patch> patches = new List<Patch>();
353 add(Path path, Immutable content, Immutable oldContent) =>
354 patches.add(new Patch(path, content, oldContent));
355
356 void serialize(PatchSetBuilder builder, EventManager events) {
357 var length = patches.length;
358 trace("MyPatchSet::serialize: length($length)");
359 var out = builder.initPatches(patches.length);
360 for (int i = 0; i < length; ++i) {
361 patches[i].serialize(out[i], events);
362 }
363 }
364 }
365
366 class Patch {
367 Path path;
368 Immutable content;
369 Immutable oldContent;
370 Patch(this.path, this.content, this.oldContent);
371
372 void serialize(PatchBuilder builder, EventManager events) {
373 trace("Patch::serialize");
374 oldContent.unregisterEvents(events);
375 Path.serialize(path, builder);
376 content.serialize(builder.initContent(), events);
377 }
378 }
OLDNEW
« no previous file with comments | « samples/todomvc/dart/todomvc_presenter.dart ('k') | samples/todomvc/ios/TodoMVC.xcodeproj/project.pbxproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698