1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
|
\documentclass[11pt,twoside,a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[scaled=0.9]{DejaVuSansMono}
\usepackage[scaled=0.9]{DejaVuSans}
\usepackage[scaled=0.9]{DejaVuSerif}
\linespread{1.05}
\pagestyle{headings}
\raggedbottom
% Semantic mark-up
\newcommand{\omniidl}{\textsf{omniidl}}
\newcommand{\func}[1]{\texttt{#1}}
\newcommand{\sfunc}[1]{\texttt{\small{#1}}}
\newcommand{\var}[1]{\texttt{#1}}
\newcommand{\class}[1]{\texttt{#1}}
\newcommand{\intf}[1]{\texttt{#1}}
\newcommand{\op}[1]{\texttt{#1()}}
\newcommand{\cmdline}[1]{\texttt{#1}}
\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\dfunc}[1]{\item[\func{#1}]\mbox{}\\}
\newcommand{\cfunc}[1]{\item[\func{#1}]}
\newenvironment{funcdesc}[1]%
{\vspace{\baselineskip}%
\noindent\begin{minipage}{\textwidth}%
\noindent\rule{\textwidth}{1.5pt}\\%
\centerline{\textbf{\texttt{#1}}}%
\vspace{-.5\baselineskip}%
\begin{description}}
{\vspace{-\baselineskip}\end{description}%
\noindent\rule{\textwidth}{1.5pt}\end{minipage}}
\newenvironment{classdesc}[2]%
{\vspace{\baselineskip}%
\noindent\begin{minipage}{\textwidth}%
\noindent\rule{\textwidth}{1.5pt}\\%
\centerline{\textbf{\texttt{#1}}}\\%
\centerline{\textit{#2}}%
\vspace{-.5\baselineskip}%
\begin{description}}
{\vspace{-\baselineskip}\end{description}%
\noindent\rule{\textwidth}{1.5pt}\end{minipage}}
% URL-like things:
\usepackage{omniURLDefs}
\addtolength{\oddsidemargin}{-0.2in}
\addtolength{\evensidemargin}{-0.6in}
\addtolength{\textwidth}{0.5in}
%BEGIN LATEX
\newcommand{\dsc}{\discretionary{}{}{}}
%END LATEX
%HEVEA\newcommand{\dsc}{}
\usepackage{listings}
\makeatletter
\let\lst@ifdraft\iffalse
\makeatother
\lstdefinelanguage{idl}%
{keywords={abstract,any,attribute,boolean,case,char,const,context,custom,default,double,enum,exception,factory,FALSE,fixed,float,in,inout,interface,local,long,module,native,Object,octet,oneway,out,private,public,raises,readonly,sequence,short,string,struct,supports,switch,TRUE,truncatable,typedef,unsigned,union,ValueBase,valuetype,void,wchar,wstring},%
sensitive,%
morecomment=[s]{/*}{*/},%
morecomment=[l]//,%
morestring=[b]",%
morestring=[b]',%
moredirectives={define,elif,else,endif,error,if,ifdef,ifndef,line,%
include,pragma,undef,warning}%
}[keywords,comments,strings,directives]%
\lstset{basicstyle=\ttfamily\small,
keywordstyle=,
commentstyle=\itshape,
numberstyle=\tiny,
showstringspaces=false,
abovecaptionskip=0pt,
belowcaptionskip=0pt,
xleftmargin=\parindent,
fontadjust}
\lstnewenvironment{idllisting}{\lstset{language=idl}}{}
\lstnewenvironment{cxxlisting}{\lstset{language=C++}}{}
\lstnewenvironment{makelisting}{\lstset{language=[gnu]make}}{}
\lstnewenvironment{pylisting}{\lstset{language=python}}{}
%END LATEX
% These things make up for HeVeA's lack of understanding:
%HEVEA\newcommand{\vfill}{}
%HEVEA\newcommand{\mainmatter}{}
%HEVEA\newcommand{\backmatter}{}
% Hyperref things for pdf and html:
\usepackage{hyperref}
\newif\ifpdf
\ifx\pdfoutput\undefined
\pdffalse
\else
\pdfoutput=1
\pdftrue
\fi
\ifpdf
\hypersetup{colorlinks,citecolor=red,urlcolor=blue}
\fi
\title{\omniidl\ --- The omniORB IDL Compiler}
\author{Duncan Grisby\\
AT\&T Laboratories Cambridge\\
}
\date{June 2000}
\begin{document}
\maketitle
\section{Introduction}
This manual describes \omniidl, the omniORB IDL compiler. It is
intended for developers who wish to write their own IDL compiler
back-ends, or to modify existing ones.
If you just wish to use \omniidl\ to create stubs for C++ or Python,
you should read the omniORB or omniORBpy manuals instead of this one.
\subsection{Requirements}
Back-ends for \omniidl\ are written in Python, so to use it you must
have an up-to-date Python interpreter. You must also understand Python
to be able to follow this manual and write back-ends. You can download
Python and associated documentation from
\weburl{http://www.python.org/}.
The front-end scanner and parser are written using flex and bison; the
rest of the front-end is written in C++. The code intentionally avoids
using any advanced (and useful) features of C++, such as templates, so
as to make it as portable as possible.
\subsection{Running \omniidl}
On all platforms, there is a command named \omniidl. On Unix
platforms, \omniidl\ is a Python script which runs Python via the
\verb|#!| mechanism. On Windows NT, there is an executable named
\file{omniidl.exe}.
The \omniidl\ command line has the form:
\begin{quote} % Not the clearest bit of mark-up ever... :-)
\cmdline{omniidl }[\textit{options}]\cmdline{ -b}%
<\textit{back-end}>\cmdline{ }[\textit{back-end options}]%
\cmdline{ }<\textit{file 1}>\cmdline{ }<\textit{file 2}>%
\cmdline{ }\dots
\end{quote}
The supported flags are:
\begin{tabbing}
\cmdline{-D}\textit{name}[\cmdline{=}\textit{value}]~~ \= \kill
%HEVEA\\
\cmdline{-D}\textit{name}[\cmdline{=}\textit{value}]
\> Define \textit{name} for the preprocessor.\\
\cmdline{-U}\textit{name}
\> Undefine \textit{name} for the preprocessor.\\
\cmdline{-I}\textit{dir}
\> Include \textit{dir} in the preprocessor search path.\\
\cmdline{-E}
\> Only run the preprocessor, sending its output to stdout.\\
\cmdline{-Y}\textit{cmd}
\> Use \textit{cmd} as the preprocessor, rather than the normal C
preprocessor.\\
\cmdline{-N}
\> Do not run the preprocessor.\\
\cmdline{-T}
\> Use a temporary file, not a pipe, for preprocessor output.\\
\cmdline{-Wp}\textit{arg}[,\textit{arg}\dots]
\> Send arguments to the preprocessor.\\
\cmdline{-b}\textit{back-end}
\> Run the specified back-end. For the C++ ORB, use \cmdline{-bcxx}.\\
\cmdline{-Wb}\textit{arg}[,\textit{arg}\dots]
\> Send arguments to the back-end.\\
\cmdline{-nf}
\> Do not warn about unresolved forward declarations.\\
\cmdline{-k}
\> Keep comments after declarations, to be used by some back-ends.\\
\cmdline{-K}
\> Keep comments before declarations, to be used by some back-ends.\\
\cmdline{-C}\textit{dir}
\> Change directory to \textit{dir} before writing output files.\\
\cmdline{-i}
\> Run the front end and back-ends, then enter the interactive loop.\\
\cmdline{-d}
\> Dump the parsed IDL then exit, without running a back-end.\\
\cmdline{-p}\textit{dir}
\> Use \textit{dir} as a path to find omniidl back-ends.\\
\cmdline{-V}
\> Print version information then exit.\\
\cmdline{-u}
\> Print usage information.\\
\cmdline{-v}
\> Verbose: trace compilation stages.\\
\end{tabbing}
If you do not specify any back-ends (with the \cmdline{-b} flag),
\omniidl\ just runs the compiler front-end, checking that the IDL is
valid. If you specify more than one back-end, the back-ends are run in
turn on the abstract syntax tree of each file. This permits you to
generate stubs for more than one language in a single run. It also
permits you to write back-ends which annotate or modify the abstract
syntax tree to be used by later back-ends.
For example, the command:
\begin{quote}
\cmdline{omniidl -bdump -bpython foo.idl bar.idl}
\end{quote}
\noindent first reads and parses \file{foo.idl}, and runs the
\file{dump} and \file{python} back-ends on it in turn. Then it reads
and parses \file{bar.idl} and runs the two back-ends on that.
\subsection{Preprocessor interactions}
IDL is processed by the C preprocessor before \omniidl\ parses it.
\omniidl\ always uses the GNU C preprocessor (which it builds with the
name omnicpp). The \cmdline{-D}, \cmdline{-U}, and \cmdline{-I}
options are just sent to the preprocessor. Note that the current
directory is not on the include search path by default---use
`\cmdline{-I.}' for that. The \cmdline{-Y} option can be used to
specify a different preprocessor to omnicpp. Beware that line
directives inserted by other preprocessors are likely to confuse
\omniidl.
\subsection{Forward-declared interfaces}
If you have an IDL file like:
\begin{idllisting}
interface I;
interface J {
attribute I the_I;
};
\end{idllisting}
\noindent then \omniidl\ will normally issue a warning:
{\small
\begin{verbatim}
test.idl:1: Warning: Forward declared interface `::I' was never
fully defined
\end{verbatim}
}
\noindent It is illegal to declare such IDL in isolation, but it
\emph{is} valid to define interface \intf{I} in a separate file. If
you have a lot of IDL with this sort of construct, you will drown
under the warning messages. Use the \cmdline{-nf} option to suppress
them.
\subsection{Comments}
\label{sec:comments}
By default, \omniidl\ discards comments in the input IDL. However,
with the \cmdline{-k} and \cmdline{-K} options, it preserves the
comments for use by the back-ends.
The two different options relate to how comments are attached to
declarations within the IDL. Given IDL like:
\begin{idllisting}
interface I {
void op1();
// A comment
void op2();
};
\end{idllisting}
\noindent the \cmdline{-k} flag will attach the comment to \op{op1};
the \cmdline{-K} flag will attach it to \op{op2}.
\subsection{Interactive loop}
When \omniidl\ is given the \cmdline{-i} option, it runs the compiler
front-end and any back-ends specified, and then drops into Python's
interactive command loop. Within the interactive loop, you can
\code{import omniidl}. The parsed AST is then available as
\code{omniidl.idlast.tree}. This mode is useful for investigating the
parsed tree.
\subsection{Copyright}
All parts of \omniidl\ are licensed under the GNU General Public
License, available in the file \file{COPYING}.
As a special exception to the terms of the GPL, we do not consider
back-ends to be derived works of \omniidl. This means that you may
distribute back-ends you write under any terms you like. The back-ends
we distribute are licensed under the GPL, so you must abide by its
terms if you distribute or modify our back-ends.
As another exception, we do not consider the output of the back-ends
we distribute to be derived works of those back-ends. You may
therefore use generated stubs with no restrictions.
\section{Back-end interface}
\label{sec:backend}
There are three elements to the back-end interface: requirements on
the back-end modules themselves, a set of output and utility
functions, and the interface to the parsed IDL.
\subsection{Back-end modules}
\label{sec:bemodules}
\omniidl\ back-ends are just normal Python modules. When you specify a
back-end with \cmdline{-bfoo}, \omniidl\ first tries to open the
Python module named \file{omniidl_be.foo}. If that fails, it tries to
open the module just named \file{foo}, using the normal
\texttt{PYTHONPATH} mechanism. As with any Python module, the module
\file{foo} can either be implemented as a single file named
\file{foo.py}, or as a directory \file{foo} containing a file named
\file{__init__.py}.
The only requirement on back-end modules is that they contain a
function with the signature \func{run(tree, args)}, where \var{tree}
is an \class{AST} object as described in section~\ref{sec:astclass},
and \var{args} is a list of argument strings passed to the back-end.
Back-ends may also optionally provide a variable named \var{cpp\_args}
which contains a list of strings containing arguments to be given to
the C preprocessor. For example, the Python back-end contains the
line:
\begin{pylisting}
cpp_args = ["-D__OMNIIDL_PYTHON__"]
\end{pylisting}
\subsection{Output and utility functions}
The purpose of most back-ends is to output source code in some
language. It is often the case that much of the output is independent
of the specifics of the IDL input. The output for an IDL interface,
for example, might be an extensive class definition containing
configuration and initialisation code which is largely independent of
the specifics of the interface. At various places throughout the class
definition, there would be items which \emph{were} dependent on the
interface definition.
\omniidl\ supports this with \emph{template} based output functions.
Templates are simply strings containing the code to be output,
including expressions surrounded by `\texttt{@}' characters. When the
templates are output, the keys inside the `\texttt{@}' expressions are
replaced with values according to the output arguments. An
`\texttt{@}' symbol can be output by putting `\texttt{@@}' in the
template.
The output facilities are provided in the \file{omniidl.output} module
by the \class{Stream} class. The primary method of \class{Stream}
objects is \func{out()}, which takes arguments of a template string
and a set of key/value pairs to be used in \texttt{@} substitutions.
For example, if \var{st} is a \class{Stream} object, then the code:
\begin{pylisting}
template = """\
class @id@ {
public:
@id@(@type@ a) : a_(a) {}
private:
@type@ a_;
};"""
st.out(template, id="foo", type="int")
\end{pylisting}
\noindent would result in output:
\begin{cxxlisting}
class foo {
public:
foo(int a) : a_(a) {}
private:
int a_;
};
\end{cxxlisting}
When \texttt{@} expressions are substituted, the expression is
actually \emph{evaluated}, not just textually replaced. This means
that you can write templates containing strings like
`\texttt{@obj.name()@}'. Expressions must evaluate to strings. This
feature should not be over-used---it is very easy to write
incomprehensible template expressions. The vast majority of templates
should only use simple string substitutions.
Commonly, it is necessary to nest definitions which are output inside
other definitions. \class{Stream} objects keep track of a current
indentation level to aid this. The methods \func{inc\_indent()} and
\func{dec\_indent()} increment and decrement the current indent level
respectively. The number of spaces corresponding to a single indent
level is configured when the \class{Stream} is created. Occasionally,
you may need to output code which ignores the current indent level
(preprocessor directives in C, for example). The \func{niout()} method
is identical to \func{out()} except that it performs no indentation.
The \class{Stream} constructor takes two arguments, a file opened for
writing, and an integer specifying how many spaces to use for each
indent level.
\begin{funcdesc}{omniidl.output.Stream}
\dfunc{Stream(file,indent\_size)}
Initialise a \class{Stream} with the given output file and indent
size.
\dfunc{inc\_indent()}
Increment the indent level.
\dfunc{dec\_indent()}
Decrement the indent level.
\dfunc{out(template,key=val,\dots)}
Output the template string \var{template} with key/value
substitution and indenting.
\dfunc{niout(template,key=val,\dots)}
As \func{out()}, but with no indenting.
\end{funcdesc}
\subsubsection{Utility functions}
The \file{omniidl.idlutil} module contains a number of useful
functions:
\begin{funcdesc}{omniidl.idlutil}
\dfunc{escapifyString(str)}
Convert any non-printable characters in string \var{str} into octal
escape sequences.
\dfunc{pruneScope(target,from)}
Given two scoped names represented as lists of strings, return
\var{target} with any prefix it shares with \var{from} removed. For
example:
%
\begin{verbatim}
>>> pruneScope(['A','B','C','D'],['A','B','D'])
['C','D']
\end{verbatim}
\dfunc{relativeScope(from,dest)}
Given two globally-scoped name lists, return a minimal scoped name
list which identifies the destination scope, without clashing with
another identifier. If the only valid result is a globally-scoped
name, the result list is prefixed with \var{None}.
\cfunc{slashName(sn,from)}
\cfunc{dotName(sn,from)}
\dfunc{ccolonName(sn,from)}
Prune scoped name list \var{sn} with \func{pruneScope(sn,from)},
then convert into a string with name components separated by
`\texttt{/}', `\texttt{.}' or `\texttt{::}'.
\end{funcdesc}
\subsection{Abstract Syntax Tree}
\label{sec:ast}
The main meat of the back-end interface is in the
\file{omniidl.idlast} and \file{omniidl.idltype} modules. When the
compiler parses an IDL file, it creates a tree of objects representing
the IDL declarations. The classes for these declarations are defined
in the \file{idlast} module. The way an IDL declaration is split into
objects closely follows the terms within the IDL grammar presented in
chapter~3 of the CORBA 2.3 specification.
\subsubsection{Visitor pattern}
All objects within the back-end interface support the \emph{visitor}
pattern. They have an \func{accept(visitor)} method which acts on a
visitor adhering to the interfaces in the \file{omniidl.idlvisitor}
module. Note that Python's dynamic type system means that visitor
objects need not actually derive from the classes defined in
\file{idlvisitor}\footnote{It is even possible to use a Python module
as a visitor object.}. Also note that you do not have to use the
visitor pattern if you do not wish to.
\subsubsection{Pragmas and comments}
Any unknown \texttt{\#pragma}s encountered in the IDL are attached to
nodes within the AST. Similarly, comments are attached if \omniidl\ is
run with the \cmdline{-k} or \cmdline{-K} fields.
\begin{funcdesc}{omniidl.idlast.Pragma}
\dfunc{text()}
Text of the pragma.
\dfunc{\_\_str\_\_()}
Same as \op{text}.
\dfunc{file()}
File containing the pragma.
\dfunc{line()}
Line within the file.
\end{funcdesc}
\begin{funcdesc}{omniidl.idlast.Comment}
\dfunc{text()}
Text of the comment.
\dfunc{\_\_str\_\_()}
Same as \op{text}.
\dfunc{file()}
File containing the comment.
\dfunc{line()}
Line within the file.
\end{funcdesc}
\subsubsection{The root of the tree}
\label{sec:astclass}
The back-end's \func{run()} function (described in
section~\ref{sec:bemodules}) is passed an object of class \class{AST}.
\begin{funcdesc}{omniidl.idlast.AST}
\dfunc{file()}
The file name of the main IDL file being compiled.
\dfunc{declarations()}
List of \class{Decl} objects corresponding to declarations at file
scope.
\dfunc{pragmas()}
List of \class{Pragma} objects containing \texttt{\#pragma}s which
occurred before any declarations. Later \texttt{\#pragma}s are
attached to \class{Decl} objects.
\dfunc{comments()}
List of \class{Comment} objects containing comments which were not
attached to declarations (see section~\ref{sec:comments}).
\dfunc{accept(visitor)}
Visitor pattern accept.
\end{funcdesc}
\subsubsection{Base declaration}
All declarations in the tree are derived from the \class{Decl} class:
\begin{funcdesc}{omniidl.idlast.Decl}
\dfunc{file()}
The name of the file in which this declaration was made.
\dfunc{line()}
The line number within the file.
\dfunc{mainFile()}
Boolean: true if the declaration is in the main IDL file; false if
it is in an included file.
\dfunc{pragmas()}
List of \class{Pragma} objects containing \texttt{\#pragma}s which
occurred after this declaration, but before any others.
\dfunc{comments()}
List of \class{Comment} objects containing comments attached to this
declaration (see section~\ref{sec:comments}).
\dfunc{accept(visitor)}
Visitor pattern accept.
\end{funcdesc}
\subsubsection{Declarations with a repository identifier}
Some classes of declaration object also inherit from the
\class{DeclRepoId} mixin class:
\begin{funcdesc}{omniidl.idlast.DeclRepoId}
\dfunc{identifier()}
Name of the declaration as a string.
\dfunc{scopedName()}
List of strings forming the fully-scoped name of the declaration.
e.g.\ \var{::foo::bar::baz} is represented as
\texttt{['foo','bar','baz']}.
\dfunc{repoId()}
Repository identifier of the declaration.
\end{funcdesc}
\subsubsection{Declaration classes}
The declaration objects making up the tree have the following classes:
\begin{classdesc}
{omniidl.idlast.Module (Decl,DeclRepoId)}
{Module declaration}
\dfunc{definitions()}
List of \class{Decl} objects declared within this module, in the
order they were declared.
\dfunc{continuations()}
List containing \class{Module} objects which are continuations of
this module. When modules are re-opened, multiple \class{Module}
objects with the same name appear in the enclosing \class{Module} or
\class{AST} object. In case it's useful, the first \class{Module}
object for a particular module has a list containing continuations
of that module. You will probably not have any use for this.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Interface (Decl,DeclRepoId)}
{Interface declaration}
\dfunc{abstract()}
Boolean: true if the interface is declared abstract.
\dfunc{inherits()}
List of interfaces from which this one inherits. Each list member is
either an \class{Interface} object, or a \class{Declarator} object
belonging to a typedef to an interface.
\dfunc{contents()}
List of \class{Decl} objects for all items declared within this
interface.
\dfunc{declarations()}
Subset of \func{contents()} containing types, constants and
exceptions.
\dfunc{callables()}
Subset of \func{contents()} containing \class{Operation}s and
\class{Attribute}s.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Forward (Decl,DeclRepoId)}
{Forward-declared interface}
\dfunc{abstract()}
Boolean: true if the interface is declared abstract.
\dfunc{fullDecl()}
\class{Interface} object corresponding to the full interface
declaration or \var{None} if there is no full declaration.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Const (Decl,DeclRepoId)}
{Constant declaration}
\dfunc{constType()}
\class{idltype.Type} object of the constant. Aliases not stripped.
\dfunc{constKind()}
TypeCode kind of the constant with aliases stripped. So for a
constant declared with:
%
\begin{verbatim}
typedef long MyLong;
const MyLong foo = 123;
\end{verbatim}
%
\func{constKind()} will return \var{tk\_long}, but
\func{constType()} will return an \class{idltype.Declared} object
(see page~\pageref{cls:typeDeclared}) which refers to \var{MyLong}'s
typedef \class{Declarator} object.
\dfunc{value()}
Value of the constant. Either an integer or an \class{Enumerator}
object.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Declarator (Decl,DeclRepoId)}
{Declarator used in typedefs, struct members, attributes, etc.}
\dfunc{sizes()}
List of array sizes, or \var{None} if it is a simple declarator.
\dfunc{alias()}
\class{Typedef} object that the declarator is part of, or \var{None}
if the object is not a typedef declarator.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Typedef (Decl)}
{Typedef declaration}
\dfunc{aliasType()}
\class{idltype.Type} object that this is an alias to.
\dfunc{constrType()}
Boolean: true if the alias type was constructed within this typedef
declaration, like
%
\begin{verbatim}
typedef struct foo { long l; } bar;
\end{verbatim}
\dfunc{declarators()}
List of \class{Declarator} objects.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Member (Decl)}
{Member of a struct or exception}
\dfunc{memberType()}
\class{idltype.Type} object for the type of this member.
\dfunc{constrType()}
Boolean: true if the member type was constructed within the member
declaration. e.g.
\begin{verbatim}
struct S {
struct T {
long l;
} the_T;
};
\end{verbatim}
\dfunc{declarators()}
List of \class{Declarator} objects.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Struct (Decl,DeclRepoId)}
{Struct declaration}
\dfunc{members()}
List of \class{Member} objects for the struct contents.
\dfunc{recursive()}
Boolean: true if the struct is recursive, e.g.
\begin{verbatim}
struct S {
long l;
sequence <S> ss;
};
\end{verbatim}
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Exception (Decl,DeclRepoId)}
{Exception declaration}
\dfunc{members()}
List of \class{Member} objects for the exception contents.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.CaseLabel (Decl)}
{One label within a union}
\dfunc{default()}
Boolean: true if this is the default label.
\dfunc{value()}
Label value. Either an integer or an \class{Enumerator} object. For
the default case, returns a value used by none of the other union
labels.
\dfunc{labelKind()}
TypeCode kind of the label.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.UnionCase (Decl)}
{One case within a union}
\dfunc{labels()}
List of \class{CaseLabel} objects.
\dfunc{caseType()}
\class{idltype.Type} object for the case type.
\dfunc{constrType()}
Boolean: true if the case type was constructed within the case.
\dfunc{declarator()}
\class{Declarator} object
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Union (Decl,DeclRepoId)}
{Union declaration}
\dfunc{switchType()}
\class{idltype.Type} object corresponding to the switch type.
\dfunc{constrType()}
Boolean: true if the switch type was declared within the switch
statement. Only possible for Enums.
\dfunc{cases()}
List of \class{UnionCase} objects.
\dfunc{recursive()}
Boolean: true if the union is recursive.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Enumerator (Decl,DeclRepoId)}
{Enumerator of an enum}
\dfunc{}
No non-inherited functions.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Enum (Decl,DeclRepoId)}
{Enum declaration}
\dfunc{enumerators()}
List of \class{Enumerator} objects.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Attribute (Decl)}
{Attribute declaration}
\dfunc{readonly()}
Boolean: true if the attribute is read only.
\dfunc{attrType()}
\class{idltype.Type} object for the attribute's type.
\dfunc{declarators()}
List of \class{Declarator} objects for this attribute. All
declarators are guaranteed to be simple.
\dfunc{identifiers()}
Convenience function returning a list of strings containing the
attribute identifiers from the declarators. e.g.\ for the
declaration
\begin{verbatim}
attribute long a, b;
\end{verbatim}
\func{identifiers()} will return \texttt{['a','b']}.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Parameter (Decl)}
{Parameter of an operation}
\dfunc{direction()}
Integer: 0 == in, 1 == out, 2 == inout.
\dfunc{is\_in()}
Boolean: true if in or inout.
\dfunc{is\_out()}
Boolean: true if out or inout.
\dfunc{paramType()}
\class{idltype.Type} object for the parameter type.
\dfunc{identifier()}
String containing the parameter identifier.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Operation (Decl,DeclRepoId)}
{Operation declaration}
\dfunc{oneway()}
Boolean: true if the operation is one way.
\dfunc{returnType()}
\class{idltype.Type} object for the return type.
\dfunc{parameters()}
List of \class{Parameter} objects.
\dfunc{raises()}
List of \class{Exception} objects which the operation can raise.
\dfunc{contexts()}
List of strings declared as context for the operation.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Native (Decl)}
{Native declaration}
\dfunc{}
Native should not be used in normal IDL.
No non-inherited functions.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.StateMember (Decl)}
{State member of a concrete valuetype}
\dfunc{memberAccess()}
Integer: 0 == public, 1 == private.
\dfunc{memberType()}
\class{idltype.Type} object for member type.
\dfunc{constrType()}
Boolean: true if the member type is declared within the StateMember.
\dfunc{declarators()}
List of \class{Declarator} objects.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Factory (Decl)}
{Factory method of a valuetype}
\dfunc{identifier()}
String containing the factory identifier.
\dfunc{parameters()}
List of \class{Parameter} objects.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.ValueForward (Decl,DeclRepoId)}
{Forward-declared valuetype}
\dfunc{abstract()}
Boolean: true if declared abstract.
\dfunc{fullDecl()}
\class{Value} or \class{ValueAbs} object corresponding to the full
valuetype declaration or \var{None} if there is no full declaration.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.ValueBox (Decl,DeclRepoId)}
{Boxed valuetype declaration}
\dfunc{boxedType()}
\class{idltype.Type} object for the boxed type.
\dfunc{constrType()}
Boolean: true if boxed type is declared inside the valuetype
declaration.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.ValueAbs (Decl,DeclRepoId)}
{Abstract valuetype declaration}
\dfunc{inherits()}
List of \class{ValueAbs} objects from which this inherits.
\dfunc{supports()}
List of \class{Interface} objects which this valuetype supports.
\dfunc{contents()}
List of \class{Decl} objects for all items defined within this
valuetype.
\dfunc{declarations()}
Subset of \func{contents()} containing types, constants and
exceptions.
\dfunc{callables()}
Subset of contents() containing \class{Operation}s and
\class{Attribute}s.
\end{classdesc}
\begin{classdesc}
{omniidl.idlast.Value (Decl,DeclRepoId)}
{Valuetype declaration}
\dfunc{custom()}
Boolean: true if declared custom.
\dfunc{inherits()}
List of valuetypes from which this inherits. The first may be a
\class{Value} object or a \class{ValueAbs} object; any others will
be \class{ValueAbs} objects.
\dfunc{truncatable()}
Boolean: true if the inherited \class{Value} is declared
truncatable; false if not, or there is no inherited \class{Value}.
\dfunc{supports()}
List of \class{Interface} objects which this valuetype supports.
\dfunc{contents()}
List of \class{Decl} objects for all items defined within this
valuetype.
\dfunc{declarations()}
Subset of \func{contents()} containing types, constants and
exceptions.
\dfunc{callables()}
Subset of \func{contents()} containing \class{Operation}s,
\class{Attribute}s, \class{StateMember}s and \class{Factory}s.
\end{classdesc}
\subsubsection{Type objects}
All type objects are derived from the base class \class{Type}:
\begin{classdesc}
{omniidl.idltype.Type}
{Base class for types}
\dfunc{kind()}
TypeCode kind of type.
\dfunc{unalias()}
Return an equivalent \class{Type} object with top-level aliases
stripped. Only has an effect with typedef types.
\dfunc{accept(visitor)}
Visitor pattern accept.
\end{classdesc}
\vspace{\baselineskip}
\noindent
The basic CORBA types (null, void, short, long, unsigned short,
unsigned long, float, double, boolean, char, octet, any, TypeCode,
Principal, long long, unsigned long long, long double, and wide char)
are represented by objects of type \class{omniidl.idltype.Base},
derived from \class{Type}, with no extra methods.
The template types---string, wstring, sequence, and fixed---do not
have associated \class{Decl} objects since they are not explicitly
declared. They are always implicitly declared as part of another
declaration.
\begin{classdesc}
{omniidl.idltype.String (Type)}
{String type}
\dfunc{bound()}
Bound of a bounded string, or 0 for unbounded strings.
\end{classdesc}
\begin{classdesc}
{omniidl.idltype.WString (Type)}
{Wide string type}
\dfunc{bound()}
Bound of a bounded wstring, or 0 for unbounded wstrings.
\end{classdesc}
\begin{classdesc}
{omniidl.idltype.Sequence (Type)}
{Sequence type}
\dfunc{seqType()}
\class{idltype.Type} object representing what the sequence contains.
\dfunc{bound()}
Bound of a bounded sequence, or 0 for unbounded sequences.
\end{classdesc}
\begin{classdesc}
{omniidl.idltype.Fixed (Type)}
{Fixed point type}
\dfunc{digits()}
Number of digits in number.
\dfunc{scale()}
Scale of number.
\end{classdesc}
\vspace{\baselineskip}
\noindent
All other types (interface, struct, union, enum, typedef, exception,
valuetype) must be explicitly declared. They are represented with
\class{Declared} objects:
\begin{classdesc}
{omniidl.idltype.Declared (Type)}
{Explicitly declared type}
\label{cls:typeDeclared}
\dfunc{decl()}
\class{omniidl.idlast.Decl} object which corresponds to this type.
\dfunc{scopedName()}
Fully scoped name of the type as a list of strings.
\dfunc{name()}
Simple name of the type, i.e.\ the last element of the scoped name.
\end{classdesc}
\subsubsection{Finding a named \class{Decl}}
Normally, back-ends walk over the tree of \class{Decl} objects,
dealing with the declarations as they encounter them. Occasionally,
however, it may be useful to find a declaration by its scoped name.
Only \class{Decl}s which inherit from \class{DeclRepoId} can be found
in this way.
\begin{funcdesc}{omniidl.idlast}
\dfunc{findDecl(scopedName)}
Find the \class{Decl} object which has the scoped name list
\var{scopedName}. If a declaration with the specified name does not
exist, the \class{DeclNotFound} exception is raised.
\end{funcdesc}
\subsection{An example back-end}
The following code is an extremely simple back-end which just prints
the names of all operations declared within an IDL file.
Unfortunately, it is so simple that it does not show many features of
the back-end interface. You should look at the \file{dump.py} and
\file{python.py} back-ends for a more extensive example.
\begin{verbatim}
from omniidl import idlast, idlvisitor, idlutil
import string
class ExampleVisitor (idlvisitor.AstVisitor):
def visitAST(self, node):
for n in node.declarations():
n.accept(self)
def visitModule(self, node):
for n in node.definitions():
n.accept(self)
def visitInterface(self, node):
name = idlutil.ccolonName(node.scopedName())
if node.mainFile():
for c in node.callables():
if isinstance(c, idlast.Operation):
print(name + "::" +
c.identifier() + "()")
def run(tree, args):
visitor = ExampleVisitor()
tree.accept(visitor)
\end{verbatim}
\noindent
The visitor object simply recurses through the \class{AST} and
\class{Module} objects, and prints the operation names it finds in
\class{Interface} objects.
Note that since \class{AstVisitor} (and similarly \class{TypeVisitor}
which is not used in the example) has all operations declared to be
no-ops, the \class{ExampleVisitor} class does not have to declare
visit functions for all node types. This can be a disadvantage if your
back-end is supposed to perform some action for all node types, since
there will be no error if you accidentally miss a node type. In those
situations it is better to declare a visitor class which does not
derive from the visitor base classes.
\end{document}
|