# Pragmas

SRC Modula-3 recognizes the following pragmas:

- <*EXTERNAL*>
- <*INLINE*>
- <*ASSERT*>
- <*TRACE*>
- <*FATAL*>
- <*UNUSED*>
- <*OBSOLETE*>
- <*NOWARN*>
- <*LINE*>
- <*PRAGMA*>
- <*calling convention*>

## <*EXTERNAL*>

The pragma `<*EXTERNAL N:L*>` may precede an interface or a procedure or variable declaration in an interface. It asserts that the following entity is named ``N'' and implemented in language ``L'' (or uses calling convention ``L''). If ``N'' is omitted, the external name is the Modula-3 name. The default and only recognized value for ``L'' are platform dependent. The ```:`'' is only required when specifying ``L''. ``N'' and ``L'' may be Modula-3 identifiers or string literals.

On Unix platforms, the default and only recognized language is `C`.

On Windows/NT, two calling standards are supported, `__cdecl` and `__stdcall`. They are treated as languages by the `<*EXTERNAL*>` pragma. `C` and `WINAPIV` are aliases for `__cdecl`. `WINAPI`, `CALLBACK`, `APIENTRY`, `APIPRIVATE`, and `PASCAL` are aliases for `__stdcall`. The default is `C`.

The names of external procedures and variables are passed through the back end unchanged. The types of external variables, the types of formal parameters, the types of results, and the raises clauses of external procedures are all assumed to be correct and are not checked against their external implementation.

Beginning an interface with `<*EXTERNAL*>` declares all of the procedures and variables in that interface external.

For example:

        <*EXTERNAL*> INTERFACE OS;
        VAR errno: INTEGER;
        PROCEDURE exit (i: INTEGER);
        END OS.

allows importers of `OS` to access the standard `Unix` symbols `errno` and `exit` through the names `OS.errno` and `OS.exit` respectively.

Alternatively, the following interface provides access to the same two symbols, but uses a more conventional Modula-3 name for the procedure:

        INTERFACE OS;
        <*EXTERNAL errno:C *> VAR errno: INTEGER;
        <*EXTERNAL exit:C  *> PROCEDURE Exit (i: INTEGER);
        END OS.

If several variables are declared within a single `<*EXTERNAL*> VAR` declaration, they are all assumed to be external.

The external pragma may optionally specify a name different from the Modula-3 name. For example:

        INTERFACE Xt;
          <*EXTERNAL "_XtCheckSubclassFlag" *>
          PROCEDURE CheckSubclassFlag (...);
          ...

defines a procedure named `Xt.CheckSubclassFlag` in Modula-3 and named `_XtCheckSubclassFlag` in the generated C.

## <*INLINE*>

The pragma `<*INLINE*>` may precede a procedure declaration. The pragma is allowed in interfaces and modules. SRC Modula-3 parses but ignores this pragma.

For example:

        INTERFACE X;
        <*INLINE*> PROCEDURE P (i: INTEGER);
        <*INLINE*> PROCEDURE Q ();
        END X.

declares `X.P` and `X.Q` to be inlined procedures.

## <*ASSERT*>

The pragma `<*ASSERT expr*>` may appear anywhere a statement may appear. It is a static error if ``expr'' is not of type `BOOLEAN`. At runtime ``expr'' is evaluated. It is a checked runtime error if the result is `FALSE`.

Assertion checking can be disabled with the `-a` compiler switch.

## <*TRACE*>

The pragma `<*TRACE expr*>` may appear at the end of any variable or formal declaration. This pragma will generate tracing calls whenever the declared variable is modified.

The ``expr'' must evaluate to a procedure of two arguments. The first argument is the name of the traced variable, a `TEXT`. The second argument is the traced variable. Note that any of the formal passing modes may be used with the second argument.

For example:

        MODULE M;
        VAR x: Foo <*TRACE MyTrace.FooChanged*>;

will cause

        MyTrace.FooChanged ("M.x", x)

to be generated after each statement that modifies x. Variable aliasing is not tracked, so

        WITH  alias = x DO  INC(alias) END

will not generate any tracing.

The pieces of Modula-3 grammar affected by `<*TRACE expr*>` are:

        VariableDecl = IdList (":" Type & ":=" Expr) V_TRACE.
        Formal       = [Mode] IdList (":" Type & ":=" ConstExpr) V_TRACE.
        ForSt        = FOR Id V_TRACE ":=" Expr TO Expr [BY Expr] DO S END.
        Handler      = QualId {"," QualId} ["(" Id V_TRACE ")"] "=>" S.
        TCase        = Type {"," Type} ["(" Id V_TRACE ")"] "=>" S.
        Binding      = Id V_TRACE "=" Expr.
        V_TRACE      = [ "<*" TRACE  Expr "*>" ].

The pragma `<*TRACE stmt-list*>` may appear immediately after any `BEGIN`. The specified ``stmt-list'' will be inserted after each statement of the block started by the `BEGIN`. For example:

        BEGIN <* TRACE  INC(cnt); MyTrace(cnt) *>
          i := j;
          j := i;
        END;

will generate `INC(cnt); MyTrace(cnt)` after each of the assignment statements.

## <*FATAL*>

The pragma `<*FATAL id-list*>` may appear anywhere a declaration may appear. It asserts that the exceptions named in ``id-list'' may be raised, but unhandled in the containing scope. If they are, it's fatal and the program should crash. Effectively, the `<*FATAL*>` pragma disables a specific set of ``potentially unhandled exception'' warnings. If ``id-list'' is `ANY`, the pragma applies to all exceptions. The effects of the `<*FATAL*>` pragma are limited to its containing scope --- they cannot be imported from interfaces.

For example:

        EXCEPTION InternalError;
        <*FATAL InternalError*>

at the top-level of a module `M` means that no warnings will be generated for procedures in `M` that raise but don't list `InternalError` in their `RAISES` clauses.

Similarly,

        PROCEDURE X() RAISES {} =
        BEGIN
          ...
          <*FATAL ANY*> BEGIN
             List.Walk (list, proc);
          END;
          ...
        END X;

specifies that although `X` raises no exceptions and `List.Walk` may, no warnings should be generated.

## <*UNUSED*>

The pragma `<*UNUSED*>` may precede any declaration. It asserts that the entity in the following declaration is not used and no warnings should be generated.

For example, the procedures that implement the default methods for an object may not need all of the actual parameters:

        PROCEDURE DefaultClose (<*UNUSED*> wr: Wr.T) =
           BEGIN (* do nothing *) END DefaultClose;

## <*OBSOLETE*>

The pragma `<*OBSOLETE*>` may precede any declaration (e.g. `<*OBSOLETE*> PROCEDURE P ();`). A warning is emitted in any module that references an obsolete symbol. This feature is used to warn clients of an evolving interface that they are using features that will disappear in the future.

## <*NOWARN*>

The pragma `<*NOWARN*>` may appear anywhere. It prevents warning messages from being issued for the line containing the pragma. It is probably better to use this pragma in a few places and enable all warnings with the `-w1` switch than to ignore all warnings.

## <*LINE*>

For the benefit of preprocessors that generate Modula-3 programs, the compiler recognizes a `<*LINE ... *>` pragma, in two forms:

        <*LINE number filename *>
        <*LINE number *>

where `number` is an integer literal and `filename` is a text literal. This pragma causes the compiler to believe, for purposes of error messages and debugging, that the line number of the following source line is `number` and that the current input file is `filename`. If `filename` is omitted, it is assumed to be unchanged. `<*LINE ... *>` may appear between any two Modula-3 tokens; it applies to the source line following the line on which it appears. Here's an example: `<*LINE 32 "SourceLoc.nw" *>`.

## <*PRAGMA*>

The pragma `<*PRAGMA id-list*>` may appear anywhere. It notifies the compiler that pragmas beginning with the identifiers in ``id-list'' may occur in this compilation unit. Since the compiler is free to ignore any pragma, the real effect of `<*PRAGMA*>` is to tell the compiler that pragmas it doesn't implement are coming, but they shouldn't cause ``unrecognized pragma'' warnings.

## <*calling convention*>

Any of the ``languages'' allowed in the `<*EXTERNAL*>` pragma may be used to indicate the calling convention associated with a procedure or procedure type. The pragma must appear immediately prior to the `PROCEDURE` keyword. For example:

        TYPE WindowsCallBack = <*CALLBACK*> PROCEDURE (h: HANDLE);

        <*CALLBACK*> PROCEDURE Foo (h: HANDLE) =
           BEGIN ....

declares a procedure and procedure type that use the Windows/NT `CALLBACK` (i.e. `__stdcall`) calling convention.

The SRC Modula-3 compiler treats procedure types that are equal except for their calling conventions as different types.

    Last modified on Thu Jan  4 11:07:59 PST 1996 by heydon
         modified on Wed Dec 21 14:47:24 PST 1994 by kalsow
         modified on Thu Jan  7 18:40:57 PST 1993 by muller