TRADE.shnl

part of shnell – a source to source compiler enhancement tool

© Jens Gustedt, 2019

The TRADE dialect – dealings in import-export

This dialect can be used to organize a whole project with a consistent naming convention that combines export and implicit import. If used without any adjustment it has the following features

All of this assumes that all long names are unique and that there are no homonyms, and this is clearly the point where our analogy to the names of people ends.

Visibility of identifiers

By that all globally visible names of objects, functions, types, enumeration constants and macros are unique across the whole project and no TU impedes on any other. Mutually visible between TU are only those that are “public”. Per default these are only names of global objects and functions that are not declared static, that is that (in C speech) have external linkage, plus the short name of the TU. Thus if you have a TU named test-string.c that defines a struct string type, the type and all global functions that are defined are visible from the outside and constitute the interface of the TU. Other TU see and can use the type as test::string and can use the functions as test::string::func for a function func defined within test-string.c.

Other identifiers, such as types or macros, that you want to share can be made public by prefixing them with the short name in their definition. See export for a summary of all the conventions that apply.

Fine-tuning of the naming conventions

Such a fine tuning can be achieved by using some other directives. These should all be used with the marker PRETRADE such as in #pragma PRETRADE alias.

private can be used to make identifiers private that would be public otherwise. This could e.g be functions that for some reason need external linkage, but which should not be part of the API of the TU.

alias can be used to introduce nick names for other TU, or to provide a different short name than the default. These can then be used as convenient prefixes if otherwise you could have long impractical names.

using establishes a whole set of identifier short-cuts that can be used directly without prefix, e.g

`#pragma PRETRADE using stdc printf fprintf stdin stdout stderr`

make it possible to use fprintf(stderr, ...) just as you would in a traditional C project.

legacy

Internally we maintain a list of pseudo-TU that are to be used in “legacy” mode. Per default this contains stdc for the whole standard C library. E.g by using stdc::printf you will have access to the printf function of the C library, just as you are used to.

To integrate a legacy project trex, say, you’d have to provide a traditional header file trex.h that provides all the symbols that are needed and you’d have to add trex to the list, something like

#pragma PRETRADE legacy trex

Then all your code can refer to the birth function in the trex project by using the name trex::birth. By that there would be no collision with a birth identifier that you’d use directly for your own project.

main is special

The main symbol is the only one from the C standard that is defined by user code, and so we must be able to do so without rewriting it to a long name. This is achieved by defining it as stdc::main, that is treating main as a legacy identifier from the C standard (which it is).

The export module then takes even care that several TU may have such a main, such that each TU may for example implement a standalone test.