Skip to content

Preprocessor

Positron edited this page Aug 4, 2017 · 4 revisions

The BCS preprocessor attempts to replicate much of the behavior of the C (C99) preprocessor. The preprocessor is case-sensitive. To be compatible with ACS, the preprocessor-based #define and #include directives only get executed if they appear in an #if/#ifdef/#ifndef block:

#if 1
   #define MAKE_STR( arg ) #arg
#endif

script MAKE_STR( 1 2 3 ) open {
   Print( s: MAKE_STR( Hello World! ) );
}

String literal concatenation

The compiler performs string literal concatenation: adjacent string literals are combined to form a single string literal. This can be used to break up a long string literal into smaller parts, making it easier to see the whole string:

script "Main" open {
   Print( s:
      "This is a very long string. It will require a lot of horizontal "
      "scrolling to see it all. Horizontal scrolling is not fun. Thankfully, "
      "we can break this string into smaller strings, which will then be "
      "combined into a single string by the compiler. Awesome!" );
}

Line concatenation

A line of code can be broken up into multiple lines. To break up a line, position your cursor somewhere on the line, type in a backslash character, then press Enter. Make sure no other characters follow the backslash, not even whitespace characters like tabs and spaces.

script "Main" open {
   str reallyniceintro = "Hello, World!";
   Print( s: really\
nice\
intro );
}

Line concatenation is useful for breaking up a long macro into multiple shorter lines:

#if 1

// Macro on one line.
#define LOOP( code, times ) for ( int i = 0; i < ( times ); ++i ) { code; }

// The same macro, but spread over multiple lines.
#define LOOP( code, times ) \
   for ( int i = 0; i < ( times ); ++i ) { \
      code; \
   }

#endif

script "Main" open {
   LOOP( Print( s: "Hello, World" ), 10 );
}

Predefined macros

Along with the standard C predefined macros, BCS defines a few of its own macros:

Macro Description
__IMPORTED__

When a library is #imported, during the preprocessing of the library, the __IMPORTED__ macro is present. Any file #included by the library will also see the __IMPORTED__ macro. The value of the __IMPORTED__ macro is 1.

The __IMPORTED__ macro can be used to do different things depending on whether the library is being compiled or is imported:

#ifdef __IMPORTED__
   // Do something when the library is imported.
#else
   // Do something when the library is being compiled.
#endif
__INCLUDED__

When a file is #included, during the preprocessing of the file, the __INCLUDED__ macro is present. The value of the __INCLUDED__ macro is 1.

The following example uses the __INCLUDED__ macro to force the user to #include a file:

#ifndef __INCLUDED__
   #error this file must be #included 
#endif