def type_from_declarator(self, parent_ast, declarator): """ Construct a partial type. Only used for typdefs currently. """ typenode = TypeNode(parent_ast, None, source = declarator) # Don't know the meta type here if declarator.my_children_are('simple_declarator'): typenode.leaf = declarator.the('simple_declarator').leaf #typenode.add_attribute('target_type', typeref) else: #complex_declarator newtype = TypeNode(parent_ast, source = declarator) newtype.add_attribute('meta_type','array') array_dcl = declarator.the('complex_declarator').the('array_declarator') array_dim = [] shape = Node(newtype, 'shape', source = declarator) newtype.add_child(shape) for dimension in array_dcl.children: exp_node = dimension.the('positive_int_const').the('const_exp') expr = self.getExpression(shape, exp_node) if expr.attribute('value') < 0: raise DimensionOutOfRangeError(dimension) shape.add_child(expr) typenode.leaf = array_dcl.leaf typenode.add_child(newtype) assert typenode.leaf != None return typenode
def create_special_MIG(arch_info, ast): poly_list =( ("MACH_MSG_TYPE_PORT_RECEIVE", '32', 'MACH_MSG_TYPE_PORT_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_PORT_SEND", '32', 'MACH_MSG_TYPE_PORT_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_PORT_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_COPY_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MAKE_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MOVE_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MAKE_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND_ONCE'), ("MACH_MSG_TYPE_MOVE_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND_ONCE'), ("MACH_MSG_TYPE_MOVE_RECEIVE", '32', 'MACH_MSG_TYPE_RECEIVE_internal', 'MACH_MSG_TYPE_PORT_RECEIVE') ) type_list = ast.children for name, size, sender, receiver in poly_list: newType = TypeNode(ast, None, source_file = '<builtin>') newType.leaf = name newType.add_attribute('meta_type', 'polymorphic') info = Node(newType, 'info') newType.add_child(info) index = [element.leaf for element in type_list].index(sender) info.add_attribute('sender_type',type_list[index] ) index = [element.leaf for element in type_list].index(receiver) info.add_attribute('receiver_type',type_list[index] ) type_list.append(newType) ast.add_child(newType)
def union_type(self,ast, pt, defining_scope = None): union_ast = TypeNode(ast, source = pt) union_ast.add_attribute('meta_type', 'union') # Discriminated unions consist of three parts: the union name, the # discriminator (a switch), and the body (a switch body). # Union name: union_ast.leaf = pt.the('identifier').leaf # Type spec: type_node, is_new_type = self._get_target_type(ast, pt.the('switch_type_spec'), wrapper = 'discriminator', defining_scope = union_ast) if not self.is_valid_discriminator(type_node): raise InvalidDiscriminatorError(union_ast) # Add the type wrapped as "disciminator" union_ast.add_child(type_node) # Switch body: switch_members = self.case_stmt_list(union_ast, pt.the('switch_body').the('case_stmt_list')) union_ast.add_child(switch_members) if defining_scope: defining_scope.add_child(union_ast) return union_ast
def enum_type(self, ast, pt, defining_scope): type_node = TypeNode(ast, source = pt) type_node.add_attribute('meta_type', 'enum') enum_list = [] for child in pt.children: if child.type == 'identifier': type_node.leaf = child.leaf elif child.type == 'enumerator_list': for enum in child['enumerator']: enum_list.append(enum.leaf) type_node.add_attribute('enumeration', enum_list) # All the enum internal names get added to the outer scope (Do they?!) if defining_scope: # Add the enum itself, too. defining_scope.add_child(type_node) for count, child_pt in enumerate(pt.the('enumerator_list')['enumerator']): enum_item_ast = TypeNode(defining_scope, leaf = child_pt.leaf, source = child) defining_scope.add_child(enum_item_ast) enum_item_ast.add_attribute('meta_type', 'enum_member') enum_item_ast.add_attribute('value', count) self._dupes_check(enum_item_ast) enum_item_target = Node(enum_item_ast, 'target') enum_item_target.add_child(type_node) enum_item_ast.add_child(enum_item_target) return type_node
def create_special_C(arch_info, ast): type_list = ast.children struct_t = TypeNode(ast, source_file = '<builtin>') struct_t.leaf = 'idl4_server_environment' struct_t.add_attribute('meta_type','struct') members = Node(struct_t, 'members') typeinst = Node(struct_t, 'type_instance') typeinst.leaf = '_action' index = [element.leaf for element in type_list].index('signed int') typeinst.add_attribute('target_type',type_list[index] ) members.add_child(typeinst) typeinst = Node(struct_t, 'type_instance') typeinst.leaf = '_data' index = [element.leaf for element in type_list].index('void') typeinst.add_attribute('target_type',type_list[index] ) members.add_child(typeinst) # Create IDL4 scope for giggles. idl4 = Node(ast, 'type', leaf = 'idl4', source_file = '<builtin>') idl4.add_attribute('meta_type', 'private') pagefault = Node(idl4, 'type', leaf = 'pagefault') idl4.add_child(pagefault) ast.add_child(idl4) #FIXME: CORBA-C Type-Hack!!! aliases = ( ('Object', 'signed int'), ('any', 'signed int'), ('ValueBase', 'signed int'), ('Word', 'signed int') ) # Create aliases to C nodes. for alias, name in aliases: newType = TypeNode(ast, source_file = '<builtin>') newType.leaf = alias newType.add_attribute('meta_type', 'alias') type_list = ast.children index = [element.leaf for element in type_list].index(name) target_node = Node(newType, 'target') target_node.add_child(type_list[index]) newType.add_child(target_node) ast.add_child(newType) # Explicitly add the IDL4 mapitem struct, yuck yuck mapitem = _make_struct(ast, 'idl4_mapitem', ('unsigned long int', 'base'), ('unsigned long int', 'fpage')) ast.add_child(mapitem)
def type_dcl(self, ast, pt, decorators): assert not decorators # FIXME: SemanticError if duplicate here. if pt.leaf == 'typedef': # Typdef consists of two parts: # 1. type_declarator -> type_spec: the target type # 2. type_declarator -> declarators: the new alias name for declarator in pt.the('type_declarator').the('declarators')['declarator']: typedef_ast = self.type_from_declarator(ast, declarator) typedef_ast.add_attribute('meta_type', 'alias') new_node = typedef_ast ast.add_child(new_node) # NB we pass "ast" here because any new types we create end up going in the # same scope as the typedef. typeref, is_new_type = self._get_target_type(ast, pt.the('type_declarator').the('type_spec'), defining_scope = typedef_ast) typedef_ast.add_child(typeref) self._dupes_check(typeref) elif pt.children[0].name in ('struct_type', 'enum_type', 'union_type'): new_node = self.constr_type_spec(ast, pt.children[0], defining_scope = ast) # NOTE! Since we pass "defining_scope" here, the child is *already* added # and does not need to be added again, hence no ast.add_child(new_node) here. elif pt.children[0].type == 'simple_declarator': typenode = TypeNode(ast, source = pt) typenode.leaf = pt.children[0].leaf typenode.add_attribute('meta_type', 'native') new_node = typenode ast.add_child(new_node) elif pt.children[0].type == 'constr_forward_decl': typenode = TypeNode(ast, source = pt) typenode.leaf = pt.the('constr_forward_decl').the('identifier').leaf typenode.add_attribute('meta_type', 'forward') #typetype = 'forward ' + pt.the('constr_forward_dcl').leaf typenode.add_attribute('meta_type' , pt.the('constr_forward_decl').leaf) new_node = typenode ast.add_child(new_node) else: new_node = UnknownNode(None, pt.children[0], source = pt.children[0]) ast.add_child(new_node) self._dupes_check(new_node)
def create_special_C(arch_info, ast): type_list = ast.children struct_t = TypeNode(ast, source_file='<builtin>') struct_t.leaf = 'idl4_server_environment' struct_t.add_attribute('meta_type', 'struct') members = Node(struct_t, 'members') typeinst = Node(struct_t, 'type_instance') typeinst.leaf = '_action' index = [element.leaf for element in type_list].index('signed int') typeinst.add_attribute('target_type', type_list[index]) members.add_child(typeinst) typeinst = Node(struct_t, 'type_instance') typeinst.leaf = '_data' index = [element.leaf for element in type_list].index('void') typeinst.add_attribute('target_type', type_list[index]) members.add_child(typeinst) # Create IDL4 scope for giggles. idl4 = Node(ast, 'type', leaf='idl4', source_file='<builtin>') idl4.add_attribute('meta_type', 'private') pagefault = Node(idl4, 'type', leaf='pagefault') idl4.add_child(pagefault) ast.add_child(idl4) #FIXME: CORBA-C Type-Hack!!! aliases = (('Object', 'signed int'), ('any', 'signed int'), ('ValueBase', 'signed int'), ('Word', 'signed int')) # Create aliases to C nodes. for alias, name in aliases: newType = TypeNode(ast, source_file='<builtin>') newType.leaf = alias newType.add_attribute('meta_type', 'alias') type_list = ast.children index = [element.leaf for element in type_list].index(name) target_node = Node(newType, 'target') target_node.add_child(type_list[index]) newType.add_child(target_node) ast.add_child(newType) # Explicitly add the IDL4 mapitem struct, yuck yuck mapitem = _make_struct(ast, 'idl4_mapitem', ('unsigned long int', 'base'), ('unsigned long int', 'fpage')) ast.add_child(mapitem)
def struct_type(self, ast, pt, defining_scope = None): type_node = TypeNode(ast, source = pt) type_node.leaf = pt.the('identifier').leaf type_node.add_attribute('meta_type', 'struct') membernode = self.member_list(type_node, pt.the('member_list')) type_node.add_children(membernode) if defining_scope: defining_scope.add_child(type_node) return type_node
def create_basictype_ast(arch_name, typetype): ast = Node(None, 'MagpieAST', None) arch_info = construct_for_arch(arch_name, typetype) if typetype == 'idl4': names = CORBA_NAMES + C_NAMES aliases = C_ALIAS if typetype == 'mig': names = CORBA_NAMES + MIG_NAMES aliases = MIG_ALIAS for name in names: newType = TypeNode(ast, None, source_file = '<builtin>') newType.leaf = name newType.add_attribute('meta_type', 'basic') newType.add_attribute('size', arch_info.size_in_bits(name)) if arch_info.smallest(name) is not None: newType.add_attribute('smallest', arch_info.smallest(name)) if arch_info.largest(name) is not None: newType.add_attribute('largest', arch_info.largest(name)) ast.add_child(newType) for alias, name in aliases: newType = TypeNode(ast, None, source_file = '<builtin>') newType.leaf = alias newType.add_attribute('meta_type', 'alias') type_list = ast.children index = [element.leaf for element in type_list].index(name) target = Node(newType, 'target', [type_list[index]]) newType.add_child(target) ast.add_child(newType) if typetype == 'idl4': create_special_C(arch_info, ast) if typetype == 'mig': create_special_MIG(arch_info, ast) return ast
def create_basictype_ast(arch_name, typetype): ast = Node(None, 'MagpieAST', None) arch_info = construct_for_arch(arch_name, typetype) if typetype == 'idl4': names = CORBA_NAMES + C_NAMES aliases = C_ALIAS if typetype == 'mig': names = CORBA_NAMES + MIG_NAMES aliases = MIG_ALIAS for name in names: newType = TypeNode(ast, None, source_file='<builtin>') newType.leaf = name newType.add_attribute('meta_type', 'basic') newType.add_attribute('size', arch_info.size_in_bits(name)) if arch_info.smallest(name) is not None: newType.add_attribute('smallest', arch_info.smallest(name)) if arch_info.largest(name) is not None: newType.add_attribute('largest', arch_info.largest(name)) ast.add_child(newType) for alias, name in aliases: newType = TypeNode(ast, None, source_file='<builtin>') newType.leaf = alias newType.add_attribute('meta_type', 'alias') type_list = ast.children index = [element.leaf for element in type_list].index(name) target = Node(newType, 'target', [type_list[index]]) newType.add_child(target) ast.add_child(newType) if typetype == 'idl4': create_special_C(arch_info, ast) if typetype == 'mig': create_special_MIG(arch_info, ast) return ast
def state_member(self, ast, pt): type_node = TypeNode(ast, None, source = pt) if pt.the('state_member') != None: type_node.leaf = child.leaf type_node.add_child(self.type_spec(ast, pt.the('type_spec'))) decls = pt.the('declarators') decl_list = [] for child in decls.children: decl_list.append(self.getDeclarator(child)) dec_node = Node(type_node, 'declarator', None, source = pt) dec_node.leaf = decl_list type_node.add_child(dec_node) return type_node
def create_special_MIG(arch_info, ast): poly_list = (("MACH_MSG_TYPE_PORT_RECEIVE", '32', 'MACH_MSG_TYPE_PORT_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_PORT_SEND", '32', 'MACH_MSG_TYPE_PORT_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_PORT_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_POLYMORPHIC'), ("MACH_MSG_TYPE_COPY_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MAKE_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MOVE_SEND", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND'), ("MACH_MSG_TYPE_MAKE_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND_ONCE'), ("MACH_MSG_TYPE_MOVE_SEND_ONCE", '32', 'MACH_MSG_TYPE_SEND_internal', 'MACH_MSG_TYPE_PORT_SEND_ONCE'), ("MACH_MSG_TYPE_MOVE_RECEIVE", '32', 'MACH_MSG_TYPE_RECEIVE_internal', 'MACH_MSG_TYPE_PORT_RECEIVE')) type_list = ast.children for name, size, sender, receiver in poly_list: newType = TypeNode(ast, None, source_file='<builtin>') newType.leaf = name newType.add_attribute('meta_type', 'polymorphic') info = Node(newType, 'info') newType.add_child(info) index = [element.leaf for element in type_list].index(sender) info.add_attribute('sender_type', type_list[index]) index = [element.leaf for element in type_list].index(receiver) info.add_attribute('receiver_type', type_list[index]) type_list.append(newType) ast.add_child(newType)
def _get_target_type(self, ast, pt, wrapper = None, defining_scope = None): """ A complicated function with side effects. Either searches for (if it is a reference) or creates (otherwise) the type specified by <pt>. The scope to begin searching is passed in <ast>. The type is returned. If a new type is created, it is always returned in a wrapper, named 'target'. If <wrapper> (a string) is passed in, that name is used instead of <target>. If <defining_scope> is supplied and the type is created, the new type (sans wrapper) is stored in <defining_scope>. If the new type is an enumeration, more than one type node is created in <defining_scope>. """ new_type = False # Walk to the lowest child. while pt.name in ('const_type', 'type_spec', 'simple_type_spec', 'base_type_spec', 'switch_type_spec', 'param_type_spec', 'constr_type_spec',) \ and len(pt.children) == 1: pt = pt.children[0] if defining_scope: ast = defining_scope # NB This means AST must already be part of the tree. if pt.name in ('struct_type', 'union_type', 'enum_type'): typeref = self.constr_type_spec(ast, pt, defining_scope = defining_scope) new_type = True # NOTE! A new type is created here, but we do not add it to defining_scope, # because constr_type_spec does that for us. This could be improved :( elif pt.name == 'template_type_spec': typeref = self.template_type_spec(ast, pt) new_type = True if defining_scope: defining_scope.add_child(typeref) self._dupes_check(typeref) elif pt.name == 'integer_type': name = self.integer_type(ast, pt) typeref = get_corba_or_c_type(name, ast) elif pt.name == 'char_type': typeref = get_corba_or_c_type('char', ast) elif pt.name == 'wide_char_type': typeref = get_corba_or_c_type('wchar', ast) elif pt.name == 'boolean_type': typeref = get_corba_or_c_type('boolean', ast) elif pt.name == 'floating_pt_type': name = self.floating_pt_type(ast, pt) typeref = get_corba_or_c_type('name', ast) elif pt.name == 'string_type': typeref = self.string_type(ast, pt) new_type = True if defining_scope: defining_scope.add_child(typeref) self._dupes_check(typeref) elif pt.name == 'wide_string_type': typeref = self.wide_string_type(ast, pt) new_type = True if defining_scope: defining_scope.add_child(typeref) self._dupes_check(typeref) elif pt.name == 'void_type': typeref = get_corba_or_c_type('void', ast) elif pt.name == '_type': raise Error("Unknown type ('fixed'?)") elif pt.name == 'scoped_name': typeref = self.scoped_name_type(ast, pt) elif pt.name == 'octet_type': typeref = infogripper.getBasicTypenode('octet', ast) elif pt.name == 'object_type': typeref = infogripper.getBasicTypenode('Object', ast) else: pt.print_tree() raise Exception() typeref = TypeNode(ast, None, source = pt) typeref.leaf = 'UNKNOWN' # Wrap the type. if wrapper is None: wrapper = 'target' typeref = self._target_wrap(ast, typeref, wrapper) # All done. return typeref, new_type