OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 3 # for details. All rights reserved. Use of this source code is governed by a |
| 4 # BSD-style license that can be found in the LICENSE file. |
| 5 |
| 6 """This module provides shared functionality for the systems to generate |
| 7 wrapping binding from the IDL database.""" |
| 8 |
| 9 import os |
| 10 from generator import * |
| 11 from systembase import * |
| 12 |
| 13 class WrappingImplementationSystem(System): |
| 14 |
| 15 def __init__(self, templates, database, emitters, output_dir): |
| 16 """Prepared for generating wrapping implementation. |
| 17 |
| 18 - Creates emitter for JS code. |
| 19 - Creates emitter for Dart code. |
| 20 """ |
| 21 super(WrappingImplementationSystem, self).__init__( |
| 22 templates, database, emitters, output_dir) |
| 23 self._dart_wrapping_file_paths = [] |
| 24 |
| 25 |
| 26 def InterfaceGenerator(self, |
| 27 interface, |
| 28 common_prefix, |
| 29 super_interface_name, |
| 30 source_filter): |
| 31 """.""" |
| 32 interface_name = interface.id |
| 33 dart_wrapping_file_path = self._FilePathForDartWrappingImpl(interface_name) |
| 34 |
| 35 self._dart_wrapping_file_paths.append(dart_wrapping_file_path) |
| 36 |
| 37 dart_code = self._emitters.FileEmitter(dart_wrapping_file_path) |
| 38 dart_code.Emit(self._templates.Load('wrapping_impl.darttemplate')) |
| 39 return WrappingInterfaceGenerator(interface, super_interface_name, |
| 40 dart_code, |
| 41 self._BaseDefines(interface)) |
| 42 |
| 43 def ProcessCallback(self, interface, info): |
| 44 pass |
| 45 |
| 46 def GenerateLibraries(self, lib_dir): |
| 47 # Library generated for implementation. |
| 48 self._GenerateLibFile( |
| 49 'wrapping_dom.darttemplate', |
| 50 os.path.join(lib_dir, 'wrapping_dom.dart'), |
| 51 (self._interface_system._dart_interface_file_paths + |
| 52 self._interface_system._dart_callback_file_paths + |
| 53 # FIXME: Move the implementation to a separate library. |
| 54 self._dart_wrapping_file_paths |
| 55 )) |
| 56 |
| 57 |
| 58 def Finish(self): |
| 59 pass |
| 60 |
| 61 |
| 62 def _FilePathForDartWrappingImpl(self, interface_name): |
| 63 """Returns the file path of the Dart wrapping implementation.""" |
| 64 return os.path.join(self._output_dir, 'src', 'wrapping', |
| 65 '_%sWrappingImplementation.dart' % interface_name) |
| 66 |
| 67 class WrappingInterfaceGenerator(object): |
| 68 """Generates Dart and JS implementation for one DOM IDL interface.""" |
| 69 |
| 70 def __init__(self, interface, super_interface, dart_code, base_members): |
| 71 """Generates Dart and JS code for the given interface. |
| 72 |
| 73 Args: |
| 74 |
| 75 interface: an IDLInterface instance. It is assumed that all types have |
| 76 been converted to Dart types (e.g. int, String), unless they are in |
| 77 the same package as the interface. |
| 78 super_interface: A string or None, the name of the common interface that |
| 79 this interface implements, if any. |
| 80 dart_code: an Emitter for the file containing the Dart implementation |
| 81 class. |
| 82 base_members: a set of names of members defined in a base class. This is |
| 83 used to avoid static member 'overriding' in the generated Dart code. |
| 84 """ |
| 85 self._interface = interface |
| 86 self._super_interface = super_interface |
| 87 self._dart_code = dart_code |
| 88 self._base_members = base_members |
| 89 self._current_secondary_parent = None |
| 90 |
| 91 |
| 92 def StartInterface(self): |
| 93 interface = self._interface |
| 94 interface_name = interface.id |
| 95 |
| 96 self._class_name = self._ImplClassName(interface_name) |
| 97 |
| 98 base = self._BaseClassName(interface) |
| 99 |
| 100 (self._members_emitter, |
| 101 self._top_level_emitter) = self._dart_code.Emit( |
| 102 '\n' |
| 103 'class $CLASS extends $BASE implements $INTERFACE {\n' |
| 104 ' $CLASS() : super() {}\n' |
| 105 '\n' |
| 106 ' static create_$CLASS() native {\n' |
| 107 ' return new $CLASS();\n' |
| 108 ' }\n' |
| 109 '$!MEMBERS' |
| 110 '\n' |
| 111 ' String get typeName() { return "$INTERFACE"; }\n' |
| 112 '}\n' |
| 113 '$!TOP_LEVEL', |
| 114 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) |
| 115 |
| 116 def _ImplClassName(self, type_name): |
| 117 return '_' + type_name + 'WrappingImplementation' |
| 118 |
| 119 def _BaseClassName(self, interface): |
| 120 if not interface.parents: |
| 121 return 'DOMWrapperBase' |
| 122 |
| 123 supertype = interface.parents[0].type.id |
| 124 |
| 125 # FIXME: We're currently injecting List<..> and EventTarget as |
| 126 # supertypes in dart.idl. We should annotate/preserve as |
| 127 # attributes instead. For now, this hack lets the interfaces |
| 128 # inherit, but not the classes. |
| 129 # List methods are injected in AddIndexer. |
| 130 if IsDartListType(supertype) or IsDartCollectionType(supertype): |
| 131 return 'DOMWrapperBase' |
| 132 |
| 133 if supertype == 'EventTarget': |
| 134 # Most implementors of EventTarget specify the EventListener operations |
| 135 # again. If the operations are not specified, try to inherit from the |
| 136 # EventTarget implementation. |
| 137 # |
| 138 # Applies to MessagePort. |
| 139 if not [op for op in interface.operations if op.id == 'addEventListener']: |
| 140 return self._ImplClassName(supertype) |
| 141 return 'DOMWrapperBase' |
| 142 |
| 143 return self._ImplClassName(supertype) |
| 144 |
| 145 def FinishInterface(self): |
| 146 """.""" |
| 147 pass |
| 148 |
| 149 def AddConstant(self, constant): |
| 150 # Constants are already defined on the interface. |
| 151 pass |
| 152 |
| 153 def _MethodName(self, prefix, name): |
| 154 method_name = prefix + name |
| 155 if name in self._base_members: # Avoid illegal Dart 'static override'. |
| 156 method_name = method_name + '_' + self._interface.id |
| 157 return method_name |
| 158 |
| 159 def AddAttribute(self, getter, setter): |
| 160 if getter: |
| 161 self._AddGetter(getter) |
| 162 if setter: |
| 163 self._AddSetter(setter) |
| 164 |
| 165 def _AddGetter(self, attr): |
| 166 # FIXME: Instead of injecting the interface name into the method when it is |
| 167 # also implemented in the base class, suppress the method altogether if it |
| 168 # has the same signature. I.e., let the JS do the virtual dispatch instead. |
| 169 method_name = self._MethodName('_get_', attr.id) |
| 170 self._members_emitter.Emit( |
| 171 '\n' |
| 172 ' $TYPE get $NAME() { return $METHOD(this); }\n' |
| 173 ' static $TYPE $METHOD(var _this) native;\n', |
| 174 NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) |
| 175 |
| 176 def _AddSetter(self, attr): |
| 177 # FIXME: See comment on getter. |
| 178 method_name = self._MethodName('_set_', attr.id) |
| 179 self._members_emitter.Emit( |
| 180 '\n' |
| 181 ' void set $NAME($TYPE value) { $METHOD(this, value); }\n' |
| 182 ' static void $METHOD(var _this, $TYPE value) native;\n', |
| 183 NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) |
| 184 |
| 185 def AddSecondaryAttribute(self, interface, getter, setter): |
| 186 self._SecondaryContext(interface) |
| 187 self.AddAttribute(getter, setter) |
| 188 |
| 189 def AddSecondaryOperation(self, interface, info): |
| 190 self._SecondaryContext(interface) |
| 191 self.AddOperation(info) |
| 192 |
| 193 def AddEventAttributes(self, event_attrs): |
| 194 pass |
| 195 |
| 196 def _SecondaryContext(self, interface): |
| 197 if interface is not self._current_secondary_parent: |
| 198 self._current_secondary_parent = interface |
| 199 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id) |
| 200 |
| 201 def AddIndexer(self, element_type): |
| 202 """Adds all the methods required to complete implementation of List.""" |
| 203 # We would like to simply inherit the implementation of everything except |
| 204 # get length(), [], and maybe []=. It is possible to extend from a base |
| 205 # array implementation class only when there is no other implementation |
| 206 # inheritance. There might be no implementation inheritance other than |
| 207 # DOMBaseWrapper for many classes, but there might be some where the |
| 208 # array-ness is introduced by a non-root interface: |
| 209 # |
| 210 # interface Y extends X, List<T> ... |
| 211 # |
| 212 # In the non-root case we have to choose between: |
| 213 # |
| 214 # class YImpl extends XImpl { add List<T> methods; } |
| 215 # |
| 216 # and |
| 217 # |
| 218 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
| 219 # |
| 220 if self._HasNativeIndexGetter(self._interface): |
| 221 self._EmitNativeIndexGetter(self._interface, element_type) |
| 222 else: |
| 223 self._members_emitter.Emit( |
| 224 '\n' |
| 225 ' $TYPE operator[](int index) {\n' |
| 226 ' return item(index);\n' |
| 227 ' }\n', |
| 228 TYPE=element_type) |
| 229 |
| 230 if self._HasNativeIndexSetter(self._interface): |
| 231 self._EmitNativeIndexSetter(self._interface, element_type) |
| 232 else: |
| 233 self._members_emitter.Emit( |
| 234 '\n' |
| 235 ' void operator[]=(int index, $TYPE value) {\n' |
| 236 ' throw new UnsupportedOperationException("Cannot assign element of
immutable List.");\n' |
| 237 ' }\n', |
| 238 TYPE=element_type) |
| 239 |
| 240 self._members_emitter.Emit( |
| 241 '\n' |
| 242 ' void add($TYPE value) {\n' |
| 243 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 244 ' }\n' |
| 245 '\n' |
| 246 ' void addLast($TYPE value) {\n' |
| 247 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 248 ' }\n' |
| 249 '\n' |
| 250 ' void addAll(Collection<$TYPE> collection) {\n' |
| 251 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 252 ' }\n' |
| 253 '\n' |
| 254 ' void sort(int compare($TYPE a, $TYPE b)) {\n' |
| 255 ' throw new UnsupportedOperationException("Cannot sort immutable List
.");\n' |
| 256 ' }\n' |
| 257 '\n' |
| 258 ' void copyFrom(List<Object> src, int srcStart, ' |
| 259 'int dstStart, int count) {\n' |
| 260 ' throw new UnsupportedOperationException("This object is immutable."
);\n' |
| 261 ' }\n' |
| 262 '\n' |
| 263 ' int indexOf($TYPE element, [int start = 0]) {\n' |
| 264 ' return _Lists.indexOf(this, element, start, this.length);\n' |
| 265 ' }\n' |
| 266 '\n' |
| 267 ' int lastIndexOf($TYPE element, [int start = null]) {\n' |
| 268 ' if (start === null) start = length - 1;\n' |
| 269 ' return _Lists.lastIndexOf(this, element, start);\n' |
| 270 ' }\n' |
| 271 '\n' |
| 272 ' int clear() {\n' |
| 273 ' throw new UnsupportedOperationException("Cannot clear immutable Lis
t.");\n' |
| 274 ' }\n' |
| 275 '\n' |
| 276 ' $TYPE removeLast() {\n' |
| 277 ' throw new UnsupportedOperationException("Cannot removeLast on immut
able List.");\n' |
| 278 ' }\n' |
| 279 '\n' |
| 280 ' $TYPE last() {\n' |
| 281 ' return this[length - 1];\n' |
| 282 ' }\n' |
| 283 '\n' |
| 284 ' void forEach(void f($TYPE element)) {\n' |
| 285 ' _Collections.forEach(this, f);\n' |
| 286 ' }\n' |
| 287 '\n' |
| 288 ' Collection map(f($TYPE element)) {\n' |
| 289 ' return _Collections.map(this, [], f);\n' |
| 290 ' }\n' |
| 291 '\n' |
| 292 ' Collection<$TYPE> filter(bool f($TYPE element)) {\n' |
| 293 ' return _Collections.filter(this, new List<$TYPE>(), f);\n' |
| 294 ' }\n' |
| 295 '\n' |
| 296 ' bool every(bool f($TYPE element)) {\n' |
| 297 ' return _Collections.every(this, f);\n' |
| 298 ' }\n' |
| 299 '\n' |
| 300 ' bool some(bool f($TYPE element)) {\n' |
| 301 ' return _Collections.some(this, f);\n' |
| 302 ' }\n' |
| 303 '\n' |
| 304 ' void setRange(int start, int length, List<$TYPE> from, [int startFrom
]) {\n' |
| 305 ' throw new UnsupportedOperationException("Cannot setRange on immutab
le List.");\n' |
| 306 ' }\n' |
| 307 '\n' |
| 308 ' void removeRange(int start, int length) {\n' |
| 309 ' throw new UnsupportedOperationException("Cannot removeRange on immu
table List.");\n' |
| 310 ' }\n' |
| 311 '\n' |
| 312 ' void insertRange(int start, int length, [$TYPE initialValue]) {\n' |
| 313 ' throw new UnsupportedOperationException("Cannot insertRange on immu
table List.");\n' |
| 314 ' }\n' |
| 315 '\n' |
| 316 ' List<$TYPE> getRange(int start, int length) {\n' |
| 317 ' throw new NotImplementedException();\n' |
| 318 ' }\n' |
| 319 '\n' |
| 320 ' bool isEmpty() {\n' |
| 321 ' return length == 0;\n' |
| 322 ' }\n' |
| 323 '\n' |
| 324 ' Iterator<$TYPE> iterator() {\n' |
| 325 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
| 326 ' }\n', |
| 327 TYPE=element_type) |
| 328 |
| 329 def _HasNativeIndexGetter(self, interface): |
| 330 return ('IndexedGetter' in interface.ext_attrs or |
| 331 'NumericIndexedGetter' in interface.ext_attrs) |
| 332 |
| 333 def _EmitNativeIndexGetter(self, interface, element_type): |
| 334 method_name = '_index' |
| 335 self._members_emitter.Emit( |
| 336 '\n' |
| 337 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' |
| 338 ' static $TYPE $METHOD(var _this, int index) native;\n', |
| 339 TYPE=element_type, METHOD=method_name) |
| 340 |
| 341 def _HasNativeIndexSetter(self, interface): |
| 342 return 'CustomIndexedSetter' in interface.ext_attrs |
| 343 |
| 344 def _EmitNativeIndexSetter(self, interface, element_type): |
| 345 method_name = '_set_index' |
| 346 self._members_emitter.Emit( |
| 347 '\n' |
| 348 ' void operator[]=(int index, $TYPE value) {\n' |
| 349 ' return $METHOD(this, index, value);\n' |
| 350 ' }\n' |
| 351 ' static $METHOD(_this, index, value) native;\n', |
| 352 TYPE=element_type, METHOD=method_name) |
| 353 |
| 354 def AddOperation(self, info): |
| 355 """ |
| 356 Arguments: |
| 357 info: An OperationInfo object. |
| 358 """ |
| 359 body = self._members_emitter.Emit( |
| 360 '\n' |
| 361 ' $TYPE $NAME($PARAMS) {\n' |
| 362 '$!BODY' |
| 363 ' }\n', |
| 364 TYPE=info.type_name, |
| 365 NAME=info.name, |
| 366 PARAMS=info.ParametersImplementationDeclaration()) |
| 367 |
| 368 # Process in order of ascending number of arguments to ensure missing |
| 369 # optional arguments are processed early. |
| 370 overloads = sorted(info.overloads, |
| 371 key=lambda overload: len(overload.arguments)) |
| 372 self._native_version = 0 |
| 373 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
| 374 if fallthrough: |
| 375 body.Emit(' throw "Incorrect number or type of arguments";\n'); |
| 376 |
| 377 def GenerateSingleOperation(self, emitter, info, indent, operation): |
| 378 """Generates a call to a single operation. |
| 379 |
| 380 Arguments: |
| 381 emitter: an Emitter for the body of a block of code. |
| 382 info: the compound information about the operation and its overloads. |
| 383 indent: an indentation string for generated code. |
| 384 operation: the IDLOperation to call. |
| 385 """ |
| 386 # TODO(sra): Do we need to distinguish calling with missing optional |
| 387 # arguments from passing 'null' which is represented as 'undefined'? |
| 388 def UnwrapArgExpression(name, type): |
| 389 # TODO: Type specific unwrapping. |
| 390 return '__dom_unwrap(%s)' % (name) |
| 391 |
| 392 def ArgNameAndUnwrapper(arg_info, overload_arg): |
| 393 (name, type, value) = arg_info |
| 394 return (name, UnwrapArgExpression(name, type)) |
| 395 |
| 396 names_and_unwrappers = [ArgNameAndUnwrapper(info.arg_infos[i], arg) |
| 397 for (i, arg) in enumerate(operation.arguments)] |
| 398 unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] |
| 399 arg_names = [name for (name, _) in names_and_unwrappers] |
| 400 |
| 401 self._native_version += 1 |
| 402 native_name = self._MethodName('_', info.name) |
| 403 if self._native_version > 1: |
| 404 native_name = '%s_%s' % (native_name, self._native_version) |
| 405 |
| 406 argument_expressions = ', '.join(['this'] + arg_names) |
| 407 if info.type_name != 'void': |
| 408 emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', |
| 409 INDENT=indent, |
| 410 NATIVENAME=native_name, |
| 411 ARGS=argument_expressions) |
| 412 else: |
| 413 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' |
| 414 '$(INDENT)return;\n', |
| 415 INDENT=indent, |
| 416 NATIVENAME=native_name, |
| 417 ARGS=argument_expressions) |
| 418 |
| 419 self._members_emitter.Emit(' static $TYPE $NAME($PARAMS) native;\n', |
| 420 NAME=native_name, |
| 421 TYPE=info.type_name, |
| 422 PARAMS=', '.join(['receiver'] + arg_names) ) |
| 423 |
| 424 |
| 425 def GenerateDispatch(self, emitter, info, indent, position, overloads): |
| 426 """Generates a dispatch to one of the overloads. |
| 427 |
| 428 Arguments: |
| 429 emitter: an Emitter for the body of a block of code. |
| 430 info: the compound information about the operation and its overloads. |
| 431 indent: an indentation string for generated code. |
| 432 position: the index of the parameter to dispatch on. |
| 433 overloads: a list of the remaining IDLOperations to dispatch. |
| 434 |
| 435 Returns True if the dispatch can fall through on failure, False if the code |
| 436 always dispatches. |
| 437 """ |
| 438 |
| 439 def NullCheck(name): |
| 440 return '%s === null' % name |
| 441 |
| 442 def TypeCheck(name, type): |
| 443 return '%s is %s' % (name, type) |
| 444 |
| 445 if position == len(info.arg_infos): |
| 446 if len(overloads) > 1: |
| 447 raise Exception('Duplicate operations ' + str(overloads)) |
| 448 operation = overloads[0] |
| 449 self.GenerateSingleOperation(emitter, info, indent, operation) |
| 450 return False |
| 451 |
| 452 # FIXME: Consider a simpler dispatch that iterates over the |
| 453 # overloads and generates an overload specific check. Revisit |
| 454 # when we move to named optional arguments. |
| 455 |
| 456 # Partition the overloads to divide and conquer on the dispatch. |
| 457 positive = [] |
| 458 negative = [] |
| 459 first_overload = overloads[0] |
| 460 (param_name, param_type, param_default) = info.arg_infos[position] |
| 461 |
| 462 if position < len(first_overload.arguments): |
| 463 # FIXME: This will not work if the second overload has a more |
| 464 # precise type than the first. E.g., |
| 465 # void foo(Node x); |
| 466 # void foo(Element x); |
| 467 type = first_overload.arguments[position].type.id |
| 468 test = TypeCheck(param_name, type) |
| 469 pred = lambda op: len(op.arguments) > position and op.arguments[position].
type.id == type |
| 470 else: |
| 471 type = None |
| 472 test = NullCheck(param_name) |
| 473 pred = lambda op: position >= len(op.arguments) |
| 474 |
| 475 for overload in overloads: |
| 476 if pred(overload): |
| 477 positive.append(overload) |
| 478 else: |
| 479 negative.append(overload) |
| 480 |
| 481 if positive and negative: |
| 482 (true_code, false_code) = emitter.Emit( |
| 483 '$(INDENT)if ($COND) {\n' |
| 484 '$!TRUE' |
| 485 '$(INDENT)} else {\n' |
| 486 '$!FALSE' |
| 487 '$(INDENT)}\n', |
| 488 COND=test, INDENT=indent) |
| 489 fallthrough1 = self.GenerateDispatch( |
| 490 true_code, info, indent + ' ', position + 1, positive) |
| 491 fallthrough2 = self.GenerateDispatch( |
| 492 false_code, info, indent + ' ', position, negative) |
| 493 return fallthrough1 or fallthrough2 |
| 494 |
| 495 if negative: |
| 496 raise Exception('Internal error, must be all positive') |
| 497 |
| 498 # All overloads require the same test. Do we bother? |
| 499 |
| 500 # If the test is the same as the method's formal parameter then checked mode |
| 501 # will have done the test already. (It could be null too but we ignore that |
| 502 # case since all the overload behave the same and we don't know which types |
| 503 # in the IDL are not nullable.) |
| 504 if type == param_type: |
| 505 return self.GenerateDispatch( |
| 506 emitter, info, indent, position + 1, positive) |
| 507 |
| 508 # Otherwise the overloads have the same type but the type is a substype of |
| 509 # the method's synthesized formal parameter. e.g we have overloads f(X) and |
| 510 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The |
| 511 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
| 512 # that Y = Z-X, so we need to check for Y. |
| 513 true_code = emitter.Emit( |
| 514 '$(INDENT)if ($COND) {\n' |
| 515 '$!TRUE' |
| 516 '$(INDENT)}\n', |
| 517 COND=test, INDENT=indent) |
| 518 self.GenerateDispatch( |
| 519 true_code, info, indent + ' ', position + 1, positive) |
| 520 return True |
OLD | NEW |