OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Nodes for PPAPI IDL AST.""" | 5 """Nodes for PPAPI IDL AST.""" |
6 | 6 |
7 from idl_namespace import IDLNamespace | 7 from idl_namespace import IDLNamespace |
8 from idl_node import IDLAttribute, IDLFile, IDLNode | 8 from idl_node import IDLAttribute, IDLFile, IDLNode |
9 from idl_option import GetOption | 9 from idl_option import GetOption |
10 from idl_visitor import IDLVisitor | 10 from idl_visitor import IDLVisitor |
11 from idl_release import IDLReleaseList, IDLReleaseMap | 11 from idl_release import IDLReleaseList, IDLReleaseMap |
12 | 12 |
13 # | 13 # |
14 # IDL Predefined types | 14 # IDL Predefined types |
15 # | 15 # |
16 BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', | 16 BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', |
17 'uint16_t', 'uint32_t', 'uint64_t', 'double_t', 'float_t', | 17 'uint16_t', 'uint32_t', 'uint64_t', 'double_t', 'float_t', |
18 'handle_t', 'interface_t', 'char', 'mem_t', 'str_t', 'void']) | 18 'handle_t', 'interface_t', 'char', 'mem_t', 'str_t', 'void']) |
19 | 19 |
20 | 20 |
21 # | 21 # |
22 # IDLNamespaceLabelResolver | 22 # IDLLabelResolver |
23 # | 23 # |
24 # Once the AST is build, we need to resolve the namespace and version | 24 # A specialized visitor which traverses the AST, building a mapping of |
25 # information. | 25 # Release names to Versions numbers and calculating a min version. |
26 # The mapping is applied to the File nodes within the AST. | |
26 # | 27 # |
27 class IDLNamespaceLabelResolver(IDLVisitor): | 28 class IDLLabelResolver(IDLVisitor): |
29 def Arrive(self, node, ignore): | |
30 # If we are entering a File, clear the visitor local mapping | |
31 if node.IsA('File'): | |
32 self.release_map = None | |
33 self.filenode = node | |
34 # For any non AST node, the filenode is the last known file | |
35 if not node.IsA('AST'): | |
36 node.filenode = self.filenode | |
37 return ignore | |
38 | |
39 def Depart(self, node, ignore, childdata): | |
40 # Build list of Release=Version | |
41 if node.IsA('LabelItem'): | |
42 return (node.GetName(), node.GetProperty('VALUE')) | |
43 | |
44 # On completion of the Label, apply to the parent File if the | |
45 # name of the label matches the generation label. | |
46 if node.IsA('Label') and node.GetName() == GetOption('label'): | |
47 try: | |
48 self.release_map = IDLReleaseMap(childdata) | |
49 node.parent.release_map = self.release_map | |
50 except Exception as err: | |
51 node.Error('Unable to build release map: %s' % str(err)) | |
52 | |
53 # For File objects, set the minimum version | |
54 if node.IsA('File'): | |
55 file_min, file_max = node.release_map.GetReleaseRange() | |
56 node.SetMin(file_min) | |
57 | |
58 return None | |
59 | |
60 | |
61 # | |
62 # IDLNamespaceVersionResolver | |
63 # | |
64 # A specialized visitor which traverses the AST, building a namespace tree | |
65 # as it goes. The namespace tree is mapping from a name to a version list. | |
66 # Labels must already be resolved to use. | |
67 # | |
68 class IDLNamespaceVersionResolver(IDLVisitor): | |
28 NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct']) | 69 NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct']) |
29 # | 70 # |
30 # When we arrive at a node we must assign it a namespace and if the | 71 # When we arrive at a node we must assign it a namespace and if the |
31 # node is named, then place it in the appropriate namespace. | 72 # node is named, then place it in the appropriate namespace. |
32 # | 73 # |
33 def Arrive(self, node, parent_namespace): | 74 def Arrive(self, node, parent_namespace): |
34 # If we are entering a parent, clear the local Label\ | 75 # If we are a File, grab the Min version and replease mapping |
35 if node.IsA('File'): self.release_map = None | 76 if node.IsA('File'): |
77 self.rmin = node.GetMinMax()[0] | |
78 self.release_map = node.release_map | |
79 | |
80 # Set the min version on any non Label within the File | |
81 if not node.IsA('AST', 'File', 'Label', 'LabelItem'): | |
82 my_min, my_max = node.GetMinMax() | |
83 if not my_min: | |
84 node.SetMin(self.rmin) | |
36 | 85 |
37 # If this object is not a namespace aware object, use the parent's one | 86 # If this object is not a namespace aware object, use the parent's one |
38 if node.cls not in self.NamespaceSet: | 87 if node.cls not in self.NamespaceSet: |
39 node.namespace = parent_namespace | 88 node.namespace = parent_namespace |
40 else: | 89 else: |
41 # otherwise create one. | 90 # otherwise create one. |
42 node.namespace = IDLNamespace(parent_namespace) | 91 node.namespace = IDLNamespace(parent_namespace, node.GetName()) |
43 node.namespace.name = node.GetName() | |
44 | 92 |
45 # If this node is named, place it in its parent's namespace | 93 # If this node is named, place it in its parent's namespace |
46 if parent_namespace and node.cls in IDLNode.NamedSet: | 94 if parent_namespace and node.cls in IDLNode.NamedSet: |
47 # Set version min and max based on properties | 95 # Set version min and max based on properties |
48 if self.release_map: | 96 if self.release_map: |
49 vmin = node.GetProperty('version') | 97 vmin = node.GetProperty('version') |
50 vmax = node.GetProperty('deprecate') | 98 vmax = node.GetProperty('deprecate') |
51 rmin = self.release_map.GetRelease(vmin) | 99 # If no min is available, the use the parent File's min |
100 if vmin == None: | |
101 rmin = self.rmin | |
102 else: | |
103 rmin = self.release_map.GetRelease(vmin) | |
52 rmax = self.release_map.GetRelease(vmax) | 104 rmax = self.release_map.GetRelease(vmax) |
53 node.SetReleaseRange(rmin, rmax) | 105 node.SetReleaseRange(rmin, rmax) |
54 parent_namespace.AddNode(node) | 106 parent_namespace.AddNode(node) |
55 | 107 |
56 # Pass this namespace to each child in case they inherit it | 108 # Pass this namespace to each child in case they inherit it |
57 return node.namespace | 109 return node.namespace |
58 | 110 |
59 # | |
60 # As we return from a node, if the node is a LabelItem we pass back | |
61 # the key=value pair representing the mapping of release to version. | |
62 # If the node is a Label take the lists of mapping and generate a | |
63 # version map which is assigned to the Labels parent as a property. | |
64 # | |
65 def Depart(self, node, data, childdata): | |
66 if node.IsA('LabelItem'): | |
67 return (node.GetName(), node.GetProperty('VALUE')) | |
68 if node.IsA('Label') and node.GetName() == GetOption('label'): | |
69 try: | |
70 self.release_map = IDLReleaseMap(childdata) | |
71 node.parent.release_map = self.release_map | |
72 except Exception as err: | |
73 node.Error('Unable to build release map: %s' % str(err)) | |
74 return None | |
75 | 111 |
76 | 112 # |
113 # IDLFileTypeRessolver | |
sehr
2012/10/22 18:20:09
one s, please.
| |
114 # | |
115 # A specialized visitor which traverses the AST and sets a FILE property | |
116 # on all file nodes. In addition, searches the namespace resolving all | |
117 # type references. The namespace tree must already have been populated | |
118 # before this visitor is used. | |
119 # | |
77 class IDLFileTypeResolver(IDLVisitor): | 120 class IDLFileTypeResolver(IDLVisitor): |
78 def VisitFilter(self, node, data): | 121 def VisitFilter(self, node, data): |
79 return not node.IsA('Comment', 'Copyright') | 122 return not node.IsA('Comment', 'Copyright') |
80 | 123 |
81 def Arrive(self, node, filenode): | 124 def Arrive(self, node, filenode): |
82 # Track the file node to update errors | 125 # Track the file node to update errors |
83 if node.IsA('File'): | 126 if node.IsA('File'): |
84 node.SetProperty('FILE', node) | 127 node.SetProperty('FILE', node) |
128 filenode = node | |
129 | |
130 if not node.IsA('AST'): | |
131 file_min, file_max = filenode.release_map.GetReleaseRange() | |
132 if not file_min: | |
133 print 'Resetting min on %s to %s' % (node, file_min) | |
134 node.SetMinRange(file_min) | |
85 | 135 |
86 # If this node has a TYPEREF, resolve it to a version list | 136 # If this node has a TYPEREF, resolve it to a version list |
87 typeref = node.property_node.GetPropertyLocal('TYPEREF') | 137 typeref = node.property_node.GetPropertyLocal('TYPEREF') |
88 if typeref: | 138 if typeref: |
89 node.typelist = node.parent.namespace.FindList(typeref) | 139 node.typelist = node.parent.namespace.FindList(typeref) |
90 if not node.typelist: | 140 if not node.typelist: |
91 node.Error('Could not resolve %s.' % typeref) | 141 node.Error('Could not resolve %s.' % typeref) |
92 else: | 142 else: |
93 node.typelist = None | 143 node.typelist = None |
94 return filenode | 144 return filenode |
95 | 145 |
146 # | |
147 # IDLReleaseResolver | |
148 # | |
149 # A specialized visitor which will traverse the AST, and generate a mapping | |
150 # from any release to the first release in which that version of the object | |
151 # was generated. Types must already be resolved to use. | |
152 # | |
153 class IDLReleaseResolver(IDLVisitor): | |
154 def Arrive(self, node, releases): | |
155 node.BuildReleaseMap(releases) | |
156 return releases | |
157 | |
96 | 158 |
97 # | 159 # |
98 # IDLAst | 160 # IDLAst |
99 # | 161 # |
100 # A specialized version of the IDLNode for containing the whole of the | 162 # A specialized version of the IDLNode for containing the whole of the |
101 # AST. The specialized BuildTree function pulls the per file namespaces | 163 # AST. Construction of the AST object will cause resolution of the |
102 # into the global AST namespace and checks for collisions. | 164 # tree including versions, types, etc... Errors counts will be collected |
165 # both per file, and on the AST itself. | |
103 # | 166 # |
104 class IDLAst(IDLNode): | 167 class IDLAst(IDLNode): |
105 def __init__(self, children): | 168 def __init__(self, children): |
106 IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children) | 169 IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children) |
107 self.Resolve() | 170 self.Resolve() |
108 | 171 |
109 def Resolve(self): | 172 def Resolve(self): |
110 self.namespace = IDLNamespace(None) | 173 # Set the appropriate Release=Version mapping for each File |
111 self.namespace.name = 'AST' | 174 IDLLabelResolver().Visit(self, None) |
112 IDLNamespaceLabelResolver().Visit(self, self.namespace) | 175 |
176 # Generate the Namesapce Tree | |
177 self.namespace = IDLNamespace(None, 'AST') | |
178 IDLNamespaceVersionResolver().Visit(self, self.namespace) | |
179 | |
180 # Using the namespace, resolve type references | |
113 IDLFileTypeResolver().Visit(self, None) | 181 IDLFileTypeResolver().Visit(self, None) |
114 | 182 |
115 # Build an ordered list of all releases | 183 # Build an ordered list of all releases |
116 self.releases = set() | 184 releases = set() |
117 for filenode in self.GetListOf('File'): | 185 for filenode in self.GetListOf('File'): |
118 self.releases |= set(filenode.release_map.GetReleases()) | 186 releases |= set(filenode.release_map.GetReleases()) |
119 self.releases = sorted(self.releases) | |
120 | 187 |
121 def SetTypeInfo(self, name, properties): | 188 # Generate a per node list of releases and release mapping |
122 node = self.namespace[name] | 189 IDLReleaseResolver().Visit(self, sorted(releases)) |
123 for prop in properties: | 190 |
124 node.properties[prop] = properties[prop] | 191 for filenode in self.GetListOf('File'): |
192 self.errors += int(filenode.GetProperty('ERRORS', 0)) | |
193 | |
194 | |
OLD | NEW |