• Nenhum resultado encontrado

Jens Gustedt

N/A
N/A
Protected

Academic year: 2023

Share "Jens Gustedt"

Copied!
38
0
0

Texto

An identifier is reserved if it is a strictly reserved keyword or is used to name a function in the C library. First, we want to ensure that Modular Cmodules can compile seamlessly with any future version of the C library.

Exported features

This makes it easier to provide extensions to the C library, e.g. the POSIX standard extends C by adding features to C library functions such as printf. Currently, the C library already has several groups of functions that provide the same functionality for different base types, such as the fabs/cabsor strlen/wcslenfunctions. In the case of offabs there are even two "functions" with the same name, one provided by math.hand the other included bytgmath.h.

If the type is astruct,enumoruniontype with label nameX, it is exported with label nameM'X. X is an object or function that is defined by external binding. M'X then refers to the same object and has the same type as X. X is the tag name of a type struct,unionorenum.M'X is then an alias of the corresponding type with the tag name M'X.

Abbreviations

The module name

As shown in Listing 2, using the module name to declare a structure then makes it easier for the importer to use that structure, here via the same abbreviation veelem. The compound name of the M module can be referred to by the abbreviation given by the animportdirective. The structure that was exported as proj'structs'list'head in Listing 1 is now accessible as proj'.

Mangling

It truncates the identifiersNi from the definition into a concatenation of stringsMi = `iNi, where `i is the length of Ni, with _ZN2_C and E before and after, respectively. Identifiers with such a prefix are actually strictly reserved and could theoretically collide with other internal identifiers on the platform. Likewise, any mangling should ensure that none of the identification patterns listed in section 7.31 of the C standard, "Future library directions", are in the image off.

For a consistent moduleM and manglingf, the mangled module f(M) is the C source file that results from using the following:. A module's compound name also specifies some of the other modules it imports, its parent modules. Keeping track of the contents of the import relation would add a lot of complexity to the Modular C implementation and likely degrade compile time significantly.

Import is binary

Modular C can mostly be implemented using scripting as provided by POSIX utilities, see section 7.1 below. Second, enforcing transitivity ensures that our approach is consistent with the rules [Srivastava et al. 2008] for modularity and information hiding: all our explicit or implicit inclusion of an interface ensures that we only have what is called a horizontal dependency, and that there is a vertical dependency.

Next, Go's main motivation for its restrictive strategy comes from observing the large overhead at compile time that C++, including hierarchies, imposes on software projects. Later we shall assume in several places that one such topological kind is given and fixed among all possible ones. The syntax for importing other modules does not refer to a file name in which such a module can be implemented.

Module initialization and cleanup

The functions listed in the initdirectives of all modules in a program are executed before the input function, in an order consistent with the import graph. Thus the call tomtx'init is always guaranteed to work in a well-defined context.5. Unlike the approach of the C standard with the typeonce flag, this approach here has the advantage that it only has an overhead at application startup, where all the theinit functions are called.

Then, during the actual execution of the program, there is no overhead at all, and it can be ensured that the application starts all its operations in a well-defined state. Functions called inatexitandat quick exit directives of all program modules are inserted as exitandquick exithandlers before the enter function (as if they were inserted with theatexitdat quick exit standard library functions). The insertion is such that the functions are executed in the reverse order of the corresponding initial functions.

CODE SHARING

Snippets

The extract directive introduces a local name, here T, which stands for the name of the import module. The function defined tests whether its argument is a valid pointer and then initializes the object with zero-initialized composition. The source code for snippets is embedded in the declaration order at the end of the import module.

The identifier (if any) specified in the snippet directive serves as an abbreviation for the name of the import module. Note that moduleC'ssnippet'alloc does not know much about the context in which the function alloc will be placed by the import mechanism. It formulates an interface contract and enforces that the name of the import module must be a complete type and that it must implement a function init with the specified prototype.

Slots

For the integration of such a fragment, these three identifiers must be replaced ("filled in") by three identifiers that the importer freely chooses. C'tmpl'vector proj'structs'toto C'tmpl'vector'vType proj'structs'toto'vec23 C'tmpl'vector'T proj'structs'toto C'tmpl'vector'size proj'structs'toto'vsize . The fill (single slot) instructions can and should appear in the pre-introduction of the user's source.

A fragment is called a template if all the functions it specifies for the importer are called throughslotdirectives. In other words, it's a template if it doesn't pollute the importer's namespace. Templates can be imported multiple times into the same module M if each import uses a different abbreviation.

Reach of snippets

In general, a SnippetScan cannot be imported multiple times into the same moduleM, because that would lead to multiple definitions in M. Any identifierN in moduleB whose definition comes from the animportdirective fragment of moduleAinB is seen by any Bas importer if B really defines it. As a result, D's namespaces would be polluted with identifiers over which it has no control.

This could even lead to a name clash if another import path would have aninit function in one of the snippets. Last but not least, we certainly cannot expect any importer of proj'structures'toto to fill the spaces in C'tmpl'vector with consistent declarations.

A FORMAL DESCRIPTION

  • Source reorganization and stability
  • The replacement procedure
  • Formal proofs
  • Stiching modules into one project

If we were to integrate chunks through transitivity, coding with them would become quite complicated. For Listing 4, this would mean that a module that imports project instructions would also define its own functions init and alloc. The third part contains the "rest" of the code of a sourceP, these are mainly object and function definitions. This follows directly from the lemma above and from the fact that most of the substitution procedures do not apply if there are no Modular Cdirectives.

As a first step to a proof, consider the case that none of the modules have extracts. For the induction step, observe that the statement holds for i < n0−1 because of the induction hypothesis. The_Importeridentifier stands for the name of the importer and is consistently replaced when adding snippets.

Figure 2 shows a formalized replacement procedure to compile a module into an archive file
Figure 2 shows a formalized replacement procedure to compile a module into an archive file

A STRUCTURED VIEW OF THE C LIBRARY

  • Basic types
  • String processing
  • Feature test
  • Snippets and templates

We have access to object-like macros for the size of a type, its integer rank, its width, and to function macros such as the minimum and maximum of a finite array of values ​​(minandmax) or to functions that operate on arrays (minvandmaxv). This requires the default branch of the generic expression node and the compiler will clearly show an error if this macro is used with another type such as pointer type. Some native functions have the added problem of dropping const qualifiers where they shouldn't.

Sorting out different versions and features of the implemented C standard is tedious, and often the only partially viable solution is a long list of special cases for different compilers, libraries, and releases. Most of the modules that implement the features of the C library should not contain snippets, simply because we don't want the user identifier namespace to be polluted by an ever-growing amount of rules. First, legacy code that already uses features of the C standard library must be able to continue to do so.

THE TRANSITION FROM C TO MODULAR C 1. A reference implementation

Interfacing existing libraries

Specifically, to provide an operational environment, we need to interface the platform's C library with module interfaces as described above. It uses an impersonation directive to reference the traditional header file, adds information for the linker with link, and then extracts all information from the header by text comparison or by compiling short test programs. To evaluate the expression written on the RHS of the=, we create a short C program that is run once to print the result of the evaluation.

As a result, the platform information is extracted only once, during the compilation of the interface modules, and the compiled modules have the same characteristics as precompiled header files. As shown in some examples, we apply similar renaming ideas to these guidelines. All of this is still surprisingly fast: thanks to the efficiency of the tools we use, a compilation of the 120 or so module files that make up our C library interface today takes just 33 seconds on a modern laptop.

A migration path for existing C projects

We see that we actually have two entries in the symbol table, one for the mangled name (retranslated here into the C++ compound naming scheme) and an alias for the conventional name, hereproj_list_proj_list_init. Now let's remove the internal name prefix by first removing all proj_list_prefixes and then replacing proj_listbylist with the type itself. So we now have an object file that we can use instead of the one created with proj list.c.

Analogously, we can then proceed to transform all units that proj'list will import in a similar way. It is still API compatible with the header files we had before, so our new version of the library written with modules can be used without any problems. But once this state is reached, the real refactoring of the code can begin: module imports from the C'std' hierarchy can be replaced, macros and X macros can be rewritten as fragments, code parts that are structurally similar can be grouped, repetitive code can be replaced by a single definition in a fragment.

CONCLUSION

Imagem

Fig. 1. The import dependency graph of the example module
Figure 2 shows a formalized replacement procedure to compile a module into an archive file

Referências

Documentos relacionados

Apesar de ser um idioma mais difundido, e do ponto de vista econômico mais rentável que o alemão e o árabe, caso o inglês seja eleito, todos os