Joy Online Manual
Preprocessor Features
Table of Contents |
Introduction | ||
Macros | ||
Header Files | ||
Conditional Compilation | ||
Miscellaneous Features |
#define - Define a macro #undef - Undefine a macro |
SYNOPSIS |
#define macro [expansion]
#define macro(arg1, arg2, ...) [expansion]
#undef macro
DESCRIPTION |
You can define macro constants and even macros with arguments. For the macro to be usable by Joy, it has to expand to a syntactically correct Joy expression. So you cannot define "synonyms" for language keywords (e.g. #define EXTERN extern), as is common practice in C. Macros with arguments are treated as JavaScript function definitions. This means that "statement" macros, or macros that use symbols from the lexical scope of their caller, won't work in Joy.
Because C header files tend to define zillions of macros of which only a few are ever used, the right hand side is compiled and evaluated lazily on the first reference to the macro (error messages will contain the file name and line number of the definition, though). |
EXAMPLES |
js> #define MAX(x,y) x > y ? x : y
js> MAX(3,4)
4
js> MAX
function MAX(x, y) {
return x > y ? x : y;
}
js> #define PI Math.PI
js> PI
3.141592653589793
js> #undef PI
js> PI
PI is not defined
Header Files
NAME |
#include - Source header file #import - Source header file if not yet included |
SYNOPSIS |
#include "file"
#include <file>
#import "file"
#import <file>
DESCRIPTION |
These commands work as in Objective-C. #import differs from #include in that each file is sourced only once (per interpreter). If you use angle brackets, file will be searched for in system includes. In the special case that file is a relative path name with two components, the PrivateHeaders and Headers directories of user frameworks and then system frameworks will be tried first. If you use quotes, and file is a relative pathname, it will be searched for in the directory of the file it is included from, then user includes, then system includes. The following environment variables determine the user includes and user frameworks: |
JOY_HEADER_PATH | equivalent to -I | |
JOY_FRAMEWORK_PATH | equivalent to -F |
Multiple directories should be separated by colons (:). |
Because sourcing large header files directly into Joy tends to produce lots of compilation warnings, and you can't rely on header files being present in client installations, you can produce a precompiled version of any header file using the precompile command. So, before searching through the above mentioned paths, Joy will look in the directories ~/Library/Joy/PrecompiledHeaders, /Local/Library/Joy/PrecompiledHeaders, and then /Network/Library/Joy/PrecompiledHeaders for file with its extension replaced by .jp. Such files load much faster and the symbols and declarations they contain will be resolved lazily on demand, so no memory is wasted on header file contents that you do not use. |
Every Joy interpreter will automatically import the file itkDefaultHeaders.jp, which is a resource of the itkRuntime.framework, on startup. That file will contain at least the whole AppKit.h as well as prototypes for the ANSI-C library; see the source file itkDefaultHeaders.h (in the same resources folder) if you are interested in the exact contents for your platform. (Or use the command ObjC.imported() from any Joy command window to get a list of all preimported headers.) |
Conditional Compilation
NAME |
#if - Compile code if condition is true #ifdef - Compile code if macro is defined #ifndef - Compile code if macro is not defined #else - Compile if previous condition was false #elif - Compile if previous condition was false and new condition is true #endif - End conditional compilation |
SYNOPSIS |
#if expr
#ifdef macro
#ifndef macro
#else
#elif expr
#endif
DESCRIPTION |
Because Joy JavaScript uses a byte-code compiler, it does make sense to speak of conditional compilation, though Joy is an interpreted language.
The most interesting use for conditional compilation in Joy is to create a single source file that can both be compiled by the Objective-C compiler and sourced into a Joy interpreter! Also, if a future version of Joy adds some new syntax that would not be accepted by the earlier version, you can use preprocessor conditionals to maintain backward compatibility. All conditionals work as they do in C. An exception is that you can only use defined(macro) in #if expressions, but not defined macro, which would be a legal alternative in the C preprocessor. Because every Joy interpreter defines a macro __JOY__, which expands into the numerical version number as returned from the version function, you can place code which should only be seen by the Joy interpreter within #ifdef __JOY__ ... #endif, and code which should be seen only by the Objective-C compiler within #ifndef __JOY__ ... #endif. |
EXAMPLE |
js> #ifdef __JOY__
static NSRect r = [[1,2],[3,4]]
#else
static NSRect r = {{1,2},{3,4}};
#endif
Miscellaneous Features
NAME |
#error - Emit compilation error #warning - Emit compilation warning #pragma - Set compiler-specific option |
SYNOPSIS |
#error line
#warning line
#pragma line
DESCRIPTION |
The #error and #warning directives work like they do in the C preprocessor. The #pragma directive is currently ignored and produces a warning message. |
EXAMPLE |
js> #ifdef __JOY__
name = name.replace(/(\w+)\s(\w+)/, "$2, $1")
#else
#warning "Regular expressions not supported in Objective-C"
#endif
Index |