blob: b7ad6f011c7f8923986b9e7aec0b74378618a7c1 [file] [log] [blame]
# 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', 'str_t', 'void'])
#
# IDLNamespaceLabelResolver
#
# Once the AST is build, we need to resolve the namespace and version
# information.
#
class IDLNamespaceLabelResolver(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 entering a parent, clear the local Label\
if node.IsA('File'): self.release_map = None
# 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.namespace.name = 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')
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
#
# As we return from a node, if the node is a LabelItem we pass back
# the key=value pair representing the mapping of release to version.
# If the node is a Label take the lists of mapping and generate a
# version map which is assigned to the Labels parent as a property.
#
def Depart(self, node, data, childdata):
if node.IsA('LabelItem'):
return (node.GetName(), node.GetProperty('VALUE'))
if node.IsA('Label') and node.GetName() == GetOption('label'):
try:
self.release_map = IDLReleaseMap(childdata)
node.parent.release_map = self.release_map
except Exception as err:
node.Error('Unable to build release map: %s' % str(err))
return None
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)
# 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
#
# IDLAst
#
# A specialized version of the IDLNode for containing the whole of the
# AST. The specialized BuildTree function pulls the per file namespaces
# into the global AST namespace and checks for collisions.
#
class IDLAst(IDLNode):
def __init__(self, children):
IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children)
self.Resolve()
def Resolve(self):
self.namespace = IDLNamespace(None)
self.namespace.name = 'AST'
IDLNamespaceLabelResolver().Visit(self, self.namespace)
IDLFileTypeResolver().Visit(self, None)
# Build an ordered list of all releases
self.releases = set()
for filenode in self.GetListOf('File'):
self.releases |= set(filenode.release_map.GetReleases())
self.releases = sorted(self.releases)
def SetTypeInfo(self, name, properties):
node = self.namespace[name]
for prop in properties:
node.properties[prop] = properties[prop]