Index: tools/immic/lib/src/plugins/dart.dart |
diff --git a/tools/immic/lib/src/plugins/dart.dart b/tools/immic/lib/src/plugins/dart.dart |
deleted file mode 100644 |
index 23556b05dffdb0d235553b07b6a9c95028cdca8b..0000000000000000000000000000000000000000 |
--- a/tools/immic/lib/src/plugins/dart.dart |
+++ /dev/null |
@@ -1,476 +0,0 @@ |
-// Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library immic.plugins.dart; |
- |
-import 'dart:core' hide Type; |
-import 'dart:io' show Platform, File; |
- |
-import 'package:path/path.dart' show withoutExtension, join, dirname; |
-import 'package:strings/strings.dart' as strings; |
- |
-import 'shared.dart'; |
-import '../emitter.dart'; |
-import '../struct_layout.dart'; |
-import '../primitives.dart' as primitives; |
- |
-const List<String> RESOURCES = const [ |
- "immi.dart", |
-]; |
- |
-const COPYRIGHT = """ |
-// Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE.md file. |
-"""; |
- |
-void generate(String path, |
- Map<String, Unit> units, |
- String outputDirectory) { |
- String directory = join(outputDirectory, 'dart'); |
- units.forEach((path, unit) => _generateNodeFile(path, unit, directory)); |
- _generateServiceFile(path, units, directory); |
- |
- String resourcesDirectory = join(dirname(Platform.script.path), |
- '..', 'lib', 'src', 'resources', 'dart'); |
- for (String resource in RESOURCES) { |
- String resourcePath = join(resourcesDirectory, resource); |
- File file = new File(resourcePath); |
- String contents = file.readAsStringSync(); |
- writeToFile(directory, resource, contents); |
- } |
-} |
- |
-String generateNodeString(String unitPath, Unit unit) { |
- _DartVisitor visitor = new _DartVisitor(unitPath); |
- visitor.visit(unit); |
- return visitor.buffer.toString(); |
-} |
- |
-String generateServiceString(String path, Map units) { |
- _DartVisitor visitor = new _DartVisitor(path); |
- units.values.forEach(visitor.collectMethodSignatures); |
- visitor._writeServiceImpl(); |
- return visitor.buffer.toString(); |
-} |
- |
-void _generateNodeFile(String unitPath, Unit unit, String directory) { |
- String content = generateNodeString(unitPath, unit); |
- writeToFile(directory, unitPath, content, extension: 'dart'); |
-} |
- |
-void _generateServiceFile(String path, |
- Map<String, Unit> units, |
- String directory) { |
- _DartVisitor visitor = new _DartVisitor(path); |
- String content = generateServiceString(path, units); |
- String file = visitor.serviceImplFile; |
- writeToFile(directory, file, content, extension: 'dart'); |
-} |
- |
-class _DartVisitor extends CodeGenerationVisitor { |
- _DartVisitor(String path) : super(path); |
- |
- visitUnit(Unit node) { |
- _writeHeader(); |
- _writeLibrary(); |
- _writeImports(); |
- node.imports.forEach(visit); |
- if (node.imports.isNotEmpty) writeln(); |
- node.structs.forEach(visit); |
- } |
- |
- visitImport(Import import) { |
- writeln("import '${withoutExtension(import.import)}.dart';"); |
- } |
- |
- getPatchType(Type type) { |
- if (type.isList) return 'ListPatch'; |
- if (type.isNode) return 'NodePatch'; |
- if (type.resolved != null) return '${type.identifier}Patch'; |
- return _types[type.identifier]; |
- } |
- |
- getSerializeMethodName(Type type) { |
- if (type.isList) return 'serializeList'; |
- if (type.isNode) return 'serializeNode'; |
- if (type.resolved != null) return 'serialize${type.identifier}'; |
- throw 'Unserializable type ${type.identifier}'; |
- } |
- |
- visitStruct(Struct node) { |
- String nodeName = '${node.name}Node'; |
- String patchName = '${node.name}Patch'; |
- String replacePatch = '${node.name}ReplacePatch'; |
- String updatePatch = '${node.name}UpdatePatch'; |
- String nodeBuilderName = '${node.name}NodeDataBuilder'; |
- String patchBuilderName = '${node.name}PatchDataBuilder'; |
- String updateBuilderName = '${node.name}UpdateDataBuilder'; |
- |
- bool hasFields = node.layout.slots.isNotEmpty; |
- bool hasMethods = node.methods.isNotEmpty; |
- bool hasSlotsAndMethods = hasFields && hasMethods; |
- |
- writeln('class $nodeName extends Node {'); |
- // Final fields. |
- forEachSlot(node, null, (Type slotType, String slotName) { |
- write(' final '); |
- writeType(slotType); |
- writeln(' $slotName;'); |
- }); |
- for (var method in node.methods) { |
- writeln(' final Function ${method.name};'); |
- } |
- // Public keyword constructor. |
- if (hasFields || hasMethods) { |
- write(' factory $nodeName({'); |
- forEachSlot(node, writeComma, (Type slotType, String slotName) { |
- writeType(slotType); |
- write(' $slotName'); |
- }); |
- if (hasSlotsAndMethods) write(', '); |
- write(node.methods.map((method) => 'Function ${method.name}').join(', ')); |
- writeln('}) =>'); |
- write(' new ${nodeName}._internal('); |
- forEachSlot(node, writeComma, (_, String slotName) { |
- write('$slotName'); |
- }); |
- if (hasSlotsAndMethods) write(', '); |
- write(node.methods.map((method) => method.name).join(', ')); |
- writeln(');'); |
- // Positional constructor. |
- write(' ${nodeName}._internal('); |
- forEachSlot(node, writeComma, (_, String slotName) { |
- write('this.${slotName}'); |
- }); |
- if (hasSlotsAndMethods) write(', '); |
- write(node.methods.map((method) => 'this.${method.name}').join(', ')); |
- writeln(');'); |
- } |
- |
- // Serialization |
- String serializeSelf = 'serialize${node.name}'; |
- writeln(' void serializeNode(NodeDataBuilder builder, ResourceManager manager) {'); |
- writeln(' $serializeSelf(builder.init${node.name}(), manager);'); |
- writeln(' }'); |
- writeln(' void $serializeSelf(${nodeName}DataBuilder builder, ResourceManager manager) {'); |
- forEachSlot(node, null, (Type slotType, String slotName) { |
- String slotNameCamel = camelize(slotName); |
- if (slotType.isList) { |
- String localSlotLength = "${slotName}Length"; |
- String localSlotBuilder = "${slotName}Builder"; |
- // TODO(zerny): Support list of primitives. |
- String serialize = slotType.elementType.isNode ? |
- 'serializeNode' : |
- 'serialize${slotType.elementType.identifier}'; |
- writeln(' var $localSlotLength = $slotName.length;'); |
- writeln(' List $localSlotBuilder ='); |
- writeln(' builder.init$slotNameCamel($localSlotLength);'); |
- writeln(' for (var i = 0; i < $localSlotLength; ++i) {'); |
- writeln(' $slotName[i].$serialize($localSlotBuilder[i], manager);'); |
- writeln(' }'); |
- } else if (slotType.isNode || slotType.resolved != null) { |
- String serialize = getSerializeMethodName(slotType); |
- writeln(' $slotName.$serialize(builder.init$slotNameCamel(), manager);'); |
- } else { |
- writeln(' builder.$slotName = $slotName;'); |
- } |
- }); |
- for (var method in node.methods) { |
- String methodName = method.name; |
- writeln(' builder.$methodName = manager.addHandler($methodName);'); |
- } |
- writeln(' }'); |
- |
- // Event handlers |
- writeln(' void unregisterHandlers(ResourceManager manager) {'); |
- for (var method in node.methods) { |
- writeln(' manager.removeHandler(${method.name});'); |
- } |
- writeln(' }'); |
- |
- // Difference. |
- writeln(' ${node.name}Patch diff(Node previousNode) {'); |
- if (!hasFields && !hasMethods) { |
- writeln(' if (previousNode is $nodeName) return null;'); |
- writeln(' return new $replacePatch(this, previousNode);'); |
- } else { |
- writeln(' if (identical(this, previousNode)) return null;'); |
- writeln(' if (previousNode is! $nodeName) {'); |
- writeln(' return new $replacePatch(this, previousNode);'); |
- writeln(' }'); |
- writeln(' $nodeName previous = previousNode;'); |
- writeln(' $updatePatch updates = null;'); |
- String ensureUpdatePatch = |
- 'if (updates == null) updates = new $updatePatch(previous);'; |
- forEachSlot(node, null, (Type slotType, String slotName) { |
- if (slotType.isList) { |
- // TODO(zerny): Support lists of primitives. |
- String type = slotType.elementType.isNode ? |
- 'ListPatchType.AnyNode' : |
- 'ListPatchType.SpecificNode'; |
- writeln(' ${getPatchType(slotType)} ${slotName}Patch ='); |
- writeln(' diffList($slotName, previous.$slotName, $type);'); |
- writeln(' if (${slotName}Patch != null) {'); |
- writeln(' $ensureUpdatePatch'); |
- writeln(' updates.$slotName = ${slotName}Patch;'); |
- writeln(' }'); |
- } else if (slotType.isNode || slotType.resolved != null) { |
- writeln(' ${getPatchType(slotType)} ${slotName}Patch ='); |
- writeln(' $slotName.diff(previous.$slotName);'); |
- writeln(' if (${slotName}Patch != null) {'); |
- writeln(' $ensureUpdatePatch'); |
- writeln(' updates.$slotName = ${slotName}Patch;'); |
- writeln(' }'); |
- } else { |
- writeln(' if ($slotName != previous.$slotName) {'); |
- writeln(' $ensureUpdatePatch'); |
- writeln(' updates.$slotName = $slotName;'); |
- writeln(' }'); |
- } |
- }); |
- for (Method method in node.methods) { |
- String name = method.name; |
- writeln(' if ($name != previous.$name) {'); |
- writeln(' $ensureUpdatePatch'); |
- writeln(' updates.$name = $name;'); |
- writeln(' }'); |
- } |
- writeln(' return updates;'); |
- } |
- writeln(' }'); |
- // Difference end. |
- |
- writeln('}'); |
- writeln(); |
- // Node class end. |
- |
- // Node specific patches. |
- String serializeSelfNode = 'serialize${node.name}'; |
- String serializeSelfPatch = 'serialize${node.name}'; |
- writeln('abstract class $patchName extends NodePatch {'); |
- writeln(' void serializeNode(NodePatchDataBuilder builder, ResourceManager manager) {'); |
- writeln(' $serializeSelfPatch(builder.init${node.name}(), manager);'); |
- writeln(' }'); |
- writeln(' void $serializeSelfPatch($patchBuilderName builder, ResourceManager manager);'); |
- writeln('}'); |
- writeln(); |
- writeln('class $replacePatch extends $patchName {'); |
- writeln(' final $nodeName replacement;'); |
- writeln(' final Node previous;'); |
- writeln(' $replacePatch(this.replacement, this.previous);'); |
- writeln(' void $serializeSelfPatch($patchBuilderName builder, ResourceManager manager) {'); |
- writeln(' if (previous != null) previous.unregisterHandlers(manager);'); |
- writeln(' replacement.$serializeSelfNode(builder.initReplace(), manager);'); |
- writeln(' }'); |
- writeln('}'); |
- writeln(); |
- if (hasFields || hasMethods) { |
- writeln('class $updatePatch extends $patchName {'); |
- writeln(' final $nodeName previous;'); |
- writeln(' $updatePatch(this.previous);'); |
- writeln(' int _count = 0;'); |
- forEachSlot(node, null, (Type slotType, String slotName) { |
- writeln(' ${getPatchType(slotType)} _$slotName;'); |
- writeln(' set $slotName(${getPatchType(slotType)} $slotName) {'); |
- writeln(' ++_count;'); |
- writeln(' _$slotName = $slotName;'); |
- writeln(' }'); |
- }); |
- for (Method method in node.methods) { |
- String name = method.name; |
- writeln(' Function _$name;'); |
- writeln(' set $name(Function $name) {'); |
- writeln(' ++_count;'); |
- writeln(' _$name = $name;'); |
- writeln(' }'); |
- } |
- writeln(' void $serializeSelfPatch($patchBuilderName builder, ResourceManager manager) {'); |
- writeln(' List<${updateBuilderName}> builders = builder.initUpdates(_count);'); |
- writeln(' int index = 0;'); |
- forEachSlot(node, null, (Type slotType, String slotName) { |
- writeln(' if (_$slotName != null) {'); |
- if (slotType.isList || slotType.isNode || slotType.resolved != null) { |
- String slotNameCamel = camelize(slotName); |
- String serializeSlot = getSerializeMethodName(slotType); |
- writeln(' _$slotName.$serializeSlot(builders[index++].init$slotNameCamel(), manager);'); |
- } else { |
- writeln(' builders[index++].$slotName = _$slotName;'); |
- } |
- writeln(' }'); |
- }); |
- for (Method method in node.methods) { |
- String name = method.name; |
- writeln(' if (_$name != null) {'); |
- writeln(' manager.removeHandler(previous.$name);'); |
- writeln(' builders[index++].$name = manager.addHandler(_$name);'); |
- writeln(' }'); |
- } |
- writeln(' assert(index == _count);'); |
- writeln(' }'); |
- writeln('}'); |
- writeln(); |
- } |
- } |
- |
- visitUnion(Union node) { |
- // Ignored for now. |
- } |
- |
- visitMethod(Method node) { |
- // Ignored for now. |
- } |
- |
- void _writeServiceImpl() { |
- _writeHeader(); |
- write(""" |
-library ${serviceImplLib}; |
- |
-import '${immiGenPkg}/dart/immi.dart'; |
-import '${serviceGenPkg}/dart/${serviceFile}.dart'; |
- |
-class ${serviceImplName} extends ${serviceName} { |
- var _nextPresenterId = 1; |
- var _presenters = [null]; |
- var _presenterGraphs = [null]; |
- var _presenterNameToId = {}; |
- |
- // TODO(zerny): Implement per-graph resource management. |
- ResourceManager _manager = new ResourceManager(); |
- |
- ${serviceImplName}(); |
- void add(String name, presenter) { |
- assert(!_presenterNameToId.containsKey(name)); |
- _presenterNameToId[name] = _addPresenter(presenter); |
- } |
- |
- int _addPresenter(presenter) { |
- assert(_presenters.length == _nextPresenterId); |
- assert(_presenterGraphs.length == _nextPresenterId); |
- _presenters.add(presenter); |
- _presenterGraphs.add(null); |
- return _nextPresenterId++; |
- } |
- |
- int getPresenter(PresenterData data) { |
- String name = data.name; |
- int pid = _presenterNameToId[name]; |
- return pid == null ? 0 : pid; |
- } |
- |
- void reset(int pid) { |
- int length = _presenterGraphs.length; |
- for (int i = 0; i < length; ++i) { |
- _presenterGraphs[i] = null; |
- } |
- _manager.clear(); |
- } |
- |
- void refresh(int pid, PatchDataBuilder builder) { |
- assert(0 < pid && pid < _nextPresenterId); |
- Node previous = _presenterGraphs[pid]; |
- Node current = _presenters[pid].present(previous); |
- NodePatch patch = current.diff(previous); |
- if (patch == null) { |
- builder.setNoPatch(); |
- } else { |
- _presenterGraphs[pid] = current; |
- patch.serializeNode(builder.initNode(), _manager); |
- } |
- } |
- |
- void run() { |
- ${serviceName}.initialize(this); |
- while (${serviceName}.hasNextEvent()) { |
- ${serviceName}.handleNextEvent(); |
- } |
- } |
- |
-"""); |
- for (List<Type> formals in methodSignatures.values) { |
- String suffix = actionTypeSuffix(formals); |
- bool boxedArguments = formals.any((t) => t.isString); |
- if (boxedArguments) { |
- writeln(' void dispatch$suffix(Action${suffix}Args args) {'); |
- writeln(' var handler = _manager.getHandler(args.id);'); |
- writeln(' if (handler != null) handler('); |
- for (int j = 0; j <= formals.length - 1; ++j) { |
- if (j != 0) write(','); |
- write('args.arg$j'); |
- } |
- writeln(');'); |
- writeln(' }'); |
- continue; |
- } |
- write(' void dispatch$suffix(int id'); |
- int i = 0; |
- for (var formal in formals) { |
- write(', '); |
- writeType(formal); |
- write(' arg${i++}'); |
- } |
- writeln(') {'); |
- writeln(' var handler = _manager.getHandler(id);'); |
- write(' if (handler != null) handler('); |
- for (int j = 0; j <= i - 1; ++j) { |
- if (j != 0) write(', '); |
- write('arg$j'); |
- } |
- writeln(');'); |
- |
- writeln(' }'); |
- writeln(); |
- } |
- writeln('}'); |
- writeln(); |
- } |
- |
- void _writeHeader() { |
- writeln(COPYRIGHT); |
- writeln('// Generated file. Do not edit.'); |
- writeln(); |
- } |
- |
- void _writeLibrary() { |
- writeln('library $libraryName;'); |
- writeln(); |
- } |
- |
- void _writeImports() { |
- writeln('import "$immiGenPkg/dart/immi.dart";'); |
- writeln('import "$serviceGenPkg/dart/$serviceFile.dart";'); |
- writeln(); |
- } |
- |
- static const Map<String, String> _types = const { |
- 'void' : 'void', |
- 'bool' : 'bool', |
- |
- 'uint8' : 'int', |
- 'uint16' : 'int', |
- |
- 'int8' : 'int', |
- 'int16' : 'int', |
- 'int32' : 'int', |
- 'int64' : 'int', |
- |
- 'float32' : 'double', |
- 'float64' : 'double', |
- |
- 'String' : 'String', |
- }; |
- |
- void writeType(Type node) { |
- if (node.isList) write('List<'); |
- if (node.isNode || (node.isList && node.elementType.isNode)) { |
- write('Node'); |
- } else if (node.resolved != null) { |
- write("${node.identifier}Node"); |
- } else { |
- String type = _types[node.identifier]; |
- write(type); |
- } |
- if (node.isList) write('>'); |
- } |
-} |