RU beehive logo ITEC dept promo banner
ITEC 380
2008fall
ibarland

homeinfolecturesexamsarchive

lect13c
macro intro

Note: On hw06, if using Java: subst should return a new parse tree, not modify the existing one. You'll find your code much shorter and simpler.

Macros

Macros are code which generates other code (in the same source-language).

Possible reasons to want to write a macro:

The C pre-processor

C has a primitive system, based purely on modifying strings. Before compiling, it makes a first pass where it does some string-substitution. (Use 'gcc -E' to show the results of pre-processing only.)

 1  #include <stdio.h>
 2  
 3  #define PI 2.14159+1
 4  #define RADIANS_PER_DEGREE 2*PI/360
 5  #define MAX(a,b)  a >= b ? a : b
 6  #define swap(x,y) {int tmp;  tmp = x; x = y; y = tmp;}
 7  
 8  int main() {
 9    double p = 360 * RADIANS_PER_DEGREE;
10    printf( "The max is: %g.\n", 1/MAX(p++,PI) );
11    
12    
13    const int ETM = 15;  // #business days between "every third Monday"
14    // This next line doesn't compile, complaining about a hyphen (?!):
15    // const int EOF = 10;  // days in the pay period: "Every Other Friday".
16    // Because the pre-processor is oblivious to C, we get weird error messages.
17  
18  
19  
20    int a = 5, b = 99;
21    printf( "Before swap: a=%d, b=%d.\n", a, b );
22    swap(a,b);
23    printf( "After  swap: a=%d, b=%d.\n", a, b );
24  
25    // Happily: swap(++a,b) gives a syntax-error.
26  
27    // Uh-oh!
28    int tmp = 5;
29    b = 99;
30    printf( "Before swap: tmp=%d, b=%d.\n", a, b );
31    swap(tmp,b);
32    printf( "After  swap: tmp=%d, b=%d.\n", a, b );
33    }
(We talk about pitfalls of using the preprocessor.)

Note that one relatively-more-robust use of the preprocessor is conditional compilation:

#define USING_WINDOWS_VISTA

#ifdef (USING_WINDOWS_XP)
// code which *only* gets compiled on some platforms
#define MAX_DISK_SIZE 300
  void writeErrorLog( string msg ) { /* XP-specific code */ }
#else
  void writeErrorLog( string msg ) { /* (non-XP)-specific code */ }
#endif
or (from Wikipedia)
#if VERBOSE >=2
  print("trace message");
#endif

Overall, C's preprocessor is a failed experiment: rather than a tool which does text-substitution (and knows nothing about the language -- scoping, variables, etc.), it's better to have features like named constants, module systems which search a library for declarations but don't actually include the code, and real functions (which you can suggest that the compiler inline). Conditional compilation can be done by having built-in functions like "getCurrentOS" plus an aggressive compiler.

Further abilities (and other sorts of pitfalls) are mentioned on wikipedia.

Now that we have the need for 'smarter' macros,
here are some applications we might use for them:

  - I wish 'let*' allowed me define functions
    w/o explicilty typing 'lambda'.
  - l1
  - Little Languages: a macro language for FSMs


 - auto-generate getters, setters, public/private fields, constructor...
 - auto-generate the boring code in 'eval', 'equals', ...
   (Though, see scheme's partial solution in L3-soln.ss)
 - when using the delegate pattern


Reflection vs Macros:
 - Reflection is a way of 'writing code expands to other code'
 - less powerful in some ways: you can't make arb. macros,
   only produce method-calls to existing methods.
 - However, it's more powerful in some ways:
   you don't need to know field-names etc in advance.

homeinfolecturesexamsarchive


©2008, Ian Barland, Radford University
Last modified 2008.Dec.08 (Mon)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme