Difference between revisions of "Generated c code"
(English translation half done) |
(plugins) |
||
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Book]] |
[[Category:Book]] |
||
+ | *** I have partially updated the examples here: the hello_world.id file was generated by se2.2beta5 and I |
||
− | {{TranslationWanted}} |
||
+ | *** have noted some statements that are now obsolete in view of recent compiler changes. |
||
+ | *** This article and its French counterpart need revising by the development team. |
||
+ | |||
*** You can also use [http://SmartEiffel.loria.fr/man/c_code.html the original article] |
*** You can also use [http://SmartEiffel.loria.fr/man/c_code.html the original article] |
||
− | People who want to interface with applications and/or libraries written in C should as far as possible limit themselves to the interfaces provided by [[Cecil]] |
+ | People who want to interface with applications and/or libraries written in C should as far as possible limit themselves to the interfaces provided by [[Cecil]], [[externals|external]] and [[plugins]]. This page gives details about the generated C code, but these details ought not to be of any use to you. ;-) |
== The type identifiers == |
== The type identifiers == |
||
Line 9: | Line 12: | ||
=== Description === |
=== Description === |
||
− | SmartEiffel generates one unique |
+ | SmartEiffel generates one unique identifying number for each active type in the Eiffel code<sup>[[Generated c code#note1|1]]</sup>. A lot of symbols in the generated C code depend on that identifier. |
'''Don't depend on those identifiers!''' The mangling table is only valid for one specific compilation of one specific application with one specific compiler version, for one compiler [[compile_to_c]] in one specific version and libraries in one specific version... We do not guarantee the stabbility of these identifiers. |
'''Don't depend on those identifiers!''' The mangling table is only valid for one specific compilation of one specific application with one specific compiler version, for one compiler [[compile_to_c]] in one specific version and libraries in one specific version... We do not guarantee the stabbility of these identifiers. |
||
Line 15: | Line 18: | ||
If ''27'' is an identifier, then: |
If ''27'' is an identifier, then: |
||
− | * The C type of an Eiffel object is T27; |
+ | * The C type of an Eiffel object is '''T27'''; |
* The corresponding C structure is '''struct S27'''; in that structure, the names of the attributes are prefixed with an underscore (there may be some other fields used by SmartEiffel, in particular, the <TT>id</TT> field, which in this case has the value 27). <br> Each reference type can be cast to <TT>T0</TT> (although some reference types may not have the <TT>id</TT> field). |
* The corresponding C structure is '''struct S27'''; in that structure, the names of the attributes are prefixed with an underscore (there may be some other fields used by SmartEiffel, in particular, the <TT>id</TT> field, which in this case has the value 27). <br> Each reference type can be cast to <TT>T0</TT> (although some reference types may not have the <TT>id</TT> field). |
||
− | * Each method is called '''r27'' |
+ | * Each method is called '''r27''method_name''()''' |
− | * Each prefix method is called '''r27_px_'' |
+ | * Each prefix method is called '''r27_px_''method_name''()''' |
− | * Each infix method is called '''r27_ix_'' |
+ | * Each infix method is called '''r27_ix_''method_name''()''' |
− | * Each late-binding method is called '''X27'' |
+ | * Each late-binding method is called '''X27''method_name''()''' |
* The object's creation method (when the [[Garbage collector|garbage collector]] is used) is called '''new27()''' |
* The object's creation method (when the [[Garbage collector|garbage collector]] is used) is called '''new27()''' |
||
− | * The type model |
+ | * The type model is a variable called '''M27'''. Models are used for initialisation. For example: |
T27 M27 = {27,NULL,NULL,0,0}; |
T27 M27 = {27,NULL,NULL,0,0}; |
||
... |
... |
||
Line 30: | Line 33: | ||
... |
... |
||
− | Some characters in method names such as <TT>"<"</TT> or <TT>"+"</TT> will be replaced by their corresponding ASCII code in decimal. |
+ | Some characters in method names, such as <TT>"<"</TT> or <TT>"+"</TT>, will be replaced by their corresponding ASCII code in decimal. |
=== An example === |
=== An example === |
||
Line 38: | Line 41: | ||
* The object type is '''T7'''. |
* The object type is '''T7'''. |
||
typedef struct S7 T7; |
typedef struct S7 T7; |
||
− | * The structure is defined in '''struct |
+ | * The structure is defined in '''struct S7'''. |
struct S7{Tid id;T9 _storage;t2 _count;t2 _capacity;}; |
struct S7{Tid id;T9 _storage;t2 _count;t2 _capacity;}; |
||
* The <TT>append</TT> method becomes: |
* The <TT>append</TT> method becomes: |
||
Line 50: | Line 53: | ||
This file is structured in ''entries'', each entry being separated from others by a hash character (<TT>#</TT>). This file looks like this: |
This file is structured in ''entries'', each entry being separated from others by a hash character (<TT>#</TT>). This file looks like this: |
||
− | + | 5 "REAL" |
|
+ | class-path: "/SmartEiffel/lib/numeric/real.e" |
||
+ | class-name: REAL |
||
+ | assertion-level: all |
||
+ | parent-count: 1 inherit: 49 |
||
# |
# |
||
− | + | 72 "FAST_ARRAY" |
|
+ | class-path: "/SmartEiffel/lib/storage/collection/fast_array.e" |
||
− | class_path: "./hello_world.e" |
||
+ | class-name: FAST_ARRAY |
||
− | class_name: HELLO_WORLD |
||
+ | assertion-level: all |
||
− | parent_count: 0 |
||
− | + | parent-count: 1 inherit: 58 |
|
+ | # |
||
+ | 62 "STD_ERROR" |
||
+ | class-path: "/SmartEiffel/lib/io/terminal/std_error.e" |
||
+ | class-name: STD_ERROR |
||
+ | assertion-level: all |
||
+ | parent-count: 1 inherit: 39 |
||
+ | c-type: T62 reference: yes |
||
ref-status: live id-field: yes |
ref-status: live id-field: yes |
||
+ | destination-graph-nodes: ->OUTPUT_STREAM |
||
run-time-set-count: 1 |
run-time-set-count: 1 |
||
run-time-set: |
run-time-set: |
||
− | + | STD_ERROR (62) |
|
− | # |
||
− | 9 "NATIVE_ARRAY[CHARACTER]" |
||
− | class-path: "/lib/se/lib/storage/low_level/native_array.e" |
||
− | class-name: NATIVE_ARRAY |
||
− | parent-count: 1 parents: 26 |
||
− | c-type: T9 reference: no |
||
− | # |
||
− | 21 "COMPARABLE" |
||
− | class-path: "/lib/se/lib/abilities/comparable.e" |
||
− | class-name: COMPARABLE |
||
− | parent-count: 1 parents: 13 |
||
# |
# |
||
. . . |
. . . |
||
− | You should never depend on these identifiers. |
+ | You should never depend on these identifiers. In any case, when an identifier is computed, collisions may occur, and affect the process. Thus, the identifier and name of each type depends not only on the type name, but also on the order in which the types are compiled. That is, on the order of ''application'' and ''library'' types combined... They also depend on the compilation mode used (since that can change the list of active types), and the version of the compiler you're using. So what is <TT>T145</TT> today may be <TT>T234</TT> tomorrow<sup>[[Generated c code#note3|3]]</sup>! |
Consequently, '''do not ever rely on the generated identifiers, because they are not constant!''' Do not try to write in your own C code horrible things like <TT>new123</TT> or <TT>T456</TT>, because the only thing we can guarantee is that this code will not work. |
Consequently, '''do not ever rely on the generated identifiers, because they are not constant!''' Do not try to write in your own C code horrible things like <TT>new123</TT> or <TT>T456</TT>, because the only thing we can guarantee is that this code will not work. |
||
Line 87: | Line 91: | ||
This shows how ''Current'' and the arguments are passed. The rules are as follows: |
This shows how ''Current'' and the arguments are passed. The rules are as follows: |
||
− | * ''Current'' is called <TT>C</TT> and is always strongly |
+ | * ''Current'' is called <TT>C</TT> and is always strongly typed (with its own exact type). This parameter may be omitted if Current is not used by the method. In some cases (when code is inlined), ''Current'' can be copied in local variables named <TT>C1</TT>, <TT>C2</TT>... |
* The arguments are called <TT>a1</TT>, <TT>a2</TT>... and are typed <TT>T0*</TT> for reference types or given their exact type for expanded types (e.g. <TT>T2</TT> for an integer) |
* The arguments are called <TT>a1</TT>, <TT>a2</TT>... and are typed <TT>T0*</TT> for reference types or given their exact type for expanded types (e.g. <TT>T2</TT> for an integer) |
||
* Inside functions, a local variable <TT>R</TT> is defined. This is ''Result''. |
* Inside functions, a local variable <TT>R</TT> is defined. This is ''Result''. |
||
Line 100: | Line 104: | ||
Let's look again at the extract of a <TT>.id</TT> file. The part shown covers nearly all the possible cases: |
Let's look again at the extract of a <TT>.id</TT> file. The part shown covers nearly all the possible cases: |
||
− | + | 5 "REAL" |
|
+ | class-path: "/SmartEiffel/lib/numeric/real.e" |
||
+ | class-name: REAL |
||
+ | assertion-level: all |
||
+ | parent-count: 1 inherit: 49 |
||
# |
# |
||
− | + | 72 "FAST_ARRAY" |
|
+ | class-path: "/SmartEiffel/lib/storage/collection/fast_array.e" |
||
− | class_path: "./hello_world.e" |
||
+ | class-name: FAST_ARRAY |
||
− | class_name: HELLO_WORLD |
||
+ | assertion-level: all |
||
− | parent_count: 0 |
||
− | + | parent-count: 1 inherit: 58 |
|
+ | # |
||
+ | 62 "STD_ERROR" |
||
+ | class-path: "/SmartEiffel/lib/io/terminal/std_error.e" |
||
+ | class-name: STD_ERROR |
||
+ | assertion-level: all |
||
+ | parent-count: 1 inherit: 39 |
||
+ | c-type: T62 reference: yes |
||
ref-status: live id-field: yes |
ref-status: live id-field: yes |
||
+ | destination-graph-nodes: ->OUTPUT_STREAM |
||
run-time-set-count: 1 |
run-time-set-count: 1 |
||
run-time-set: |
run-time-set: |
||
− | + | STD_ERROR (62) |
|
− | # |
||
− | 9 "NATIVE_ARRAY[CHARACTER]" |
||
− | class-path: "/lib/se/lib/storage/low_level/native_array.e" |
||
− | class-name: NATIVE_ARRAY |
||
− | parent-count: 1 parents: 26 |
||
− | c-type: T9 reference: no |
||
− | # |
||
− | 21 "COMPARABLE" |
||
− | class-path: "/lib/se/lib/abilities/comparable.e" |
||
− | class-name: COMPARABLE |
||
− | parent-count: 1 parents: 13 |
||
# |
# |
||
. . . |
. . . |
||
Line 144: | Line 149: | ||
| Le number of parents. |
| Le number of parents. |
||
|- |
|- |
||
− | | ''' |
+ | | '''inherit''' |
| On the same line as '''parent-count''' if the latter is not null; it gives the list of parent class identifiers. |
| On the same line as '''parent-count''' if the latter is not null; it gives the list of parent class identifiers. |
||
|- |
|- |
||
Line 162: | Line 167: | ||
* or the structure may be accessed by an [[external]] or by [[cecil]]. |
* or the structure may be accessed by an [[external]] or by [[cecil]]. |
||
Note that a lot of calls are statically computed; the type inference algorithm used in SmartEiffel increases the number of such types that do not need the id field. |
Note that a lot of calls are statically computed; the type inference algorithm used in SmartEiffel increases the number of such types that do not need the id field. |
||
+ | |||
+ | |- |
||
+ | | '''destination-graph-nodes''' |
||
+ | | ????? <!-- someone please write an explanation for this --> |
||
|- |
|- |
||
| '''run-time-set-count''' |
| '''run-time-set-count''' |
||
Line 176: | Line 185: | ||
Technically, the SmartEiffel stack is built upon the native (C) stack. Each stack element is a <TT>se_dump_stack</TT><sup>[[Generated c code#note4|4]]</sup> usually allocated on the stack. It is made up of several parts: |
Technically, the SmartEiffel stack is built upon the native (C) stack. Each stack element is a <TT>se_dump_stack</TT><sup>[[Generated c code#note4|4]]</sup> usually allocated on the stack. It is made up of several parts: |
||
− | * a frame descriptor, of type <TT>se_frame_descriptor4</TT><sup>[[Generated c code#note4|4]]</sup> |
+ | * a frame descriptor, of type <TT>se_frame_descriptor4</TT><sup>[[Generated c code#note4|4]]</sup> which is a static description of the feature, as follows: |
+ | ** run type, |
||
− | * une partie statique : le descripteur de cadre <!-- translation: frame descriptor -->, de type <TT>se_frame_descriptor</TT><sup>[[Generated c code#note4|4]]</sup> qui décrit statiquement la ''feature'' : type de ''Current'', nombre et type des variables locales, type de ''Result'', flag anti-récursion (pour les contrats)... |
||
+ | ** does it use Current, |
||
− | * une partie dynamique : |
||
+ | ** number and type of the local variables, and |
||
− | ** un pointeur vers ''Current'' (i.e. soit un pointer sur l'objet expansé, ou bien un pointer sur la référence qui est elle-même un pointeur sur l'objet). C'est pourquoi le type du champ <TT>current</TT> est <TT>void**</TT>. Ce champ peut être <TT>NULL</TT> si ''Current'' n'est pas utilisé par la ''feature'', |
||
+ | ** an anti-recursion flag (for contracts)... |
||
− | ** la position (utilisée principalement par [[sedb]]), |
||
+ | * a dynamic part: |
||
− | ** un pointeur vers l'appelant (i.e. le <TT>se_dump_stack</TT> de l'appelant), |
||
+ | ** a pointer to ''Current'' (i.e. either a pointer to an expanded object, or else a pointer to a reference object, it being a pointer to the object itself). That is why the type of the <TT>current</TT> field is <TT>Void**</TT>. This field will be <TT>NULL</TT> if ''Current'' is not used by the ''feature'',o |
||
− | ** un pointeur vers l'origine de l'exception : si non <TT>NULL</TT>, cela signifie que <TT>se_dump_stack</TT> ''n'est pas'' sur la pile, mais a été alloué dans le tas pour préserver la trace de l'exception, |
||
+ | ** the position (used mainly by [[sedb]]), |
||
− | ** un tableau de variables locales (avec la double indirection pour ''Current''), d'où le type <TT>void***</TT>. |
||
+ | ** a pointer to the caller (i.e. the <TT>se_dump_stack</TT> of the calling function), |
||
+ | ** a pointer to the exception origin: if not <TT>NULL</TT>, it means that this <TT>se_dump_stack</TT> ''is not'' in the stack, but was malloc'ed to preserve the exception stack trace, |
||
+ | ** an array of local variables (with double indirection as for ''Current''), hence the type void***. |
||
− | + | Macros handle the linking between the <TT>se_dump_stack</TT> frames. |
|
− | * |
+ | * Normally, the top of the dump stack is the global variable <TT>se_dst</TT> defined in <TT>SmartEiffel/sys/runtime/no_check.c</TT>. The macro <TT>set_dump_stack_top</TT> accomplishes the assignment of its argument in this variable. |
− | * |
+ | * In [[SCOOP]] mode, each processor has its own stack. So the <TT>set_dump_stack_top</TT> macro has two arguments: the processor and the new dump stack top. |
---- |
---- |
||
− | <div id="note1">1. |
+ | <div id="note1">1. There is a bijection (a one to one relationship) between the number and the ''name'' of the type (including the value of its generic parameters in the case of generic types). </div> |
− | <div id="note2">2. |
+ | <div id="note2">2. There are some identifiers that are reserved for "basic" types. They are: |
− | * '''0''' |
+ | * '''0''': the type any other can be cast to |
− | * '''1''' |
+ | * '''1''': [[library_class:INTEGER_8|<TT>INTEGER_8</TT>]] |
− | * '''2''' |
+ | * '''2''': [[library_class:INTEGER|<TT>INTEGER</TT>]] (or [[library_class:INTEGER_32|<TT>INTEGER_32</TT>]]) |
− | * '''3''' |
+ | * '''3''': [[library_class:CHARACTER|<TT>CHARACTER</TT>]] |
− | * '''4''' |
+ | * '''4''': [[library_class:REAL|<TT>REAL</TT>]] |
− | * '''5''' |
+ | * '''5''': [[library_class:DOUBLE|<TT>DOUBLE</TT>]] ''[out of date: DOUBLE is no longer supported in 2.2beta5]'' |
− | * '''6''' |
+ | * '''6''': [[library_class:BOOLEAN|<TT>BOOLEAN</TT>]] |
− | * '''7''' |
+ | * '''7''': [[library_class:STRING|<TT>STRING</TT>]] |
− | * '''8''' |
+ | * '''8''': [[library_class:POINTER|<TT>POINTER</TT>]] |
− | * '''9''' |
+ | * '''9''': [[library_class:NATIVE_ARRAY|<TT>NATIVE_ARRAY</TT>]]<TT>[</TT>[[library_class:CHARACTER|<TT>CHARACTER</TT>]]<TT>]</TT> |
− | * '''10''' |
+ | * '''10''': [[library_class:INTEGER_16|<TT>INTEGER_16</TT>]] |
− | * '''11''' |
+ | * '''11''': [[library_class:INTEGER_64|<TT>INTEGER_64</TT>]] |
+ | * ''[what about the various kinds of REAL?]'' |
||
− | + | So it is likely that the root class of the system may have the identifier '''12'''. But do not rely on that too much (before all the changes to INTEGERs, it was '''11'''). |
|
</div> |
</div> |
||
− | <div id="note3">3. |
+ | <div id="note3">3. The compiler will do its best not to change the identifiers uselessly. The <TT>.id</TT> file is loaded at the beginning of the compilation process, and saved again at its end. But [[clean]], for example, erases that file.</div> |
− | <div id="note4">4. |
+ | <div id="note4">4. You can find the definition of these structures in the <TT>SmartEiffel/sys/runtime/c/no_check.h</TT> file.</div> |
− | <div id="note5">5. |
+ | <div id="note5">5. The exception is when an exception is raised: in that case, part of the stack is allocated onto the heap before the <TT>longjmp</TT>. </div> |
Revision as of 11:58, 24 July 2006
*** I have partially updated the examples here: the hello_world.id file was generated by se2.2beta5 and I *** have noted some statements that are now obsolete in view of recent compiler changes. *** This article and its French counterpart need revising by the development team.
*** You can also use the original article
People who want to interface with applications and/or libraries written in C should as far as possible limit themselves to the interfaces provided by Cecil, external and plugins. This page gives details about the generated C code, but these details ought not to be of any use to you. ;-)
The type identifiers
Description
SmartEiffel generates one unique identifying number for each active type in the Eiffel code1. A lot of symbols in the generated C code depend on that identifier.
Don't depend on those identifiers! The mangling table is only valid for one specific compilation of one specific application with one specific compiler version, for one compiler compile_to_c in one specific version and libraries in one specific version... We do not guarantee the stabbility of these identifiers.
If 27 is an identifier, then:
- The C type of an Eiffel object is T27;
- The corresponding C structure is struct S27; in that structure, the names of the attributes are prefixed with an underscore (there may be some other fields used by SmartEiffel, in particular, the id field, which in this case has the value 27).
Each reference type can be cast to T0 (although some reference types may not have the id field). - Each method is called r27method_name()
- Each prefix method is called r27_px_method_name()
- Each infix method is called r27_ix_method_name()
- Each late-binding method is called X27method_name()
- The object's creation method (when the garbage collector is used) is called new27()
- The type model is a variable called M27. Models are used for initialisation. For example:
T27 M27 = {27,NULL,NULL,0,0}; ... {T27*n=((T27*)se_malloc(sizeof(*n))); *n=M27; r27make(n); ...
Some characters in method names, such as "<" or "+", will be replaced by their corresponding ASCII code in decimal.
An example
For example: STRING has the identifier 72. So:
- The object type is T7.
typedef struct S7 T7;
- The structure is defined in struct S7.
struct S7{Tid id;T9 _storage;t2 _count;t2 _capacity;};
- The append method becomes:
void r7append(se_dump_stack*caller,T7* C,T0* a1)
(See below for details on the dump stack execution stack.)
The .id file
When the application is compiled, the list of identifiers is stored in a file whose name is suffixed .id. The file is reread in incremental compilations (which allows some stability in the identifiers, so long as the whole project is not recompiled).
This file is structured in entries, each entry being separated from others by a hash character (#). This file looks like this:
5 "REAL" class-path: "/SmartEiffel/lib/numeric/real.e" class-name: REAL assertion-level: all parent-count: 1 inherit: 49 # 72 "FAST_ARRAY" class-path: "/SmartEiffel/lib/storage/collection/fast_array.e" class-name: FAST_ARRAY assertion-level: all parent-count: 1 inherit: 58 # 62 "STD_ERROR" class-path: "/SmartEiffel/lib/io/terminal/std_error.e" class-name: STD_ERROR assertion-level: all parent-count: 1 inherit: 39 c-type: T62 reference: yes ref-status: live id-field: yes destination-graph-nodes: ->OUTPUT_STREAM run-time-set-count: 1 run-time-set: STD_ERROR (62) # . . .
You should never depend on these identifiers. In any case, when an identifier is computed, collisions may occur, and affect the process. Thus, the identifier and name of each type depends not only on the type name, but also on the order in which the types are compiled. That is, on the order of application and library types combined... They also depend on the compilation mode used (since that can change the list of active types), and the version of the compiler you're using. So what is T145 today may be T234 tomorrow3!
Consequently, do not ever rely on the generated identifiers, because they are not constant! Do not try to write in your own C code horrible things like new123 or T456, because the only thing we can guarantee is that this code will not work.
Naming convention
The preceding section has explained how methods are generated.
The function prototype r7append() from the example above is presented as
v7append(se_dump_stack*caller,T7* C,T0* a1);
This shows how Current and the arguments are passed. The rules are as follows:
- Current is called C and is always strongly typed (with its own exact type). This parameter may be omitted if Current is not used by the method. In some cases (when code is inlined), Current can be copied in local variables named C1, C2...
- The arguments are called a1, a2... and are typed T0* for reference types or given their exact type for expanded types (e.g. T2 for an integer)
- Inside functions, a local variable R is defined. This is Result.
- Local variable keep their Eiffel name, prefixed by an underscore.
The mangling table
OK, now you understand why you cannot use type numbers, but you still want to know what those fields in the mangling table mean (in the .id file)>..
First, a big caveat. Although it may have been very stable for quite some time now, the mangling table coding may change! We currently have no plans to change it, and we prefer keeping it the way it is. But once again, we do not commit ourselves to the current representation.
Let's look again at the extract of a .id file. The part shown covers nearly all the possible cases:
5 "REAL" class-path: "/SmartEiffel/lib/numeric/real.e" class-name: REAL assertion-level: all parent-count: 1 inherit: 49 # 72 "FAST_ARRAY" class-path: "/SmartEiffel/lib/storage/collection/fast_array.e" class-name: FAST_ARRAY assertion-level: all parent-count: 1 inherit: 58 # 62 "STD_ERROR" class-path: "/SmartEiffel/lib/io/terminal/std_error.e" class-name: STD_ERROR assertion-level: all parent-count: 1 inherit: 39 c-type: T62 reference: yes ref-status: live id-field: yes destination-graph-nodes: ->OUTPUT_STREAM run-time-set-count: 1 run-time-set: STD_ERROR (62) # . . .
There is one entry per type (active or not); each entry spans many lines and is terminated by a hash symbol (#).
Each entry contains a lot of information. Not all of it is always present; missing entries take default values.
Only the first line is compulsory. It contains the type identifier, and its name (as would be returned by generating_type).
The following lines contain different fields, marked by a keyword, a colon and a value. There may be one or more fields on a single line. Those fields are:
class-path | The path to the file containing the source code. May be omitted if the class has no associated file (uncommon). |
class-name | The name of the class, as returned by generator. |
parent-count | Le number of parents. |
inherit | On the same line as parent-count if the latter is not null; it gives the list of parent class identifiers. |
c-type | The C type, usually in the form T27. If it is omitted, the class has no runnable type.
In that case, the following fields do not appear either. |
reference | On the same line as c-type, yes for a reference type or no for an expanded type. |
ref-status | Either live for an active type (i.e. instances of this type are created at run-time), or dead otherwise. |
id-field | On the same line as ref-status, yes if the id field has to be generated in the C structure (as its first element), no otherwise. This field is present if one of these confitions is true:
Note that a lot of calls are statically computed; the type inference algorithm used in SmartEiffel increases the number of such types that do not need the id field. |
destination-graph-nodes | ????? |
run-time-set-count | The number of concrete, active descendants of the type (including itself). This is the number of items in run-time-set below. |
run-time-set | The concrete, active heirs of this type (including itself). One class per line, tab-indented. |
The dump stack
When not in boost mode, a stack is managed by the runtime environment generated by SmartEiffel. This stack is displayed when an uncaught exception is raised. It is also used by the debugger sedb.
Technically, the SmartEiffel stack is built upon the native (C) stack. Each stack element is a se_dump_stack4 usually allocated on the stack. It is made up of several parts:
- a frame descriptor, of type se_frame_descriptor44 which is a static description of the feature, as follows:
- run type,
- does it use Current,
- number and type of the local variables, and
- an anti-recursion flag (for contracts)...
- a dynamic part:
- a pointer to Current (i.e. either a pointer to an expanded object, or else a pointer to a reference object, it being a pointer to the object itself). That is why the type of the current field is Void**. This field will be NULL if Current is not used by the feature,o
- the position (used mainly by sedb),
- a pointer to the caller (i.e. the se_dump_stack of the calling function),
- a pointer to the exception origin: if not NULL, it means that this se_dump_stack is not in the stack, but was malloc'ed to preserve the exception stack trace,
- an array of local variables (with double indirection as for Current), hence the type void***.
Macros handle the linking between the se_dump_stack frames.
- Normally, the top of the dump stack is the global variable se_dst defined in SmartEiffel/sys/runtime/no_check.c. The macro set_dump_stack_top accomplishes the assignment of its argument in this variable.
- In SCOOP mode, each processor has its own stack. So the set_dump_stack_top macro has two arguments: the processor and the new dump stack top.
- 0: the type any other can be cast to
- 1: INTEGER_8
- 2: INTEGER (or INTEGER_32)
- 3: CHARACTER
- 4: REAL
- 5: DOUBLE [out of date: DOUBLE is no longer supported in 2.2beta5]
- 6: BOOLEAN
- 7: STRING
- 8: POINTER
- 9: NATIVE_ARRAY[CHARACTER]
- 10: INTEGER_16
- 11: INTEGER_64
- [what about the various kinds of REAL?]
So it is likely that the root class of the system may have the identifier 12. But do not rely on that too much (before all the changes to INTEGERs, it was 11).