# -*- python -*-
# Package : omniidl
# defs.py Created on: 1999/11/2
# Author : David Scott (djs)
#
# Copyright (C) 2003-2008 Apasphere Ltd
# Copyright (C) 1999 AT&T Laboratories Cambridge
#
# This file is part of omniidl.
#
# omniidl is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# Description:
#
# Produce the main header definitions for the C++ backend
# $Id: defs.py,v 1.36.2.17 2009/05/06 16:15:46 dgrisby Exp $
# $Log: defs.py,v $
# Revision 1.36.2.17 2009/05/06 16:15:46 dgrisby
# Update lots of copyright notices.
#
# Revision 1.36.2.16 2008/12/29 18:44:38 dgrisby
# Globally scope array functions to avoid ambiguities.
#
# Revision 1.36.2.15 2007/09/19 14:16:07 dgrisby
# Avoid namespace clashes if IDL defines modules named CORBA.
#
# Revision 1.36.2.14 2007/04/12 19:51:16 dgrisby
# Fixed point member values should not go in a union's union.
#
# Revision 1.36.2.13 2006/05/25 18:19:12 dgrisby
# Incorrect code generated for valuebox containing sequence of value;
# clean up class nesting tracking.
#
# Revision 1.36.2.12 2006/01/18 19:23:18 dgrisby
# Code generation problems with valuetype inheritance / typedefs.
#
# Revision 1.36.2.11 2006/01/10 12:24:04 dgrisby
# Merge from omni4_0_develop pre 4.0.7 release.
#
# Revision 1.36.2.10 2005/11/09 12:22:17 dgrisby
# Local interfaces support.
#
# Revision 1.36.2.9 2005/08/16 13:51:21 dgrisby
# Problems with valuetype / abstract interface C++ mapping.
#
# Revision 1.36.2.8 2005/01/06 23:10:03 dgrisby
# Big merge from omni4_0_develop.
#
# Revision 1.36.2.7 2004/10/13 17:58:23 dgrisby
# Abstract interfaces support; values support interfaces; value bug fixes.
#
# Revision 1.36.2.6 2004/07/23 10:29:59 dgrisby
# Completely new, much simpler Any implementation.
#
# Revision 1.36.2.5 2004/07/04 23:53:38 dgrisby
# More ValueType TypeCode and Any support.
#
# Revision 1.36.2.4 2004/02/16 10:10:31 dgrisby
# More valuetype, including value boxes. C++ mapping updates.
#
# Revision 1.36.2.3 2003/11/06 11:56:56 dgrisby
# Yet more valuetype. Plain valuetype and abstract valuetype are now working.
#
# Revision 1.36.2.2 2003/10/23 11:25:55 dgrisby
# More valuetype support.
#
# Revision 1.36.2.1 2003/03/23 21:02:38 dgrisby
# Start of omniORB 4.1.x development branch.
#
# Revision 1.33.2.14 2001/10/29 17:42:39 dpg1
# Support forward-declared structs/unions, ORB::create_recursive_tc().
#
# Revision 1.33.2.13 2001/10/18 12:45:28 dpg1
# IDL compiler tweaks.
#
# Revision 1.33.2.12 2001/08/17 13:45:55 dpg1
# C++ mapping fixes.
#
# Revision 1.33.2.11 2001/08/15 10:29:53 dpg1
# Update DSI to use Current, inProcessIdentity.
#
# Revision 1.33.2.10 2001/07/31 19:25:11 sll
# Array _var should be separated into fixed and variable size ones.
#
# Revision 1.33.2.9 2001/07/26 11:27:26 dpg1
# Typo in C++ back-end broke wstring constants.
#
# Revision 1.33.2.8 2001/06/08 17:12:16 dpg1
# Merge all the bug fixes from omni3_develop.
#
# Revision 1.33.2.7 2001/03/13 10:32:08 dpg1
# Fixed point support.
#
# Revision 1.33.2.6 2000/11/20 14:43:25 sll
# Added support for wchar and wstring.
#
# Revision 1.33.2.5 2000/11/10 15:40:52 dpg1
# Missed an update in yesterday's merge.
#
# Revision 1.33.2.4 2000/11/07 18:29:56 sll
# Choose a default constant not too large to avoid g++ complaining.
#
# Revision 1.33.2.3 2000/11/03 19:19:46 sll
# visitTypedef() just rely on types.base() to give the right type name for
# object reference, instead of adding in a "_ptr" suffix.
#
# Revision 1.33.2.2 2000/10/12 15:37:50 sll
# Updated from omni3_1_develop.
#
# Revision 1.34.2.3 2000/08/21 11:35:15 djs
# Lots of tidying
#
# Revision 1.34.2.2 2000/08/04 17:10:29 dpg1
# Long long support
#
# Revision 1.34.2.1 2000/08/02 10:52:02 dpg1
# New omni3_1_develop branch, merged from omni3_develop.
#
# Revision 1.34 2000/07/13 15:26:00 dpg1
# Merge from omni3_develop for 3.0 release.
#
# Revision 1.31.2.19 2000/08/03 21:27:39 djs
# Typo in -Wbvirtual_objref code caused incorrect operation signatures to be
# generated in the _objref class of an interface.
#
# Revision 1.31.2.18 2000/07/26 15:29:08 djs
# Missing typedef and forward when generating BOA skeletons
#
# Revision 1.31.2.17 2000/07/18 15:34:25 djs
# Added -Wbvirtual_objref option to make attribute and operation _objref
# methods virtual
#
# Revision 1.31.2.16 2000/07/12 17:16:11 djs
# Minor bugfix to option -Wbsplice-modules
#
# Revision 1.31.2.15 2000/06/27 16:15:10 sll
# New classes: _CORBA_String_element, _CORBA_ObjRef_Element,
# _CORBA_ObjRef_tcDesc_arg to support assignment to an element of a
# sequence of string and a sequence of object reference.
#
# Revision 1.31.2.14 2000/06/26 16:23:57 djs
# Better handling of #include'd files (via new commandline options)
# Refactoring of configuration state mechanism.
#
# Revision 1.31.2.13 2000/06/19 18:19:49 djs
# Implemented union discriminant setting function _d(_value) with checks for
# illegal uses (setting to a label corresponding to a non-current member and
# setting before initialisation)
#
# Revision 1.31.2.12 2000/06/16 08:36:40 djs
# For a union with a boolean discriminant and an implied default, sets a
# better default discriminator in _default()
#
# Revision 1.31.2.11 2000/06/05 13:03:55 djs
# Removed union member name clash (x & pd_x, pd__default, pd__d)
# Removed name clash when a sequence is called "pd_seq"
# Nested union within union fix
# Actually generates BOA non-flattened tie templates
#
# Revision 1.31.2.10 2000/05/31 18:02:56 djs
# Better output indenting (and preprocessor directives now correctly output at
# the beginning of lines)
#
# Revision 1.31.2.9 2000/05/30 15:59:23 djs
# Removed inheritance ambiguity in generated BOA _sk_ and POA_ classes
#
# Revision 1.31.2.8 2000/05/18 15:57:32 djs
# Added missing T* data constructor for bounded sequence types
#
# Revision 1.31.2.7 2000/05/04 14:35:02 djs
# Added new flag splice-modules which causes all continuations to be output
# as one lump. Default is now to output them in pieces following the IDL.
#
# Revision 1.31.2.6 2000/04/26 18:22:28 djs
# Rewrote type mapping code (now in types.py)
# Rewrote identifier handling code (now in id.py)
#
# Revision 1.31.2.5 2000/04/05 10:57:37 djs
# Minor source tidying (removing commented out blocks)
#
# Revision 1.31.2.4 2000/03/24 17:18:48 djs
# Missed _ from typedefs to objrefs
#
# Revision 1.31.2.3 2000/03/24 16:24:22 djs
# Produced 2 invalid typedefs in the case of a typedef to an object reference
# (it transformed a " " into a "_" by mistake)
#
# Revision 1.31.2.2 2000/03/20 11:50:18 djs
# Removed excess buffering- output templates have code attached which is
# lazily evaluated when required.
#
# Revision 1.31.2.1 2000/02/14 18:34:55 dpg1
# New omniidl merged in.
#
# Revision 1.31 2000/01/19 11:23:27 djs
# Moved most C++ code to template file
#
# Revision 1.30 2000/01/18 18:05:52 djs
# Extracted most C++ from header/defs and put in a template file.
# General refactoring.
#
# Revision 1.29 2000/01/17 17:01:49 djs
# Many fixes including:
# Module continuations
# Constructed types
# Union discriminator handling
#
# Revision 1.28 2000/01/14 17:38:27 djs
# Preliminary support for unions with multiple case labels
#
# Revision 1.27 2000/01/13 17:02:00 djs
# Added support for operation contexts.
#
# Revision 1.26 2000/01/13 15:56:38 djs
# Factored out private identifier prefix rather than hard coding it all through
# the code.
#
# Revision 1.25 2000/01/13 14:16:29 djs
# Properly clears state between processing separate IDL input files
#
# Revision 1.24 2000/01/12 17:48:31 djs
# Added option to create BOA compatible skeletons (same as -BBOA in omniidl3)
#
# Revision 1.23 2000/01/11 14:13:15 djs
# Updated array mapping to include NAME_copy(to, from) as per 2.3 spec
#
# Revision 1.22 2000/01/11 11:34:27 djs
# Added support for fragment generation (-F) mode
#
# Revision 1.21 2000/01/10 16:13:13 djs
# Removed a chunk of redundant code.
#
# Revision 1.20 2000/01/10 15:38:55 djs
# Better name and scope handling.
#
# Revision 1.19 2000/01/07 20:31:27 djs
# Regression tests in CVSROOT/testsuite now pass for
# * no backend arguments
# * tie templates
# * flattened tie templates
# * TypeCode and Any generation
#
# Revision 1.18 1999/12/26 16:43:06 djs
# Enum scope fix
# Handling default case of char discriminated switch fixed
#
# Revision 1.17 1999/12/25 21:47:18 djs
# Better TypeCode support
#
# Revision 1.16 1999/12/24 18:14:29 djs
# Fixed handling of #include'd .idl files
#
# Revision 1.15 1999/12/16 16:10:46 djs
# TypeCode fixes
#
# Revision 1.14 1999/12/15 12:13:16 djs
# Multiple forward declarations of interface fix
#
# Revision 1.13 1999/12/14 17:38:22 djs
# Fixed anonymous sequences of sequences bug
#
# Revision 1.12 1999/12/14 11:52:30 djs
# Support for CORBA::TypeCode and CORBA::Any
#
# Revision 1.11 1999/12/01 17:03:15 djs
# Added support for Typecodes and Anys
#
# Revision 1.10 1999/11/23 18:46:34 djs
# Constant fixes
# Moved exception constructor argument generator into a more central place
#
# Revision 1.9 1999/11/19 20:08:09 djs
# Removed references to a non-existant utility function
#
# Revision 1.8 1999/11/15 19:12:45 djs
# Tidied up sequence template handling
# Moved useful functions into separate utility module
#
# Revision 1.7 1999/11/12 17:18:39 djs
# Lots of header generation bugfixes
#
# Revision 1.6 1999/11/10 20:19:43 djs
# Array struct element fix
# Union sequence element fix
#
# Revision 1.5 1999/11/08 19:29:03 djs
# Rewrite of sequence template code
# Fixed lots of typedef problems
#
# Revision 1.4 1999/11/04 19:05:08 djs
# Finished moving code from tmp_omniidl. Regression tests ok.
#
# Revision 1.3 1999/11/03 18:18:12 djs
# Struct and Exception fixes
#
# Revision 1.2 1999/11/03 17:35:11 djs
# Brought more of the old tmp_omniidl code into the new tree
#
# Revision 1.1 1999/11/03 11:09:56 djs
# General module renaming
#
"""Produce the main header definitions"""
# similar to o2be_root::produce_hdr_defs in the old C++ BE
import string
from omniidl import idlast,idltype,idlutil
from omniidl_be.cxx import output,config,id,types,iface,cxx,ast,util
from omniidl_be.cxx import value
from omniidl_be.cxx.header import template
# We behave as if the global code here is really inside a class
import defs
self = defs
stream = None
_insideClass = 0
_insideModule = 0
_insideInterface = 0
_interfaces = {}
_completedModules = {}
def pushInsideClass():
global _insideClass
_insideClass = _insideClass + 1
def popInsideClass():
global _insideClass
_insideClass = _insideClass - 1
def pushInsideModule():
global _insideModule
_insideModule = _insideModule + 1
def popInsideModule():
global _insideModule
_insideModule = _insideModule - 1
def pushInsideInterface():
global _insideInterface
_insideInterface = _insideInterface + 1
def popInsideInterface():
global _insideInterface
_insideInterface = _insideInterface - 1
def __init__(_stream):
global stream, _insideClass, _insideModule, _insideInterface
global _interfaces, _completedModules
stream = _stream
# Need to keep track of how deep within the AST we are.
# In a recursive procedure these would be extra arguments,
# but the visitor pattern necessitates them being global.
_insideInterface = 0
_insideModule = 0
_insideClass = 0
# A repository id entry in this hash indicates that an interface
# has been declared- therefore any more AST forward nodes for this
# interface are ignored.
_interfaces = {}
# When we first encounter a module, we sometimes deal with all the
# continuations straight away. Therefore when we reencounter a
# continuation later, we don't duplicate the definitions.
_completedModules = {}
import defs
return defs
# Returns the prefix required inside a const declaration (it depends on
# exactly what the declaration is nested inside)
def const_qualifier(insideModule=None, insideClass=None):
if insideModule is None:
insideModule = _insideModule
insideClass = _insideClass
if not insideModule and not insideClass:
return "_CORBA_GLOBAL_VAR"
elif insideClass:
return "static"
else:
return "_CORBA_MODULE_VAR"
# Same logic for function qualifiers
def func_qualifier():
return const_qualifier(_insideModule, _insideClass)
# Inline functions are subtly different
def inline_qualifier():
if not _insideModule and not _insideClass:
return "inline"
elif _insideClass:
return "static inline"
else:
return "_CORBA_MODULE_INLINE"
#
# Control arrives here
#
def visitAST(node):
global stream, _insideClass, _insideModule, _insideInterface
global _interfaces, _completedModules
_insideInterface = 0
_insideModule = 0
_insideClass = 0
_interfaces = {}
_completedModules = {}
for n in node.declarations():
if ast.shouldGenerateCodeForDecl(n):
n.accept(self)
def visitModule(node):
# Ensure we only output the definitions once.
# In particular, when the splice-modules flag is set and this is
# a reopened module, the node will be marked as completed already.
if _completedModules.has_key(node):
return
_completedModules[node] = 1
ident = node.identifier()
cxx_id = id.mapID(ident)
if not config.state['Fragment']:
stream.out(template.module_begin, name = cxx_id)
stream.inc_indent()
# push self.__insideModule, true
pushInsideModule()
for n in node.definitions():
n.accept(self)
# deal with continuations (only if the splice-modules flag is set)
if config.state['Splice Modules']:
for c in node.continuations():
for n in c.definitions():
n.accept(self)
_completedModules[c] = 1
popInsideModule()
if not config.state['Fragment']:
stream.dec_indent()
stream.out(template.module_end, name = cxx_id)
def visitInterface(node):
# It's legal to have a forward interface declaration after
# the actual interface definition. Make sure we ignore these.
_interfaces[node.repoId()] = 1
name = node.identifier()
cxx_name = id.mapID(name)
outer_environment = id.lookup(node)
environment = outer_environment.enter(name)
pushInsideInterface()
pushInsideClass()
# make the necessary forward references, typedefs and define
# the _Helper class
I = iface.Interface(node)
I_Helper = iface.instance("I_Helper")(I)
I_Helper.hh(stream)
# recursively take care of other IDL declared within this
# scope (evaluate function later- lazy eval though 'thunking')
def Other_IDL(node = node):
for n in node.declarations():
n.accept(self)
# Output the this interface's corresponding class
Ibase = iface.instance("I")(I,Other_IDL)
Ibase.hh(stream)
if not node.local():
_objref_I = iface.instance("_objref_I")(I)
_objref_I.hh(stream)
_pof_I = iface.instance("_pof_I")(I)
_pof_I.hh(stream)
# Skeleton class
_impl_I = iface.instance("_impl_I")(I)
_impl_I.hh(stream)
# Generate BOA compatible skeletons?
if config.state['BOA Skeletons']:
_sk_I = iface.instance("_sk_I")(I)
_sk_I.hh(stream)
popInsideClass()
popInsideInterface()
# Typecode and Any
if config.state['Typecode']:
qualifier = const_qualifier(_insideModule, _insideClass)
stream.out(template.typecode,
qualifier = qualifier,
name = cxx_name)
return
def visitForward(node):
# Note it's legal to have multiple forward declarations
# of the same name. So ignore the duplicates.
if _interfaces.has_key(node.repoId()):
return
_interfaces[node.repoId()] = 1
environment = id.lookup(node)
scope = environment.scope()
cxx_id = id.mapID(node.identifier())
name = id.Name(node.scopedName())
guard = name.guard()
# Potentially forward declare BOA skeleton class
class_sk = ""
if config.state['BOA Skeletons']:
class_sk = "class _sk_" + name.unambiguous(environment) + ";"
# output the definition
if node.abstract():
stream.out(template.abstract_interface_Helper,
guard = guard,
class_sk_name = class_sk,
name = name.unambiguous(environment))
elif node.local():
stream.out(template.local_interface_Helper,
guard = guard,
class_sk_name = class_sk,
name = name.unambiguous(environment))
else:
stream.out(template.interface_Helper,
guard = guard,
class_sk_name = class_sk,
name = name.unambiguous(environment))
def visitConst(node):
environment = id.lookup(node)
scope = environment.scope()
constType = types.Type(node.constType())
d_constType = constType.deref()
if d_constType.string():
type_string = "char *"
elif d_constType.wstring():
type_string = "::CORBA::WChar *"
elif d_constType.fixed():
type_string = constType.member()
else:
type_string = d_constType.member()
# should this be .base?
cxx_name = id.mapID(node.identifier())
value = d_constType.literal(node.value(), environment)
representedByInteger = d_constType.representable_by_int()
# depends on whether we are inside a class / in global scope
# etc
# should be rationalised with tyutil.const_qualifier
if _insideClass:
if representedByInteger:
stream.out(template.const_inclass_isinteger,
type = type_string, name = cxx_name, val = value)
else:
stream.out(template.const_inclass_notinteger,
type = type_string, name = cxx_name)
else:
where = "GLOBAL"
if _insideModule:
where = "MODULE"
if representedByInteger:
stream.out(template.const_outsideclass_isinteger,
where = where,
type = type_string,
name = cxx_name,
val = value)
else:
stream.out(template.const_outsideclass_notinteger,
where = where,
type = type_string,
name = cxx_name)
def visitTypedef(node):
environment = id.lookup(node)
scope = environment.scope()
is_global_scope = not (_insideModule or _insideInterface)
aliasType = types.Type(node.aliasType())
aliasTypeID = aliasType.member(environment)
# is _this_ type a constructed type?
if node.constrType():
node.aliasType().decl().accept(self)
d_type = aliasType.deref()
derefTypeID = d_type.base(environment)
basicReferencedTypeID = aliasType.member(environment)
# each one is handled independently
for d in node.declarators():
# derivedName is the new typedef'd name
# alias_dims is a list of dimensions of the type being aliased
derivedName = id.mapID(d.identifier())
alias_dims = aliasType.dims()
# array_declarator indicates whether this is a simple (non-array)
# declarator or not
array_declarator = d.sizes() != []
# Typecode and Any
if config.state['Typecode']:
qualifier = const_qualifier(_insideModule,_insideClass)
stream.out(template.typecode,
qualifier = qualifier,
name = derivedName)
# is it a simple alias (ie not an array at this level)?
if not array_declarator:
# not an array declarator but a simple declarator to an array
if aliasType.array():
# simple alias to an array should alias all the
# array handling functions, but we don't need to duplicate
# array looping code since we can just call the functions
# for the base type
stream.out(template.typedef_simple_to_array,
base = basicReferencedTypeID,
derived = derivedName,
qualifier = func_qualifier(),
inline_qualifier = inline_qualifier())
# Non-array of string
elif d_type.string():
stream.out(template.typedef_simple_string,
name = derivedName)
elif d_type.wstring():
stream.out(template.typedef_simple_wstring,
name = derivedName)
elif d_type.typecode():
stream.out(template.typedef_simple_typecode,
name = derivedName)
elif d_type.any():
stream.out(template.typedef_simple_any,
name = derivedName)
elif d_type.fixed():
stream.out(template.typedef_simple_fixed,
name = derivedName,
digits = d_type.type().digits(),
scale = d_type.type().scale())
# Non-array of basic type
elif isinstance(d_type.type(), idltype.Base):
stream.out(template.typedef_simple_basic,
base = basicReferencedTypeID,
derived = derivedName)
# a typedef to a struct or union, or a typedef to a
# typedef to a sequence
elif d_type.struct() or d_type.structforward() or \
d_type.union() or d_type.unionforward() or \
(d_type.sequence() and aliasType.typedef()):
stream.out(template.typedef_simple_constructed,
base = basicReferencedTypeID,
name = derivedName)
# Non-array of object reference
elif d_type.interface():
derefTypeID = string.replace(derefTypeID,"_ptr","")
# Note that the base name is fully flattened
is_CORBA_Object = d_type.type().scopedName() ==\
["CORBA", "Object"]
impl_base = ""
objref_base = ""
sk_base = ""
if not is_CORBA_Object:
scopedName = d_type.type().decl().scopedName()
name = id.Name(scopedName)
impl_scopedName = name.prefix("_impl_")
objref_scopedName = name.prefix("_objref_")
sk_scopedName = name.prefix("_sk_")
impl_name = impl_scopedName.unambiguous(environment)
objref_name = objref_scopedName.unambiguous(environment)
sk_name = sk_scopedName.unambiguous(environment)
impl_base = "typedef " + impl_name + " _impl_" +\
derivedName + ";"
objref_base = "typedef " + objref_name + " _objref_" +\
derivedName + ";"
sk_base = "typedef " + sk_name + " _sk_" +\
derivedName + ";"
stream.out(template.typedef_simple_objref,
base = derefTypeID,
name = derivedName,
impl_base = impl_base,
objref_base = objref_base)
if config.state['BOA Skeletons']:
stream.out(sk_base)
# Non-array of valuetype
elif d_type.value() or d_type.valuebox():
basicReferencedTypeID = string.replace(basicReferencedTypeID,
"_member", "")
stream.out(template.typedef_simple_constructed,
base = basicReferencedTypeID,
name = derivedName)
# Non-array of enum
elif d_type.enum():
stream.out(template.typedef_simple_basic,
base = basicReferencedTypeID,
derived = derivedName)
# Non-array of sequence
elif d_type.sequence():
seqType = types.Type(d_type.type().seqType())
d_seqType = seqType.deref()
bounded = d_type.type().bound()
templateName = d_type.sequenceTemplate(environment)
if d_seqType.structforward() or d_seqType.unionforward():
# Sequence of forward-declared struct or union.
# We cannot use the normal sequence templates
# since they have inline methods that require the
# full definition of the member type. We use
# templates with abstract virtual functions
# instead.
element = element_ptr = seqType.base(environment)
def bounds(bounded = bounded,
derivedName = derivedName,
derived = templateName,
element = element):
if bounded:
ct = template.sequence_bounded_ctors
else:
ct = template.sequence_unbounded_ctors
stream.out(ct, name = derivedName, element=element,
bound=bounded, derived=derived)
stream.out(template.sequence_forward_type,
name = derivedName,
derived = templateName,
element = element,
bounds = bounds)
else:
# Normal case using a template class.
if seqType.array():
element = "*** INVALID"
element_ptr = seqType.base(environment)
else:
if d_seqType.string():
element = "_CORBA_String_element"
element_ptr = "char*"
elif d_seqType.wstring():
element = "_CORBA_WString_element"
element_ptr = "::CORBA::WChar*"
elif d_seqType.interface():
element = seqType.base(environment)
element_ptr = element
elif d_seqType.value() or d_seqType.valuebox():
element = seqType.base(environment)
element_ptr = element + "*"
# only if an anonymous sequence
elif seqType.sequence():
element = d_seqType.sequenceTemplate(environment)
element_ptr = element
elif d_seqType.typecode():
element = "::CORBA::TypeCode_member"
element_ptr = element
else:
element = seqType.base(environment)
element_ptr = element
# enums are a special case
# from o2be_sequence.cc:795:
# ----
# gcc requires that the marshalling operators for the
# element be declared before the sequence template is
# typedef'd. This is a problem for enums, as the
# marshalling operators are not yet defined (and are
# not part of the type itself).
# ----
# Note that the fully dereferenced name is used
friend = "friend"
if is_global_scope:
friend = ""
if d_seqType.enum() and not seqType.array():
stream.out(template.typedef_enum_oper_friend,
element = d_seqType.base(environment),
friend = friend)
# derivedName is the new type identifier
# element is the name of the basic element type
# templateName contains the template instantiation
def bounds(bounded = bounded, derivedName = derivedName,
element_ptr = element_ptr,
templateName = templateName):
if bounded:
ctor_template = template.sequence_bounded_ctors
else:
ctor_template = template.sequence_unbounded_ctors
stream.out(ctor_template,
name = derivedName,
element = element_ptr,
derived = templateName)
# output the main sequence definition
stream.out(template.sequence_type,
name = derivedName,
derived = templateName,
bounds = bounds)
# start building the _var and _out types
element_reference = "*** INVALID"
if not aliasType.array():
if d_seqType.string():
# special case alert
element_reference = element
elif d_seqType.wstring():
# special case alert
element_reference = element
elif d_seqType.interface():
element_reference = d_seqType.objRefTemplate("Element",
environment)
elif d_seqType.value() or d_seqType.valuebox():
element_reference = d_seqType.valueTemplate("Element",
environment)
# only if an anonymous sequence
elif seqType.sequence():
element_reference = d_seqType.sequenceTemplate(environment) + "&"
else:
element_reference = element + "&"
def subscript_operator_var(stream = stream,
is_array = seqType.array(),
element_ptr = element_ptr,
element_ref = element_reference):
if is_array:
stream.out(template.sequence_var_array_subscript,
element = element_ptr)
else:
stream.out(template.sequence_var_subscript,
element = element_ref)
def subscript_operator_out(stream = stream,
is_array = seqType.array(),
element_ptr = element_ptr,
element_ref = element_reference):
if is_array:
stream.out(template.sequence_out_array_subscript,
element = element_ptr)
else:
stream.out(template.sequence_out_subscript,
element = element_ref)
# write the _var class definition
stream.out(template.sequence_var,
name = derivedName,
subscript_operator = subscript_operator_var)
# write the _out class definition
stream.out(template.sequence_out,
name = derivedName,
subscript_operator = subscript_operator_out)
else:
util.fatalError("Inexhaustive Case Match")
# ----------------------------------------------------------------
# declarator is an array typedef declarator
elif array_declarator:
all_dims = d.sizes() + alias_dims
dimsString = cxx.dimsToString(d.sizes())
taildims = cxx.dimsToString(d.sizes()[1:])
typestring = aliasType.member(environment)
# build the _dup loop
def dup_loop(stream = stream, all_dims = all_dims):
loop = cxx.For(stream, all_dims)
stream.out("\n_data@index@ = _s@index@;\n",
index = loop.index())
loop.end()
# build the _copy loop
def copy_loop(stream = stream, all_dims = all_dims):
loop = cxx.For(stream, all_dims)
stream.out("\n_to@index@ = _from@index@;\n",
index = loop.index())
loop.end()
stream.out(template.typedef_array,
name = derivedName,
type = typestring,
dims = dimsString,
taildims = taildims,
firstdim = repr(all_dims[0]),
dup_loop = dup_loop,
copy_loop = copy_loop,
qualifier = func_qualifier(),
inline_qualifier = inline_qualifier())
# output the _copyHelper class
fqname = id.Name(d.scopedName()).fullyQualify()
if types.variableDecl(node):
stream.out(template.typedef_array_copyHelper,
var_or_fix = "Variable",
name = derivedName,
fqname = fqname)
stream.out(template.typedef_array_variable_out_type,
name = derivedName)
else:
stream.out(template.typedef_array_copyHelper,
var_or_fix = "Fix",
name = derivedName,
fqname = fqname)
stream.out(template.typedef_array_fix_out_type,
name = derivedName)
def visitMember(node):
memberType = node.memberType()
if node.constrType():
# if the type was declared here, it must be an instance
# of idltype.Declared!
assert isinstance(memberType, idltype.Declared)
memberType.decl().accept(self)
def visitStruct(node):
name = node.identifier()
cxx_name = id.mapID(name)
outer_environment = id.lookup(node)
environment = outer_environment.enter(name)
scope = environment.scope()
pushInsideClass()
# Deal with types constructed here
def Other_IDL(stream = stream, node = node, environment = environment):
for m in node.members():
if m.constrType():
m.memberType().decl().accept(self)
# Deal with the actual struct members
def members(stream = stream, node = node, environment = environment):
for m in node.members():
memberType = types.Type(m.memberType())
memtype = memberType.member(environment)
for d in m.declarators():
ident = d.identifier()
cxx_id = id.mapID(ident)
decl_dims = d.sizes()
is_array_declarator = decl_dims != []
# non-arrays of direct sequences are done via a typedef
if not is_array_declarator and memberType.sequence():
stream.out(template.struct_nonarray_sequence,
memtype = memtype,
cxx_id = cxx_id)
else:
dims_string = cxx.dimsToString(decl_dims)
if is_array_declarator:
stream.out(template.struct_array_declarator,
memtype = memtype,
cxx_id = cxx_id,
dims = dims_string,
tail_dims = cxx.dimsToString(d.sizes()[1:]),
prefix = config.state['Private Prefix'])
stream.out(template.struct_normal_member,
memtype = memtype,
cxx_id = cxx_id,
dims = dims_string)
# Output the structure itself
if types.variableDecl(node):
stream.out(template.struct,
name = cxx_name,
fix_or_var = "Variable",
Other_IDL = Other_IDL,
members = members)
stream.out(template.struct_variable_out_type,
name = cxx_name)
else:
stream.out(template.struct,
name = cxx_name,
fix_or_var = "Fix",
Other_IDL = Other_IDL,
members = members)
stream.out(template.struct_fix_out_type,
name = cxx_name)
popInsideClass()
# TypeCode and Any
if config.state['Typecode']:
# structs in C++ are classes with different default privacy policies
qualifier = const_qualifier(_insideModule, _insideClass)
stream.out(template.typecode,
qualifier = qualifier,
name = cxx_name)
def visitStructForward(node):
cxx_name = id.mapID(node.identifier())
stream.out(template.struct_forward, name = cxx_name)
def visitException(node):
exname = node.identifier()
cxx_exname = id.mapID(exname)
outer_environment = id.lookup(node)
environment = outer_environment.enter(exname)
scope = environment.scope()
pushInsideClass()
# if the exception has no members, inline some no-ops
no_members = (node.members() == [])
# other types constructed within this one
def Other_IDL(stream = stream, node = node):
for m in node.members():
if m.constrType():
m.memberType().decl().accept(self)
# deal with the exceptions members
def members(stream = stream, node = node, environment = environment):
for m in node.members():
memberType = types.Type(m.memberType())
for d in m.declarators():
decl_dims = d.sizes()
full_dims = decl_dims + memberType.dims()
is_array = full_dims != []
is_array_declarator = decl_dims != []
memtype = memberType.member(environment)
ident = d.identifier()
cxx_id = id.mapID(ident)
dims_string = cxx.dimsToString(decl_dims)
if is_array_declarator:
stream.out(template.exception_array_declarator,
memtype = memtype,
cxx_id = cxx_id,
dims = dims_string,
tail_dims = cxx.dimsToString(d.sizes()[1:]),
private_prefix = config.state['Private Prefix'])
stream.out(template.exception_member,
memtype = memtype,
cxx_id = cxx_id,
dims = dims_string)
# deal with ctor args
ctor_args = []
for m in node.members():
memberType = types.Type(m.memberType())
d_memberType = memberType.deref()
for d in m.declarators():
decl_dims = d.sizes()
is_array_declarator = decl_dims != []
ctor_arg_type = memberType.op(types.IN, environment)
# sequences are not passed by reference here
if d_memberType.sequence():
if memberType.typedef():
ctor_arg_type = "const " + id.Name(memberType.type().decl().scopedName()).unambiguous(environment)
else:
ctor_arg_type = "const " + memberType.sequenceTemplate(environment)
elif d_memberType.typecode():
ctor_arg_type = "::CORBA::TypeCode_ptr"
ident = d.identifier()
cxx_id = id.mapID(ident)
if is_array_declarator:
ctor_arg_type = "const " + config.state['Private Prefix'] +\
"_" + cxx_id
ctor_args.append(ctor_arg_type + " i_" + cxx_id)
ctor = ""
if ctor_args != []:
ctor = cxx_exname + "(" + string.join(ctor_args, ", ") + ");"
if no_members:
inline = "inline "
body = "{ }"
alignedSize = ""
else:
inline = ""
body = ";"
alignedSize = "size_t _NP_alignedSize(size_t) const;"
# output the main exception declaration
stream.out(template.exception,
name = cxx_exname,
Other_IDL = Other_IDL,
members = members,
constructor = ctor,
alignedSize = alignedSize,
inline = inline,
body = body)
popInsideClass()
# Typecode and Any
if config.state['Typecode']:
qualifier = const_qualifier(_insideModule, _insideClass)
stream.out(template.typecode,
qualifier = qualifier,
name = cxx_exname)
def visitUnion(node):
ident = node.identifier()
cxx_id = id.mapID(ident)
outer_environment = id.lookup(node)
environment = outer_environment.enter(ident)
scope = environment.scope()
pushInsideClass()
switchType = types.Type(node.switchType())
d_switchType = switchType.deref()
####################################################################
# in the case where there is no default case and an implicit default
# member, choose a discriminator value to set. Note that attempting
# to access the data is undefined
def chooseArbitraryDefault(switchType = switchType,
values = ast.allCaseLabelValues(node),
environment = environment):
# dereference the switch_type (ie if CASE <scoped_name>)
switchType = switchType.deref()
# for integer types, find the lowest unused number
def min_unused(start, used = values):
x = start
while x in used:
x = x + 1
return x
kind = switchType.type().kind()
if switchType.integer():
(low, high) = ast.integer_type_ranges[kind]
s = switchType.literal(min_unused(low+1))
return s
# for other types, first compute the set of all legal values
# (sets are all fairly small)
elif kind == idltype.tk_char:
all = map(chr, range(0, 255))
elif kind == idltype.tk_boolean:
all = [0, 1]
elif kind == idltype.tk_enum:
all = switchType.type().decl().enumerators()
else:
util.fatalError("Failed to generate a default union " +\
"discriminator value")
# remove all those values which are already in use to leave
# a set of possible unused values
possibles = util.minus(all, values)
# return the first one for simplicity
return switchType.literal(possibles[0], environment)
#
###############################################################
# does the IDL union have any default case?
# It'll be handy to know which case is the default one later-
# so add a new attribute to mark it
ast.markDefaultCase(node)
hasDefault = ast.defaultCase(node) != None
# CORBA 2.3 C++ Mapping 1-34
# "A union has an implicit default member if it does not have
# a default case and not all permissible values of the union
# discriminant are listed"
exhaustive = ast.exhaustiveMatch(switchType, ast.allCaseLabelValues(node))
implicitDefault = not hasDefault and not exhaustive
if types.variableDecl(node):
fixed = "Variable"
else:
fixed = "Fix"
def Other_IDL(stream = stream, node = node):
# deal with constructed switch type
if node.constrType():
node.switchType().decl().accept(self)
# deal with children defined in this scope
for n in node.cases():
if n.constrType():
n.caseType().decl().accept(self)
# create the default constructor body
def default_constructor(stream = stream,
implicitDefault = implicitDefault,
hasDefault = hasDefault,
choose = chooseArbitraryDefault):
if implicitDefault:
stream.out(template.union_constructor_implicit)
elif hasDefault:
stream.out(template.union_constructor_default,
default = choose())
return
def ctor_cases(stream = stream, node = node, switchType = switchType,
environment = environment, exhaustive = exhaustive):
for c in node.cases():
for l in c.labels():
if l.default(): continue
discrimvalue = switchType.literal(l.value(), environment)
name = id.mapID(c.declarator().identifier())
stream.out(template.union_ctor_case,
discrimvalue = discrimvalue,
name = name)
# Booleans are a special case (isn't everything?)
booleanWrap = switchType.boolean() and exhaustive
if booleanWrap:
stream.out(template.union_ctor_bool_default)
else:
stream.out(template.union_ctor_default)
return
# create the copy constructor and the assignment operator
# bodies
def copy_constructor(stream = stream, exhaustive = exhaustive,
node = node, ctor_cases = ctor_cases):
if not exhaustive:
# grab the default case
default = ""
for c in node.cases():
if c.isDefault:
case_id = c.declarator().identifier()
cxx_case_id = id.mapID(case_id)
default = cxx_case_id + "(_value._pd_" + cxx_case_id + ");"
stream.out(template.union_ctor_nonexhaustive,
default = default,
cases = ctor_cases)
else:
stream.out(template.union_ctor_exhaustive,
cases = ctor_cases)
return
# do we need an implicit _default function?
def implicit_default(stream = stream, choose = chooseArbitraryDefault,
implicitDefault = implicitDefault):
if implicitDefault:
stream.out(template.union_implicit_default,
arbitraryDefault = choose())
return
# The body of the union _d(_value) function generated here
def _d_fn(stream = stream, node = node, switchType = switchType,
implicitDefault = implicitDefault,
environment = environment):
# The plan:
# * Check the _pd__initialised flag is set, else throw BAD_PARAM
# * Check for the simple case where _value == _pd__d and return
# * Have a nested switch, the outer switch is keyed on the current
# discriminator value and the inner one is the requested new value
#
# Possibilities:
# * Could perform some code minimisation eg for the case
# union foo switch(boolean){
# case TRUE:
# case FALSE:
# T bar;
# };
# This is equivalent to a single default: case and no switch is
# required.
# Make sure we don't output a switch with no cases (if there is a
# one-to-one mapping of labels to cases)
need_switch = 0
# Need to fill in a default case only if the union has none itself
outer_has_default = 0
cases = output.StringStream()
# keep track of which cases have been done
cases_done = []
# Produce a set of "case <foo>: goto fail;" for every label
# except those in an exception list
def fail_all_but(exceptions, node = node, cases = cases,
switchType = switchType, environment = environment):
for c in node.cases():
for l in c.labels():
if l not in exceptions:
cases.out("case @label@: goto fail;",
label = switchType.literal(l.value(),
environment))
# switch (currently active case){
#
outer_has_default = 0 # only mention default: once
for c in node.cases():
need_switch = 1
# If the currently active case has only one non-default label,
# then the only legal action is to set it to its current value.
# We've already checked for this in an if (...) statement before
# here.
if len(c.labels()) == 1 and not c.labels()[0].default():
cases.out("case @label@: goto fail;",
label = switchType.literal(c.labels()[0].value(),
environment))
continue
# output one C++ case label for each IDL case label
# case 1:
# case 2:
# default:
this_case_is_default = 0
for l in c.labels():
if l.default():
this_case_is_default = 1
outer_has_default = 1
cases.out("default:")
continue
cases.out("case @label@:",
label = switchType.literal(l.value(), environment))
# switch (case to switch to){
#
cases.inc_indent()
cases.out("switch (_value){\n")
cases.inc_indent()
inner_has_default = 0
# If we currently are in the default case, fail all attempts
# to switch cases.
if this_case_is_default:
fail_all_but(c.labels())
cases.out("default: _pd__d = _value; return;")
cases.dec_indent()
cases.out("}\n")
cases.dec_indent()
continue
# This is not the default case, all possibilities have associated
# UnionCaseLabels
for l in c.labels():
cases.out("case @label@: _pd__d = @label@; return;",
label = switchType.literal(l.value(), environment))
cases.out("default: goto fail;")
cases.dec_indent()
cases.out("}\n")
cases.dec_indent()
if not outer_has_default and not implicitDefault:
cases.out("default: goto fail;")
# handle situation where have an implicit default member
# (ie no actual case, but a legal set of discriminator values)
# (assumes that the current discriminator is set to one of the
# defaults)
if implicitDefault:
need_switch = 1
cases.out("default:")
cases.out("switch (_value){")
cases.inc_indent()
# again, make sure we aren't currently in the default state
# and trying to set the discriminator to a non-default state
fail_all_but([])
cases.out("default: _pd__d = _value; return;")
cases.dec_indent()
cases.out("}")
# output the code here
switch = output.StringStream()
if need_switch:
switch.out("switch (_pd__d){\n @cases@\n};", cases = cases)
stream.out(template.union_d_fn_body, switch = switch)
# get and set functions for each case:
def members(stream = stream, node = node, environment = environment,
choose = chooseArbitraryDefault, switchType = switchType):
for c in node.cases():
# Following the typedef chain will deliver the base type of
# the alias. Whether or not it is an array is stored in an
# ast.Typedef node.
caseType = types.Type(c.caseType())
d_caseType = caseType.deref()
# the mangled name of the member
decl = c.declarator()
decl_dims = decl.sizes()
full_dims = decl_dims + caseType.dims()
is_array = full_dims != []
is_array_declarator = decl_dims != []
alias_array = caseType.dims() != []
member = id.mapID(decl.identifier())
memtype = caseType.member(environment)
# CORBA 2.3 C++ language mapping (June, 1999) 1-34:
# ... Setting the union value through a modifier function
# automatically sets the discriminant and may release the
# storage associated with the previous value ... If a
# modifier for a union member with multiple legal
# discriminant values is used to set the value of the
# discriminant, the union implementation is free to set
# the discriminant to any one of the legal values for that
# member. The actual discriminant value chose under these
# circumstances is implementation-dependent. ...
# Do we pick the first element (seems obvious)?
# Or pick another one, hoping to trip-up people who write
# non-compliant code and make an incorrect assumption?
labels = c.labels()
if labels != []:
non_default_labels = filter(lambda x:not x.default(), labels)
if non_default_labels == []:
# only one label and it's the default
label = labels[0]
discrimvalue = choose()
elif len(non_default_labels) > 1:
# oooh, we have a choice. Let's pick the second one.
# no-one will be expecting that
label = non_default_labels[1]
else:
# just the one interesting label
label = non_default_labels[0]
if label.default():
discrimvalue = choose()
else:
discrimvalue = switchType.literal(label.value(),
environment)
# only different when array declarator
const_type_str = memtype
# anonymous arrays are handled slightly differently
if is_array_declarator:
prefix = config.state['Private Prefix']
stream.out(template.union_array_declarator,
prefix = prefix,
memtype = memtype,
name = member,
dims = cxx.dimsToString(decl.sizes()),
tail_dims = cxx.dimsToString(decl.sizes()[1:]))
const_type_str = prefix + "_" + member
memtype = "_" + member
if is_array:
# build the loop
def loop(stream = stream, full_dims = full_dims,
member = member):
loop = cxx.For(stream, full_dims)
index = loop.index()
stream.out("\n_pd_" + member + index + " = _value" +\
index + ";\n")
loop.end()
return
stream.out(template.union_array,
memtype = memtype,
const_type = const_type_str,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue,
loop = loop)
elif d_caseType.any():
# note type != CORBA::Any when its an alias...
stream.out(template.union_any,
type = memtype,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.typecode():
stream.out(template.union_typecode,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif isinstance(d_caseType.type(), idltype.Base) or \
d_caseType.enum():
# basic type
stream.out(template.union_basic,
type = memtype,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.string():
stream.out(template.union_string,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.wstring():
stream.out(template.union_wstring,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.interface():
scopedName = d_caseType.type().decl().scopedName()
name = id.Name(scopedName)
ptr_name = name.suffix("_ptr").unambiguous(environment)
Helper_name = name.suffix("_Helper").unambiguous(
environment)
var_name = name.suffix("_var").unambiguous(environment)
stream.out(template.union_objref,
member = member,
memtype = memtype,
ptr_name = ptr_name,
var_name = var_name,
Helper_name = Helper_name,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif caseType.typedef() or d_caseType.struct() or \
d_caseType.union() or d_caseType.fixed():
stream.out(template.union_constructed,
type = memtype,
name = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.sequence():
sequence_template = d_caseType.sequenceTemplate(environment)
stream.out(template.union_sequence,
sequence_template = sequence_template,
member = member,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
elif d_caseType.value() or d_caseType.valuebox():
scopedName = d_caseType.type().decl().scopedName()
name = id.Name(scopedName)
type = name.unambiguous(environment)
stream.out(template.union_value,
member=member,
type=type,
isDefault = str(c.isDefault),
discrimvalue = discrimvalue)
pass
else:
util.fatalError("Unknown union case type encountered")
return
# declare the instance of the discriminator and
# the actual data members (shock, horror)
# FIXME: there is some interesting behaviour in
# o2be_union::produce_hdr which I should examine more
# carefully
inside = output.StringStream()
outside = output.StringStream()
used_inside = 0
used_outside = 0
for c in node.cases():
# find the dereferenced type of the member if its an alias
caseType = types.Type(c.caseType())
d_caseType = caseType.deref()
decl = c.declarator()
decl_dims = decl.sizes()
full_dims = caseType.dims() + decl_dims
is_array = full_dims != []
is_array_declarator = decl_dims != []
member_name = id.mapID(c.declarator().identifier())
type_str = caseType.member(environment)
# non-array sequences have had their template typedef'd somewhere
if not is_array_declarator and caseType.sequence():
type_str = "_" + member_name + "_seq"
dims_str = cxx.dimsToString(decl_dims)
# Decide what does inside and outside the union {} itself
# Note: floats in unions are special cases
if (d_caseType.float() or d_caseType.double()) and \
not is_array:
inside.out(template.union_noproxy_float,
type = type_str, name = member_name,
dims = dims_str)
outside.out(template.union_proxy_float,
type = type_str, name = member_name,
dims = dims_str)
used_inside = used_outside = 1
else:
if is_array and d_caseType.struct() and \
not caseType.variable():
this_stream = inside
used_inside = 1
else:
if d_caseType.type().kind() in \
[ idltype.tk_struct,
idltype.tk_union,
idltype.tk_except,
idltype.tk_string,
idltype.tk_wstring,
idltype.tk_sequence,
idltype.tk_any,
idltype.tk_TypeCode,
idltype.tk_objref,
idltype.tk_fixed,
idltype.tk_value,
idltype.tk_value_box,
idltype.tk_abstract_interface,
idltype.tk_local_interface ]:
this_stream = outside
used_outside = 1
else:
this_stream = inside
used_inside = 1
this_stream.out(template.union_member,
type = type_str,
name = member_name,
dims = dims_str)
discrimtype = d_switchType.base(environment)
if used_inside:
_union = output.StringStream()
_union.out(template.union_union, members = str(inside))
inside = _union
# write out the union class
stream.out(template.union,
unionname = cxx_id,
fixed = fixed,
Other_IDL = Other_IDL,
default_constructor = default_constructor,
copy_constructor = copy_constructor,
discrimtype = discrimtype,
_d_body = _d_fn,
implicit_default = implicit_default,
members = members,
union = str(inside),
outsideUnion = str(outside))
if types.variableDecl(node):
stream.out(template.union_variable_out_type,
unionname = cxx_id)
else:
stream.out(template.union_fix_out_type,
unionname = cxx_id)
popInsideClass()
# TypeCode and Any
if config.state['Typecode']:
qualifier = const_qualifier(_insideModule, _insideClass)
stream.out(template.typecode,
qualifier = qualifier,
name = cxx_id)
return
def visitUnionForward(node):
cxx_name = id.mapID(node.identifier())
stream.out(template.union_forward, name = cxx_name)
def visitEnum(node):
name = id.mapID(node.identifier())
enumerators = node.enumerators()
memberlist = map(lambda x: id.Name(x.scopedName()).simple(), enumerators)
stream.out(template.enum,
name = name,
memberlist = string.join(memberlist, ", "))
# TypeCode and Any
if config.state['Typecode']:
qualifier = const_qualifier(_insideModule, _insideClass)
stream.out(template.typecode,
qualifier = qualifier, name = name)
return
def visitValue(node):
v = value.getValueType(node)
v.module_decls(stream, self)
def visitValueAbs(node):
v = value.getValueType(node)
v.module_decls(stream, self)
def visitValueForward(node):
v = value.getValueType(node)
v.module_decls(stream, self)
def visitValueBox(node):
v = value.getValueType(node)
v.module_decls(stream, self)
|