Macro definition

Note that this is a new definition since Som v.3.1.  See the old definition (since som v.1.5) here.

To reduce the overhead of a function call, a function can be defined as a "macro".  A macro definition is just like a function definition, the difference is that the body of a macro definition is substituted into the call. It is done by textual substitution (similar to macro language).  Hence, the size of a program with a macro is larger than with a function (which is reused).  The advantage is that the program will be executed faster.  The syntax of a macro definition is similar to a function definition, only the keyword is ":" instead of "to".  For example,

: print x = syscall {1 x}

Whenever the macro appears in the program, the macro body is substituted.

to report a b =
  ...
  print a
  ...

will become

to report a b =
  ...
  syscall {1 a}
  ...

Macro is suitable for defining "access function" such as,

(from list-s.txt in Som v2 som-in-som)

to setcar a value = cell[a] = value
to setcdr a value = cell[a+1] = value
to car a = if a == NIL a else cell[a]
to cdr a = if a == NIL a else cell[a+1]

These functions will be executed much faster because there is no overhead associated with "call" "return" such as create/destroy the stack frame.

Sometimes the use of macro can create a new control flow, for example in the library, the "short-circuit"  and/or are defined :

: or a b = if a 1 else b
: and a b = if a b else 0

These and/or  evaluated their arguments just enough to decide the outcome.  This is dfferent from the use of "&" and "|" which always evaluate both of their arguments.  (see example in the "test" directory of somv15.zip, the file "queen2.txt"). 

Previously, (since som v.1.5) there are two kinds of macro, one is what presented here.  The other is called a "full" macro which evaluate its arguments, like a function call.   See the old definition here.  However, now I adopt only the current definition, the full macro is eliminated from the language.  The discussion below described the reasoning behind this decision.

Discussion

After a careful inspection of how macro work, I found that the meaning of a full macro is different from a normal macro.  Consider this example of swapping two variables (as in bubble sort):

to swap ar i j | t =
  t = ar[i]
  ar[i] = ar[j]
  ar[j] = t

it is probably called from:

  swap ax a b

If swap is a full macro it will work as expect. However if it is a normal macro it will not work at all because there is no place for the local "t" to participate in substitution of variables.  A normal macro "swap" (as written above) will be expanded (incorrectly) to:

  ? = ax[a]
  ax[a] = ax[b]
  ax[b] = ?

where as if "swap" is written as a normal macro, it will be:

: swap i j t =
  t = i
  i = j
  j = t

If it is called with a supply of variables as:

  swap ax[a] ax[b] c

and by "textual" substitution (which is how a normal macro is expanded), the expanded expression will be:

  c = ax[a]
  ax[a] = ax[b]
  ax[b] = c

which will work correctly.

The meaning of a normal macro is therefore not the same as an expression in the language.  A full macro is supposed to be the "inline" of the expression. The meaning of a full macro is the same as the expression in the language.  So, the meaning of a full macro and a normal macro are different. It is not good to have a syntax construction that has two meanings in the same language.  I have to choose only one.  A normal macro is simpler to compile and very powerful. It is also proved to be much more useful (one evidence is that the som-compiler itself never use a full macro).  Therefore I choose to adopt a normal macro and discard a full macro from the language.

A normal macro is similar to a macro in C language as it is a textual substitution.  I have not yet pondered their differences in full.  A macro in C has been considered by many language designers as "not recommend".  An expression written in a macro in C is different from a normal expression and can caused a subtle bug if it is used carelessly. 

last update 26 Aug 2007