15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Nodes for PPAPI IDL AST."""
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_namespace import IDLNamespace
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)from idl_node import IDLNode
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_option import GetOption
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_visitor import IDLVisitor
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)from idl_release import IDLReleaseMap
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLLabelResolver
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST, building a mapping of
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Release names to Versions numbers and calculating a min version.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The mapping is applied to the File nodes within the AST.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLLabelResolver(IDLVisitor):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Depart(self, node, ignore, childdata):
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Build list of Release=Version
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('LabelItem'):
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      channel = node.GetProperty('channel')
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if not channel:
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        channel = 'stable'
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return (node.GetName(), node.GetProperty('VALUE'), channel)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # On completion of the Label, apply to the parent File if the
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # name of the label matches the generation label.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Label') and node.GetName() == GetOption('label'):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      try:
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        node.parent.release_map = IDLReleaseMap(childdata)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      except Exception as err:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.Error('Unable to build release map: %s' % str(err))
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For File objects, set the minimum version
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_min, _ = node.release_map.GetReleaseRange()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.SetMin(file_min)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLNamespaceVersionResolver
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST, building a namespace tree
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# as it goes.  The namespace tree is mapping from a name to a version list.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Labels must already be resolved to use.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLNamespaceVersionResolver(IDLVisitor):
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct'])
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # When we arrive at a node we must assign it a namespace and if the
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # node is named, then place it in the appropriate namespace.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, parent_namespace):
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If we are a File, grab the Min version and replease mapping
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.rmin = node.GetMinMax()[0]
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.release_map = node.release_map
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set the min version on any non Label within the File
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not node.IsA('AST', 'File', 'Label', 'LabelItem'):
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      my_min, _ = node.GetMinMax()
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not my_min:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetMin(self.rmin)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this object is not a namespace aware object, use the parent's one
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.cls not in self.NamespaceSet:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.namespace = parent_namespace
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # otherwise create one.
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      node.namespace = IDLNamespace(parent_namespace)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this node is named, place it in its parent's namespace
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if parent_namespace and node.cls in IDLNode.NamedSet:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Set version min and max based on properties
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.release_map:
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        vmin = node.GetProperty('dev_version')
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if vmin == None:
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          vmin = node.GetProperty('version')
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vmax = node.GetProperty('deprecate')
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # If no min is available, the use the parent File's min
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if vmin == None:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rmin = self.rmin
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rmin = self.release_map.GetRelease(vmin)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rmax = self.release_map.GetRelease(vmax)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetReleaseRange(rmin, rmax)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent_namespace.AddNode(node)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Pass this namespace to each child in case they inherit it
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return node.namespace
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLFileTypeRessolver
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST and sets a FILE property
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# on all file nodes.  In addition, searches the namespace resolving all
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# type references.  The namespace tree must already have been populated
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# before this visitor is used.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLFileTypeResolver(IDLVisitor):
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def VisitFilter(self, node, data):
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not node.IsA('Comment', 'Copyright')
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, filenode):
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Track the file node to update errors
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.SetProperty('FILE', node)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filenode = node
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not node.IsA('AST'):
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_min, _ = filenode.release_map.GetReleaseRange()
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not file_min:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print 'Resetting min on %s to %s' % (node, file_min)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetMinRange(file_min)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this node has a TYPEREF, resolve it to a version list
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    typeref = node.GetPropertyLocal('TYPEREF')
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if typeref:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.typelist = node.parent.namespace.FindList(typeref)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not node.typelist:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.Error('Could not resolve %s.' % typeref)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.typelist = None
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return filenode
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLReleaseResolver
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which will traverse the AST, and generate a mapping
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# from any release to the first release in which that version of the object
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# was generated.  Types must already be resolved to use.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLReleaseResolver(IDLVisitor):
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, releases):
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.BuildReleaseMap(releases)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return releases
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLAst
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized version of the IDLNode for containing the whole of the
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# AST.  Construction of the AST object will cause resolution of the
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# tree including versions, types, etc...  Errors counts will be collected
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# both per file, and on the AST itself.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLAst(IDLNode):
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, children):
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Resolve()
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Resolve(self):
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set the appropriate Release=Version mapping for each File
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLLabelResolver().Visit(self, None)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate the Namesapce Tree
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    self.namespace = IDLNamespace(None)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLNamespaceVersionResolver().Visit(self, self.namespace)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Using the namespace, resolve type references
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLFileTypeResolver().Visit(self, None)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Build an ordered list of all releases
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    releases = set()
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for filenode in self.GetListOf('File'):
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      releases |= set(filenode.release_map.GetReleases())
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate a per node list of releases and release mapping
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLReleaseResolver().Visit(self, sorted(releases))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for filenode in self.GetListOf('File'):
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      errors = filenode.GetProperty('ERRORS')
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if errors:
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        self.errors += errors
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183