Skip to main content

##expression

Evaluates an ObjectScript expression at compile time.

Description

This macro preprocessor function evaluates an ObjectScript expression at compile time. It has the form:

##expression(content)

where content is valid ObjectScript code that does not include any quoted strings or any preprocessor directives (with the exception of a nested ##expression, as described below).

The preprocessor evaluates the value of the function’s argument at compile time and replaces ##expression(content) with the evaluation in the ObjectScript .int code. Variables must appear in quotation marks within ##expression; otherwise, they are evaluated at compile time.

The following example shows some simple expressions:

#define NumFunc ##expression(1+2*3)
#define StringFunc ##expression("""This is"_" a concatenated string""")
  WRITE $$$NumFunc,!
  WRITE $$$StringFunc,!

The following example defines an expression containing the compile timestamp of the current routine:

#define CompTS ##expression("""Compiled: " _ $ZDATETIME($HOROLOG) _ """,!")
  WRITE $$$CompTS

where the argument of ##expression is parsed in three parts, which are concatenated using the _ operator:

  • The initial string, """Compiled: ". This is delimited by double-quotes. Within that, the pair of double-quotes specifies a double-quote to appear after evaluation.

  • The value, $ZDATETIME($HOROLOG). The value of the $HOROLOG special variable at compile-time, as converted and formatted by the $ZDATETIME function.

  • The final string, """,!". This is also delimited by double-quotes. Within that, there are a pair of double-quotes (which results in a single double-quote after evaluation). Since the value being defined is being passed to the WRITE command, the final string includes ,!, so that the WRITE command includes a carriage return.

The routine’s intermediate (.int) code would then include a line such as:

  WRITE "Compiled: 05/29/2018 07:49:30",! 

##expression and Literal Strings

Parsing with ##expression does not recognize literal strings; bracketing characters inside of quotes are not treated specially. For example, in the directive:

#define MyMacro ##expression(^abc(")",1))

the quoted right parenthesis is treated as if it is a closing parenthesis for specifying the argument.

##expression Nesting

InterSystems IRIS supports nested ##expressions. You can define an ##expression that contains macros that expand to other ##expressions, as long as the expansion can be evaluated at the ObjectScript level (that is, it contains no preprocessor directives) and stored in an ObjectScript variable. With nested ##expressions, the macros with the ##expression expression are expanded first, then the nested ##expression is expanded.

##expression can also nest the following macro functions: ##BeginLit...##EndLit, ##function, ##lit, ##quote, ##SafeExpression, ##stripq, ##unique.

##expression, Subclasses, and ##SafeExpression

When a method contains an ##expression this is detected when the class is compiled. Because the compiler does not parse the content of the ##expression, this ##expression could generate different code in a subclass. To avoid this, InterSystems IRIS causes the compiler to regenerate the method code for each subclass. For example, ##expression(%classname) inserts the current classname; when you compile a subclass, the code expects it will insert the subclass classname. InterSystems IRIS forces this method to be regenerated in the subclass to ensure that this occurs.

If you know that the code will never be different in a subclass, you can avoid regenerating the method for each subclass. To do this, substitute the ##SafeExpression preprocessor function for ##expression. These two preprocessor functions are otherwise identical.

How ##expression Works

The argument to ##expression is set into a value via the ObjectScript XECUTE command:

 SET value="Set value="_expression XECUTE value

where expression is an ObjectScript expression that determines the value of value and may not contain macros or a ##expression preprocessor function.

However, the results of the XECUTE value may contain macros, another ##expression, or both. The ObjectScript preprocessor further expands any of these, as in this example.

Suppose the content of routine A.mac includes:

#define BB ##expression(10_"_"_$$aa^B())
 SET CC = $$$BB
 QUIT

and routine B.mac includes:

aa()
 QUIT "##expression(10+10+10)"

A.int then includes the following:

 SET CC = 10_30
 QUIT 
FeedbackOpens in a new tab