| OLD | NEW |
| (Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Nodes for PPAPI IDL AST.""" |
| 6 |
| 7 from idl_namespace import IDLNamespace |
| 8 from idl_node import IDLAttribute, IDLFile, IDLNode |
| 9 from idl_option import GetOption |
| 10 from idl_visitor import IDLVisitor |
| 11 from idl_release import IDLReleaseList, IDLReleaseMap |
| 12 |
| 13 # |
| 14 # IDL Predefined types |
| 15 # |
| 16 BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', |
| 17 'uint16_t', 'uint32_t', 'uint64_t', 'double_t', 'float_t', |
| 18 'handle_t', 'interface_t', 'char', 'mem_t', 'str_t', 'void']) |
| 19 |
| 20 |
| 21 # |
| 22 # IDLLabelResolver |
| 23 # |
| 24 # A specialized visitor which traverses the AST, building a mapping of |
| 25 # Release names to Versions numbers and calculating a min version. |
| 26 # The mapping is applied to the File nodes within the AST. |
| 27 # |
| 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): |
| 69 NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct']) |
| 70 # |
| 71 # When we arrive at a node we must assign it a namespace and if the |
| 72 # node is named, then place it in the appropriate namespace. |
| 73 # |
| 74 def Arrive(self, node, parent_namespace): |
| 75 # If we are a File, grab the Min version and replease mapping |
| 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) |
| 85 |
| 86 # If this object is not a namespace aware object, use the parent's one |
| 87 if node.cls not in self.NamespaceSet: |
| 88 node.namespace = parent_namespace |
| 89 else: |
| 90 # otherwise create one. |
| 91 node.namespace = IDLNamespace(parent_namespace, node.GetName()) |
| 92 |
| 93 # If this node is named, place it in its parent's namespace |
| 94 if parent_namespace and node.cls in IDLNode.NamedSet: |
| 95 # Set version min and max based on properties |
| 96 if self.release_map: |
| 97 vmin = node.GetProperty('version') |
| 98 vmax = node.GetProperty('deprecate') |
| 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) |
| 104 rmax = self.release_map.GetRelease(vmax) |
| 105 node.SetReleaseRange(rmin, rmax) |
| 106 parent_namespace.AddNode(node) |
| 107 |
| 108 # Pass this namespace to each child in case they inherit it |
| 109 return node.namespace |
| 110 |
| 111 |
| 112 # |
| 113 # IDLFileTypeRessolver |
| 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 # |
| 120 class IDLFileTypeResolver(IDLVisitor): |
| 121 def VisitFilter(self, node, data): |
| 122 return not node.IsA('Comment', 'Copyright') |
| 123 |
| 124 def Arrive(self, node, filenode): |
| 125 # Track the file node to update errors |
| 126 if node.IsA('File'): |
| 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) |
| 135 |
| 136 # If this node has a TYPEREF, resolve it to a version list |
| 137 typeref = node.property_node.GetPropertyLocal('TYPEREF') |
| 138 if typeref: |
| 139 node.typelist = node.parent.namespace.FindList(typeref) |
| 140 if not node.typelist: |
| 141 node.Error('Could not resolve %s.' % typeref) |
| 142 else: |
| 143 node.typelist = None |
| 144 return filenode |
| 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 |
| 158 |
| 159 # |
| 160 # IDLAst |
| 161 # |
| 162 # A specialized version of the IDLNode for containing the whole of the |
| 163 # AST. Construction of the AST object will cause resolution of the |
| 164 # tree including versions, types, etc... Errors counts will be collected |
| 165 # both per file, and on the AST itself. |
| 166 # |
| 167 class IDLAst(IDLNode): |
| 168 def __init__(self, children): |
| 169 IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children) |
| 170 self.Resolve() |
| 171 |
| 172 def Resolve(self): |
| 173 # Set the appropriate Release=Version mapping for each File |
| 174 IDLLabelResolver().Visit(self, None) |
| 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 |
| 181 IDLFileTypeResolver().Visit(self, None) |
| 182 |
| 183 # Build an ordered list of all releases |
| 184 releases = set() |
| 185 for filenode in self.GetListOf('File'): |
| 186 releases |= set(filenode.release_map.GetReleases()) |
| 187 |
| 188 # Generate a per node list of releases and release mapping |
| 189 IDLReleaseResolver().Visit(self, sorted(releases)) |
| 190 |
| 191 for filenode in self.GetListOf('File'): |
| 192 self.errors += int(filenode.GetProperty('ERRORS', 0)) |
| 193 |
| 194 |
| OLD | NEW |