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

Side by Side Diff: tools/servicec/lib/src/plugins/cc.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
« no previous file with comments | « tools/servicec/lib/src/parser.dart ('k') | tools/servicec/lib/src/plugins/dart.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 file.
4
5 library old_servicec.plugins.cc;
6
7 import 'dart:core' hide Type;
8 import 'dart:io' show Platform, File;
9
10 import 'package:path/path.dart' show basenameWithoutExtension, join, dirname;
11 import 'package:servicec/util.dart' as strings;
12
13 import 'shared.dart';
14
15 import '../emitter.dart';
16 import '../primitives.dart' as primitives;
17 import '../struct_layout.dart';
18
19 const COPYRIGHT = """
20 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
21 // for details. All rights reserved. Use of this source code is governed by a
22 // BSD-style license that can be found in the LICENSE.md file.
23 """;
24
25 const List<String> RESOURCES = const [
26 "struct.h",
27 "struct.cc",
28 "unicode.h",
29 "unicode.cc",
30 ];
31
32 const int RESPONSE_HEADER_SIZE = 8;
33
34 void generate(String path,
35 Unit unit,
36 String resourcesDirectory,
37 String outputDirectory) {
38 String directory = join(outputDirectory, "cc");
39 _generateHeaderFile(path, unit, directory);
40 _generateImplementationFile(path, unit, directory);
41
42 resourcesDirectory = join(resourcesDirectory, 'cc');
43 for (String resource in RESOURCES) {
44 String resourcePath = join(resourcesDirectory, resource);
45 File file = new File(resourcePath);
46 String contents = file.readAsStringSync();
47 writeToFile(directory, resource, contents);
48 }
49 }
50
51 void _generateHeaderFile(String path, Unit unit, String directory) {
52 _HeaderVisitor visitor = new _HeaderVisitor(path);
53 visitor.visit(unit);
54 String contents = visitor.buffer.toString();
55 writeToFile(directory, path, contents, extension: 'h');
56 }
57
58 void _generateImplementationFile(String path, Unit unit, String directory) {
59 _ImplementationVisitor visitor = new _ImplementationVisitor(path);
60 visitor.visit(unit);
61 String contents = visitor.buffer.toString();
62 writeToFile(directory, path, contents, extension: 'cc');
63 }
64
65 abstract class CcVisitor extends CodeGenerationVisitor {
66 CcVisitor(String path) : super(path);
67
68 static const int REQUEST_HEADER_SIZE = 56;
69 static const PRIMITIVE_TYPES = const <String, String> {
70 'void' : 'void',
71 'bool' : 'bool',
72
73 'uint8' : 'uint8_t',
74 'uint16' : 'uint16_t',
75
76 'int8' : 'int8_t',
77 'int16' : 'int16_t',
78 'int32' : 'int32_t',
79 'int64' : 'int64_t',
80
81 'float32' : 'float',
82 'float64' : 'double',
83 };
84
85 static String cast(String type, bool cStyle) => cStyle
86 ? '($type)'
87 : 'reinterpret_cast<$type>';
88
89 visitUnion(Union node) {
90 throw "Unreachable";
91 }
92
93 visitFormal(Formal node) {
94 writeType(node.type);
95 write(' ${node.name}');
96 }
97
98 void writeType(Type node) {
99 Node resolved = node.resolved;
100 if (resolved != null) {
101 write('${node.identifier}Builder');
102 } else {
103 String type = PRIMITIVE_TYPES[node.identifier];
104 write(type);
105 }
106 }
107
108 void writeReturnType(Type node) {
109 Node resolved = node.resolved;
110 if (resolved != null) {
111 write('${node.identifier}');
112 } else {
113 String type = PRIMITIVE_TYPES[node.identifier];
114 write(type);
115 }
116 }
117
118 visitArguments(List<Formal> formals) {
119 visitNodes(formals, (first) => first ? '' : ', ');
120 }
121
122 visitStructArgumentMethodBody(String id,
123 Method method,
124 {String callback}) {
125 bool async = callback != null;
126 String argumentName = method.arguments.single.name;
127 if (method.outputKind == OutputKind.STRUCT) {
128 if (async) {
129 write(' ');
130 writeln('$argumentName.InvokeMethodAsync(service_id_, $id,'
131 ' $callback, reinterpret_cast<void*>(callback), callback_data);' );
132 } else {
133 writeln(' int64_t result = $argumentName.'
134 'InvokeMethod(service_id_, $id);');
135 writeln(' char* memory = reinterpret_cast<char*>(result);');
136 // TODO(ajohnsen): Do range-check between size and segment size.
137 writeln(' Segment* segment = MessageReader::GetRootSegment(memory);');
138 writeln(' return ${method.returnType.identifier}'
139 '(segment, $RESPONSE_HEADER_SIZE);');
140 }
141 } else {
142 write(' ');
143 if (!method.returnType.isVoid && !async) write('return ');
144 String suffix = async ? 'Async' : '';
145 String cb = async ? ', $callback, reinterpret_cast<void*>(callback), callb ack_data' : '';
146 writeln('$argumentName.InvokeMethod$suffix(service_id_, $id$cb);');
147 }
148 }
149
150 visitMethodBody(String id,
151 Method method,
152 {bool cStyle: false,
153 List<String> extraArguments: const [],
154 String callback}) {
155 List<Formal> arguments = method.arguments;
156 assert(method.inputKind == InputKind.PRIMITIVES);
157 StructLayout layout = method.inputPrimitiveStructLayout;
158 final bool async = callback != null;
159 int size = REQUEST_HEADER_SIZE + layout.size;
160 if (async) {
161 write(' static const int kSize = ');
162 writeln('${size} + ${extraArguments.length} * sizeof(void*);');
163 } else {
164 writeln(' static const int kSize = ${size};');
165 }
166
167 String cast(String type) => CcVisitor.cast(type, cStyle);
168
169 String pointerToArgument(int offset, int pointers, String type) {
170 offset += REQUEST_HEADER_SIZE;
171 String prefix = cast('$type*');
172 if (pointers == 0) return '$prefix(_buffer + $offset)';
173 return '$prefix(_buffer + $offset + $pointers * sizeof(void*))';
174 }
175
176 if (async) {
177 writeln(' char* _buffer = ${cast("char*")}(malloc(kSize));');
178 } else {
179 writeln(' char _bits[kSize];');
180 writeln(' char* _buffer = _bits;');
181 }
182
183 // Mark the message as being non-segmented.
184 writeln(' *${pointerToArgument(-8, 0, "int64_t")} = 0;');
185
186 int arity = arguments.length;
187 for (int i = 0; i < arity; i++) {
188 String name = arguments[i].name;
189 int offset = layout[arguments[i]].offset;
190 String type = PRIMITIVE_TYPES[arguments[i].type.identifier];
191 writeln(' *${pointerToArgument(offset, 0, type)} = $name;');
192 }
193
194 if (async) {
195 String callbackFunction = pointerToArgument(-16, 0, 'void*');
196 String callbackData = pointerToArgument(-24, 0, 'void*');
197 writeln(' *$callbackFunction = ${cast("void*")}(callback);');
198 writeln(' *$callbackData = callback_data;');
199 for (int i = 0; i < extraArguments.length; i++) {
200 String dataArgument = pointerToArgument(layout.size, i, 'void*');
201 String arg = extraArguments[i];
202 writeln(' *$dataArgument = ${cast("void*")}($arg);');
203 }
204 write(' ServiceApiInvokeAsync(service_id_, $id, $callback, ');
205 writeln('_buffer, kSize);');
206 } else {
207 writeln(' ServiceApiInvoke(service_id_, $id, _buffer, kSize);');
208 if (method.outputKind == OutputKind.STRUCT) {
209 writeln(' int64_t result = *${pointerToArgument(0, 0, 'int64_t')};');
210 writeln(' char* memory = reinterpret_cast<char*>(result);');
211 // TODO(ajohnsen): Do range-check between size and segment size.
212 writeln(' Segment* segment = MessageReader::GetRootSegment(memory);');
213 writeln(' return ${method.returnType.identifier}'
214 '(segment, $RESPONSE_HEADER_SIZE);');
215 } else if (!method.returnType.isVoid) {
216 writeln(' return *${pointerToArgument(0, 0, 'int64_t')};');
217 }
218 }
219 }
220 }
221
222 class _HeaderVisitor extends CcVisitor {
223 _HeaderVisitor(String path) : super(path);
224
225 String computeHeaderGuard() {
226 String base = basenameWithoutExtension(path).toUpperCase();
227 return '${base}_H';
228 }
229
230 visitUnit(Unit node) {
231 String headerGuard = computeHeaderGuard();
232 writeln(COPYRIGHT);
233
234 writeln('// Generated file. Do not edit.');
235 writeln();
236
237 writeln('#ifndef $headerGuard');
238 writeln('#define $headerGuard');
239
240 writeln();
241 writeln('#include <inttypes.h>');
242 writeln('#include "struct.h"');
243
244 if (node.structs.isNotEmpty) writeln();
245 for (Struct struct in node.structs) {
246 writeln('class ${struct.name};');
247 writeln('class ${struct.name}Builder;');
248 }
249
250 node.services.forEach(visit);
251 node.structs.forEach(visit);
252
253 writeln();
254 writeln('#endif // $headerGuard');
255 }
256
257 visitService(Service node) {
258 writeln();
259 writeln('class ${node.name} {');
260 writeln(' public:');
261 writeln(' static void setup();');
262 writeln(' static void tearDown();');
263
264 node.methods.forEach(visit);
265
266 writeln('};');
267 }
268
269 visitMethod(Method node) {
270 write(' static ');
271 writeReturnType(node.returnType);
272 write(' ${node.name}(');
273 visitArguments(node.arguments);
274 writeln(');');
275
276 write(' static void ${node.name}Async(');
277 visitArguments(node.arguments);
278 if (node.arguments.isNotEmpty) write(', ');
279 write('void (*callback)(');
280 if (!node.returnType.isVoid) {
281 writeReturnType(node.returnType);
282 write(', ');
283 }
284 writeln('void*), void* callback_data);');
285 }
286
287 visitStruct(Struct node) {
288 writeReader(node);
289 writeBuilder(node);
290 }
291
292 void writeReader(Struct node) {
293 String name = node.name;
294 StructLayout layout = node.layout;
295
296 writeln();
297 writeln('class $name : public Reader {');
298 writeln(' public:');
299 writeln(' static const int kSize = ${layout.size};');
300
301 writeln(' $name(Segment* segment, int offset)');
302 writeln(' : Reader(segment, offset) { }');
303 writeln();
304
305 for (StructSlot slot in layout.slots) {
306 Type slotType = slot.slot.type;
307 String camel = camelize(slot.slot.name);
308
309 if (slot.isUnionSlot) {
310 String tagName = camelize(slot.union.tag.name);
311 int tag = slot.unionTag;
312 writeln(' bool is$camel() const { return $tag == get$tagName(); }');
313 }
314
315 if (slotType.isList) {
316 write(' ');
317 write('List<');
318 writeReturnType(slotType);
319 write('> get$camel() const { ');
320 write('return ReadList<');
321 writeReturnType(slotType);
322 writeln('>(${slot.offset}); }');
323 } else if (slotType.isVoid) {
324 // No getters for void slots.
325 } else if (slotType.isString) {
326 writeln(' char* get$camel() const '
327 '{ return ReadString(${slot.offset}); }');
328 writeln(' List<uint16_t> get${camel}Data() const '
329 '{ return ReadList<uint16_t>(${slot.offset}); }');
330 } else if (slotType.isPrimitive) {
331 write(' ');
332 writeType(slotType);
333 write(' get$camel() const { return *PointerTo<');
334 if (slotType.isBool) {
335 writeln('uint8_t>(${slot.offset}) != 0; }');
336 } else {
337 writeType(slotType);
338 writeln('>(${slot.offset}); }');
339 }
340 } else {
341 write(' ');
342 writeReturnType(slotType);
343 writeln(' get$camel() const;');
344 }
345 }
346
347 writeln('};');
348 }
349
350 void writeBuilder(Struct node) {
351 String name = "${node.name}Builder";
352 StructLayout layout = node.layout;
353
354 writeln();
355 writeln('class $name : public Builder {');
356 writeln(' public:');
357 writeln(' static const int kSize = ${layout.size};');
358 writeln();
359
360 writeln(' explicit $name(const Builder& builder)');
361 writeln(' : Builder(builder) { }');
362 writeln(' $name(Segment* segment, int offset)');
363 writeln(' : Builder(segment, offset) { }');
364 writeln();
365
366 for (StructSlot slot in layout.slots) {
367 String slotName = slot.slot.name;
368 Type slotType = slot.slot.type;
369
370 String updateTag = '';
371 if (slot.isUnionSlot) {
372 String tagName = camelize(slot.union.tag.name);
373 int tag = slot.unionTag;
374 updateTag = 'set$tagName($tag); ';
375 }
376
377 String camel = camelize(slotName);
378 if (slotType.isList) {
379 write(' List<');
380 writeType(slotType);
381 writeln('> init$camel(int length);');
382 } else if (slotType.isVoid) {
383 assert(slot.isUnionSlot);
384 String tagName = camelize(slot.union.tag.name);
385 int tag = slot.unionTag;
386 writeln(' void set$camel() { set$tagName($tag); }');
387 } else if (slotType.isString) {
388 write(' void set$camel(const char* value) { ');
389 write(updateTag);
390 writeln('NewString(${slot.offset}, value); }');
391 writeln(' List<uint16_t> init${camel}Data(int length);');
392 } else if (slotType.isPrimitive) {
393 write(' void set$camel(');
394 writeType(slotType);
395 write(' value) { ');
396 write(updateTag);
397 write('*PointerTo<');
398 if (slotType.isBool) {
399 writeln('uint8_t>(${slot.offset}) = value ? 1 : 0; }');
400 } else {
401 writeType(slotType);
402 writeln('>(${slot.offset}) = value; }');
403 }
404 } else {
405 write(' ');
406 writeType(slotType);
407 writeln(' init$camel();');
408 }
409 }
410
411 writeln('};');
412 }
413 }
414
415 class _ImplementationVisitor extends CcVisitor {
416 int methodId = 1;
417 String serviceName;
418
419 _ImplementationVisitor(String path) : super(path);
420
421 String computeHeaderFile() {
422 String base = basenameWithoutExtension(path);
423 return '$base.h';
424 }
425
426 visitUnit(Unit node) {
427 String headerFile = computeHeaderFile();
428 writeln(COPYRIGHT);
429
430 writeln('// Generated file. Do not edit.');
431 writeln();
432
433 writeln('#include "$headerFile"');
434 writeln('#include "include/service_api.h"');
435 writeln('#include <stdlib.h>');
436
437 node.services.forEach(visit);
438 node.structs.forEach(visit);
439 }
440
441 visitService(Service node) {
442 writeln();
443 writeln('static ServiceId service_id_ = kNoServiceId;');
444
445 serviceName = node.name;
446
447 writeln();
448 writeln('void ${serviceName}::setup() {');
449 writeln(' service_id_ = ServiceApiLookup("$serviceName");');
450 writeln('}');
451
452 writeln();
453 writeln('void ${serviceName}::tearDown() {');
454 writeln(' ServiceApiTerminate(service_id_);');
455 writeln(' service_id_ = kNoServiceId;');
456 writeln('}');
457
458 node.methods.forEach(visit);
459 }
460
461 visitStruct(Struct node) {
462 writeBuilder(node);
463 writeReader(node);
464 }
465
466 void writeBuilder(Struct node) {
467 String name = "${node.name}Builder";
468 StructLayout layout = node.layout;
469
470 for (StructSlot slot in layout.slots) {
471 String slotName = slot.slot.name;
472 Type slotType = slot.slot.type;
473
474 String updateTag = '';
475 if (slot.isUnionSlot) {
476 String tagName = camelize(slot.union.tag.name);
477 int tag = slot.unionTag;
478 updateTag = ' set$tagName($tag);\n';
479 }
480
481 String camel = camelize(slotName);
482 if (slotType.isList) {
483 writeln();
484 write('List<');
485 writeType(slotType);
486 writeln('> $name::init$camel(int length) {');
487 write(updateTag);
488 int size = 0;
489 if (slotType.isPrimitive) {
490 size = primitives.size(slotType.primitiveType);
491 } else {
492 Struct element = slot.slot.type.resolved;
493 StructLayout elementLayout = element.layout;
494 size = elementLayout.size;
495 }
496 writeln(' Reader result = NewList(${slot.offset}, length, $size);');
497 write(' return List<');
498 writeType(slotType);
499 writeln('>(result.segment(), result.offset(), length);');
500 writeln('}');
501 } else if (slotType.isString) {
502 writeln();
503 writeln('List<uint16_t> $name::init${camel}Data(int length) {');
504 write(updateTag);
505 writeln(' Reader result = NewList(${slot.offset}, length, 2);');
506 writeln(' return List<uint16_t>(result.segment(), result.offset(),'
507 ' length);');
508 writeln('}');
509 } else if (!slotType.isPrimitive) {
510 writeln();
511 writeType(slotType);
512 writeln(' $name::init$camel() {');
513 Struct element = slot.slot.type.resolved;
514 StructLayout elementLayout = element.layout;
515 int size = elementLayout.size;
516 write(updateTag);
517 if (!slotType.isPointer) {
518 write(' return ');
519 writeType(slotType);
520 writeln('(segment(), offset() + ${slot.offset});');
521 } else {
522 writeln(' Builder result = NewStruct(${slot.offset}, $size);');
523 write(' return ');
524 writeType(slotType);
525 writeln('(result);');
526 }
527 writeln('}');
528 }
529 }
530 }
531
532 void writeReader(Struct node) {
533 String name = "${node.name}";
534 StructLayout layout = node.layout;
535
536 for (StructSlot slot in layout.slots) {
537 String slotName = slot.slot.name;
538 Type slotType = slot.slot.type;
539
540 String camel = camelize(slotName);
541 if (!slotType.isPrimitive && !slotType.isList && !slotType.isString) {
542 writeln();
543 writeReturnType(slotType);
544 write(' $name::get$camel() const { return ');
545 if (!slotType.isPointer) {
546 writeReturnType(slotType);
547 writeln('(segment(), offset() + ${slot.offset}); }');
548 } else {
549 write('ReadStruct<');
550 writeReturnType(slotType);
551 writeln('>(${slot.offset}); }');
552 }
553 }
554 }
555 }
556
557 visitMethod(Method node) {
558 String name = node.name;
559 String id = 'k${camelize(name)}Id_';
560
561 writeln();
562 write('static const MethodId $id = ');
563 writeln('reinterpret_cast<MethodId>(${methodId++});');
564
565 writeln();
566 writeReturnType(node.returnType);
567 write(' $serviceName::${name}(');
568 visitArguments(node.arguments);
569 writeln(') {');
570
571 if (node.inputKind == InputKind.STRUCT) {
572 visitStructArgumentMethodBody(id, node);
573 } else {
574 assert(node.inputKind == InputKind.PRIMITIVES);
575 visitMethodBody(id, node);
576 }
577
578 writeln('}');
579
580 String callback;
581 if (node.inputKind == InputKind.STRUCT) {
582 Struct struct = node.arguments.single.type.resolved;
583 StructLayout layout = struct.layout;
584 callback = ensureCallback(node.returnType, layout);
585 } else {
586 callback =
587 ensureCallback(node.returnType, node.inputPrimitiveStructLayout);
588 }
589
590 writeln();
591 write('void $serviceName::${name}Async(');
592 visitArguments(node.arguments);
593 if (node.arguments.isNotEmpty) write(', ');
594 write('void (*callback)(');
595 if (!node.returnType.isVoid) {
596 writeReturnType(node.returnType);
597 write(', ');
598 }
599 writeln('void*), void* callback_data) {');
600
601 if (node.inputKind == InputKind.STRUCT) {
602 visitStructArgumentMethodBody(id, node, callback: callback);
603 } else {
604 visitMethodBody(id, node, callback: callback);
605 }
606
607 writeln('}');
608 }
609
610 final Map<String, String> callbacks = {};
611 String ensureCallback(Type type,
612 StructLayout layout,
613 {bool cStyle: false}) {
614 String key = '${type.identifier}_${layout.size}';
615 return callbacks.putIfAbsent(key, () {
616 String cast(String type) => CcVisitor.cast(type, cStyle);
617 String pointerToArgument(int offset, int pointers, String type) {
618 offset += CcVisitor.REQUEST_HEADER_SIZE;
619 String prefix = cast('$type*');
620 if (pointers == 0) return '$prefix(buffer + $offset)';
621 return '$prefix(buffer + $offset + $pointers * sizeof(void*))';
622 }
623 String name = 'Unwrap_$key';
624 writeln();
625 writeln('static void $name(void* raw) {');
626 if (type.isVoid) {
627 writeln(' typedef void (*cbt)(void*);');
628 } else {
629 write(' typedef void (*cbt)(');
630 writeReturnType(type);
631 writeln(', void*);');
632 }
633 writeln(' char* buffer = ${cast('char*')}(raw);');
634 int offset = CcVisitor.REQUEST_HEADER_SIZE;
635 if (!type.isVoid) {
636 writeln(' int64_t result = *${cast('int64_t*')}(buffer + $offset);');
637 if (!type.isPrimitive) {
638 writeln(' char* memory = reinterpret_cast<char*>(result);');
639 writeln(' Segment* segment = '
640 'MessageReader::GetRootSegment(memory);');
641 }
642 }
643 String callbackFunction = pointerToArgument(-16, 0, 'cbt');
644 String callbackData = pointerToArgument(-24, 0, 'void*');
645 writeln(' cbt callback = *$callbackFunction;');
646 writeln(' void* callback_data = *$callbackData;');
647 writeln(' MessageBuilder::DeleteMessage(buffer);');
648 if (type.isVoid) {
649 writeln(' callback(callback_data);');
650 } else {
651 if (type.isPrimitive) {
652 writeln(' callback(result, callback_data);');
653 } else {
654 write(' callback(');
655 writeReturnType(type);
656 writeln('(segment, 8), callback_data);');
657 }
658 }
659 writeln('}');
660 return name;
661 });
662 }
663 }
OLDNEW
« no previous file with comments | « tools/servicec/lib/src/parser.dart ('k') | tools/servicec/lib/src/plugins/dart.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698