Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Unified Diff: tools/nixysa/nixysa/syntax_tree.py

Issue 2043006: WTF NPAPI extension. Early draft. Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/nixysa/nixysa/static_glue/npapi/static_object.cc ('k') | tools/nixysa/nixysa/syntax_tree_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/nixysa/nixysa/syntax_tree.py
===================================================================
--- tools/nixysa/nixysa/syntax_tree.py (revision 0)
+++ tools/nixysa/nixysa/syntax_tree.py (revision 0)
@@ -0,0 +1,1359 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Classes describing the parsed IDL as a syntax tree.
+
+This module contains all the classes that are used to describe the IDL as a
+syntax tree.
+"""
+
+# TODO: this module has grown too big, it should be split.
+
+
+class Error(Exception):
+ """Base exception for the syntax_tree module."""
+
+
+class TypeNotFoundError(Error):
+ """Raised when a type reference doesn't resolve to a definition."""
+
+ def __init__(self, type_defn, location=None):
+ Error.__init__(self)
+ self.type_defn = type_defn
+ self.location = location
+
+ def __str__(self):
+ if self.location == None:
+ return self.type_defn
+ else:
+ return '%s at %s' % (self.type_defn, self.location)
+
+class DerivingFromNonClassError(Error):
+ """Raised when a class derives from a non-class."""
+
+ def __init__(self, type_defn, base_type, location=None):
+ Error.__init__(self)
+ self.type_defn = type_defn
+ self.base_type = base_type
+ self.location = location
+
+
+class ArrayOfNonTypeError(Error):
+ """Raised when trying to reference an array of a non-type definition."""
+
+ def __init__(self, data_defn, size):
+ Error.__init__(self)
+ self.type_defn = data_defn
+ self.size = size
+
+
+class UnknownBindingModelError(Error):
+ """Raised when a binding model cannot be found."""
+
+ def __init__(self, name):
+ Error.__init__(self)
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+class CircularTypedefError(Error):
+ """Raised when 2 typedefs reference each other (even indirectly)."""
+
+ def __init__(self, type1, type2):
+ Error.__init__(self)
+ self.type1 = type1
+ self.type2 = type2
+
+ def __str__(self):
+ return '%s and %s' % (self.type1, self.type2)
+
+
+class UnimplementedMethodError(Error):
+ """Raised when an "abstract" method is not implemented in a derived type."""
+
+
+class TypeReference(object):
+ """Base class for type references.
+
+ TypeReference objects are constructed while parsing the IDL file and provide
+ a deferred lookup mechanism, removing the necessity to forward-declare all
+ the types before using them.
+ """
+
+ def __init__(self, location):
+ """Inits a TypeReference instance.
+
+ Args:
+ location: idl_parser.SourceLocation object, describing the source
+ location of the reference in the IDL.
+ """
+ self.location = location
+
+ def GetType(self, context):
+ """Look-up the referenced type.
+
+ Args:
+ context: context in which to look-up named items (scopes, types). This
+ must be a Definition instance.
+
+ Returns:
+ The type, as a Definition instance.
+
+ Raises:
+ TypeNotFoundError: the type wasn't found.
+ """
+ type_defn = self.GetTypeInternal(context, False)
+ if type_defn:
+ return type_defn
+ else:
+ raise TypeNotFoundError(self, self.location)
+
+ def GetTypeInternal(self, context, scoped):
+ """Implements type look-up.
+
+ This method should be implemented in derived classes to perform the
+ reference-specific look-up.
+
+ Args:
+ context: context in which to look-up named items (scopes, types). This
+ must be a Definition instance.
+ scoped: boolean deciding whether or not the look-up is scoped by the
+ context, or if parent context should be looked-up as well.
+
+ Returns:
+ The type, if found, or None if not.
+ """
+ context, scoped = context, scoped # silence lint
+ return None
+
+
+class NameTypeReference(TypeReference):
+ """Class representing a type reference by name.
+
+ This class represents the reference to a type by name. Look-up will produce a
+ type that has the specified name, within the specified look-up context - if
+ it exists.
+
+ Produced by the IDL construct 'Type' where Type is the name of a type
+ (typedef, typename, class, enum).
+ """
+
+ def __init__(self, location, name):
+ """Inits a NameTypeReference instance.
+
+ Args:
+ location: idl_parser.SourceLocation object, describing the source
+ location of the reference in the IDL.
+ name: the name of the type to look for.
+ """
+ TypeReference.__init__(self, location)
+ self.name = name
+
+ def GetTypeInternal(self, context, scoped):
+ """Implementation of the type look-up for NameTypeReference."""
+ if scoped:
+ type_defn = context.LookUpType(self.name)
+ else:
+ type_defn = context.LookUpTypeRecursive(self.name)
+ return type_defn or None
+
+ def __str__(self):
+ return self.name
+
+
+class ScopedTypeReference(TypeReference):
+ """Class representing a scoped type reference.
+
+ This class represents the reference to a type that is scoped by a particular
+ name. Look-up will produce a type that can be referenced inside that
+ particular scope.
+
+ Produced by the IDL construct 'Scope::TypeRef' where Scope is the name of a
+ scope, and TypeRef is a type reference.
+ """
+
+ def __init__(self, location, scope_name, type_ref):
+ """Inits a ScopedTypeReference instance.
+
+ Args:
+ location: idl_parser.SourceLocation object, describing the source
+ location of the reference in the IDL.
+ scope_name: the name of the scope to look inside.
+ type_ref: the type reference to look for, inside the named scope.
+ """
+ TypeReference.__init__(self, location)
+ self.scope_name = scope_name
+ self.type_ref = type_ref
+
+ def GetTypeInternal(self, context, scoped):
+ """Implementation of the type look-up for ScopedTypeReference."""
+ if scoped:
+ scope_list = context.FindScopes(self.scope_name)
+ else:
+ scope_list = context.FindScopesRecursive(self.scope_name)
+
+ for scope in scope_list:
+ type_defn = self.type_ref.GetTypeInternal(scope, True)
+ if type_defn:
+ return type_defn
+ return None
+
+ def __str__(self):
+ return '%s::%s' % (self.scope_name, self.type_ref)
+
+
+class ArrayTypeReference(TypeReference):
+ """Class representing an array type reference.
+
+ This class represents the reference to a type that is an array of a referenced
+ data type.
+ The array can be either sized or unsized.
+
+ Produced by the IDL constructs 'TypeRef[]' or 'TypeRef[size]' where TypeRef
+ is a type reference.
+ """
+
+ def __init__(self, location, type_ref, size):
+ """Inits a ArrayTypeReference instance.
+
+ Args:
+ location: idl_parser.SourceLocation object, describing the source
+ location of the reference in the IDL.
+ type_ref: the type reference for the data type.
+ size: the size of the array, or None if unsized.
+ """
+ TypeReference.__init__(self, location)
+ self.type_ref = type_ref
+ self.size = size
+
+ def GetTypeInternal(self, context, scoped):
+ """Implementation of the type look-up for ArrayTypeReference."""
+ type_defn = self.type_ref.GetTypeInternal(context, scoped)
+ if type_defn:
+ return type_defn.GetArrayType(self.size)
+ else:
+ return None
+
+ def __str__(self):
+ if self.size == None:
+ return '%s[]' % self.type_ref
+ else:
+ return '%s[%s]' % (self.type_ref, self.size)
+
+
+class QualifiedTypeReference(TypeReference):
+ """Class representing a type reference with a qualifier.
+
+ This class represents the reference to a type that is specialized by a type
+ qualifier, such as const or volatile or nullable.
+
+ Produced by the IDL construct 'qualifier TypeRef' where qualifier is a type
+ qualifier (const, restrict, volatile), and TypeRef is a type reference.
+ """
+
+ def __init__(self, location, qualifier, type_ref):
+ """Inits a QualifiedTypeReference instance.
+
+ Args:
+ location: idl_parser.SourceLocation object, describing the source
+ location of the reference in the IDL.
+ qualifier: the qualifier.
+ type_ref: the type reference for the un-qualified type.
+ """
+ TypeReference.__init__(self, location)
+ self.qualifier = qualifier
+ self.type_ref = type_ref
+
+ def GetTypeInternal(self, context, scoped):
+ """Implementation of the type look-up for QualifiedTypeReference."""
+ type_defn = self.type_ref.GetTypeInternal(context, scoped)
+ if type_defn:
+ if self.qualifier == 'nullable':
+ return type_defn.GetNullableType()
+ else:
+ return type_defn
+ else:
+ return None
+
+ def __str__(self):
+ return '%s %s' % (self.qualifier, self.type_ref)
+
+
+class Definition(object):
+ """Base class for definitions.
+
+ Definition objects represent all the items that are defined in the IDL, such
+ as classes or functions. This class provides some common functionality, such
+ as walking the syntax tree to look for types, and provide an interface that
+ should be implemented by sub-classes, such as listing all the scopes the
+ object may contain.
+
+ Attributes:
+ defn_type: a string representing the type of this definition
+ source: idl_parser.SourceLocation object, describing the source location
+ of this definition
+ attributes: a dictionary of attributes associated with that definition
+ name: (optional) the name of the definition. None if undefined
+ is_type: this definition is a type, and should be found by LookUpType. e.g.
+ Class, Typedef, Enum, ...
+ is_scope: this definition is a scope, and should be found by FindScopes.
+ e.g. Class, Namespace, ...
+ parent: the parent scope of that definition
+ array_defns: a dictionary of array definitions of this type, hashed by the
+ array size. Empty for non-types
+ nullable: the nullable form of this type.
+ binding_model: the binding model module for this type. None for non-types
+ """
+ defn_type = 'Definition'
+
+ def __init__(self, source, attributes, name):
+ """Inits a Definition instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this definition
+ attributes: a dictionary of attributes associated with that definition
+ name: (optional) the name of the definition
+ """
+ self.source = source
+ self.attributes = attributes
+ self.name = name
+ self.is_type = False
+ self.is_scope = False
+ self.parent = None
+ self.array_defns = {}
+ self.nullable = None
+ self.binding_model = None
+
+ def __repr__(self):
+ return '%s(%s)' % (self.defn_type, self.name)
+
+ def GetParentScopeStack(self):
+ """Gets the stack of englobing scopes."""
+ stack = []
+ cursor = self.parent
+ while cursor:
+ stack = [cursor] + stack
+ cursor = cursor.parent
+ return stack
+
+ def LookUpTypeRecursive(self, name):
+ """Looks up a type by name, recursively.
+
+ This method looks for a type by name, in the current definition and all
+ the parent scopes recursively. The first type found will be returned. See
+ LookUpType.
+
+ Args:
+ name: the name of the type looked for.
+
+ Returns:
+ The type that was found, or None if no type was found.
+ """
+ lookup_context = self
+ while lookup_context:
+ type_defn = lookup_context.LookUpType(name)
+ if type_defn:
+ return type_defn
+ lookup_context = lookup_context.parent
+ return None
+
+ def FindScopesRecursive(self, name):
+ """Finds all scopes matching a name, recursively.
+
+ This method finds all scopes matching a name, in the current definition
+ and recursively in all the parent scopes. See FindScopes.
+
+ Args:
+ name: the name of the scope looked for.
+
+ Returns:
+ The list of all the scopes that were found, in traversal order. May be []
+ if no scope of that name was found.
+ """
+ scopes = []
+ lookup_context = self
+ while lookup_context:
+ scopes.extend(lookup_context.FindScopes(name))
+ lookup_context = lookup_context.parent
+ return scopes
+
+ def GetDefinitionInclude(self):
+ """Returns the include file that has the C++ definition of this type."""
+ if 'include' in self.attributes:
+ return self.attributes['include']
+ else:
+ return self.source.file.header
+
+ def SetBindingModel(self, binding_models):
+ """Assigns the binding model module to this description.
+
+ This method assigns the binding model module to this description, and all
+ its array types. Binding models are usually defined as the 'binding_model'
+ attribute, but some types may inherit binding models from some other types
+ (e.g. Classes inherit the binding model from their base class, and
+ Typedefs inherit the binding model from their type). See
+ LookUpBindingModel.
+
+ Args:
+ binding_models: a dictionary mapping binding model names to binding model
+ modules
+
+ Raises:
+ UnknownBindingModelError if this description doesn't have a valid binding
+ model.
+ """
+ for k in self.array_defns:
+ self.array_defns[k].SetBindingModel(binding_models)
+ if self.nullable and self.nullable != self:
+ self.nullable.SetBindingModel(binding_models)
+ name = self.LookUpBindingModel()
+ try:
+ self.binding_model = binding_models[name]
+ except KeyError:
+ raise UnknownBindingModelError(name)
+
+ def GetArrayType(self, size):
+ """Returns a Definition representing an array of this type.
+
+ This method returns a Description representing an array of this type.
+ Arrays of the same data type and same size are shared.
+
+ Args:
+ size: the size of the array, or None for an unsized array.
+
+ Returns:
+ The array type description.
+
+ Raises:
+ ArrayOfNonTypeError: this description is not a type.
+ """
+ if not self.is_type:
+ raise ArrayOfNonTypeError(self, size)
+ # An array is not a 'definition' per say, it is a construct that is
+ # instanciated on use. For several purposes (looking up binding models for
+ # example), we want to treat them as a definition, so hook a unique version
+ # of each array (unsized, each size) in the type.
+ if size in self.array_defns:
+ return self.array_defns[size]
+ else:
+ array = Array(self, size)
+ self.array_defns[size] = array
+ return array
+
+ def GetNullableType(self):
+ """Returns a Definition representing a nullable version of this type."""
+ if not self.nullable:
+ self.nullable = Nullable(self)
+ return self.nullable
+
+ # members to be overridden by sub-types
+ def LookUpBindingModel(self):
+ """Looks up the binding model name for this description.
+
+ This method should be overridden by Description sub-types that are types.
+
+ Returns:
+ The binding model name, or None if not found.
+
+ Raises:
+ UnimplementedMethodError: the method was not overridden in the sub-type.
+ """
+ raise UnimplementedMethodError
+
+ def GetObjectsRecursive(self):
+ """Gets the list of all objects defined in this description, recursively.
+
+ This method gets the list of all objects defined within this description,
+ going recursively through them. In this list, parent objects must be
+ returned before their children. This method should be overridden by
+ Description sub-types that are scopes, but the default behavior is valid
+ for non-scopes.
+
+ Returns:
+ The list of objects.
+ """
+ return [self]
+
+ def ResolveTypeReferences(self):
+ """Resolve all type references needed for this type.
+
+ This method should be overridden by Description sub-types that have type
+ references (like Functions or Classes).
+
+ Raises:
+ TypeNotFoundError: a type reference could not be resolved.
+ CircularTypedefError: circular type references were found.
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ """
+ pass
+
+ def LookUpType(self, name):
+ """Looks up a type by name, in the current definition.
+
+ This method looks up a type by name, in the current definition. The first
+ type found will be returned. Since this method may be used while resolving
+ type references, it may raise the same exceptions as ResolveTypeReferences.
+ This method should be overridden by Description sub-types that are scopes,
+ but the default behavior is correct for non-scopes.
+
+ Args:
+ name: the name of the type looked for.
+
+ Returns:
+ The type that was found, or None if no type was found.
+
+ Raises:
+ TypeNotFoundError: a type reference could not be resolved.
+ CircularTypedefError: circular type references were found.
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ """
+ name = name # silence lint
+ return None
+
+ def FindScopes(self, name):
+ """Finds all scopes matching a name, in the current definition.
+
+ This method finds all scopes matching a name, in the current definition.
+ Since this method may be used while resolving type references, it may raise
+ the same exceptions as ResolveTypeReferences. This method should be
+ overridden by Description sub-types that are scopes, but the default
+ behavior is correct for non-scopes.
+
+ Args:
+ name: the name of the scope looked for.
+
+ Returns:
+ The list of all the scopes that were found, in traversal order. May be []
+ if no scope of that name was found.
+ """
+ name = name # silence lint
+ return []
+
+ def GetFinalType(self):
+ """Returns the final type of this description, following Typedefs links.
+
+ This method should be overridden by Description sub-types that are types,
+ and represent links to other types (like Typedefs).
+
+ Returns:
+ The final type.
+ """
+ return self
+
+
+class Class(Definition):
+ """Class definition.
+
+ Class objects represent classes as defined in the IDL by the 'class Name {};'
+ constructs. A Class is a type and a scope, it can contain definitions within
+ itself, such as member fields and methods, or other types. Only single
+ inheritance is supported.
+
+ Attributes:
+ base_type_ref: the reference to the base type of the class.
+ base_type: the base type of the class, once the reference has been
+ resolved.
+ defn_list: the list of definitions contained in the class scope.
+ """
+ defn_type = 'Class'
+
+ def __init__(self, source, attributes, name, base_type_ref, defn_list):
+ """Inits a Class instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this class.
+ attributes: a dictionary of attributes associated with that class.
+ name: the name of the class.
+ base_type_ref: a TypeReference, referencing the base class if any, or
+ None if this class doesn't derive from another class.
+ defn_list: the list of definitions within the class scope.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.base_type_ref = base_type_ref
+ self.base_type = None
+ self.defn_list = defn_list
+ self._scope = LookUpScope(defn_list)
+ self.is_type = True
+ self.is_scope = True
+ self._types_resolved = False
+ for o in defn_list:
+ o.parent = self
+
+ def GetObjectsRecursive(self):
+ """Implementation of GetObjectsRecursive for Class."""
+ return [self] + GetObjectsRecursive(self.defn_list)
+
+ def ResolveTypeReferences(self):
+ """Implementation of ResolveTypeReferences for Class.
+
+ This method will resolve the base class reference.
+
+ Raises:
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ """
+ if self._types_resolved:
+ return
+ self._types_resolved = True
+ if self.base_type_ref is None:
+ self.base_type = None
+ else:
+ base_type = self.base_type_ref.GetType(self.parent)
+ CheckTypeInChain(self, base_type)
+ self.base_type = base_type
+ if self.base_type.GetFinalType().defn_type != 'Class':
+ raise DerivingFromNonClassError(self, self.base_type, self.source)
+
+ def GetBaseSafe(self):
+ """Gets the base type safely, by making sure it is resolved if needed.
+
+ Returns:
+ The base type.
+
+ Raises:
+ TypeNotFoundError: a type reference could not be resolved.
+ CircularTypedefError: circular type references were found.
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ """
+ self.ResolveTypeReferences()
+ return self.base_type
+
+ def LookUpType(self, name):
+ """Implementation of LookUpType for Class."""
+ type_defn = self._scope.LookUpType(name)
+ if type_defn:
+ return type_defn
+ base = self.GetBaseSafe()
+ if base:
+ return base.LookUpType(name)
+ return None
+
+ def FindScopes(self, name):
+ """Implementation of FindScopes for Class."""
+ scopes = self._scope.FindScopes(name)
+ base = self.GetBaseSafe()
+ if base:
+ scopes.extend(base.FindScopes(name))
+ return scopes
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Class."""
+ base = self.GetBaseSafe()
+ if 'binding_model' in self.attributes:
+ return self.attributes['binding_model']
+ elif base:
+ return base.LookUpBindingModel()
+ else:
+ return None
+
+
+class Namespace(Definition):
+ """Namespace definition.
+
+ Namespace objects represent namespaces as defined in the IDL by the
+ 'namespace Name {}' constructs. A Namespace is a scope, it can contain
+ definitions within itself, such as member fields and methods, or other types.
+ Namespaces can be defined by parts, namespaces that have the same name, and
+ are defined within the same outer scope are semantically merged for type and
+ scope lookup purposes. See the MergeNamespacesRecursive function.
+
+ Attributes:
+ defn_list: the list of definitions contained in the namespace scope.
+ scope: a LookUpScope object, that will be shared across namespaces that
+ should be merged for lookup.
+ """
+ defn_type = 'Namespace'
+
+ def __init__(self, source, attributes, name, defn_list):
+ """Inits a Namespace instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this namespace.
+ attributes: a dictionary of attributes associated with that namespace.
+ name: the name of the namespace.
+ defn_list: the list of definitions within the namespace scope.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.defn_list = defn_list
+ self.scope = LookUpScope(defn_list)
+ self.is_scope = True
+ for o in defn_list:
+ o.parent = self
+
+ def GetObjectsRecursive(self):
+ """Implementation of GetObjectsRecursive for Namespace."""
+ return [self] + GetObjectsRecursive(self.defn_list)
+
+ def MergeLookUpScope(self, other):
+ """Merges the LookUpScope object from another Namespace into this one.
+
+ See the MergeNamespacesRecursive function.
+
+ Args:
+ other: the other Namespace to merge into this one.
+ """
+ self.scope.ResetCache()
+ # self.scope.list may be a reference to the namespace defn_list, so create
+ # a copy before modifying the list.
+ self.scope.list = self.scope.list[:]
+ self.scope.list.extend(other.scope.list)
+ other.scope = self.scope
+
+ def LookUpType(self, name):
+ """Implementation of LookUpType for Namespace."""
+ return self.scope.LookUpType(name)
+
+ def FindScopes(self, name):
+ """Implementation of FindScopes for Namespace."""
+ return self.scope.FindScopes(name)
+
+
+class Enum(Definition):
+ """Enum definition.
+
+ Enum objects represent enums as defined in the IDL by the
+ 'enum Name {VALUE1, VALUE2};' constructs. An Enum is a type.
+
+ Attributes:
+ values: the list of values defined in the enum, as Enum.Value objects.
+ """
+
+ class Value(object):
+ """Enum value description.
+
+ This is simple structure, with a name and an optional value.
+
+ Attributes:
+ name: the name of the value.
+ value: the value, or None for the default value.
+ """
+
+ def __init__(self, name, value):
+ """Inits an Enum.Value instance.
+
+ Args:
+ name: the name of the value.
+ value: the value, or None for the default value.
+ """
+ self.name = name
+ self.value = value
+
+ defn_type = 'Enum'
+
+ def __init__(self, source, attributes, name, values):
+ """Inits an Enum instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this enum.
+ attributes: a dictionary of attributes associated with that enum.
+ name: the name of the enum.
+ values: the list of values defined for this enum, as Enum.Value objects.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.values = values
+ self.is_type = True
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Enum."""
+ return 'enum'
+
+
+class Function(Definition):
+ """Function definition.
+
+ Function objects represent functions, methods and constructors/destructors, as
+ defined in the IDL by the 'Type Function(Type param1, Type param2);'
+ constructs.
+
+ Attributes:
+ type_ref: the reference to the return type of the function, or None for
+ constructors/destructors.
+ type: the return type of the function, once the reference has been
+ resolved, or None for constructors/destructors.
+ params: the list of the function parameters, as Function.Param objects.
+ """
+
+ class Param(object):
+ """Function parameter description.
+
+ This represents any of the function parameter, with its name and type.
+
+ Attributes:
+ type_ref: the reference to the type of the parameter.
+ type: the type of the parameter, once the reference has been resolved.
+ name: the name of the parameter.
+ mutable: a boolean indicating whether the parameter is mutable. While
+ (currently) there is no mechanism to specify it in the IDL, code
+ generation internals use this flag to generate functions with a mutable
+ 'this' parameter for methods.
+ """
+
+ def __init__(self, type_ref, name):
+ """Inits a Function.Param instance.
+
+ Args:
+ type_ref: the reference to the type of the parameter.
+ name: the name of the parameter.
+ """
+ self.type_ref = type_ref
+ self.type_defn = None
+ self.name = name
+ self.mutable = False
+
+ defn_type = 'Function'
+
+ def __init__(self, source, attributes, name, type_ref, params):
+ """Inits a Function instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this function.
+ attributes: a dictionary of attributes associated with that function.
+ name: the name of the function.
+ type_ref: a TypeReference, referencing the return type if any, or
+ None for constructors/destructors.
+ params: the list of parameters, as (TypeReference, name) pairs.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.type_ref = type_ref
+ self.type_defn = None
+ self.params = [self.Param(type_ref, name) for type_ref, name in params]
+
+ def ResolveTypeReferences(self):
+ """Implementation of ResolveTypeReferences for Function."""
+ if self.type_ref is None:
+ self.type_defn = None
+ else:
+ self.type_defn = self.type_ref.GetType(self.parent)
+ for param in self.params:
+ param.type_defn = param.type_ref.GetType(self.parent)
+
+
+class Callback(Definition):
+ """Callback definition.
+
+ Callback objects represent callback functions as defined in the IDL by the
+ 'callback Type Function(Type param1, Type param2);' constructs. Callbacks are
+ meant to behave like function objects. Callbacks are types.
+
+ Attributes:
+ type_ref: the reference to the return type of the callback.
+ type: the return type of the callback, once the reference has been
+ resolved.
+ params: the list of the function parameters, as Function.Param objects.
+ """
+
+ defn_type = 'Callback'
+
+ def __init__(self, source, attributes, name, type_ref, params):
+ """Inits a Callback instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this callback.
+ attributes: a dictionary of attributes associated with that callback.
+ name: the name of the callback.
+ type_ref: a TypeReference, referencing the return type if any, or
+ None for constructors/destructors.
+ params: the list of parameters, as (TypeReference, name) pairs.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.type_ref = type_ref
+ self.type_defn = None
+ self.params = [Function.Param(type_ref, name) for type_ref, name in params]
+ self.is_type = True
+
+ def ResolveTypeReferences(self):
+ """Implementation of ResolveTypeReferences for Callback."""
+ if self.type_ref is None:
+ self.type_defn = None
+ else:
+ self.type_defn = self.type_ref.GetType(self.parent)
+ for param in self.params:
+ param.type_defn = param.type_ref.GetType(self.parent)
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Callback."""
+ if 'binding_model' in self.attributes:
+ return self.attributes['binding_model']
+ else:
+ return 'callback'
+
+
+class Variable(Definition):
+ """Variable definition.
+
+ Variable objects represent variables, whether global, or class member fields,
+ as defined in the IDL by the 'Type variable;' constructs.
+
+ Attributes:
+ type_ref: the reference to the type of the variable
+ type: the type of the variable, once the reference has been resolved.
+ """
+ defn_type = 'Variable'
+
+ def __init__(self, source, attributes, name, type_ref):
+ """Inits a Variable instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this variable.
+ attributes: a dictionary of attributes associated with that variable.
+ name: the name of the variable.
+ type_ref: a TypeReference, referencing the type of the variable.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.type_ref = type_ref
+ self.type_defn = None
+
+ def ResolveTypeReferences(self):
+ """Implementation of ResolveTypeReferences for Variable."""
+ self.type_defn = self.type_ref.GetType(self.parent)
+
+ def MakeGetter(self, attributes, name):
+ """Creates a Function for the getter for the variable.
+
+ Args:
+ attributes: the attributes for the getter function.
+ name: the name of the getter function.
+
+ Returns:
+ the getter definition.
+ """
+ func = Function(self.source, attributes, name, self.type_ref, [])
+ func.parent = self.parent
+ func.ResolveTypeReferences()
+ return func
+
+ def MakeSetter(self, attributes, name):
+ """Creates a Function for the setter for the variable.
+
+ Args:
+ attributes: the attributes for the setter function.
+ name: the name of the setter function.
+
+ Returns:
+ the setter definition.
+ """
+ void_ref = NameTypeReference(self.source, 'void')
+ func = Function(self.source, attributes, name, void_ref, [(self.type_ref,
+ self.name)])
+ func.parent = self.parent
+ func.ResolveTypeReferences()
+ return func
+
+
+class Typedef(Definition):
+ """Typedef definition.
+
+ Typedef objects represent type 'symbolic links', defining a new name for an
+ existing type, as defined in the IDL by the 'typedef Type NewType;'
+ constructs. Typedefs are types, and scopes.
+
+ Attributes:
+ type_ref: the reference to the original type of the typedef
+ type: the original type of the typedef, once the reference has been
+ resolved.
+ """
+ defn_type = 'Typedef'
+
+ def __init__(self, source, attributes, name, type_ref):
+ """Inits a Typedef instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this typedef.
+ attributes: a dictionary of attributes associated with that typedef.
+ name: the name of the typedef.
+ type_ref: a TypeReference, referencing the original type of the typedef.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.type_ref = type_ref
+ self.type_defn = None
+ self.is_type = True
+ self.is_scope = True
+ self._types_resolved = False
+
+ def ResolveTypeReferences(self):
+ """Implementation of ResolveTypeReferences for Typedef."""
+ if self._types_resolved:
+ return
+ self._types_resolved = True
+ type_defn = self.type_ref.GetType(self.parent)
+ CheckTypeInChain(self, type_defn)
+ self.type_defn = type_defn
+
+ def GetTypeSafe(self):
+ """Gets the original type safely, by making sure it is resolved if needed.
+
+ Returns:
+ The original type.
+
+ Raises:
+ TypeNotFoundError: a type reference could not be resolved.
+ CircularTypedefError: circular type references were found.
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ """
+ self.ResolveTypeReferences()
+ return self.type_defn
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Typedef."""
+ if 'binding_model' in self.attributes:
+ return self.attributes['binding_model']
+ else:
+ return self.GetTypeSafe().LookUpBindingModel()
+
+ def GetFinalType(self):
+ """Implementation of GetFinalType for Typedef."""
+ return self.GetTypeSafe().GetFinalType()
+
+ def LookUpType(self, name):
+ """Implementation of LookUpType for Typedef."""
+ return self.GetTypeSafe().LookUpType(name)
+
+ def FindScopes(self, name):
+ """Implementation of FindScopes for Typedef."""
+ return self.GetTypeSafe().FindScopes(name)
+
+
+class Typename(Definition):
+ """Typename definition.
+
+ Typename objects represent unknown types, whose definition cannot be
+ expressed in IDL, but still need to be referenced in the IDL. They are
+ declared in IDL with the 'typename Type;' constructs. Typenames are types.
+
+ Attributes:
+ None
+ """
+ defn_type = 'Typename'
+
+ def __init__(self, source, attributes, name):
+ """Inits a Typename instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this typename.
+ attributes: a dictionary of attributes associated with that typename.
+ name: the name of the typename.
+ """
+ Definition.__init__(self, source, attributes, name)
+ self.is_type = True
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Typename."""
+ try:
+ return self.attributes['binding_model']
+ except KeyError:
+ return None
+
+
+class Verbatim(Definition):
+ """Verbatim definition.
+
+ Verbatim objects represent text that needs to be included as is into the
+ generated code. Attributes control in which context the code should be
+ included. They are defined in IDL within '%{' and '%}' quotes.
+
+ Attributes:
+ text: the verbatim text.
+ """
+ defn_type = 'Verbatim'
+
+ def __init__(self, source, attributes, text):
+ """Inits a Verbatim instance.
+
+ Args:
+ source: idl_parser.SourceLocation object, describing the source location
+ of this verbatim.
+ attributes: a dictionary of attributes associated with that verbatim.
+ text: the text of the verbatim.
+ """
+ Definition.__init__(self, source, attributes, None)
+ self.text = text
+
+
+class Array(Definition):
+ """Array definition.
+
+ Array objects represent sized and unsized arrays of a data type. They are not
+ defined explicitly in IDL, but implicitly through array references. Arrays
+ are types.
+
+ Attributes:
+ data_type: the type of individual elements of the array
+ size: the size of the array, as an integer, or None for an unsized array
+ """
+ defn_type = 'Array'
+
+ def __init__(self, data_type, size):
+ """Inits an Array instance.
+
+ Args:
+ data_type: the type of individual elements of the array
+ size: the size of the array, as an integer, or None for an unsized array
+ """
+ Definition.__init__(self, data_type.source, [], None)
+ self.data_type = data_type
+ self.size = size
+ self.is_type = True
+
+ def __repr__(self):
+ return '%s[]' % str(self.data_type)
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Array."""
+ if self.size:
+ return 'sized_array'
+ else:
+ return 'unsized_array'
+
+
+class Nullable(Definition):
+ """Nullable definition.
+
+ Nullable objects are those that can have a null value. They are not
+ defined explicitly in IDL, but implicitly through nullable references.
+ Nullables are types.
+
+ Attributes:
+ data_type: the type this Nullable has when it is not null.
+ """
+ defn_type = 'Nullable'
+
+ def __init__(self, data_type):
+ """Inits an Array instance.
+
+ Args:
+ data_type: the type this Nullable has when it is not null.
+ """
+ Definition.__init__(self, data_type.source, [], None)
+ self.data_type = data_type
+ self.is_type = True
+ self.nullable = self
+
+ def __repr__(self):
+ return '%s?' % str(self.data_type)
+
+ def LookUpBindingModel(self):
+ """Implementation of LookUpBindingModel for Nullable."""
+ return 'nullable'
+
+
+def CheckTypeInChain(type_defn, chain_head):
+ """Checks that a type isn't in a type chain.
+
+ Circular references of types shouldn't happen within typedefs, base class or
+ array chains. For example the following IDL constructs should be forbidden:
+
+ typedef Typedef1 Typedef2;
+ typedef Typedef2 Typedef1;
+
+ class Class1: Class2 {};
+ class Class2: Class1 {};
+
+ typedef Typedef1[] Typedef1;
+
+ typedef Class Typedef;
+ class Class: Typedef {};
+
+ and so on. This function checks that a particular type doesn't already exists
+ in a chain, defined by following typedefs, base classes and array data types.
+
+ Args:
+ type_defn: the type to look for.
+ chain_head: the head of the chain to look into.
+
+ Raises:
+ CircularTypedefError: a circular reference was found, that is 'type' was
+ found in the chain.
+ """
+ current = chain_head
+ while current:
+ if type_defn == current:
+ raise CircularTypedefError(type_defn, current)
+ if current.defn_type == 'Typedef':
+ # Don't use GetTypeSafe, just break if the type hasn't been set
+ # using GetTypeSafe would produce an infinite loop...
+ # It is ok to break if the type hasn't been set yet. If there is a
+ # cycle, it will be detected when that other type calls GetTypeSafe
+ current = current.type_defn
+ elif current.defn_type == 'Class':
+ # same as above, don't use GetBaseTypeSafe
+ current = current.base_type
+ elif current.defn_type == 'Array':
+ current = current.data_type
+ else:
+ break
+
+
+class LookUpScope(object):
+ """Helper class for lookup in scope definitions.
+
+ This class provides basic functionality for LookUpType and FindScope
+ implementations, when the definition is a scope, like classes and namespaces.
+ Caching and such is implemented here. Currently, only type lookups is cached
+ with a name -> definition dictionary.
+
+ Attributes:
+ list: the list of definition the lookup operates on.
+ """
+
+ def __init__(self, definition_list):
+ """Inits a LookUpScope instance.
+
+ Args:
+ definition_list: the list of definition the lookup operates on.
+ """
+ self.list = definition_list
+ self.ResetCache()
+
+ def ResetCache(self):
+ """Resets all caches. To be used if the definition list changes."""
+ self._types = None
+
+ def MakeCache(self):
+ """Initializes caches."""
+ if not self._types:
+ self._types = dict([(i.name, i) for i in self.list if i.is_type])
+
+ def LookUpType(self, name):
+ """Looks up a type by name within the definition list.
+
+ Args:
+ name: the name of the type looked for.
+
+ Returns:
+ The type definition if found, None otherwise.
+ """
+ self.MakeCache()
+ try:
+ return self._types[name]
+ except KeyError:
+ return None
+
+ def FindScopes(self, name):
+ """Finds all socpes matching a name, in the definition list.
+
+ Args:
+ name: the name of the scopes looked for.
+
+ Returns:
+ The list of all the scopes that were found. May be [] if no scope of that
+ name was found.
+ """
+ return [i for i in self.list if i.is_scope and i.name == name]
+
+
+def GetObjectsRecursive(object_list):
+ """Gets the list of all objects recursively defined in a list of objects.
+
+ This method gets the list of all objects defined within a list of top-level
+ objects, going recursively through them.
+
+ Args:
+ object_list: the list of top-level objects.
+
+ Returns:
+ The list of objects.
+ """
+ return sum([obj.GetObjectsRecursive() for obj in object_list], [])
+
+
+def MergeNamespacesRecursive(namespace):
+ """Merges scopes described by namespaces constructs.
+
+ Namespaces can be defined by parts, this function merges scopes of namespaces
+ that have the same name, and are defined within the same outer scope. E.g.
+ the following:
+ namespace Foo {
+ namespace Bar {
+ class Class1 {};
+ void Function2();
+ }
+
+ namespace Bar {
+ int my_variable;
+ }
+ }
+ will create within the namespace 'Foo' two Namespace objects, both named
+ 'Bar', each containing different definitions, and different inner LookUpScope
+ objects.
+ This function will merge the LookUpScope objects between these namespaces, for
+ it to contain all the definitions. The Namespace objects will still exist as
+ separate entities, only their scope member changes.
+
+ Args:
+ namespace: the root namespace containing namespace definitions to merge.
+ """
+ namespaces = [o for o in namespace.scope.list if o.defn_type == 'Namespace']
+ namespace_dict = {}
+ for o in namespaces:
+ if o.name in namespace_dict:
+ namespace_dict[o.name].MergeLookUpScope(o)
+ else:
+ namespace_dict[o.name] = o
+ for name in namespace_dict:
+ MergeNamespacesRecursive(namespace_dict[name])
+
+
+def FinalizeObjects(namespace, binding_models):
+ """Finalize all objects after parsing.
+
+ When objects are first parsed, they are not completely ready for code
+ generation. This functions takes care of finalizing objects:
+ - merging namespace scopes that have the same name in the same outer scope.
+ - resolving type references.
+ - setting binding models on types.
+
+ Args:
+ namespace: 'global' namespace, containing all the definitions.
+ binding_models: a dictionary that maps binding model name -> binding model
+ module.
+
+ Raises:
+ TypeNotFoundError: a type reference could not be resolved.
+ CircularTypedefError: circular type references were found.
+ DerivingFromNonClassError: a class definition derives from a non-class
+ definition.
+ UnknownBindingModelError: a type definition doesn't have a valid binding
+ model.
+ """
+ MergeNamespacesRecursive(namespace)
+ all_defns = namespace.GetObjectsRecursive()
+ for defn in all_defns:
+ defn.ResolveTypeReferences()
+ for defn in all_defns:
+ if defn.is_type:
+ defn.SetBindingModel(binding_models)
+
+
+def main():
+ pass
+
+
+if __name__ == '__main__':
+ main()
Property changes on: tools/nixysa/nixysa/syntax_tree.py
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « tools/nixysa/nixysa/static_glue/npapi/static_object.cc ('k') | tools/nixysa/nixysa/syntax_tree_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698