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

Side by Side Diff: lib/dom/scripts/systemnative.py

Issue 10449019: Revert "Dispatch changes to be more like V8." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 4 # BSD-style license that can be found in the LICENSE file.
5 5
6 """This module provides shared functionality for the systems to generate 6 """This module provides shared functionality for the systems to generate
7 native binding from the IDL database.""" 7 native binding from the IDL database."""
8 8
9 import emitter 9 import emitter
10 import os 10 import os
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 body = self._members_emitter.Emit( 858 body = self._members_emitter.Emit(
859 '\n' 859 '\n'
860 ' $MODIFIER$TYPE $NAME($PARAMETERS) {\n' 860 ' $MODIFIER$TYPE $NAME($PARAMETERS) {\n'
861 '$!BODY' 861 '$!BODY'
862 ' }\n', 862 ' }\n',
863 MODIFIER=modifier, 863 MODIFIER=modifier,
864 TYPE=self._DartType(info.type_name), 864 TYPE=self._DartType(info.type_name),
865 NAME=info.name, 865 NAME=info.name,
866 PARAMETERS=parameters) 866 PARAMETERS=parameters)
867 867
868 # Process in order of ascending number of arguments to ensure missing
869 # optional arguments are processed early.
870 overloads = sorted(info.overloads,
871 key=lambda overload: len(overload.arguments))
868 self._native_version = 0 872 self._native_version = 0
869 overloads = self.CombineOverloads(info.overloads) 873 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads)
870 fallthrough = self.GenerateDispatch(body, info, ' ', overloads)
871 if fallthrough: 874 if fallthrough:
872 body.Emit(' throw "Incorrect number or type of arguments";\n'); 875 body.Emit(' throw "Incorrect number or type of arguments";\n');
873 876
874 def CombineOverloads(self, overloads): 877 def GenerateDispatch(self, emitter, info, indent, position, overloads):
875 # Combine overloads that can be implemented by the same native method. This
876 # undoes the expansion of optional arguments into multiple overloads unless
877 # IDL merging has made the overloads necessary. Starting with overload with
878 # no optional arguments and grow it by adding optional arguments, then the
879 # longest overload can serve for all the shorter ones.
880 out = []
881 seed_index = 0
882 while seed_index < len(overloads):
883 seed = overloads[seed_index]
884 if len(seed.arguments) > 0 and seed.arguments[-1].is_optional:
885 # Must start with no optional arguments.
886 out.append(seed)
887 seed_index += 1
888 continue
889
890 prev = seed
891 probe_index = seed_index + 1
892 while probe_index < len(overloads):
893 probe = overloads[probe_index]
894 # Check that 'probe' extends 'prev' by one optional argument.
895 if len(probe.arguments) != len(prev.arguments) + 1:
896 break
897 if probe.arguments[:-1] != prev.arguments:
898 break
899 if not probe.arguments[-1].is_optional:
900 break
901 # See Issue 3177. This test against known implemented types is to
902 # prevent combining a possibly unimplemented type. Combining with an
903 # unimplemented type will cause all set of combined overloads to become
904 # 'unimplemented', even if no argument is passed to the the
905 # unimplemented parameter.
906 if DartType(probe.arguments[-1].type.id) not in [
907 'String', 'int', 'num', 'double', 'bool',
908 'IDBKeyRange']:
909 break
910 probe_index += 1
911 prev = probe
912 out.append(prev)
913 seed_index = probe_index
914
915 return out
916
917 def PrintOverloadsComment(self, emitter, info, indent, note, overloads):
918 emitter.Emit('$(INDENT)//$NOTE\n', INDENT=indent, NOTE=note)
919 for operation in overloads:
920 params = ', '.join([
921 ('[Optional] ' if arg.is_optional else '') + DartType(arg.type.id) + ' '
922 + arg.id for arg in operation.arguments])
923 emitter.Emit('$(INDENT)// $NAME($PARAMS)\n',
924 INDENT=indent,
925 NAME=info.name,
926 PARAMS=params)
927 emitter.Emit('$(INDENT)//\n', INDENT=indent)
928
929 def GenerateDispatch(self, emitter, info, indent, overloads):
930 """Generates a dispatch to one of the overloads. 878 """Generates a dispatch to one of the overloads.
931 879
932 Arguments: 880 Arguments:
933 emitter: an Emitter for the body of a block of code. 881 emitter: an Emitter for the body of a block of code.
934 info: the compound information about the operation and its overloads. 882 info: the compound information about the operation and its overloads.
935 indent: an indentation string for generated code. 883 indent: an indentation string for generated code.
936 position: the index of the parameter to dispatch on. 884 position: the index of the parameter to dispatch on.
937 overloads: a list of the IDLOperations to dispatch. 885 overloads: a list of the remaining IDLOperations to dispatch.
938 886
939 Returns True if the dispatch can fall through on failure, False if the code 887 Returns True if the dispatch can fall through on failure, False if the code
940 always dispatches. 888 always dispatches.
941 """ 889 """
942 890
943 def NullCheck(name): 891 def NullCheck(name):
944 return '%s === null' % name 892 return '%s === null' % name
945 893
946 def TypeCheck(name, type): 894 def TypeCheck(name, type):
947 return '%s is %s' % (name, type) 895 return '%s is %s' % (name, type)
948 896
949 def IsNullable(type): 897 def ShouldGenerateSingleOperation():
950 #return type != 'int' and type != 'num' 898 if position == len(info.param_infos):
951 return True 899 if len(overloads) > 1:
900 raise Exception('Duplicate operations ' + str(overloads))
901 return True
952 902
953 def PickRequiredCppSingleOperation(): 903 # Check if we dispatch on RequiredCppParameter arguments. In this
954 # Returns a special case single operation, or None. Check if we dispatch 904 # case all trailing arguments must be RequiredCppParameter and there
955 # on RequiredCppParameter arguments. In this case all trailing arguments 905 # is no need in dispatch.
956 # must be RequiredCppParameter and there is no need in dispatch. 906 # TODO(antonm): better diagnositics.
957 def IsRequiredCppParameter(arg): 907 if position >= len(overloads[0].arguments):
958 return 'RequiredCppParameter' in arg.ext_attrs 908 def IsRequiredCppParameter(arg):
959 def HasRequiredCppParameters(op): 909 return 'RequiredCppParameter' in arg.ext_attrs
960 matches = filter(IsRequiredCppParameter, op.arguments) 910 last_overload = overloads[-1]
961 if matches: 911 if (len(last_overload.arguments) > position and
962 # Validate all the RequiredCppParameter ones are at the end. 912 IsRequiredCppParameter(last_overload.arguments[position])):
963 rematches = filter(IsRequiredCppParameter, 913 for overload in overloads:
964 op.arguments[len(op.arguments) - len(matches):]) 914 args = overload.arguments[position:]
965 if len(matches) != len(rematches): 915 if not all([IsRequiredCppParameter(arg) for arg in args]):
966 raise Exception('Invalid RequiredCppParameter - all subsequent ' 916 raise Exception('Invalid overload for RequiredCppParameter')
967 'parameters must also be RequiredCppParameter.')
968 return True 917 return True
969 return False
970 if any(HasRequiredCppParameters(op) for op in overloads):
971 longest = max(overloads, key=lambda op: len(op.arguments))
972 # Validate all other overloads are prefixes.
973 for op in overloads:
974 for (index, arg) in enumerate(op.arguments):
975 type1 = arg.type.id
976 type2 = longest.arguments[index].type.id
977 if type1 != type2:
978 raise Exception(
979 'Overloads for method %s with RequiredCppParameter have '
980 'inconsistent types %s and %s for parameter #%s' %
981 (info.name, type1, type2, index))
982 return longest
983 return None
984 918
985 single_operation = PickRequiredCppSingleOperation()
986 if single_operation:
987 self.GenerateSingleOperation(emitter, info, indent, single_operation)
988 return False 919 return False
989 920
990 # Print just the interesting sets of overloads. 921 if ShouldGenerateSingleOperation():
991 if len(overloads) > 1 or len(info.overloads) > 1: 922 self.GenerateSingleOperation(emitter, info, indent, overloads[-1])
992 self.PrintOverloadsComment(emitter, info, indent, '', info.overloads) 923 return False
993 if overloads != info.overloads:
994 self.PrintOverloadsComment(emitter, info, indent, ' -- reduced:',
995 overloads)
996 924
997 # Match each operation in turn. 925 # FIXME: Consider a simpler dispatch that iterates over the
998 # TODO: Optimize the dispatch to avoid repeated tests. 926 # overloads and generates an overload specific check. Revisit
999 fallthrough = True 927 # when we move to named optional arguments.
1000 for operation in overloads: 928
1001 tests = [] 929 # Partition the overloads to divide and conquer on the dispatch.
1002 for (position, param) in enumerate(info.param_infos): 930 positive = []
1003 if position < len(operation.arguments): 931 negative = []
1004 arg = operation.arguments[position] 932 first_overload = overloads[0]
1005 dart_type = DartType(arg.type.id) 933 param = info.param_infos[position]
1006 if dart_type == param.dart_type: 934
1007 # The overload type matches the method parameter type exactly. We 935 if position < len(first_overload.arguments):
1008 # will have already tested this type in checked mode, and the target 936 # FIXME: This will not work if the second overload has a more
1009 # will expect (i.e. check) this type. This case happens when all 937 # precise type than the first. E.g.,
1010 # the overloads have the same type in this position, including the 938 # void foo(Node x);
1011 # trivial case of one overload. 939 # void foo(Element x);
1012 test = None 940 type = self._DartType(first_overload.arguments[position].type.id)
1013 else: 941 test = TypeCheck(param.name, type)
1014 test = TypeCheck(param.name, dart_type) 942 pred = lambda op: len(op.arguments) > position and self._DartType(op.argum ents[position].type.id) == type
1015 if IsNullable(dart_type) or arg.is_optional: 943 else:
1016 test = '(%s || %s)' % (NullCheck(param.name), test) 944 type = None
1017 else: 945 test = NullCheck(param.name)
1018 test = NullCheck(param.name) 946 pred = lambda op: position >= len(op.arguments)
1019 if test: 947
1020 tests.append(test) 948 for overload in overloads:
1021 if tests: 949 if pred(overload):
1022 cond = ' && '.join(tests) 950 positive.append(overload)
1023 if len(cond) + len(indent) + 7 > 80:
1024 cond = (' &&\n' + indent + ' ').join(tests)
1025 call = emitter.Emit(
1026 '$(INDENT)if ($COND) {\n'
1027 '$!CALL'
1028 '$(INDENT)}\n',
1029 COND=cond,
1030 INDENT=indent)
1031 self.GenerateSingleOperation(call, info, indent + ' ', operation)
1032 else: 951 else:
1033 self.GenerateSingleOperation(emitter, info, indent, operation) 952 negative.append(overload)
1034 fallthrough = False 953
1035 return fallthrough 954 if positive and negative:
955 (true_code, false_code) = emitter.Emit(
956 '$(INDENT)if ($COND) {\n'
957 '$!TRUE'
958 '$(INDENT)} else {\n'
959 '$!FALSE'
960 '$(INDENT)}\n',
961 COND=test, INDENT=indent)
962 fallthrough1 = self.GenerateDispatch(
963 true_code, info, indent + ' ', position + 1, positive)
964 fallthrough2 = self.GenerateDispatch(
965 false_code, info, indent + ' ', position, negative)
966 return fallthrough1 or fallthrough2
967
968 if negative:
969 raise Exception('Internal error, must be all positive')
970
971 # All overloads require the same test. Do we bother?
972
973 # If the test is the same as the method's formal parameter then checked mode
974 # will have done the test already. (It could be null too but we ignore that
975 # case since all the overload behave the same and we don't know which types
976 # in the IDL are not nullable.)
977 if type == param.dart_type:
978 return self.GenerateDispatch(
979 emitter, info, indent, position + 1, positive)
980
981 # Otherwise the overloads have the same type but the type is a subtype of
982 # the method's synthesized formal parameter. e.g we have overloads f(X) and
983 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The
984 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee
985 # that Y = Z-X, so we need to check for Y.
986 true_code = emitter.Emit(
987 '$(INDENT)if ($COND) {\n'
988 '$!TRUE'
989 '$(INDENT)}\n',
990 COND=test, INDENT=indent)
991 self.GenerateDispatch(
992 true_code, info, indent + ' ', position + 1, positive)
993 return True
1036 994
1037 def AddOperation(self, info): 995 def AddOperation(self, info):
1038 self._AddOperation(info) 996 self._AddOperation(info)
1039 997
1040 def AddStaticOperation(self, info): 998 def AddStaticOperation(self, info):
1041 self._AddOperation(info) 999 self._AddOperation(info)
1042 1000
1043 def AddSecondaryOperation(self, interface, info): 1001 def AddSecondaryOperation(self, interface, info):
1044 self.AddOperation(info) 1002 self.AddOperation(info)
1045 1003
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 for parent in interface.parents: 1237 for parent in interface.parents:
1280 parent_name = parent.type.id 1238 parent_name = parent.type.id
1281 if not database.HasInterface(parent.type.id): 1239 if not database.HasInterface(parent.type.id):
1282 continue 1240 continue
1283 parent_interface = database.GetInterface(parent.type.id) 1241 parent_interface = database.GetInterface(parent.type.id)
1284 if callback(parent_interface): 1242 if callback(parent_interface):
1285 return parent_interface 1243 return parent_interface
1286 parent_interface = _FindParent(parent_interface, database, callback) 1244 parent_interface = _FindParent(parent_interface, database, callback)
1287 if parent_interface: 1245 if parent_interface:
1288 return parent_interface 1246 return parent_interface
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698