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'):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (node.GetName(), node.GetProperty('VALUE'))
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # On completion of the Label, apply to the parent File if the
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # name of the label matches the generation label.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Label') and node.GetName() == GetOption('label'):
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      try:
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        node.parent.release_map = IDLReleaseMap(childdata)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      except Exception as err:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.Error('Unable to build release map: %s' % str(err))
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For File objects, set the minimum version
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_min, _ = node.release_map.GetReleaseRange()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.SetMin(file_min)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLNamespaceVersionResolver
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST, building a namespace tree
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# as it goes.  The namespace tree is mapping from a name to a version list.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Labels must already be resolved to use.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLNamespaceVersionResolver(IDLVisitor):
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct'])
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # When we arrive at a node we must assign it a namespace and if the
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # node is named, then place it in the appropriate namespace.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, parent_namespace):
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If we are a File, grab the Min version and replease mapping
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.rmin = node.GetMinMax()[0]
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.release_map = node.release_map
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set the min version on any non Label within the File
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not node.IsA('AST', 'File', 'Label', 'LabelItem'):
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      my_min, _ = node.GetMinMax()
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not my_min:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetMin(self.rmin)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this object is not a namespace aware object, use the parent's one
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.cls not in self.NamespaceSet:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.namespace = parent_namespace
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # otherwise create one.
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      node.namespace = IDLNamespace(parent_namespace)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this node is named, place it in its parent's namespace
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if parent_namespace and node.cls in IDLNode.NamedSet:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Set version min and max based on properties
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.release_map:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vmin = node.GetProperty('version')
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vmax = node.GetProperty('deprecate')
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # If no min is available, the use the parent File's min
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if vmin == None:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rmin = self.rmin
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rmin = self.release_map.GetRelease(vmin)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rmax = self.release_map.GetRelease(vmax)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetReleaseRange(rmin, rmax)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent_namespace.AddNode(node)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Pass this namespace to each child in case they inherit it
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return node.namespace
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLFileTypeRessolver
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST and sets a FILE property
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# on all file nodes.  In addition, searches the namespace resolving all
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# type references.  The namespace tree must already have been populated
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# before this visitor is used.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLFileTypeResolver(IDLVisitor):
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def VisitFilter(self, node, data):
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return not node.IsA('Comment', 'Copyright')
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, filenode):
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Track the file node to update errors
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('File'):
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.SetProperty('FILE', node)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filenode = node
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not node.IsA('AST'):
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_min, _ = filenode.release_map.GetReleaseRange()
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not file_min:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print 'Resetting min on %s to %s' % (node, file_min)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.SetMinRange(file_min)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this node has a TYPEREF, resolve it to a version list
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    typeref = node.GetPropertyLocal('TYPEREF')
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if typeref:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.typelist = node.parent.namespace.FindList(typeref)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not node.typelist:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.Error('Could not resolve %s.' % typeref)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.typelist = None
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return filenode
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLReleaseResolver
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which will traverse the AST, and generate a mapping
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# from any release to the first release in which that version of the object
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# was generated.  Types must already be resolved to use.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLReleaseResolver(IDLVisitor):
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Arrive(self, node, releases):
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.BuildReleaseMap(releases)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return releases
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLAst
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized version of the IDLNode for containing the whole of the
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# AST.  Construction of the AST object will cause resolution of the
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# tree including versions, types, etc...  Errors counts will be collected
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# both per file, and on the AST itself.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLAst(IDLNode):
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, children):
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Resolve()
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Resolve(self):
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set the appropriate Release=Version mapping for each File
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLLabelResolver().Visit(self, None)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate the Namesapce Tree
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    self.namespace = IDLNamespace(None)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLNamespaceVersionResolver().Visit(self, self.namespace)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Using the namespace, resolve type references
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLFileTypeResolver().Visit(self, None)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Build an ordered list of all releases
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    releases = set()
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for filenode in self.GetListOf('File'):
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      releases |= set(filenode.release_map.GetReleases())
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate a per node list of releases and release mapping
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDLReleaseResolver().Visit(self, sorted(releases))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for filenode in self.GetListOf('File'):
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      errors = filenode.GetProperty('ERRORS')
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if errors:
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        self.errors += errors
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178