$COMPILE (ObjectScript)
Synopsis
$COMPILE(source,language,errors,object)
$COMPILE(source,language,errors,object,,,rname)
Arguments
Argument | Description |
---|---|
source | A local or global variable that specifies a subscripted array containing the source code to be compiled. |
language | An integer flag specifying the programming language of the source code. 0 = ObjectScript. |
errors | An unsubscripted local variable that receives any errors that occur during compilation. This variable is a List structure, with one element for each error reported. Each error is itself a List structure, specifying error location and type (see below). |
object |
1st Syntax — An unsubscripted local or global variable that is used to generate an array used to hold the compiled object code. 2nd Syntax — This argument is optional. If specified, object is cleared of its prior value, but not set. Commonly, 2nd syntax omits object and specifies a placeholder comma. |
rname | 2nd Syntax — A string specifying a routine name used to store the compiled object code in the ^rOBJ global. |
Description
$COMPILE compiles source code and produces OBJ (object) code (the executable form of the routine). $COMPILE reports compilation errors, and can be used to check source code for compilation errors without actually producing object code. $COMPILE takes as input INT code, not MAC code. Therefore, before compiling, any macros in the source code must be resolved by a preprocessor such as the ObjectScript macro preprocessor.
Commonly, source code compilation is performed using your choice of IDE, rather than the $COMPILE function.
$COMPILE has two syntactic forms:
-
The first $COMPILE syntax form returns the object code in the object array. It first kills the object variable. After the compilation the object array is set to the size of the compiled object code.
The object array contains the object code in the same format as it would be in the ^rOBJ global. The object code in ^rOBJ can be replaced with the new object code by the command MERGE ^rOBJ(rname)=object(1). However, the MERGE command is not atomic when setting multiple nodes, so this operation could cause unpredictable results if another process is concurrently loading the same routine.
If you omit the object argument, the source code is compiled and checked for errors, but no object code is created.
-
The second $COMPILE syntax form returns the object code directly into a routine named rname This OBJ code can be viewed by returning ^rOBJ(rname). The $COMPILE operation internally locks ^rOBJ(rname), preventing any other process from loading the routine object code until the new object code is completely stored.
If you omit the rname argument, the source code is compiled and checked for errors, but no object code is created.
Commonly, the object argument (4th argument) is omitted with this syntactic form. If you specify the object argument, the object variable is killed, but is not set. The other omitted arguments (represented by placeholder commas) are for internal use and should not be specified.
$COMPILE returns an integer code as follows: 0 = no errors were detected and object code was created. 1 = errors were detected and object code was created. -1 = errors were detected and no object code was created. The same return codes are returned when the argument that holds the object code (1st syntax: object; 2nd syntax rname) was omitted.
When the ObjectScript compiler detects an error, it creates object code at that point which throws an error when that line is executed.
Arguments
source
An array containing the source code to be compiled (in the format of an INT routine). The array element source(0) must contain the number of lines of source code, and each source(n) contains line number n of the source code. The source lines must be numbered consecutively from 1 through n with no omitted lines. Executable ObjectScript code must be indented. For example:
SET mysrc(0)=6
SET mysrc(1)=" SET x=1"
SET mysrc(2)="Main" // a label
SET mysrc(3)=" WRITE ""x is:"",x,!"
SET mysrc(4)=" SET x=x+1"
SET mysrc(5)=" IF x=4 {WRITE ""x is:"",x,"" all done"" QUIT}"
SET mysrc(6)=" GOTO Main"
SET rtn=$COMPILE(mysrc,0,errs,,,,"myobj")
IF rtn=0 {WRITE "OBJ code successfully generated",!}
ELSE {WRITE "no OBJ code generated return code: ",rtn,! QUIT}
WRITE "Running the code",!!
DO ^myobj
The source argument can be an unsubscripted local variable name, or a possibly subscripted global name.
If source(0) is undefined, the system generates an <UNDEFINED> error, regardless of the %SYSTEM.Process.Undefined()Opens in a new tab method setting.
If a source(0) value is larger than the number of lines of source code, or a consecutive source code line is missing, the system generates an <UNDEFINED> error, followed by the name of the missing source code line. This behavior can be changed by setting the %SYSTEM.Process.Undefined()Opens in a new tab method. These types of errors are shown in the following examples:
SET src(0)=4,src(1)="TestA ",src(2)=" WRITE 123",src(3)=" WRITE 456,!"
SET stat=$COMPILE(src,0,errs,TestA) /* generates <UNDEFINED> *src(4) */
SET src(0)=4,src(1)="TestA ",src(3)=" WRITE 123",src(4)=" WRITE 456,!"
SET stat=$COMPILE(src,0,errs,TestA) /* generates <UNDEFINED> *src(2) */
SET src(0)=3,src(1)="TestA ",src(3)=" WRITE 123",src(4)=" WRITE 456,!"
SET stat=$COMPILE(src,0,errs,TestA) /* generates <UNDEFINED> *src(2) */
language
The language mode specifying the type of source to be compiled. Use 0 for ObjectScript.
Other values specify legacy modes and should be used only after consultation with InterSystems support.
errors
An unsubscripted local variable that is set to any errors detected by the compiler. Any existing value is killed. If no errors are detected, the variable is set to the empty string (""). If errors are detected, the errors variable is set to a $LIST structure with one element for each error. Each error is itself a $LIST structure with the format $LISTBUILD(line,offset,errnum,text) where:
-
line = the line number where the error was detected
-
offset = the offset in the source line of the error
-
errnum = an error number for the type of error
-
text = text describing the error
object
An array that receives the object code output of the compiler. The object argument can be an unsubscripted local variable name, or a possibly subscripted global name. The contents of the object array are described above.
rname
The routine name that specifies where the object code should saved in the ^rOBJ subscripted global. $COMPILE kills any existing contents of ^rOBJ(rname) before saving the new object code. In the following examples, rname=”myobj”:
To view the OBJ code:
WRITE ^rOBJ("myobj")
or
ZWRITE ^rOBJ("myobj")
To execute the OBJ code:
DO ^myobj
To list the creation timestamp and length of the OBJ code:
ZWRITE ^rINDEX("myobj")
Note that ^rINDEX() only list an OBJ code line, because code created by $COMPILE has no corresponding stored MAC or INT code version.
Other Compile Interfaces
InterSystems IRIS provides class methods to compile one or more classes:
-
$SYSTEM.OBJ.Compile()Opens in a new tab compiles the specified class and all routines within that class.
-
$SYSTEM.OBJ.CompileList()Opens in a new tab compiles a list of specified classes and all routines within those classes.
-
$SYSTEM.OBJ.CompilePackage()Opens in a new tab compiles all classes/routines in the specified package (schema).
-
$SYSTEM.OBJ.CompileAll()Opens in a new tab compiles all classes/routines in the current namespace.
-
$SYSTEM.OBJ.CompileAllNamespaces()Opens in a new tab compiles all classes/routines in all namespaces.
These methods provide numerous qualifiers and flags to more precisely specify compilation options; see System Flags and Qualifiers (qspec).
Interrupting a Compile
You can issue a Ctrl-C or invoke the ^RESJOB utility to interrupt a compile in progress. These compile interrupts are supported for all language modes.
Compiler Version
You can use the %SYSTEM.Version.GetCompilerVersion()Opens in a new tab method to return the current compiler version. InterSystems IRIS can only execute object code compiled with the same major compiler version number. It can execute object code compiled with any minor compiler version number that is less than or equal to the current minor compiler version.
Examples
The following example compiles a four-line ObjectScript program using the first $COMPILE format:
SourceCode
SET src(0)=4
SET src(1)="TestA "
SET src(2)=" WRITE ""Hello "" "
SET src(3)=" WRITE ""World"",!"
SET src(4)=" QUIT"
CompileSource
SET stat=$COMPILE(src,0,errs,TestA)
IF stat=0 {WRITE "Compile successful" }
ELSE {WRITE "status=",stat,!
WRITE "number of compile errors=",$LISTLENGTH(errs) }
The following example compiles the same four-line ObjectScript program using the second $COMPILE format:
SourceCode
SET src(0)=4
SET src(1)="TestB "
SET src(2)=" WRITE ""Hello "" "
SET src(3)=" WRITE ""World"",!"
SET src(4)=" QUIT"
CompileSource
SET stat=$COMPILE(src,0,errs,,,,"TestB")
IF stat=0 {WRITE "Compile successful",!
DO ^TestB }
ELSE {WRITE "status=",stat,!
WRITE "number of compile errors=",$LISTLENGTH(errs) }
The following example performs compilation error checking on a seven-line ObjectScript program. Note that this $COMPILE only tests for errors; it does not provide a variable to receive the object code from a successful compile. In this example every line of source code contains an error; $COMPILE only returns the compile-time errors in lines 1, 3, 5, 6, and 7, not runtime errors such as a divide-by-zero error (line 2) or an undefined variable error (line 4):
SourceCode
SET src(0)=7
SET src(1)="?TestC "
SET src(2)=" SET a=2/0"
SET src(3)=" SET b=3+#2"
SET src(4)=" SET c=xxx"
SET src(5)=" SET? d=5"
SET src(6)=" SET 123=""abc"""
SET src(7)=" SETT f=7"
CompileSource
SET stat=$COMPILE(src,0,errs)
IF stat {WRITE $LISTLENGTH(errs)," Compile Errors ",!
FOR i=1:1:$LISTLENGTH(errs) {
WRITE !,i,": "
SET errn=$LIST(errs,i)
FOR j=1:1:$LISTLENGTH(errn) {
WRITE $LIST(errn,j)," "
}
}
}
ELSE {WRITE "Compile successful",!
WRITE "but no object code generated" }