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